16 changed files with 234 additions and 275 deletions
@ -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); |
|||
}; |
|||
}, |
|||
}); |
|||
@ -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> |
|||
); |
|||
}, |
|||
}); |
|||
@ -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; |
|||
} |
|||
Loading…
Reference in new issue