feat: 完成分享、单会话与发布审批改造
- 增加工作流协作分享与知识库卡片分享入口,统一低版本浏览器复制反馈 - Web 新登录替换旧会话,并保持 API Key 会话隔离 - 发布审批增加必填说明并在审批详情展示 - 账号重置与导入改用可配置默认强密码
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { confirmPublishSubmission } from './approval-application-reason';
|
||||
|
||||
const { confirm, prompt } = vi.hoisted(() => ({
|
||||
confirm: vi.fn(),
|
||||
prompt: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('element-plus', () => ({
|
||||
ElMessageBox: {
|
||||
confirm,
|
||||
prompt,
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('#/locales', () => ({
|
||||
$t: (key: string) => key,
|
||||
}));
|
||||
|
||||
describe('confirmPublishSubmission', () => {
|
||||
const api = {
|
||||
get: vi.fn(),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('uses the normal confirmation when no approval flow matches', async () => {
|
||||
api.get.mockResolvedValue({ data: false, errorCode: 0 });
|
||||
confirm.mockResolvedValue('confirm');
|
||||
|
||||
await expect(
|
||||
confirmPublishSubmission({
|
||||
api,
|
||||
confirmMessage: '确认发布?',
|
||||
id: '1',
|
||||
resourcePath: '/api/v1/workflow',
|
||||
title: '提示',
|
||||
}),
|
||||
).resolves.toEqual({});
|
||||
|
||||
expect(confirm).toHaveBeenCalled();
|
||||
expect(prompt).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('requires and trims a reason when an approval flow matches', async () => {
|
||||
api.get.mockResolvedValue({ data: true, errorCode: 0 });
|
||||
prompt.mockResolvedValue({ value: ' 本次修复复制兼容问题 ' });
|
||||
|
||||
await expect(
|
||||
confirmPublishSubmission({
|
||||
api,
|
||||
confirmMessage: '确认提交发布审批?',
|
||||
id: '1',
|
||||
resourcePath: '/api/v1/workflow',
|
||||
title: '提示',
|
||||
}),
|
||||
).resolves.toEqual({
|
||||
applicationReason: '本次修复复制兼容问题',
|
||||
});
|
||||
|
||||
const promptOptions = prompt.mock.calls[0]?.[2];
|
||||
expect(promptOptions.inputValidator(' ')).toBe(
|
||||
'approval.message.applicationReasonRequired',
|
||||
);
|
||||
expect(promptOptions.inputValidator('a'.repeat(501))).toBe(
|
||||
'approval.message.applicationReasonTooLong',
|
||||
);
|
||||
expect(promptOptions.inputValidator('有效说明')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns null when the user cancels', async () => {
|
||||
api.get.mockResolvedValue({ data: true, errorCode: 0 });
|
||||
prompt.mockRejectedValue(new Error('cancel'));
|
||||
|
||||
await expect(
|
||||
confirmPublishSubmission({
|
||||
api,
|
||||
confirmMessage: '确认提交发布审批?',
|
||||
id: '1',
|
||||
resourcePath: '/api/v1/workflow',
|
||||
title: '提示',
|
||||
}),
|
||||
).resolves.toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,75 @@
|
||||
import { ElMessageBox } from 'element-plus';
|
||||
|
||||
import { $t } from '#/locales';
|
||||
|
||||
type ApprovalRequirementApi = {
|
||||
get: (
|
||||
url: string,
|
||||
config: { params: { id: number | string } },
|
||||
) => Promise<{ data?: boolean; errorCode?: number }>;
|
||||
};
|
||||
|
||||
type ConfirmPublishOptions = {
|
||||
api: ApprovalRequirementApi;
|
||||
confirmMessage: string;
|
||||
id: number | string;
|
||||
resourcePath: string;
|
||||
title: string;
|
||||
};
|
||||
|
||||
export type PublishConfirmation = {
|
||||
applicationReason?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* 预检发布审批并完成相应的确认交互。
|
||||
*
|
||||
* @param options 发布确认参数
|
||||
* @returns 用户取消时返回 null,否则返回提交参数
|
||||
*/
|
||||
export async function confirmPublishSubmission(
|
||||
options: ConfirmPublishOptions,
|
||||
): Promise<null | PublishConfirmation> {
|
||||
const response = await options.api.get(
|
||||
`${options.resourcePath}/publishApprovalRequirement`,
|
||||
{
|
||||
params: { id: options.id },
|
||||
},
|
||||
);
|
||||
try {
|
||||
if (!response.data) {
|
||||
await ElMessageBox.confirm(options.confirmMessage, options.title, {
|
||||
cancelButtonText: $t('button.cancel'),
|
||||
confirmButtonText: $t('button.confirm'),
|
||||
type: 'info',
|
||||
});
|
||||
return {};
|
||||
}
|
||||
const { value } = await ElMessageBox.prompt(
|
||||
$t('approval.message.applicationReasonPrompt'),
|
||||
options.title,
|
||||
{
|
||||
cancelButtonText: $t('button.cancel'),
|
||||
confirmButtonText: $t('approval.action.submit'),
|
||||
inputPlaceholder: $t('approval.placeholder.applicationReason'),
|
||||
inputType: 'textarea',
|
||||
inputValidator: (input: string) => {
|
||||
const normalized = String(input || '').trim();
|
||||
if (!normalized) {
|
||||
return $t('approval.message.applicationReasonRequired');
|
||||
}
|
||||
if (normalized.length > 500) {
|
||||
return $t('approval.message.applicationReasonTooLong');
|
||||
}
|
||||
return true;
|
||||
},
|
||||
type: 'info',
|
||||
},
|
||||
);
|
||||
return {
|
||||
applicationReason: String(value || '').trim(),
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user