feat: 添加下载文档和显示数据按钮 (#1370)
Reviewed-on: daoyoucloud/tachybase#1370 Co-authored-by: wjh <wwwjh0710@163.com> Co-committed-by: wjh <wwwjh0710@163.com>
This commit is contained in:
parent
bc563534a3
commit
c3c8b5b655
@ -831,5 +831,10 @@
|
|||||||
"Load": "Load",
|
"Load": "Load",
|
||||||
"Dump": "Dump",
|
"Dump": "Dump",
|
||||||
"Chang on Parent": "Chang on Parent",
|
"Chang on Parent": "Chang on Parent",
|
||||||
"Please enter search content": "Please enter search content"
|
"Please enter search content": "Please enter search content",
|
||||||
|
"Is DownLoad":"Is DownLoad",
|
||||||
|
"Show Data":"Show Data",
|
||||||
|
"Setting Down Title":"Setting Down Title",
|
||||||
|
"The current return type is not a document type":"The current return type is not a document type",
|
||||||
|
"Test Data":"Test Data"
|
||||||
}
|
}
|
||||||
|
@ -934,5 +934,10 @@
|
|||||||
"Sorry, the page you visited does not exist.": "对不起,您访问的页面不存在。",
|
"Sorry, the page you visited does not exist.": "对不起,您访问的页面不存在。",
|
||||||
"Back Home": "回到主页",
|
"Back Home": "回到主页",
|
||||||
"Chang on Parent": "选择父级",
|
"Chang on Parent": "选择父级",
|
||||||
"Please enter search content": "请输入查询内容"
|
"Please enter search content": "请输入查询内容",
|
||||||
|
"Is DownLoad":"下载文件",
|
||||||
|
"Show Data":"显示数据",
|
||||||
|
"Setting Down Title":"设置文件名称",
|
||||||
|
"The current return type is not a document type":"当前返回类型不是文档类型",
|
||||||
|
"Test Data":"测试数据"
|
||||||
}
|
}
|
||||||
|
@ -787,6 +787,102 @@ export function SecondConFirm() {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
export function IsDownLoad() {
|
||||||
|
const { dn } = useDesignable();
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SchemaSettingsSwitchItem
|
||||||
|
title={t('Is DownLoad')}
|
||||||
|
checked={!!fieldSchema?.['x-action-settings']?.onSuccess?.down}
|
||||||
|
onChange={(value) => {
|
||||||
|
if (!fieldSchema?.['x-action-settings']?.onSuccess) {
|
||||||
|
fieldSchema['x-action-settings'] = {
|
||||||
|
...fieldSchema?.['x-action-settings'],
|
||||||
|
onSuccess: {
|
||||||
|
down: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
fieldSchema['x-action-settings'].onSuccess.down = value;
|
||||||
|
|
||||||
|
dn.emit('patch', {
|
||||||
|
schema: {
|
||||||
|
['x-uid']: fieldSchema['x-uid'],
|
||||||
|
'x-action-settings': { ...fieldSchema['x-action-settings'] },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export function ShowData() {
|
||||||
|
const { dn } = useDesignable();
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const field = useField();
|
||||||
|
return (
|
||||||
|
<SchemaSettingsSwitchItem
|
||||||
|
title={t('Show Data')}
|
||||||
|
checked={!!fieldSchema?.['x-component-props']?.showData}
|
||||||
|
onChange={(value) => {
|
||||||
|
if (!fieldSchema?.['x-component-props']) {
|
||||||
|
fieldSchema['x-component-props'] = { showData: false };
|
||||||
|
}
|
||||||
|
fieldSchema['x-component-props'].showData = value;
|
||||||
|
field.componentProps = fieldSchema['x-component-props'];
|
||||||
|
dn.emit('patch', {
|
||||||
|
schema: {
|
||||||
|
['x-uid']: fieldSchema['x-uid'],
|
||||||
|
'x-component-props': { ...fieldSchema['x-component-props'] },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SettingDownTitle() {
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const { dn } = useDesignable();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
return (
|
||||||
|
<SchemaSettingsModalItem
|
||||||
|
title={t('Setting Down Title')}
|
||||||
|
onSubmit={({ title }) => {
|
||||||
|
if (!fieldSchema?.['x-action-settings']) {
|
||||||
|
fieldSchema['x-action-settings'] = {
|
||||||
|
onSussess: {
|
||||||
|
downTitle: title,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
fieldSchema['x-action-settings']['onSuccess'] = {
|
||||||
|
...fieldSchema['x-action-settings']?.['onSuccess'],
|
||||||
|
downTitle: title,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
dn.emit('patch', {
|
||||||
|
schema: {
|
||||||
|
['x-uid']: fieldSchema['x-uid'],
|
||||||
|
'x-action-settings': { ...fieldSchema['x-action-settings'] },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
schema={{
|
||||||
|
type: 'item',
|
||||||
|
title: t('Setting Down Title'),
|
||||||
|
properties: {
|
||||||
|
title: {
|
||||||
|
'x-component': 'Input',
|
||||||
|
default: fieldSchema['x-action-settings']?.['onSuccess']?.downTitle || 'document.docx',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"@tachybase/components": "workspace:*",
|
"@tachybase/components": "workspace:*",
|
||||||
"@tachybase/schema": "workspace:*",
|
"@tachybase/schema": "workspace:*",
|
||||||
"antd": "5.19.1",
|
"antd": "5.19.1",
|
||||||
|
"file-saver": "^2.0.5",
|
||||||
"lodash": "~4.17.21",
|
"lodash": "~4.17.21",
|
||||||
"react-i18next": "^14.1.2",
|
"react-i18next": "^14.1.2",
|
||||||
"react-router-dom": "~6.25.1"
|
"react-router-dom": "~6.25.1"
|
||||||
|
@ -11,8 +11,11 @@ import { useField, useFieldSchema, useForm } from '@tachybase/schema';
|
|||||||
import { isURL } from '@tachybase/utils/client';
|
import { isURL } from '@tachybase/utils/client';
|
||||||
|
|
||||||
import { App } from 'antd';
|
import { App } from 'antd';
|
||||||
|
import { saveAs } from 'file-saver';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { useTranslation } from '../locale';
|
||||||
|
|
||||||
export const useCustomizeRequestActionProps = () => {
|
export const useCustomizeRequestActionProps = () => {
|
||||||
const apiClient = useAPIClient();
|
const apiClient = useAPIClient();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -26,6 +29,7 @@ export const useCustomizeRequestActionProps = () => {
|
|||||||
const actionField = useField();
|
const actionField = useField();
|
||||||
const { setVisible } = useActionContext();
|
const { setVisible } = useActionContext();
|
||||||
const { modal, message } = App.useApp();
|
const { modal, message } = App.useApp();
|
||||||
|
const { t } = useTranslation();
|
||||||
return {
|
return {
|
||||||
async onClick() {
|
async onClick() {
|
||||||
const { skipValidator, onSuccess } = actionSchema?.['x-action-settings'] ?? {};
|
const { skipValidator, onSuccess } = actionSchema?.['x-action-settings'] ?? {};
|
||||||
@ -42,9 +46,10 @@ export const useCustomizeRequestActionProps = () => {
|
|||||||
actionField.data ??= {};
|
actionField.data ??= {};
|
||||||
actionField.data.loading = true;
|
actionField.data.loading = true;
|
||||||
try {
|
try {
|
||||||
await apiClient.request({
|
const res = (await apiClient.request({
|
||||||
url: `/customRequests:send/${fieldSchema['x-uid']}`,
|
url: `/customRequests:send/${fieldSchema['x-uid']}`,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
responseType: onSuccess?.down ? 'blob' : 'json',
|
||||||
data: {
|
data: {
|
||||||
currentRecord: {
|
currentRecord: {
|
||||||
id: record[getPrimaryKey()],
|
id: record[getPrimaryKey()],
|
||||||
@ -52,7 +57,16 @@ export const useCustomizeRequestActionProps = () => {
|
|||||||
data: formValues,
|
data: formValues,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
})) as any;
|
||||||
|
const headerContentType = res.headers.getContentType();
|
||||||
|
if (onSuccess?.down) {
|
||||||
|
if (headerContentType === 'application/octet-stream') {
|
||||||
|
const downTitle = onSuccess.downTitle;
|
||||||
|
saveAs(res.data, downTitle);
|
||||||
|
} else {
|
||||||
|
message.error(t('The current return type is not a document type'));
|
||||||
|
}
|
||||||
|
}
|
||||||
actionField.data.loading = false;
|
actionField.data.loading = false;
|
||||||
if (!(resource instanceof TableFieldResource)) {
|
if (!(resource instanceof TableFieldResource)) {
|
||||||
__parent?.service?.refresh?.();
|
__parent?.service?.refresh?.();
|
||||||
@ -61,6 +75,15 @@ export const useCustomizeRequestActionProps = () => {
|
|||||||
if (xAction === 'customize:form:request') {
|
if (xAction === 'customize:form:request') {
|
||||||
setVisible?.(false);
|
setVisible?.(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (actionSchema?.['x-component-props']?.showData) {
|
||||||
|
modal.confirm({
|
||||||
|
title: 'Test Data',
|
||||||
|
content: `${JSON.stringify(res.data)}`,
|
||||||
|
okText: t('Confirm'),
|
||||||
|
cancelText: t('Cancel'),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
if (!onSuccess?.successMessage) {
|
if (!onSuccess?.successMessage) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -87,6 +110,7 @@ export const useCustomizeRequestActionProps = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
actionField.data.loading = false;
|
actionField.data.loading = false;
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
import {
|
import {
|
||||||
AfterSuccess,
|
AfterSuccess,
|
||||||
ButtonEditor,
|
ButtonEditor,
|
||||||
|
IsDownLoad,
|
||||||
RemoveButton,
|
RemoveButton,
|
||||||
SchemaSettings,
|
SchemaSettings,
|
||||||
SchemaSettingsLinkageRules,
|
SchemaSettingsLinkageRules,
|
||||||
SecondConFirm,
|
SecondConFirm,
|
||||||
|
SettingDownTitle,
|
||||||
|
ShowData,
|
||||||
useCollection,
|
useCollection,
|
||||||
useSchemaToolbar,
|
useSchemaToolbar,
|
||||||
} from '@tachybase/client';
|
} from '@tachybase/client';
|
||||||
|
import { useFieldSchema } from '@tachybase/schema';
|
||||||
|
|
||||||
import { CustomRequestACL, CustomRequestSettingsItem } from './components/CustomRequestActionDesigner';
|
import { CustomRequestACL, CustomRequestSettingsItem } from './components/CustomRequestActionDesigner';
|
||||||
|
|
||||||
@ -41,6 +45,23 @@ export const customizeCustomRequestActionSettings = new SchemaSettings({
|
|||||||
name: 'secondConFirm',
|
name: 'secondConFirm',
|
||||||
Component: SecondConFirm,
|
Component: SecondConFirm,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'isDownLoad',
|
||||||
|
Component: IsDownLoad,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'settingDownTitle',
|
||||||
|
Component: SettingDownTitle,
|
||||||
|
useVisible() {
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const down = fieldSchema?.['x-action-settings']?.onSuccess?.down;
|
||||||
|
return down;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'showData',
|
||||||
|
Component: ShowData,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'afterSuccessfulSubmission',
|
name: 'afterSuccessfulSubmission',
|
||||||
Component: AfterSuccess,
|
Component: AfterSuccess,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import fs from 'fs';
|
||||||
|
import http from 'http';
|
||||||
import { Context, Next } from '@tachybase/actions';
|
import { Context, Next } from '@tachybase/actions';
|
||||||
import { appendArrayColumn } from '@tachybase/evaluators';
|
import { appendArrayColumn } from '@tachybase/evaluators';
|
||||||
import { parse } from '@tachybase/utils';
|
import { parse } from '@tachybase/utils';
|
||||||
@ -160,10 +162,14 @@ export async function send(this: CustomRequestPlugin, ctx: Context, next: Next)
|
|||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ctx.body = await axios(axiosRequestConfig).then((res) => {
|
const res = await axios({ ...axiosRequestConfig, responseType: 'stream' });
|
||||||
|
ctx.set('Content-Type', `${res.headers['content-type']}`);
|
||||||
|
ctx.set('Content-disposition', `${res.headers['content-disposition']}`);
|
||||||
this.logger.info(`custom-request:send:${filterByTk} success`);
|
this.logger.info(`custom-request:send:${filterByTk} success`);
|
||||||
return res.data;
|
|
||||||
});
|
const readable = res.data as http.IncomingMessage;
|
||||||
|
|
||||||
|
ctx.body = readable;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (axios.isAxiosError(err)) {
|
if (axios.isAxiosError(err)) {
|
||||||
ctx.status = err.response?.status || 500;
|
ctx.status = err.response?.status || 500;
|
||||||
|
@ -18,7 +18,6 @@ export const generate = async (ctx: Context) => {
|
|||||||
},
|
},
|
||||||
appends: ['template'],
|
appends: ['template'],
|
||||||
});
|
});
|
||||||
console.log(template.get());
|
|
||||||
|
|
||||||
const rawTemplate = template.get();
|
const rawTemplate = template.get();
|
||||||
const templatePath = path.join(process.env.PWD, rawTemplate.template[0].get().url);
|
const templatePath = path.join(process.env.PWD, rawTemplate.template[0].get().url);
|
||||||
@ -27,18 +26,8 @@ export const generate = async (ctx: Context) => {
|
|||||||
try {
|
try {
|
||||||
// 生成定制的 docx 文件
|
// 生成定制的 docx 文件
|
||||||
const buffer = generateDocxFromTemplate(templatePath, data);
|
const buffer = generateDocxFromTemplate(templatePath, data);
|
||||||
|
|
||||||
// 创建一个可读流
|
|
||||||
const readableStream = new Readable({
|
|
||||||
read(size) {
|
|
||||||
this.push(buffer);
|
|
||||||
this.push(null);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
ctx.withoutDataWrapping = true;
|
ctx.withoutDataWrapping = true;
|
||||||
ctx.set('Content-Type', 'application/octet-stream');
|
ctx.body = buffer;
|
||||||
ctx.body = readableStream;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
ctx.status = 500;
|
ctx.status = 500;
|
||||||
@ -66,7 +55,6 @@ export const getTags = async (ctx: Context) => {
|
|||||||
|
|
||||||
// 获取所有占位符
|
// 获取所有占位符
|
||||||
const allTags = iModule.getAllTags();
|
const allTags = iModule.getAllTags();
|
||||||
console.log('All tags in the document:', allTags);
|
|
||||||
|
|
||||||
// 将 tags 转换为 JSON 格式的字符串
|
// 将 tags 转换为 JSON 格式的字符串
|
||||||
const tagsJson = JSON.stringify(allTags, null, 2);
|
const tagsJson = JSON.stringify(allTags, null, 2);
|
||||||
|
@ -16,6 +16,7 @@ export class PluginPrintTemplateServer extends Plugin {
|
|||||||
getTags,
|
getTags,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
this.app.acl.allow('printTemplates', '*', 'public');
|
||||||
}
|
}
|
||||||
|
|
||||||
async install() {}
|
async install() {}
|
||||||
|
@ -2454,6 +2454,9 @@ importers:
|
|||||||
antd:
|
antd:
|
||||||
specifier: 5.19.1
|
specifier: 5.19.1
|
||||||
version: 5.19.1(react-dom@18.3.1)(react@18.3.1)
|
version: 5.19.1(react-dom@18.3.1)(react@18.3.1)
|
||||||
|
file-saver:
|
||||||
|
specifier: ^2.0.5
|
||||||
|
version: 2.0.5
|
||||||
lodash:
|
lodash:
|
||||||
specifier: ~4.17.21
|
specifier: ~4.17.21
|
||||||
version: 4.17.21
|
version: 4.17.21
|
||||||
|
Loading…
Reference in New Issue
Block a user