Compare commits

..

12 Commits

Author SHA1 Message Date
xiaoxian521
30209f62a9 release: update 3.9.7 2022-12-26 14:31:04 +08:00
xiaoxian521
1081506d10 chore: 默认关闭 CachingAsyncRoutes 动态路由缓存本地,可自行开启 2022-12-26 12:53:28 +08:00
xiaoxian521
590d6bf607 chore: update 2022-12-23 18:34:16 +08:00
xiaoxian521
3365b99d3d docs: update README.md 2022-12-21 11:37:25 +08:00
xiaoxian521
31707cebf7 chore: update 2022-12-19 14:20:56 +08:00
xiaoxian521
dac3ea3c21 release: update 3.9.6 2022-12-19 12:14:18 +08:00
xiaoxian521
01a32988c1 chore: 更新流程图业务代码 2022-12-19 12:02:32 +08:00
xiaoxian521
2e2c306097 chore: 升级vite4 2022-12-19 11:58:49 +08:00
xiaoxian521
d36d5b09c5 fix: 修复tailwind.css错误的引入方式导致vitehmr慢的问题 2022-12-19 10:42:26 +08:00
RealityBoy
923f09db5b refactor: system pages (#399)
* refactor: system pages

* chore: update

* chore: update

* chore: update

* chore: update

* chore: update

* chore: update

* chore: update

* chore: update

* chore: update
2022-12-16 14:34:10 +08:00
xiaoxian521
66fdfebb5e chore: update @pureadmin/theme latest 2022-12-15 12:28:51 +08:00
xiaoxian521
e032f9a6a7 chore: update 2022-12-13 15:24:29 +08:00
50 changed files with 1004 additions and 858 deletions

View File

@@ -1,3 +1,26 @@
# 3.9.7 (2022-12-26)
### 🍏 Perf
- Use `path.posix.resolve` instead of `path.resolve` to avoid drive letter problems when using `electron` in `windows` environment
- By default, the `CachingAsyncRoutes` dynamic routing cache is turned off locally, making it easier to debug in the development environment. It is not necessary to clear the local cached dynamic routing every time you modify the dynamic routing. It is recommended to enable it in the production environment
# 3.9.6 (2022-12-19)
### 🎫 Chores
- Upgrade `vite4` version
### 🐞 Bug fixes
- Fix the problem that `hmr` of `vite` is slow due to the wrong way of importing `tailwind.css`
### 🍏 Perf
- Update [@pureadmin/theme](https://github.com/pure-admin/pure-admin-theme) to the latest version, bringing more friendly type hints
- Optimize [PureTableBar](https://github.com/xiaoxian521/vue-pure-admin/tree/main/src/components/RePureTableBar) component
- Optimize the business code of the system management page to bring better code reference
# 3.9.5 (2022-12-13)
### ✔️ refactor

View File

@@ -1,3 +1,26 @@
# 3.9.7 (2022-12-26)
### 🍏 Perf
- Use `path.posix.resolve` instead of `path.resolve` to avoid drive letter problems when using `electron` in `windows` environment
- By default, the `CachingAsyncRoutes` dynamic routing cache is turned off locally, making it easier to debug in the development environment. It is not necessary to clear the local cached dynamic routing every time you modify the dynamic routing. It is recommended to enable it in the production environment
# 3.9.6 (2022-12-19)
### 🎫 Chores
- Upgrade `vite4` version
### 🐞 Bug fixes
- Fix the problem that `hmr` of `vite` is slow due to the wrong way of importing `tailwind.css`
### 🍏 Perf
- Update [@pureadmin/theme](https://github.com/pure-admin/pure-admin-theme) to the latest version, bringing more friendly type hints
- Optimize [PureTableBar](https://github.com/xiaoxian521/vue-pure-admin/tree/main/src/components/RePureTableBar) component
- Optimize the business code of the system management page to bring better code reference
# 3.9.5 (2022-12-13)
### ✔️ refactor

View File

@@ -1,3 +1,26 @@
# 3.9.7 (2022-12-26)
### 🍏 Perf
- 使用 `path.posix.resolve` 替代 `path.resolve` 避免 `windows` 环境下使用 `electron` 出现盘符问题
- 默认关闭 `CachingAsyncRoutes` 动态路由缓存本地,使其在开发环境下调试更方便,不用每次修改动态路由都要先清空本地缓存的动态路由,更推荐在生产环境开启
# 3.9.6 (2022-12-19)
### 🎫 Chores
- 升级 `vite4` 版本
### 🐞 Bug fixes
- 修复 `tailwind.css` 错误的引入方式导致 `vite``hmr` 慢的问题
### 🍏 Perf
- 更新 [@pureadmin/theme](https://github.com/pure-admin/pure-admin-theme) 至最新版,带来更友好的类型提示
- 优化 [PureTableBar](https://github.com/xiaoxian521/vue-pure-admin/tree/main/src/components/RePureTableBar) 组件
- 优化系统管理页面业务代码,带来更好的代码参考
# 3.9.5 (2022-12-13)
### ✔️ refactor

View File

@@ -140,7 +140,7 @@ pnpm build
[xiaoxian521](https://github.com/xiaoxian521)、[Ten-K](https://github.com/Ten-K)
## 捐赠
## 支持
如果您觉得这个项目对您有帮助,可以帮作者买一杯果汁 🍹 表示支持
@@ -148,9 +148,7 @@ pnpm build
## `QQ` 交流群
一群已满,下面是二群,群里严禁`黄``赌``毒``vpn`等违法行为!
<img src="https://yiming_chang.gitee.io/pure-admin-doc/img/support/qq.png" width="150px" height="225px" />
[点击去加入](https://yiming_chang.gitee.io/pure-admin-doc/pages/support/#qq-%E4%BA%A4%E6%B5%81%E7%BE%A4)
## 许可证
@@ -158,7 +156,7 @@ pnpm build
[MIT © xiaoxian521-2020](./LICENSE)
## 捐赠
## 支持
非常感谢您们的支持,相信项目会越来越好 :heart:

View File

@@ -27,9 +27,4 @@ const warpperEnv = (envConf: Recordable): ViteEnv => {
return ret;
};
/** 获取环境变量 */
const loadEnv = (): ViteEnv => {
return import.meta.env;
};
export { warpperEnv, loadEnv };
export { warpperEnv };

View File

@@ -52,7 +52,6 @@ const include = [
const exclude = [
"@iconify-icons/ep",
"@iconify-icons/ri",
"@iconify-icons/mdi",
"@pureadmin/theme/dist/browser-utils"
];

View File

@@ -6,10 +6,10 @@ import svgLoader from "vite-svg-loader";
import vueJsx from "@vitejs/plugin-vue-jsx";
import { viteMockServe } from "vite-plugin-mock";
import { configCompressPlugin } from "./compress";
import VueI18n from "@intlify/vite-plugin-vue-i18n";
import { visualizer } from "rollup-plugin-visualizer";
import removeConsole from "vite-plugin-remove-console";
import themePreprocessorPlugin from "@pureadmin/theme";
import VueI18nPlugin from "@intlify/unplugin-vue-i18n/vite";
import DefineOptions from "unplugin-vue-define-options/vite";
import { genScssMultipleScopeVars } from "../src/layout/theme";
@@ -22,8 +22,7 @@ export function getPluginsList(
const lifecycle = process.env.npm_lifecycle_event;
return [
vue(),
// https://github.com/intlify/bundle-tools/tree/main/packages/vite-plugin-vue-i18n
VueI18n({
VueI18nPlugin({
runtimeOnly: true,
compositionOnly: true,
include: [resolve("locales/**")]
@@ -40,14 +39,7 @@ export function getPluginsList(
themePreprocessorPlugin({
scss: {
multipleScopeVars: genScssMultipleScopeVars(),
// 在生产模式是否抽取独立的主题css文件extract为true以下属性有效
extract: true,
// 会选取defaultScopeName对应的主题css文件在html添加link
themeLinkTagId: "head",
// "head"||"head-prepend" || "body" ||"body-prepend"
themeLinkTagInjectTo: "head",
// 是否对抽取的css文件内对应scopeName的权重类名移除
removeCssScopeName: false
extract: true
}
}),
// svg组件化支持

View File

@@ -1,6 +1,6 @@
{
"name": "vue-pure-admin",
"version": "3.9.5",
"version": "3.9.7",
"private": true,
"scripts": {
"dev": "NODE_OPTIONS=--max-old-space-size=4096 vite",
@@ -47,7 +47,7 @@
"dayjs": "^1.11.6",
"echarts": "^5.4.0",
"el-table-infinite-scroll": "^3.0.1",
"element-plus": "^2.2.26",
"element-plus": "^2.2.27",
"element-resize-detector": "^1.2.4",
"intro.js": "^6.0.0",
"js-cookie": "^3.0.1",
@@ -57,7 +57,7 @@
"mockjs": "^1.1.0",
"nprogress": "^0.2.0",
"path": "^0.12.7",
"pinia": "^2.0.27",
"pinia": "^2.0.28",
"qrcode": "^1.5.1",
"qs": "^6.11.0",
"responsive-storage": "^2.1.0",
@@ -71,8 +71,8 @@
"vue-pdf-embed": "^1.1.5",
"vue-router": "^4.1.6",
"vue-types": "^4.2.1",
"vue-virtual-scroller": "^2.0.0-alpha.1",
"vue3-danmaku": "^1.1.0",
"vue-virtual-scroller": "2.0.0-beta.7",
"vue3-danmaku": "^1.2.0",
"vuedraggable": "^4.1.0",
"xgplayer": "^2.32.1",
"xlsx": "^0.18.5"
@@ -81,11 +81,10 @@
"@commitlint/cli": "13.1.0",
"@commitlint/config-conventional": "13.1.0",
"@iconify-icons/ep": "^1.2.7",
"@iconify-icons/mdi": "^1.2.8",
"@iconify-icons/ri": "^1.2.3",
"@iconify/vue": "^4.0.0",
"@intlify/vite-plugin-vue-i18n": "^6.0.3",
"@pureadmin/theme": "^2.4.0",
"@intlify/unplugin-vue-i18n": "^0.8.1",
"@pureadmin/theme": "^3.0.0",
"@types/element-resize-detector": "1.1.3",
"@types/intro.js": "^5.1.0",
"@types/js-cookie": "^3.0.1",
@@ -97,8 +96,8 @@
"@types/sortablejs": "^1.15.0",
"@typescript-eslint/eslint-plugin": "^5.43.0",
"@typescript-eslint/parser": "^5.43.0",
"@vitejs/plugin-vue": "^3.2.0",
"@vitejs/plugin-vue-jsx": "^2.1.1",
"@vitejs/plugin-vue": "^4.0.0",
"@vitejs/plugin-vue-jsx": "^3.0.0",
"@vue/eslint-config-prettier": "^7.0.0",
"@vue/eslint-config-typescript": "^11.0.2",
"autoprefixer": "^10.4.13",
@@ -131,7 +130,7 @@
"terser": "^5.15.1",
"typescript": "^4.9.3",
"unplugin-vue-define-options": "^1.0.0",
"vite": "3.1.8",
"vite": "^4.0.3",
"vite-plugin-cdn-import": "^0.3.5",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-mock": "^2.9.6",

732
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
{
"Version": "3.9.5",
"Version": "3.9.7",
"Title": "PureAdmin",
"FixedHeader": true,
"HiddenSideBar": false,
@@ -17,7 +17,7 @@
"ShowLogo": true,
"ShowModel": "smart",
"MenuArrowIconNoTransition": true,
"CachingAsyncRoutes": true,
"CachingAsyncRoutes": false,
"TooltipEffect": "light",
"MapConfigure": {
"amapKey": "97b3248d1553172e81f168cf94ea667e",

View File

@@ -10,6 +10,11 @@ type Result = {
};
};
type ResultDept = {
success: boolean;
data?: Array<any>;
};
/** 获取用户管理列表 */
export const getUserList = (data?: object) => {
return http.request<Result>("post", "/user", { data });
@@ -22,5 +27,5 @@ export const getRoleList = (data?: object) => {
/** 获取部门管理列表 */
export const getDeptList = (data?: object) => {
return http.request<Result>("post", "/dept", { data });
return http.request<ResultDept>("post", "/dept", { data });
};

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -43,7 +43,3 @@ addIcon("setting", Setting);
addIcon("dept", Dept);
addIcon("lollipop", Lollipop);
addIcon("monitor", Monitor);
// 非菜单图标
import RefreshRight from "@iconify-icons/ep/refresh-right";
addIcon("refreshRight", RefreshRight);

View File

@@ -0,0 +1,5 @@
import pureTableBar from "./src/bar";
import { withInstall } from "@pureadmin/utils";
/** 配合 `@pureadmin/table` 实现快速便捷的表格操作 https://github.com/xiaoxian521/pure-admin-table */
export const PureTableBar = withInstall(pureTableBar);

View File

@@ -1,54 +1,25 @@
import { defineComponent, ref, computed, PropType } from "vue";
import { delay } from "@pureadmin/utils";
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
import UnExpand from "@iconify-icons/mdi/arrow-expand-right";
import { IconifyIconOffline } from "../../ReIcon";
import Expand from "@iconify-icons/mdi/arrow-expand-down";
import ArrowCollapse from "@iconify-icons/mdi/arrow-collapse-vertical";
import Setting from "@iconify-icons/ri/settings-3-line";
export const loadingSvg = `
<path class="path" d="
M 30 15
L 28 17
M 25.61 25.61
A 15 15, 0, 0, 1, 15 30
A 15 15, 0, 1, 1, 27.99 7.5
L 15 15
"
style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"
/>
`;
import { defineComponent, ref, computed, type PropType } from "vue";
import ExpandIcon from "./svg/expand.svg?component";
import RefreshIcon from "./svg/refresh.svg?component";
import SettingIcon from "./svg/settings.svg?component";
import CollapseIcon from "./svg/collapse.svg?component";
const props = {
// 头部最左边的标题
/** 头部最左边的标题 */
title: {
type: String,
default: "列表"
},
// 表格数据
dataList: {
type: Array,
default: () => {
return [];
}
},
// 对于树形表格如果想启用展开和折叠功能传入当前表格的ref即可
/** 对于树形表格如果想启用展开和折叠功能传入当前表格的ref即可 */
tableRef: {
type: Object as PropType<any>,
default() {
return {};
}
},
// 是否显示加载动画默认false 不加载
loading: {
type: Boolean,
default: false
type: Object as PropType<any>
}
};
export default defineComponent({
name: "TableProBar",
name: "PureTableBar",
props,
emits: ["refresh"],
setup(props, { emit, slots, attrs }) {
@@ -56,6 +27,7 @@ export default defineComponent({
const checkList = ref([]);
const size = ref("default");
const isExpandAll = ref(true);
const loading = ref(false);
const getDropdownItemStyle = computed(() => {
return s => {
@@ -67,9 +39,26 @@ export default defineComponent({
};
});
const iconClass = computed(() => {
return [
"text-black",
"dark:text-white",
"duration-100",
"hover:!text-primary",
"cursor-pointer",
"outline-none"
];
});
function onReFresh() {
loading.value = true;
emit("refresh");
delay(500).then(() => (loading.value = false));
}
function onExpand() {
isExpandAll.value = !isExpandAll.value;
toggleRowExpansionAll(props.dataList, isExpandAll.value);
toggleRowExpansionAll(props.tableRef.data, isExpandAll.value);
}
function toggleRowExpansionAll(data, isExpansion) {
@@ -88,7 +77,7 @@ export default defineComponent({
style={getDropdownItemStyle.value("large")}
onClick={() => (size.value = "large")}
>
</el-dropdown-item>
<el-dropdown-item
style={getDropdownItemStyle.value("default")}
@@ -108,11 +97,8 @@ export default defineComponent({
const reference = {
reference: () => (
<IconifyIconOffline
class="cursor-pointer"
icon={Setting}
width="16"
color="text_color_regular"
<SettingIcon
class={["w-[16px]", iconClass.value]}
onMouseover={e => (buttonRef.value = e.currentTarget)}
/>
)
@@ -120,13 +106,7 @@ export default defineComponent({
return () => (
<>
<div
{...attrs}
class="w-[99/100] mt-6 p-2 bg-bg_color"
v-loading={props.loading}
element-loading-svg={loadingSvg}
element-loading-svg-view-box="-10, -10, 50, 50"
>
<div {...attrs} class="w-[99/100] mt-6 p-2 bg-bg_color">
<div class="flex justify-between w-full h-[60px] p-4">
<p class="font-bold truncate">{props.title}</p>
<div class="flex items-center justify-around">
@@ -138,36 +118,32 @@ export default defineComponent({
content={isExpandAll.value ? "折叠" : "展开"}
placement="top"
>
<IconifyIconOffline
class="cursor-pointer"
icon={isExpandAll.value ? UnExpand : Expand}
width="16"
color="text_color_regular"
<ExpandIcon
class={["w-[16px]", iconClass.value]}
style={{
transform: isExpandAll.value ? "none" : "rotate(-90deg)"
}}
onClick={() => onExpand()}
/>
</el-tooltip>
<el-divider direction="vertical" />
</>
) : undefined}
) : null}
<el-tooltip effect="dark" content="刷新" placement="top">
<IconifyIconOffline
class="cursor-pointer"
icon="refreshRight"
width="16"
color="text_color_regular"
onClick={() => emit("refresh")}
<RefreshIcon
class={[
"w-[16px]",
iconClass.value,
loading.value ? "animate-spin" : ""
]}
onClick={() => onReFresh()}
/>
</el-tooltip>
<el-divider direction="vertical" />
<el-tooltip effect="dark" content="密度" placement="top">
<el-dropdown v-slots={dropdown} trigger="click">
<IconifyIconOffline
class="cursor-pointer"
icon={ArrowCollapse}
width="16"
color="text_color_regular"
/>
<CollapseIcon class={["w-[16px]", iconClass.value]} />
</el-dropdown>
</el-tooltip>
<el-divider direction="vertical" />
@@ -199,11 +175,7 @@ export default defineComponent({
content="列设置"
/>
</div>
{props.dataList.length > 0 ? (
slots.default({ size: size.value, checkList: checkList.value })
) : (
<el-empty description="暂无数据" />
)}
{slots.default({ size: size.value, checkList: checkList.value })}
</div>
</>
);

View File

@@ -0,0 +1 @@
<svg width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M13.79 10.21a1 1 0 0 0 1.42 0 1 1 0 0 0 0-1.42l-2.5-2.5a1 1 0 0 0-.33-.21 1 1 0 0 0-.76 0 1 1 0 0 0-.33.21l-2.5 2.5a1 1 0 0 0 1.42 1.42l.79-.8v5.18l-.79-.8a1 1 0 0 0-1.42 1.42l2.5 2.5a1 1 0 0 0 .33.21.94.94 0 0 0 .76 0 1 1 0 0 0 .33-.21l2.5-2.5a1 1 0 0 0-1.42-1.42l-.79.8V9.41ZM7 4h10a1 1 0 0 0 0-2H7a1 1 0 0 0 0 2Zm10 16H7a1 1 0 0 0 0 2h10a1 1 0 0 0 0-2Z"/></svg>

After

Width:  |  Height:  |  Size: 441 B

View File

@@ -0,0 +1 @@
<svg width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M22 4V2H2v2h9v14.17l-5.5-5.5-1.42 1.41L12 22l7.92-7.92-1.42-1.41-5.5 5.5V4h9Z"/></svg>

After

Width:  |  Height:  |  Size: 163 B

View File

@@ -0,0 +1 @@
<svg width="32" height="32" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 11A8.1 8.1 0 0 0 4.5 9M4 5v4h4m-4 4a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4"/></svg>

After

Width:  |  Height:  |  Size: 235 B

View File

@@ -0,0 +1 @@
<svg width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M3.34 17a10.018 10.018 0 0 1-.978-2.326 3 3 0 0 0 .002-5.347A9.99 9.99 0 0 1 4.865 4.99a3 3 0 0 0 4.631-2.674 9.99 9.99 0 0 1 5.007.002 3 3 0 0 0 4.632 2.672A9.99 9.99 0 0 1 20.66 7c.433.749.757 1.53.978 2.326a3 3 0 0 0-.002 5.347 9.99 9.99 0 0 1-2.501 4.337 3 3 0 0 0-4.631 2.674 9.99 9.99 0 0 1-5.007-.002 3 3 0 0 0-4.632-2.672A10.018 10.018 0 0 1 3.34 17zm5.66.196a4.993 4.993 0 0 1 2.25 2.77c.499.047 1 .048 1.499.001A4.993 4.993 0 0 1 15 17.197a4.993 4.993 0 0 1 3.525-.565c.29-.408.54-.843.748-1.298A4.993 4.993 0 0 1 18 12c0-1.26.47-2.437 1.273-3.334a8.126 8.126 0 0 0-.75-1.298A4.993 4.993 0 0 1 15 6.804a4.993 4.993 0 0 1-2.25-2.77c-.499-.047-1-.048-1.499-.001A4.993 4.993 0 0 1 9 6.803a4.993 4.993 0 0 1-3.525.565 7.99 7.99 0 0 0-.748 1.298A4.993 4.993 0 0 1 6 12a4.99 4.99 0 0 1-1.273 3.334 8.126 8.126 0 0 0 .75 1.298A4.993 4.993 0 0 1 9 17.196zM12 15a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>

After

Width:  |  Height:  |  Size: 1011 B

View File

@@ -9,9 +9,9 @@ import {
} from "vue";
import "./index.scss";
import { propTypes } from "@/utils/propTypes";
import { IconifyIconOffline } from "../../ReIcon";
import { isString, cloneDeep } from "@pureadmin/utils";
import QRCode, { QRCodeRenderersOptions } from "qrcode";
import RefreshRight from "@iconify-icons/ep/refresh-right";
interface QrcodeLogo {
src?: string;
@@ -244,9 +244,9 @@ export default defineComponent({
onClick={disabledClick}
>
<div class="absolute top-[50%] left-[50%] font-bold">
<IconifyIconOffline
<iconify-icon-offline
class="cursor-pointer"
icon="refreshRight"
icon={RefreshRight}
width="30"
color="var(--el-color-primary)"
/>

View File

@@ -1,5 +0,0 @@
import tableProBar from "./src/bar";
import { withInstall } from "@pureadmin/utils";
/** table-crud组件 */
export const TableProBar = withInstall(tableProBar);

View File

@@ -1,9 +1,8 @@
import { App } from "vue";
import axios from "axios";
import { loadEnv } from "@build/index";
let config: object = {};
const { VITE_PUBLIC_PATH } = loadEnv();
const { VITE_PUBLIC_PATH } = import.meta.env;
const setConfig = (cfg?: unknown) => {
config = Object.assign(config, cfg);

View File

@@ -70,14 +70,8 @@ notices.value.map(v => (noticesNum.value += v.list.length));
height: 1px;
}
// 如果上面的 notices 长度大于 3 请注释掉下面代码
:deep(.el-tabs__nav-wrap) {
padding: 0 36px 0 36px;
}
// 如果上面的 notices 长度大于 3 请注释掉下面代码
:deep(.el-tabs__active-bar) {
margin: 0 36px 0 36px;
}
}
</style>

View File

@@ -144,7 +144,8 @@ function resolvePath(routePath) {
if (httpReg.test(routePath) || httpReg.test(props.basePath)) {
return routePath || props.basePath;
} else {
return path.resolve(props.basePath, routePath);
// 使用path.posix.resolve替代path.resolve 避免windows环境下使用electron出现盘符问题
return path.posix.resolve(props.basePath, routePath);
}
}
</script>

View File

@@ -2,10 +2,7 @@
* @description ⚠️:此文件仅供主题插件使用,请不要在此文件中导出别的工具函数(仅在页面加载前运行)
*/
type MultipleScopeVarsItem = {
scopeName: string;
varsContent: string;
};
import { type multipleScopeVarsOptions } from "@pureadmin/theme";
/** 预设主题色 */
const themeColors = {
@@ -113,8 +110,8 @@ const themeColors = {
/**
* @description 将预设主题色处理成主题插件所需格式
*/
export const genScssMultipleScopeVars = (): MultipleScopeVarsItem[] => {
const result = [] as MultipleScopeVarsItem[];
export const genScssMultipleScopeVars = (): multipleScopeVarsOptions[] => {
const result = [] as multipleScopeVarsOptions[];
Object.keys(themeColors).forEach(key => {
result.push({
scopeName: `layout-theme-${key}`,
@@ -129,7 +126,7 @@ export const genScssMultipleScopeVars = (): MultipleScopeVarsItem[] => {
$menuTitleHover: ${themeColors[key].menuTitleHover} !default;
$menuActiveBefore: ${themeColors[key].menuActiveBefore} !default;
`
} as MultipleScopeVarsItem);
} as multipleScopeVarsOptions);
});
return result;
};

View File

@@ -16,6 +16,8 @@ import PureDescriptions from "@pureadmin/descriptions";
import "./style/reset.scss";
// 导入公共样式
import "./style/index.scss";
// 一定要在main.ts中导入tailwind.css防止vite每次hmr都会请求src/style/index.scss整体css文件导致热更新慢的问题
import "./style/tailwind.css";
import "element-plus/dist/index.css";
// 导入字体图标
import "./assets/iconfont/iconfont.js";

View File

@@ -8,7 +8,6 @@ import {
} from "vue-router";
import { router } from "./index";
import { isProxy, toRaw } from "vue";
import { loadEnv } from "../../build";
import { useTimeoutFn } from "@vueuse/core";
import { RouteConfigs } from "@/layout/types";
import {
@@ -324,7 +323,7 @@ function addAsyncRoutes(arrRoutes: Array<RouteRecordRaw>) {
/** 获取路由历史模式 https://next.router.vuejs.org/zh/guide/essentials/history-mode.html */
function getHistoryMode(): RouterHistory {
const routerHistory = loadEnv().VITE_ROUTER_HISTORY;
const routerHistory = import.meta.env.VITE_ROUTER_HISTORY;
// len为1 代表只有历史模式 为2 代表历史模式中存在base参数 https://next.router.vuejs.org/zh/api/#%E5%8F%82%E6%95%B0-1
const historyMode = routerHistory.split(",");
const leftMode = historyMode[0];

View File

@@ -3,7 +3,6 @@
@import "./element-plus.scss";
@import "./sidebar.scss";
@import "./dark.scss";
@import "./tailwind.css";
/* 自定义全局 CssVar */
:root {

View File

@@ -1,12 +1,11 @@
<script setup lang="ts">
import { ref } from "vue";
import { loadEnv } from "@build/index";
defineOptions({
name: "Button"
});
const { VITE_PUBLIC_PATH } = loadEnv();
const { VITE_PUBLIC_PATH } = import.meta.env;
const url = ref(`${VITE_PUBLIC_PATH}html/button.html`);
</script>

View File

@@ -1,5 +1,6 @@
<script setup lang="ts">
import { initRouter } from "@/router/utils";
import { storageSession } from "@pureadmin/utils";
import { type CSSProperties, ref, computed } from "vue";
import { useUserStoreHook } from "@/store/modules/user";
import { usePermissionStoreHook } from "@/store/modules/permission";
@@ -33,7 +34,7 @@ function onChange() {
.loginByUsername({ username: username.value, password: "admin123" })
.then(res => {
if (res.success) {
sessionStorage.removeItem("async-routes");
storageSession().removeItem("async-routes");
usePermissionStoreHook().clearAllCachePage();
initRouter();
}

View File

@@ -1,4 +1,3 @@
import { IconifyIconOffline } from "@/components/ReIcon";
import ArrowRightSLine from "@iconify-icons/ri/arrow-right-s-line";
import CloseCircleLine from "@iconify-icons/ri/close-circle-line";
@@ -8,7 +7,7 @@ export function useColumns() {
cellRenderer: () => {
return (
<span class="flex items-center -mt-6">
<IconifyIconOffline
<iconify-icon-offline
icon={CloseCircleLine}
color="#F56C6C"
width="18px"
@@ -21,7 +20,7 @@ export function useColumns() {
style="color: var(--el-color-primary)"
>
<IconifyIconOffline
<iconify-icon-offline
icon={ArrowRightSLine}
color="var(--el-color-primary)"
width="18px"
@@ -36,7 +35,7 @@ export function useColumns() {
cellRenderer: () => {
return (
<span class="flex items-center -mt-8">
<IconifyIconOffline
<iconify-icon-offline
icon={CloseCircleLine}
color="#F56C6C"
width="18px"
@@ -49,7 +48,7 @@ export function useColumns() {
style="color: var(--el-color-primary)"
>
<IconifyIconOffline
<iconify-icon-offline
icon={ArrowRightSLine}
color="var(--el-color-primary)"
width="18px"

View File

@@ -1,64 +0,0 @@
import dayjs from "dayjs";
export function useColumns() {
const columns: TableColumnList = [
{
type: "selection",
width: 55,
align: "left",
hide: ({ checkList }) => !checkList.includes("勾选列")
},
{
label: "序号",
type: "index",
width: 60,
hide: ({ checkList }) => !checkList.includes("序号列")
},
{
label: "部门名称",
prop: "name",
width: 180,
align: "left"
},
{
label: "排序",
prop: "sort",
width: 60
},
{
label: "状态",
prop: "status",
width: 80,
cellRenderer: ({ row, props }) => (
<el-tag
size={props.size}
type={row.status === 1 ? "danger" : "success"}
effect="plain"
>
{row.status === 0 ? "关闭" : "开启"}
</el-tag>
)
},
{
label: "创建时间",
width: 180,
prop: "createTime",
formatter: ({ createTime }) =>
dayjs(createTime).format("YYYY-MM-DD HH:mm:ss")
},
{
label: "备注",
prop: "remark"
},
{
label: "操作",
fixed: "right",
width: 140,
slot: "operation"
}
];
return {
columns
};
}

View File

@@ -0,0 +1,114 @@
import dayjs from "dayjs";
import { handleTree } from "@/utils/tree";
import { getDeptList } from "@/api/system";
import { reactive, ref, onMounted } from "vue";
export function useDept() {
const form = reactive({
user: "",
status: ""
});
const dataList = ref([]);
const loading = ref(true);
const columns: TableColumnList = [
{
type: "selection",
width: 55,
align: "left",
hide: ({ checkList }) => !checkList.includes("勾选列")
},
{
label: "序号",
type: "index",
minWidth: 70,
hide: ({ checkList }) => !checkList.includes("序号列")
},
{
label: "部门名称",
prop: "name",
width: 180,
align: "left"
},
{
label: "排序",
prop: "sort",
minWidth: 70
},
{
label: "状态",
prop: "status",
minWidth: 100,
cellRenderer: ({ row, props }) => (
<el-tag
size={props.size}
type={row.status === 1 ? "danger" : "success"}
effect="plain"
>
{row.status === 0 ? "关闭" : "开启"}
</el-tag>
)
},
{
label: "创建时间",
minWidth: 200,
prop: "createTime",
formatter: ({ createTime }) =>
dayjs(createTime).format("YYYY-MM-DD HH:mm:ss")
},
{
label: "备注",
prop: "remark",
minWidth: 200
},
{
label: "操作",
fixed: "right",
width: 160,
slot: "operation"
}
];
function handleUpdate(row) {
console.log(row);
}
function handleDelete(row) {
console.log(row);
}
function handleSelectionChange(val) {
console.log("handleSelectionChange", val);
}
function resetForm(formEl) {
if (!formEl) return;
formEl.resetFields();
onSearch();
}
async function onSearch() {
loading.value = true;
const { data } = await getDeptList();
dataList.value = handleTree(data);
setTimeout(() => {
loading.value = false;
}, 500);
}
onMounted(() => {
onSearch();
});
return {
form,
loading,
columns,
dataList,
onSearch,
resetForm,
handleUpdate,
handleDelete,
handleSelectionChange
};
}

View File

@@ -1,11 +1,9 @@
<script setup lang="ts">
import { useColumns } from "./columns";
import { handleTree } from "@/utils/tree";
import { getDeptList } from "@/api/system";
import { FormInstance } from "element-plus";
import { reactive, ref, onMounted } from "vue";
import { TableProBar } from "@/components/ReTable";
import { ref } from "vue";
import { useDept } from "./hook";
import { PureTableBar } from "@/components/RePureTableBar";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import Delete from "@iconify-icons/ep/delete";
import EditPen from "@iconify-icons/ep/edit-pen";
import Search from "@iconify-icons/ep/search";
@@ -16,47 +14,19 @@ defineOptions({
name: "Dept"
});
const form = reactive({
user: "",
status: ""
});
const dataList = ref([]);
const loading = ref(true);
const { columns } = useColumns();
const formRef = ref<FormInstance>();
const formRef = ref();
const tableRef = ref();
function handleUpdate(row) {
console.log(row);
}
function handleDelete(row) {
console.log(row);
}
function handleSelectionChange(val) {
console.log("handleSelectionChange", val);
}
async function onSearch() {
loading.value = true;
const { data } = await getDeptList();
dataList.value = handleTree(data as any);
setTimeout(() => {
loading.value = false;
}, 500);
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.resetFields();
onSearch();
};
onMounted(() => {
onSearch();
});
const {
form,
loading,
columns,
dataList,
onSearch,
resetForm,
handleUpdate,
handleDelete,
handleSelectionChange
} = useDept();
</script>
<template>
@@ -68,10 +38,20 @@ onMounted(() => {
class="bg-bg_color w-[99/100] pl-8 pt-4"
>
<el-form-item label="部门名称:" prop="user">
<el-input v-model="form.user" placeholder="请输入部门名称" clearable />
<el-input
v-model="form.user"
placeholder="请输入部门名称"
clearable
class="!w-[200px]"
/>
</el-form-item>
<el-form-item label="状态:" prop="status">
<el-select v-model="form.status" placeholder="请选择状态" clearable>
<el-select
v-model="form.status"
placeholder="请选择状态"
clearable
class="!w-[180px]"
>
<el-option label="开启" value="1" />
<el-option label="关闭" value="0" />
</el-select>
@@ -91,11 +71,9 @@ onMounted(() => {
</el-form-item>
</el-form>
<TableProBar
<PureTableBar
title="部门列表"
:loading="loading"
:tableRef="tableRef?.getTableRef()"
:dataList="dataList"
@refresh="onSearch"
>
<template #buttons>
@@ -112,6 +90,7 @@ onMounted(() => {
showOverflowTooltip
table-layout="auto"
default-expand-all
:loading="loading"
:size="size"
:data="dataList"
:columns="columns"
@@ -150,6 +129,6 @@ onMounted(() => {
</template>
</pure-table>
</template>
</TableProBar>
</PureTableBar>
</div>
</template>

View File

@@ -1,11 +1,25 @@
import { ref } from "vue";
import dayjs from "dayjs";
import { message } from "@/utils/message";
import { getRoleList } from "@/api/system";
import { ElMessageBox } from "element-plus";
import { type PaginationProps } from "@pureadmin/table";
import { reactive, ref, computed, onMounted } from "vue";
export function useColumns() {
export function useRole() {
const form = reactive({
name: "",
code: "",
status: ""
});
const dataList = ref([]);
const loading = ref(true);
const switchLoadMap = ref({});
const pagination = reactive<PaginationProps>({
total: 0,
pageSize: 10,
currentPage: 1,
background: true
});
const columns: TableColumnList = [
{
type: "selection",
@@ -21,19 +35,23 @@ export function useColumns() {
},
{
label: "角色编号",
prop: "id"
prop: "id",
minWidth: 100
},
{
label: "角色名称",
prop: "name"
prop: "name",
minWidth: 120
},
{
label: "角色标识",
prop: "code"
prop: "code",
minWidth: 150
},
{
label: "角色类型",
prop: "type",
minWidth: 150,
cellRenderer: ({ row, props }) => (
<el-tag
size={props.size}
@@ -46,12 +64,12 @@ export function useColumns() {
},
{
label: "显示顺序",
prop: "sort"
prop: "sort",
minWidth: 100
},
{
label: "状态",
prop: "status",
width: 130,
minWidth: 130,
cellRenderer: scope => (
<el-switch
size={scope.props.size === "small" ? "small" : "default"}
@@ -68,7 +86,7 @@ export function useColumns() {
},
{
label: "创建时间",
width: 180,
minWidth: 180,
prop: "createTime",
formatter: ({ createTime }) =>
dayjs(createTime).format("YYYY-MM-DD HH:mm:ss")
@@ -80,6 +98,15 @@ export function useColumns() {
slot: "operation"
}
];
const buttonClass = computed(() => {
return [
"!h-[20px]",
"reset-margin",
"!text-gray-500",
"dark:!text-white",
"dark:hover:!text-primary"
];
});
function onChange({ row, index }) {
ElMessageBox.confirm(
@@ -123,7 +150,59 @@ export function useColumns() {
});
}
function handleUpdate(row) {
console.log(row);
}
function handleDelete(row) {
console.log(row);
}
function handleSizeChange(val: number) {
console.log(`${val} items per page`);
}
function handleCurrentChange(val: number) {
console.log(`current page: ${val}`);
}
function handleSelectionChange(val) {
console.log("handleSelectionChange", val);
}
async function onSearch() {
loading.value = true;
const { data } = await getRoleList();
dataList.value = data.list;
pagination.total = data.total;
setTimeout(() => {
loading.value = false;
}, 500);
}
const resetForm = formEl => {
if (!formEl) return;
formEl.resetFields();
onSearch();
};
onMounted(() => {
onSearch();
});
return {
columns
form,
loading,
columns,
dataList,
pagination,
buttonClass,
onSearch,
resetForm,
handleUpdate,
handleDelete,
handleSizeChange,
handleCurrentChange,
handleSelectionChange
};
}

View File

@@ -1,11 +1,9 @@
<script setup lang="ts">
import { useColumns } from "./columns";
import { getRoleList } from "@/api/system";
import { reactive, ref, onMounted } from "vue";
import { type FormInstance } from "element-plus";
import { TableProBar } from "@/components/ReTable";
import { type PaginationProps } from "@pureadmin/table";
import { ref } from "vue";
import { useRole } from "./hook";
import { PureTableBar } from "@/components/RePureTableBar";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import Database from "@iconify-icons/ri/database-2-line";
import More from "@iconify-icons/ep/more-filled";
import Delete from "@iconify-icons/ep/delete";
@@ -19,64 +17,22 @@ defineOptions({
name: "Role"
});
const form = reactive({
name: "",
code: "",
status: ""
});
const dataList = ref([]);
const loading = ref(true);
const { columns } = useColumns();
const formRef = ref<FormInstance>();
const pagination = reactive<PaginationProps>({
total: 0,
pageSize: 10,
currentPage: 1,
background: true
});
function handleUpdate(row) {
console.log(row);
}
function handleDelete(row) {
console.log(row);
}
function handleCurrentChange(val: number) {
console.log(`current page: ${val}`);
}
function handleSizeChange(val: number) {
console.log(`${val} items per page`);
}
function handleSelectionChange(val) {
console.log("handleSelectionChange", val);
}
async function onSearch() {
loading.value = true;
const { data } = await getRoleList();
dataList.value = data.list;
pagination.total = data.total;
setTimeout(() => {
loading.value = false;
}, 500);
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.resetFields();
onSearch();
};
onMounted(() => {
onSearch();
});
const formRef = ref();
const {
form,
loading,
columns,
dataList,
pagination,
buttonClass,
onSearch,
resetForm,
handleUpdate,
handleDelete,
handleSizeChange,
handleCurrentChange,
handleSelectionChange
} = useRole();
</script>
<template>
@@ -88,13 +44,28 @@ onMounted(() => {
class="bg-bg_color w-[99/100] pl-8 pt-4"
>
<el-form-item label="角色名称:" prop="name">
<el-input v-model="form.name" placeholder="请输入角色名称" clearable />
<el-input
v-model="form.name"
placeholder="请输入角色名称"
clearable
class="!w-[200px]"
/>
</el-form-item>
<el-form-item label="角色标识:" prop="code">
<el-input v-model="form.code" placeholder="请输入角色标识" clearable />
<el-input
v-model="form.code"
placeholder="请输入角色标识"
clearable
class="!w-[180px]"
/>
</el-form-item>
<el-form-item label="状态:" prop="status">
<el-select v-model="form.status" placeholder="请选择状态" clearable>
<el-select
v-model="form.status"
placeholder="请选择状态"
clearable
class="!w-[180px]"
>
<el-option label="已开启" value="1" />
<el-option label="已关闭" value="0" />
</el-select>
@@ -114,12 +85,7 @@ onMounted(() => {
</el-form-item>
</el-form>
<TableProBar
title="角色列表"
:loading="loading"
:dataList="dataList"
@refresh="onSearch"
>
<PureTableBar title="角色列表" @refresh="onSearch">
<template #buttons>
<el-button type="primary" :icon="useRenderIcon(AddFill)">
新增角色
@@ -131,6 +97,7 @@ onMounted(() => {
align-whole="center"
showOverflowTooltip
table-layout="auto"
:loading="loading"
:size="size"
:data="dataList"
:columns="columns"
@@ -151,8 +118,8 @@ onMounted(() => {
link
type="primary"
:size="size"
@click="handleUpdate(row)"
:icon="useRenderIcon(EditPen)"
@click="handleUpdate(row)"
>
修改
</el-button>
@@ -172,18 +139,18 @@ onMounted(() => {
</el-popconfirm>
<el-dropdown>
<el-button
class="ml-3"
class="ml-3 mt-[2px]"
link
type="primary"
:size="size"
@click="handleUpdate(row)"
:icon="useRenderIcon(More)"
@click="handleUpdate(row)"
/>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>
<el-button
class="reset-margin !h-[20px] !text-gray-500 dark:!text-white dark:hover:!text-primary"
:class="buttonClass"
link
type="primary"
:size="size"
@@ -194,7 +161,7 @@ onMounted(() => {
</el-dropdown-item>
<el-dropdown-item>
<el-button
class="reset-margin !h-[20px] !text-gray-500 dark:!text-white dark:hover:!text-primary"
:class="buttonClass"
link
type="primary"
:size="size"
@@ -209,7 +176,7 @@ onMounted(() => {
</template>
</pure-table>
</template>
</TableProBar>
</PureTableBar>
</div>
</template>

View File

@@ -1,11 +1,25 @@
import { ref } from "vue";
import dayjs from "dayjs";
import { message } from "@/utils/message";
import { getUserList } from "@/api/system";
import { ElMessageBox } from "element-plus";
import { type PaginationProps } from "@pureadmin/table";
import { reactive, ref, computed, onMounted } from "vue";
export function useColumns() {
export function useUser() {
const form = reactive({
username: "",
mobile: "",
status: ""
});
const dataList = ref([]);
const loading = ref(true);
const switchLoadMap = ref({});
const pagination = reactive<PaginationProps>({
total: 0,
pageSize: 10,
currentPage: 1,
background: true
});
const columns: TableColumnList = [
{
type: "selection",
@@ -21,19 +35,23 @@ export function useColumns() {
},
{
label: "用户编号",
prop: "id"
prop: "id",
minWidth: 130
},
{
label: "用户名称",
prop: "username"
prop: "username",
minWidth: 130
},
{
label: "用户昵称",
prop: "nickname"
prop: "nickname",
minWidth: 130
},
{
label: "性别",
prop: "sex",
minWidth: 90,
cellRenderer: ({ row, props }) => (
<el-tag
size={props.size}
@@ -47,16 +65,18 @@ export function useColumns() {
{
label: "部门",
prop: "dept",
minWidth: 90,
formatter: ({ dept }) => dept.name
},
{
label: "手机号码",
prop: "mobile"
prop: "mobile",
minWidth: 90
},
{
label: "状态",
prop: "status",
width: 130,
minWidth: 90,
cellRenderer: scope => (
<el-switch
size={scope.props.size === "small" ? "small" : "default"}
@@ -73,7 +93,7 @@ export function useColumns() {
},
{
label: "创建时间",
width: 180,
minWidth: 90,
prop: "createTime",
formatter: ({ createTime }) =>
dayjs(createTime).format("YYYY-MM-DD HH:mm:ss")
@@ -85,6 +105,15 @@ export function useColumns() {
slot: "operation"
}
];
const buttonClass = computed(() => {
return [
"!h-[20px]",
"reset-margin",
"!text-gray-500",
"dark:!text-white",
"dark:hover:!text-primary"
];
});
function onChange({ row, index }) {
ElMessageBox.confirm(
@@ -128,7 +157,59 @@ export function useColumns() {
});
}
function handleUpdate(row) {
console.log(row);
}
function handleDelete(row) {
console.log(row);
}
function handleSizeChange(val: number) {
console.log(`${val} items per page`);
}
function handleCurrentChange(val: number) {
console.log(`current page: ${val}`);
}
function handleSelectionChange(val) {
console.log("handleSelectionChange", val);
}
async function onSearch() {
loading.value = true;
const { data } = await getUserList();
dataList.value = data.list;
pagination.total = data.total;
setTimeout(() => {
loading.value = false;
}, 500);
}
const resetForm = formEl => {
if (!formEl) return;
formEl.resetFields();
onSearch();
};
onMounted(() => {
onSearch();
});
return {
columns
form,
loading,
columns,
dataList,
pagination,
buttonClass,
onSearch,
resetForm,
handleUpdate,
handleDelete,
handleSizeChange,
handleCurrentChange,
handleSelectionChange
};
}

View File

@@ -1,11 +1,8 @@
<script setup lang="ts">
import { ref } from "vue";
import tree from "./tree.vue";
import { useColumns } from "./columns";
import { getUserList } from "@/api/system";
import { reactive, ref, onMounted } from "vue";
import { type FormInstance } from "element-plus";
import { TableProBar } from "@/components/ReTable";
import { type PaginationProps } from "@pureadmin/table";
import { useUser } from "./hook";
import { PureTableBar } from "@/components/RePureTableBar";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import Role from "@iconify-icons/ri/admin-line";
@@ -21,69 +18,28 @@ defineOptions({
name: "User"
});
const form = reactive({
username: "",
mobile: "",
status: ""
});
const dataList = ref([]);
const loading = ref(true);
const { columns } = useColumns();
const formRef = ref<FormInstance>();
const pagination = reactive<PaginationProps>({
total: 0,
pageSize: 10,
currentPage: 1,
background: true
});
function handleUpdate(row) {
console.log(row);
}
function handleDelete(row) {
console.log(row);
}
function handleCurrentChange(val: number) {
console.log(`current page: ${val}`);
}
function handleSizeChange(val: number) {
console.log(`${val} items per page`);
}
function handleSelectionChange(val) {
console.log("handleSelectionChange", val);
}
async function onSearch() {
loading.value = true;
const { data } = await getUserList();
dataList.value = data.list;
pagination.total = data.total;
setTimeout(() => {
loading.value = false;
}, 500);
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.resetFields();
onSearch();
};
onMounted(() => {
onSearch();
});
const formRef = ref();
const {
form,
loading,
columns,
dataList,
pagination,
buttonClass,
onSearch,
resetForm,
handleUpdate,
handleDelete,
handleSizeChange,
handleCurrentChange,
handleSelectionChange
} = useUser();
</script>
<template>
<div class="main flex">
<tree />
<div class="flex-1 ml-4">
<div class="main">
<tree class="w-[17%] float-left" />
<div class="float-right w-[81%]">
<el-form
ref="formRef"
:inline="true"
@@ -95,6 +51,7 @@ onMounted(() => {
v-model="form.username"
placeholder="请输入用户名称"
clearable
class="!w-[160px]"
/>
</el-form-item>
<el-form-item label="手机号码:" prop="mobile">
@@ -102,10 +59,16 @@ onMounted(() => {
v-model="form.mobile"
placeholder="请输入手机号码"
clearable
class="!w-[160px]"
/>
</el-form-item>
<el-form-item label="状态:" prop="status">
<el-select v-model="form.status" placeholder="请选择" clearable>
<el-select
v-model="form.status"
placeholder="请选择"
clearable
class="!w-[160px]"
>
<el-option label="已开启" value="1" />
<el-option label="已关闭" value="0" />
</el-select>
@@ -125,12 +88,7 @@ onMounted(() => {
</el-form-item>
</el-form>
<TableProBar
title="用户管理"
:loading="loading"
:dataList="dataList"
@refresh="onSearch"
>
<PureTableBar title="用户管理" @refresh="onSearch">
<template #buttons>
<el-button type="primary" :icon="useRenderIcon(AddFill)">
新增用户
@@ -141,6 +99,7 @@ onMounted(() => {
border
align-whole="center"
table-layout="auto"
:loading="loading"
:size="size"
:data="dataList"
:columns="columns"
@@ -182,7 +141,7 @@ onMounted(() => {
</el-popconfirm>
<el-dropdown>
<el-button
class="ml-3"
class="ml-3 mt-[2px]"
link
type="primary"
:size="size"
@@ -193,7 +152,7 @@ onMounted(() => {
<el-dropdown-menu>
<el-dropdown-item>
<el-button
class="reset-margin !h-[20px] !text-gray-500 dark:!text-white dark:hover:!text-primary"
:class="buttonClass"
link
type="primary"
:size="size"
@@ -204,7 +163,7 @@ onMounted(() => {
</el-dropdown-item>
<el-dropdown-item>
<el-button
class="reset-margin !h-[20px] !text-gray-500 dark:!text-white dark:hover:!text-primary"
:class="buttonClass"
link
type="primary"
:size="size"
@@ -219,7 +178,7 @@ onMounted(() => {
</template>
</pure-table>
</template>
</TableProBar>
</PureTableBar>
</div>
</div>
</template>

View File

@@ -0,0 +1 @@
<svg width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M22 4V2H2v2h9v14.17l-5.5-5.5-1.42 1.41L12 22l7.92-7.92-1.42-1.41-5.5 5.5V4h9Z"/></svg>

After

Width:  |  Height:  |  Size: 163 B

View File

@@ -0,0 +1 @@
<svg width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M4 2H2v20h2v-9h14.17l-5.5 5.5l1.41 1.42L22 12l-7.92-7.92l-1.41 1.42l5.5 5.5H4V2Z"/></svg>

After

Width:  |  Height:  |  Size: 166 B

View File

@@ -1,18 +1,17 @@
<script setup lang="ts">
import { handleTree } from "@/utils/tree";
import type { ElTree } from "element-plus";
import { getDeptList } from "@/api/system";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import { ref, watch, onMounted, getCurrentInstance } from "vue";
import { ref, computed, watch, onMounted, getCurrentInstance } from "vue";
import LocationCompany from "@iconify-icons/ep/add-location";
import UnExpand from "@iconify-icons/mdi/arrow-expand-right";
import Expand from "@iconify-icons/mdi/arrow-expand-down";
import More2Fill from "@iconify-icons/ri/more-2-fill";
import Reset from "@iconify-icons/ri/restart-line";
import Dept from "@iconify-icons/ri/git-branch-line";
import OfficeBuilding from "@iconify-icons/ep/office-building";
import Reset from "@iconify-icons/ri/restart-line";
import Search from "@iconify-icons/ep/search";
import More2Fill from "@iconify-icons/ri/more-2-fill";
import OfficeBuilding from "@iconify-icons/ep/office-building";
import LocationCompany from "@iconify-icons/ep/add-location";
import ExpandIcon from "./svg/expand.svg?component";
import UnExpandIcon from "./svg/unexpand.svg?component";
interface Tree {
id: number;
@@ -20,17 +19,26 @@ interface Tree {
highlight?: boolean;
children?: Tree[];
}
const treeRef = ref();
const treeData = ref([]);
const isExpand = ref(true);
const searchValue = ref("");
const highlightMap = ref({});
const { proxy } = getCurrentInstance();
const defaultProps = {
children: "children",
label: "name"
};
const treeData = ref([]);
const searchValue = ref("");
const { proxy } = getCurrentInstance();
const treeRef = ref<InstanceType<typeof ElTree>>();
const highlightMap = ref({});
const buttonClass = computed(() => {
return [
"!h-[20px]",
"reset-margin",
"!text-gray-500",
"dark:!text-white",
"dark:hover:!text-primary"
];
});
const filterNode = (value: string, data: Tree) => {
if (!value) return true;
@@ -54,13 +62,14 @@ function nodeClick(value) {
}
function toggleRowExpansionAll(status) {
isExpand.value = status;
const nodes = (proxy.$refs["treeRef"] as any).store._getAllNodes();
for (let i = 0; i < nodes.length; i++) {
nodes[i].expanded = status;
}
}
// 重置状态(选中状态、搜索框值、树初始化)
/** 重置状态(选中状态、搜索框值、树初始化) */
function onReset() {
highlightMap.value = {};
searchValue.value = "";
@@ -73,12 +82,12 @@ watch(searchValue, val => {
onMounted(async () => {
const { data } = await getDeptList();
treeData.value = handleTree(data as any);
treeData.value = handleTree(data);
});
</script>
<template>
<div class="max-w-[260px] h-full min-h-[780px] bg-bg_color">
<div class="h-full min-h-[780px] bg-bg_color overflow-auto">
<div class="flex items-center h-[34px]">
<p class="flex-1 ml-2 font-bold text-base truncate" title="部门列表">
部门列表
@@ -99,7 +108,7 @@ onMounted(async () => {
</el-icon>
</template>
</el-input>
<el-dropdown>
<el-dropdown :hide-on-click="false">
<IconifyIconOffline
class="w-[28px] cursor-pointer"
width="18px"
@@ -109,29 +118,18 @@ onMounted(async () => {
<el-dropdown-menu>
<el-dropdown-item>
<el-button
class="reset-margin !h-[20px] !text-gray-500 dark:!text-white dark:hover:!text-primary"
:class="buttonClass"
link
type="primary"
:icon="useRenderIcon(Expand)"
@click="toggleRowExpansionAll(true)"
:icon="useRenderIcon(isExpand ? ExpandIcon : UnExpandIcon)"
@click="toggleRowExpansionAll(isExpand ? false : true)"
>
展开全部
{{ isExpand ? "折叠全部" : "展开全部" }}
</el-button>
</el-dropdown-item>
<el-dropdown-item>
<el-button
class="reset-margin !h-[20px] !text-gray-500 dark:!text-white dark:hover:!text-primary"
link
type="primary"
:icon="useRenderIcon(UnExpand)"
@click="toggleRowExpansionAll(false)"
>
折叠全部
</el-button>
</el-dropdown-item>
<el-dropdown-item>
<el-button
class="reset-margin !h-[20px] !text-gray-500 dark:!text-white dark:hover:!text-primary"
:class="buttonClass"
link
type="primary"
:icon="useRenderIcon(Reset)"

View File

@@ -1,4 +1,3 @@
import { IconifyIconOffline } from "@/components/ReIcon";
import TypeIt from "@/components/ReTypeit";
import OfficeBuilding from "@iconify-icons/ep/office-building";
import Tickets from "@iconify-icons/ep/tickets";
@@ -21,7 +20,7 @@ export function useColumns() {
labelRenderer: () => (
<div class="flex items-center">
<el-icon>
<IconifyIconOffline icon={User} />
<iconify-icon-offline icon={User} />
</el-icon>
</div>
@@ -32,7 +31,7 @@ export function useColumns() {
labelRenderer: () => (
<div class="flex items-center">
<el-icon>
<IconifyIconOffline icon={Iphone} />
<iconify-icon-offline icon={Iphone} />
</el-icon>
</div>
@@ -43,7 +42,7 @@ export function useColumns() {
labelRenderer: () => (
<div class="flex items-center">
<el-icon>
<IconifyIconOffline icon={Location} />
<iconify-icon-offline icon={Location} />
</el-icon>
</div>
@@ -57,7 +56,7 @@ export function useColumns() {
labelRenderer: () => (
<div class="flex items-center">
<el-icon>
<IconifyIconOffline icon={Tickets} />
<iconify-icon-offline icon={Tickets} />
</el-icon>
</div>
@@ -76,7 +75,7 @@ export function useColumns() {
labelRenderer: () => (
<div class="flex items-center">
<el-icon>
<IconifyIconOffline icon={OfficeBuilding} />
<iconify-icon-offline icon={OfficeBuilding} />
</el-icon>
</div>
@@ -90,7 +89,7 @@ export function useColumns() {
labelRenderer: () => (
<div class="flex items-center">
<el-icon>
<IconifyIconOffline icon={Notebook} />
<iconify-icon-offline icon={Notebook} />
</el-icon>
</div>

View File

@@ -9,7 +9,5 @@ declare module "*.scss" {
export default scss;
}
declare module "@pureadmin/theme";
declare module "vue-virtual-scroller";
declare module "vuedraggable/src/vuedraggable";
declare module "@pureadmin/theme/dist/browser-utils";