提交 e034d1ba 编写于 作者: V vben

perf: remove optional chain

上级 144fde8a
## Wip ## Wip
### ✨ Features
- 面包屑支持显示图标
- 新增 tinymce 富文本组件
### 🎫 Chores
- 删除代码内的可选链语法
### 🐛 Bug Fixes ### 🐛 Bug Fixes
- 修复抽屉组件自动高度及显示 footer 显示问题 - 修复抽屉组件自动高度及显示 footer 显示问题
- 修复表单查询后重置回默认值 - 修复表单查询后重置回默认值
- 修复菜单没有子节点时显示折叠的问题
- 修复面包屑显示样式问题
- 修复 modal 在 destroyOnClose=true 时多次打开拖拽失效
# 2.0.0-rc.4 (2020-10-21) # 2.0.0-rc.4 (2020-10-21)
......
import Authority from './src/index.vue';
export default Authority;
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 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>
export { default as BasicArrow } from './src/BasicArrow.vue'; 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'; export { default as BasicTitle } from './src/BasicTitle.vue';
@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;
}
}
}
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>
);
},
});
<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>
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({ ...@@ -84,10 +84,11 @@ export default defineComponent({
const { dropDownActions = [], actions } = props; const { dropDownActions = [], actions } = props;
return ( return (
<div class={prefixCls}> <div class={prefixCls}>
{actions?.map((action, index) => { {actions &&
return renderPopConfirm(action, index); actions.map((action, index) => {
})} return renderPopConfirm(action, index);
{dropDownActions?.length && ( })}
{dropDownActions && dropDownActions.length && (
<Dropdown> <Dropdown>
{{ {{
default: dropdownDefaultSLot, default: dropdownDefaultSLot,
......
...@@ -45,8 +45,8 @@ const EditableCell = defineComponent({ ...@@ -45,8 +45,8 @@ const EditableCell = defineComponent({
const isEditRef = ref(false); const isEditRef = ref(false);
const currentValueRef = ref<string | boolean>(props.value); const currentValueRef = ref<string | boolean>(props.value);
function handleChange(e: ChangeEvent | string | boolean) { function handleChange(e: any) {
if (Reflect.has((e as ChangeEvent)?.target, 'value')) { if (e && e.target && Reflect.has(e.target, 'value')) {
currentValueRef.value = (e as ChangeEvent).target.value; currentValueRef.value = (e as ChangeEvent).target.value;
} }
if (isString(e) || isBoolean(e)) { if (isString(e) || isBoolean(e)) {
...@@ -58,7 +58,7 @@ const EditableCell = defineComponent({ ...@@ -58,7 +58,7 @@ const EditableCell = defineComponent({
isEditRef.value = true; isEditRef.value = true;
nextTick(() => { nextTick(() => {
const el = unref(elRef); const el = unref(elRef);
el?.focus(); el && el.focus();
}); });
} }
...@@ -84,7 +84,7 @@ const EditableCell = defineComponent({ ...@@ -84,7 +84,7 @@ const EditableCell = defineComponent({
function onClickOutside() { function onClickOutside() {
const { component } = props; const { component } = props;
if (component?.includes('Input')) { if (component && component.includes('Input')) {
handleCancel(); handleCancel();
} }
} }
......
...@@ -89,7 +89,7 @@ export function useDataSource( ...@@ -89,7 +89,7 @@ export function useDataSource(
pageParams = {}; pageParams = {};
} else { } else {
const { current, pageSize } = unref(getPaginationRef) as PaginationProps; const { current, pageSize } = unref(getPaginationRef) as PaginationProps;
pageParams[pageField] = opt?.page || current; pageParams[pageField] = (opt && opt.page) || current;
pageParams[sizeField] = pageSize; pageParams[sizeField] = pageSize;
} }
......
...@@ -53,13 +53,12 @@ ...@@ -53,13 +53,12 @@
}); });
const initOptions = computed(() => { const initOptions = computed(() => {
const { height, menubar } = props; const { height, options } = props;
return { return {
selector: `#${unref(tinymceId)}`, selector: `#${unref(tinymceId)}`,
height: height, height: height,
toolbar: toolbar, toolbar: toolbar,
theme: 'silver', menubar: 'file edit insert view format table',
menubar: menubar,
plugins: plugins, plugins: plugins,
// 语言包 // 语言包
language_url: 'resource/tinymce/langs/zh_CN.js', language_url: 'resource/tinymce/langs/zh_CN.js',
...@@ -70,6 +69,7 @@ ...@@ -70,6 +69,7 @@
advlist_bullet_styles: 'square', advlist_bullet_styles: 'square',
advlist_number_styles: 'default', advlist_number_styles: 'default',
object_resizing: false, object_resizing: false,
...options,
setup: (editor: any) => { setup: (editor: any) => {
editorRef.value = editor; editorRef.value = editor;
editor.on('init', (e: Event) => initSetup(e)); editor.on('init', (e: Event) => initSetup(e));
......
import { PropType } from 'vue'; import { PropType } from 'vue';
export const basicProps = { export const basicProps = {
menubar: { options: {
type: String as PropType<string>, type: Object as PropType<any>,
default: 'file edit insert view format table', default: {},
}, },
value: { value: {
type: String as PropType<string>, type: String as PropType<string>,
......
<template> <template>
<div class="flex p-4"> <div class="p-4">
{{ value }}
<Tinymce v-model="value" @change="handleChange" width="100%" /> <Tinymce v-model="value" @change="handleChange" width="100%" />
</div> </div>
</template> </template>
...@@ -15,9 +14,6 @@ ...@@ -15,9 +14,6 @@
function handleChange(value: string) { function handleChange(value: string) {
console.log(value); console.log(value);
} }
// setTimeout(() => {
// value.value = '1233';
// }, 5000);
return { handleChange, value }; return { handleChange, value };
}, },
}); });
......
...@@ -8,7 +8,6 @@ import { ...@@ -8,7 +8,6 @@ import {
// externals, // externals,
cdnConf, cdnConf,
} from './build/config/vite/cdn'; } from './build/config/vite/cdn';
import { createProxy } from './build/config/vite/proxy'; import { createProxy } from './build/config/vite/proxy';
import { createMockServer } from 'vite-plugin-mock'; import { createMockServer } from 'vite-plugin-mock';
import PurgeIcons from 'vite-plugin-purge-icons'; import PurgeIcons from 'vite-plugin-purge-icons';
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册