feat: 完成分享、单会话与发布审批改造
- 增加工作流协作分享与知识库卡片分享入口,统一低版本浏览器复制反馈 - Web 新登录替换旧会话,并保持 API Key 会话隔离 - 发布审批增加必填说明并在审批详情展示 - 账号重置与导入改用可配置默认强密码
This commit is contained in:
@@ -5,7 +5,7 @@ import { computed } from 'vue';
|
||||
|
||||
import { useAccess } from '@easyflow/access';
|
||||
|
||||
import { MoreFilled } from '@element-plus/icons-vue';
|
||||
import { Loading, MoreFilled } from '@element-plus/icons-vue';
|
||||
import {
|
||||
ElAvatar,
|
||||
ElButton,
|
||||
@@ -27,6 +27,8 @@ export interface ActionButton {
|
||||
icon?: any;
|
||||
text: ((row: any) => string) | string;
|
||||
className?: string;
|
||||
disabled?: ((row: any) => boolean) | boolean;
|
||||
loading?: ((row: any) => boolean) | boolean;
|
||||
permission?: string;
|
||||
placement?: ActionPlacement;
|
||||
tone?: ActionTone;
|
||||
@@ -87,6 +89,13 @@ function isActionVisible(action: ActionButton, row: any) {
|
||||
return action.visible !== false;
|
||||
}
|
||||
|
||||
function resolveActionState(
|
||||
state: ((row: any) => boolean) | boolean | undefined,
|
||||
row: any,
|
||||
) {
|
||||
return typeof state === 'function' ? state(row) : state === true;
|
||||
}
|
||||
|
||||
const resolvedPrimaryAction = computed(() => {
|
||||
if (!props.primaryAction || !hasPermission(props.primaryAction.permission)) {
|
||||
return undefined;
|
||||
@@ -125,6 +134,12 @@ function handlePrimaryAction(item: any) {
|
||||
|
||||
function handleActionClick(event: Event, action: ActionButton, item: any) {
|
||||
event.stopPropagation();
|
||||
if (
|
||||
resolveActionState(action.disabled, item) ||
|
||||
resolveActionState(action.loading, item)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
action.onClick(item);
|
||||
}
|
||||
|
||||
@@ -265,6 +280,8 @@ function resolveMetaItems(item: any) {
|
||||
size="small"
|
||||
class="card-action-btn"
|
||||
:class="{ 'card-action-btn--danger': action.tone === 'danger' }"
|
||||
:disabled="resolveActionState(action.disabled, item)"
|
||||
:loading="resolveActionState(action.loading, item)"
|
||||
link
|
||||
@click.stop="handleActionClick($event, action, item)"
|
||||
>
|
||||
@@ -293,10 +310,20 @@ function resolveMetaItems(item: any) {
|
||||
:class="{
|
||||
'card-menu-item--danger': action.tone === 'danger',
|
||||
}"
|
||||
@click="action.onClick(item)"
|
||||
:disabled="
|
||||
resolveActionState(action.disabled, item) ||
|
||||
resolveActionState(action.loading, item)
|
||||
"
|
||||
@click="handleActionClick($event, action, item)"
|
||||
>
|
||||
<div class="menu-action-content">
|
||||
<ElIcon v-if="action.icon">
|
||||
<ElIcon
|
||||
v-if="resolveActionState(action.loading, item)"
|
||||
class="is-loading"
|
||||
>
|
||||
<Loading />
|
||||
</ElIcon>
|
||||
<ElIcon v-else-if="action.icon">
|
||||
<IconifyIcon
|
||||
v-if="typeof action.icon === 'string'"
|
||||
:icon="action.icon"
|
||||
|
||||
@@ -89,6 +89,28 @@ describe('cardList', () => {
|
||||
expect(primaryAction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('异步次级操作执行中会禁用重复点击并展示加载态', async () => {
|
||||
const inlineAction = vi.fn();
|
||||
const wrapper = mountCardList({
|
||||
actions: [
|
||||
{
|
||||
disabled: () => true,
|
||||
loading: () => true,
|
||||
text: '分享',
|
||||
placement: 'inline',
|
||||
onClick: inlineAction,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const actionButton = wrapper.get('.card-action-btn');
|
||||
await actionButton.trigger('click');
|
||||
|
||||
expect(actionButton.classes()).toContain('is-loading');
|
||||
expect(actionButton.classes()).toContain('is-disabled');
|
||||
expect(inlineAction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('键盘 Enter 可以触发主动作', async () => {
|
||||
const primaryAction = vi.fn();
|
||||
const wrapper = mountCardList({
|
||||
|
||||
Reference in New Issue
Block a user