提交 e034d1ba 编写于 作者: V vben

perf: remove optional chain

上级 144fde8a
## Wip
### ✨ Features
- 面包屑支持显示图标
- 新增 tinymce 富文本组件
### 🎫 Chores
- 删除代码内的可选链语法
### 🐛 Bug Fixes
- 修复抽屉组件自动高度及显示 footer 显示问题
- 修复表单查询后重置回默认值
- 修复菜单没有子节点时显示折叠的问题
- 修复面包屑显示样式问题
- 修复 modal 在 destroyOnClose=true 时多次打开拖拽失效
# 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 BasicHelp } from './src/BasicHelp';
export { default as BasicHelp } from './src/BasicHelp.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({
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));
......
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>,
......
<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';
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册