mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-02-03 02:54:40 +08:00
perf: remove optional chain
This commit is contained in:
parent
144fde8a68
commit
e034d1bacc
@ -1,9 +1,21 @@
|
||||
## Wip
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- 面包屑支持显示图标
|
||||
- 新增 tinymce 富文本组件
|
||||
|
||||
### 🎫 Chores
|
||||
|
||||
- 删除代码内的可选链语法
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- 修复抽屉组件自动高度及显示 footer 显示问题
|
||||
- 修复表单查询后重置回默认值
|
||||
- 修复菜单没有子节点时显示折叠的问题
|
||||
- 修复面包屑显示样式问题
|
||||
- 修复 modal 在 destroyOnClose=true 时多次打开拖拽失效
|
||||
|
||||
# 2.0.0-rc.4 (2020-10-21)
|
||||
|
||||
|
2
src/components/Authority/index.ts
Normal file
2
src/components/Authority/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
import Authority from './src/index.vue';
|
||||
export default Authority;
|
@ -1,61 +0,0 @@
|
||||
import { defineComponent, PropType, computed, unref } from 'vue';
|
||||
|
||||
import { PermissionModeEnum } from '/@/enums/appEnum';
|
||||
import { RoleEnum } from '/@/enums/roleEnum';
|
||||
import { usePermission } from '/@/hooks/web/usePermission';
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { getSlot } from '/@/utils/helper/tsxHelper';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Authority',
|
||||
props: {
|
||||
// 指定角色可见
|
||||
value: {
|
||||
type: [Number, Array, String] as PropType<RoleEnum | RoleEnum[]>,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
setup(props, { slots }) {
|
||||
const getModeRef = computed(() => {
|
||||
return appStore.getProjectConfig.permissionMode;
|
||||
});
|
||||
|
||||
/**
|
||||
* 渲染角色按钮
|
||||
*/
|
||||
function renderRoleAuth() {
|
||||
const { value } = props;
|
||||
if (!value) {
|
||||
return getSlot(slots);
|
||||
}
|
||||
const { hasPermission } = usePermission();
|
||||
return hasPermission(value) ? getSlot(slots) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染编码按钮
|
||||
* 这里只判断是否包含,具体实现可以根据项目自行写逻辑
|
||||
*/
|
||||
function renderCodeAuth() {
|
||||
const { value } = props;
|
||||
if (!value) {
|
||||
return getSlot(slots);
|
||||
}
|
||||
const { hasPermission } = usePermission();
|
||||
return hasPermission(value) ? getSlot(slots) : null;
|
||||
}
|
||||
|
||||
return () => {
|
||||
const mode = unref(getModeRef);
|
||||
// 基于角色渲染
|
||||
if (mode === PermissionModeEnum.ROLE) {
|
||||
return renderRoleAuth();
|
||||
}
|
||||
// 基于后台编码渲染
|
||||
if (mode === PermissionModeEnum.BACK) {
|
||||
return renderCodeAuth();
|
||||
}
|
||||
return getSlot(slots);
|
||||
};
|
||||
},
|
||||
});
|
65
src/components/Authority/src/index.vue
Normal file
65
src/components/Authority/src/index.vue
Normal file
@ -0,0 +1,65 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, computed, unref } from 'vue';
|
||||
|
||||
import { PermissionModeEnum } from '/@/enums/appEnum';
|
||||
import { RoleEnum } from '/@/enums/roleEnum';
|
||||
import { usePermission } from '/@/hooks/web/usePermission';
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { getSlot } from '/@/utils/helper/tsxHelper';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Authority',
|
||||
props: {
|
||||
// 指定角色可见
|
||||
value: {
|
||||
type: [Number, Array, String] as PropType<RoleEnum | RoleEnum[]>,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
setup(props, { slots }) {
|
||||
const getModeRef = computed(() => {
|
||||
return appStore.getProjectConfig.permissionMode;
|
||||
});
|
||||
|
||||
/**
|
||||
* 渲染角色按钮
|
||||
*/
|
||||
function renderRoleAuth() {
|
||||
const { value } = props;
|
||||
if (!value) {
|
||||
return getSlot(slots);
|
||||
}
|
||||
const { hasPermission } = usePermission();
|
||||
return hasPermission(value) ? getSlot(slots) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染编码按钮
|
||||
* 这里只判断是否包含,具体实现可以根据项目自行写逻辑
|
||||
*/
|
||||
function renderCodeAuth() {
|
||||
const { value } = props;
|
||||
if (!value) {
|
||||
return getSlot(slots);
|
||||
}
|
||||
const { hasPermission } = usePermission();
|
||||
return hasPermission(value) ? getSlot(slots) : null;
|
||||
}
|
||||
|
||||
return () => {
|
||||
const mode = unref(getModeRef);
|
||||
// 基于角色渲染
|
||||
if (mode === PermissionModeEnum.ROLE) {
|
||||
return renderRoleAuth();
|
||||
}
|
||||
|
||||
// 基于后台编码渲染
|
||||
if (mode === PermissionModeEnum.BACK) {
|
||||
return renderCodeAuth();
|
||||
}
|
||||
|
||||
return getSlot(slots);
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
@ -1,3 +1,3 @@
|
||||
export { default as BasicArrow } from './src/BasicArrow.vue';
|
||||
export { default as BasicHelp } from './src/BasicHelp';
|
||||
export { default as BasicHelp } from './src/BasicHelp.vue';
|
||||
export { default as BasicTitle } from './src/BasicTitle.vue';
|
||||
|
@ -1,19 +0,0 @@
|
||||
@import (reference) '../../../design/index.less';
|
||||
|
||||
.base-help {
|
||||
display: inline-block;
|
||||
margin-left: 6px;
|
||||
font-size: 14px;
|
||||
color: @text-color-help-dark;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: @primary-color;
|
||||
}
|
||||
|
||||
&__wrap {
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
import type { PropType } from 'vue';
|
||||
|
||||
import { Tooltip } from 'ant-design-vue';
|
||||
import { InfoCircleOutlined } from '@ant-design/icons-vue';
|
||||
import { defineComponent, computed, unref } from 'vue';
|
||||
|
||||
import { getPopupContainer } from '/@/utils';
|
||||
|
||||
import { isString, isArray } from '/@/utils/is';
|
||||
import { getSlot } from '/@/utils/helper/tsxHelper';
|
||||
import './BasicHelp.less';
|
||||
export default defineComponent({
|
||||
name: 'BaseHelp',
|
||||
props: {
|
||||
// max-width
|
||||
maxWidth: {
|
||||
type: String as PropType<string>,
|
||||
default: '600px',
|
||||
},
|
||||
// Whether to display the serial number
|
||||
showIndex: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false,
|
||||
},
|
||||
// Text list
|
||||
text: {
|
||||
type: [Array, String] as PropType<string[] | string>,
|
||||
},
|
||||
// color
|
||||
color: {
|
||||
type: String as PropType<string>,
|
||||
default: '#ffffff',
|
||||
},
|
||||
fontSize: {
|
||||
type: String as PropType<string>,
|
||||
default: '14px',
|
||||
},
|
||||
absolute: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false,
|
||||
},
|
||||
// 定位
|
||||
position: {
|
||||
type: [Object] as PropType<any>,
|
||||
default: () => ({
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
}),
|
||||
},
|
||||
},
|
||||
setup(props, { slots }) {
|
||||
const getOverlayStyleRef = computed(() => {
|
||||
return {
|
||||
maxWidth: props.maxWidth,
|
||||
};
|
||||
});
|
||||
const getWrapStyleRef = computed(() => {
|
||||
return {
|
||||
color: props.color,
|
||||
fontSize: props.fontSize,
|
||||
};
|
||||
});
|
||||
const getMainStyleRef = computed(() => {
|
||||
return props.absolute ? props.position : {};
|
||||
});
|
||||
|
||||
/**
|
||||
* @description: 渲染内容
|
||||
*/
|
||||
const renderTitle = () => {
|
||||
const list = props.text;
|
||||
if (isString(list)) {
|
||||
return <p>{list}</p>;
|
||||
}
|
||||
if (isArray(list)) {
|
||||
return list.map((item, index) => {
|
||||
return (
|
||||
<p key={item}>
|
||||
{props.showIndex ? `${index + 1}. ` : ''}
|
||||
{item}
|
||||
</p>
|
||||
);
|
||||
});
|
||||
}
|
||||
return null;
|
||||
};
|
||||
return () => (
|
||||
<Tooltip
|
||||
title={(<div style={unref(getWrapStyleRef)}>{renderTitle()}</div>) as any}
|
||||
placement="right"
|
||||
overlayStyle={unref(getOverlayStyleRef)}
|
||||
autoAdjustOverflow={true}
|
||||
overlayClassName="base-help__wrap"
|
||||
getPopupContainer={() => getPopupContainer()}
|
||||
>
|
||||
{{
|
||||
default: () => (
|
||||
<span class="base-help" style={unref(getMainStyleRef)}>
|
||||
{getSlot(slots) || <InfoCircleOutlined />}
|
||||
</span>
|
||||
),
|
||||
}}
|
||||
</Tooltip>
|
||||
);
|
||||
},
|
||||
});
|
137
src/components/Basic/src/BasicHelp.vue
Normal file
137
src/components/Basic/src/BasicHelp.vue
Normal file
@ -0,0 +1,137 @@
|
||||
<script lang="ts">
|
||||
import type { PropType } from 'vue';
|
||||
|
||||
import { Tooltip } from 'ant-design-vue';
|
||||
import { InfoCircleOutlined } from '@ant-design/icons-vue';
|
||||
import { defineComponent, computed, unref, h } from 'vue';
|
||||
|
||||
import { getPopupContainer } from '/@/utils';
|
||||
|
||||
import { isString, isArray } from '/@/utils/is';
|
||||
import { getSlot } from '/@/utils/helper/tsxHelper';
|
||||
export default defineComponent({
|
||||
name: 'BaseHelp',
|
||||
components: { Tooltip },
|
||||
props: {
|
||||
// max-width
|
||||
maxWidth: {
|
||||
type: String as PropType<string>,
|
||||
default: '600px',
|
||||
},
|
||||
// Whether to display the serial number
|
||||
showIndex: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false,
|
||||
},
|
||||
// Text list
|
||||
text: {
|
||||
type: [Array, String] as PropType<string[] | string>,
|
||||
},
|
||||
// color
|
||||
color: {
|
||||
type: String as PropType<string>,
|
||||
default: '#ffffff',
|
||||
},
|
||||
fontSize: {
|
||||
type: String as PropType<string>,
|
||||
default: '14px',
|
||||
},
|
||||
absolute: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false,
|
||||
},
|
||||
// 定位
|
||||
position: {
|
||||
type: [Object] as PropType<any>,
|
||||
default: () => ({
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
}),
|
||||
},
|
||||
},
|
||||
setup(props, { slots }) {
|
||||
const getOverlayStyleRef = computed(() => {
|
||||
return {
|
||||
maxWidth: props.maxWidth,
|
||||
};
|
||||
});
|
||||
const getWrapStyleRef = computed(() => {
|
||||
return {
|
||||
color: props.color,
|
||||
fontSize: props.fontSize,
|
||||
};
|
||||
});
|
||||
const getMainStyleRef = computed(() => {
|
||||
return props.absolute ? props.position : {};
|
||||
});
|
||||
|
||||
/**
|
||||
* @description: 渲染内容
|
||||
*/
|
||||
const renderTitle = () => {
|
||||
const list = props.text;
|
||||
if (isString(list)) {
|
||||
return h('p', list);
|
||||
}
|
||||
if (isArray(list)) {
|
||||
return list.map((item, index) => {
|
||||
return h('p', { key: item }, [props.showIndex ? `${index + 1}. ` : '', item]);
|
||||
});
|
||||
}
|
||||
return null;
|
||||
};
|
||||
return () => {
|
||||
return h(
|
||||
Tooltip,
|
||||
{
|
||||
title: h(
|
||||
'div',
|
||||
{
|
||||
style: unref(getWrapStyleRef),
|
||||
},
|
||||
[renderTitle()]
|
||||
) as any,
|
||||
overlayClassName: 'base-help__wrap',
|
||||
autoAdjustOverflow: true,
|
||||
overlayStyle: unref(getOverlayStyleRef),
|
||||
placement: 'right',
|
||||
getPopupContainer: () => getPopupContainer(),
|
||||
},
|
||||
{
|
||||
default: () =>
|
||||
h(
|
||||
'span',
|
||||
{
|
||||
class: 'base-help',
|
||||
style: unref(getMainStyleRef),
|
||||
},
|
||||
getSlot(slots) || h(InfoCircleOutlined)
|
||||
),
|
||||
}
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less">
|
||||
@import (reference) '../../../design/index.less';
|
||||
|
||||
.base-help {
|
||||
display: inline-block;
|
||||
margin-left: 6px;
|
||||
font-size: 14px;
|
||||
color: @text-color-help-dark;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: @primary-color;
|
||||
}
|
||||
|
||||
&__wrap {
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,66 +0,0 @@
|
||||
import { VNodeChild } from 'vue';
|
||||
|
||||
export interface BasicButtonProps {
|
||||
/**
|
||||
* can be set to primary ghost dashed danger(added in 2.7) or omitted (meaning default)
|
||||
* @default 'default'
|
||||
* @type string
|
||||
*/
|
||||
type?: 'primary' | 'danger' | 'dashed' | 'ghost' | 'default';
|
||||
|
||||
/**
|
||||
* set the original html type of button
|
||||
* @default 'button'
|
||||
* @type string
|
||||
*/
|
||||
htmlType?: 'button' | 'submit' | 'reset' | 'menu';
|
||||
|
||||
/**
|
||||
* set the icon of button
|
||||
* @type string
|
||||
*/
|
||||
icon?: VNodeChild | JSX.Element;
|
||||
|
||||
/**
|
||||
* can be set to circle or circle-outline or omitted
|
||||
* @type string
|
||||
*/
|
||||
shape?: 'circle' | 'circle-outline';
|
||||
|
||||
/**
|
||||
* can be set to small large or omitted
|
||||
* @default 'default'
|
||||
* @type string
|
||||
*/
|
||||
size?: 'small' | 'large' | 'default';
|
||||
|
||||
/**
|
||||
* set the loading status of button
|
||||
* @default false
|
||||
* @type boolean | { delay: number }
|
||||
*/
|
||||
loading?: boolean | { delay: number };
|
||||
|
||||
/**
|
||||
* disabled state of button
|
||||
* @default false
|
||||
* @type boolean
|
||||
*/
|
||||
disabled?: boolean;
|
||||
|
||||
/**
|
||||
* make background transparent and invert text and border colors, added in 2.7
|
||||
* @default false
|
||||
* @type boolean
|
||||
*/
|
||||
ghost?: boolean;
|
||||
|
||||
/**
|
||||
* option to fit button width to its parent width
|
||||
* @default false
|
||||
* @type boolean
|
||||
*/
|
||||
block?: boolean;
|
||||
|
||||
onClick?: (e?: Event) => void;
|
||||
}
|
@ -84,10 +84,11 @@ export default defineComponent({
|
||||
const { dropDownActions = [], actions } = props;
|
||||
return (
|
||||
<div class={prefixCls}>
|
||||
{actions?.map((action, index) => {
|
||||
return renderPopConfirm(action, index);
|
||||
})}
|
||||
{dropDownActions?.length && (
|
||||
{actions &&
|
||||
actions.map((action, index) => {
|
||||
return renderPopConfirm(action, index);
|
||||
})}
|
||||
{dropDownActions && dropDownActions.length && (
|
||||
<Dropdown>
|
||||
{{
|
||||
default: dropdownDefaultSLot,
|
||||
|
@ -45,8 +45,8 @@ const EditableCell = defineComponent({
|
||||
const isEditRef = ref(false);
|
||||
const currentValueRef = ref<string | boolean>(props.value);
|
||||
|
||||
function handleChange(e: ChangeEvent | string | boolean) {
|
||||
if (Reflect.has((e as ChangeEvent)?.target, 'value')) {
|
||||
function handleChange(e: any) {
|
||||
if (e && e.target && Reflect.has(e.target, 'value')) {
|
||||
currentValueRef.value = (e as ChangeEvent).target.value;
|
||||
}
|
||||
if (isString(e) || isBoolean(e)) {
|
||||
@ -58,7 +58,7 @@ const EditableCell = defineComponent({
|
||||
isEditRef.value = true;
|
||||
nextTick(() => {
|
||||
const el = unref(elRef);
|
||||
el?.focus();
|
||||
el && el.focus();
|
||||
});
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ const EditableCell = defineComponent({
|
||||
function onClickOutside() {
|
||||
const { component } = props;
|
||||
|
||||
if (component?.includes('Input')) {
|
||||
if (component && component.includes('Input')) {
|
||||
handleCancel();
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ export function useDataSource(
|
||||
pageParams = {};
|
||||
} else {
|
||||
const { current, pageSize } = unref(getPaginationRef) as PaginationProps;
|
||||
pageParams[pageField] = opt?.page || current;
|
||||
pageParams[pageField] = (opt && opt.page) || current;
|
||||
pageParams[sizeField] = pageSize;
|
||||
}
|
||||
|
||||
|
@ -53,13 +53,12 @@
|
||||
});
|
||||
|
||||
const initOptions = computed(() => {
|
||||
const { height, menubar } = props;
|
||||
const { height, options } = props;
|
||||
return {
|
||||
selector: `#${unref(tinymceId)}`,
|
||||
height: height,
|
||||
toolbar: toolbar,
|
||||
theme: 'silver',
|
||||
menubar: menubar,
|
||||
menubar: 'file edit insert view format table',
|
||||
plugins: plugins,
|
||||
// 语言包
|
||||
language_url: 'resource/tinymce/langs/zh_CN.js',
|
||||
@ -70,6 +69,7 @@
|
||||
advlist_bullet_styles: 'square',
|
||||
advlist_number_styles: 'default',
|
||||
object_resizing: false,
|
||||
...options,
|
||||
setup: (editor: any) => {
|
||||
editorRef.value = editor;
|
||||
editor.on('init', (e: Event) => initSetup(e));
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { PropType } from 'vue';
|
||||
|
||||
export const basicProps = {
|
||||
menubar: {
|
||||
type: String as PropType<string>,
|
||||
default: 'file edit insert view format table',
|
||||
options: {
|
||||
type: Object as PropType<any>,
|
||||
default: {},
|
||||
},
|
||||
value: {
|
||||
type: String as PropType<string>,
|
||||
|
@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<div class="flex p-4">
|
||||
{{ value }}
|
||||
<div class="p-4">
|
||||
<Tinymce v-model="value" @change="handleChange" width="100%" />
|
||||
</div>
|
||||
</template>
|
||||
@ -15,9 +14,6 @@
|
||||
function handleChange(value: string) {
|
||||
console.log(value);
|
||||
}
|
||||
// setTimeout(() => {
|
||||
// value.value = '1233';
|
||||
// }, 5000);
|
||||
return { handleChange, value };
|
||||
},
|
||||
});
|
||||
|
@ -8,7 +8,6 @@ import {
|
||||
// externals,
|
||||
cdnConf,
|
||||
} from './build/config/vite/cdn';
|
||||
|
||||
import { createProxy } from './build/config/vite/proxy';
|
||||
import { createMockServer } from 'vite-plugin-mock';
|
||||
import PurgeIcons from 'vite-plugin-purge-icons';
|
||||
|
Loading…
Reference in New Issue
Block a user