This commit is contained in:
Archer
2023-12-27 11:07:39 +08:00
committed by GitHub
parent 86286efb54
commit 759a2330e6
182 changed files with 3099 additions and 81685 deletions

View File

@@ -1,6 +1,10 @@
import { postUploadImg, postUploadFiles } from '@/web/common/file/api';
import { UploadImgProps } from '@fastgpt/global/common/file/api';
import { BucketNameEnum } from '@fastgpt/global/common/file/constants';
import {
compressBase64ImgAndUpload as compressBase64ImgAndUploadControl,
type CompressImgProps
} from '@fastgpt/web/common/file/img';
/**
* upload file to mongo gridfs
@@ -30,76 +34,40 @@ export const uploadFiles = ({
});
};
export const getUploadMdImgController = ({
base64Img,
metadata
}: {
base64Img: string;
metadata: Record<string, any>;
}) =>
compressBase64ImgAndUpload({
base64Img,
maxW: 4000,
maxH: 4000,
maxSize: 1024 * 1024 * 5,
metadata
});
/**
* compress image. response base64
* @param maxSize The max size of the compressed image
*/
export const compressBase64ImgAndUpload = ({
base64Img,
maxW = 1080,
maxH = 1080,
maxSize = 1024 * 500, // 300kb
expiredTime,
metadata,
shareId
}: UploadImgProps & {
maxW?: number;
maxH?: number;
maxSize?: number;
}) => {
return new Promise<string>((resolve, reject) => {
const fileType =
/^data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,/.exec(base64Img)?.[1] || 'image/jpeg';
const img = new Image();
img.src = base64Img;
img.onload = async () => {
let width = img.width;
let height = img.height;
if (width > height) {
if (width > maxW) {
height *= maxW / width;
width = maxW;
}
} else {
if (height > maxH) {
width *= maxH / height;
height = maxH;
}
}
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
if (!ctx) {
return reject('压缩图片异常');
}
ctx.drawImage(img, 0, 0, width, height);
const compressedDataUrl = canvas.toDataURL(fileType, 1);
// 移除 canvas 元素
canvas.remove();
if (compressedDataUrl.length > maxSize) {
return reject('图片太大了');
}
try {
const src = await postUploadImg({
shareId,
base64Img: compressedDataUrl,
expiredTime,
metadata
});
resolve(src);
} catch (error) {
reject(error);
}
};
img.onerror = reject;
shareId,
...props
}: UploadImgProps & CompressImgProps) => {
return compressBase64ImgAndUploadControl({
...props,
uploadController: (base64Img) =>
postUploadImg({
shareId,
base64Img,
expiredTime,
metadata
})
});
};
export const compressImgFileAndUpload = async ({

View File

@@ -3,94 +3,23 @@ import Papa from 'papaparse';
import { compressBase64ImgAndUpload } from './controller';
import { simpleMarkdownText } from '@fastgpt/global/common/string/markdown';
import { htmlStr2Md } from '@fastgpt/web/common/string/markdown';
/**
* 读取 txt 文件内容
*/
export const readTxtContent = (file: File) => {
return new Promise((resolve: (_: string) => void, reject) => {
try {
const reader = new FileReader();
reader.onload = () => {
resolve(reader.result as string);
};
reader.onerror = (err) => {
console.log('error txt read:', err);
reject('读取 txt 文件失败');
};
reader.readAsText(file);
} catch (error) {
reject('浏览器不支持文件内容读取');
}
});
};
import { readPdfFile } from '@fastgpt/global/common/file/read/index';
import { readFileRawText } from '@fastgpt/web/common/file/read';
/**
* read pdf to raw text
*/
export const readPdfContent = (file: File) =>
new Promise<string>((resolve, reject) => {
type TokenType = {
str: string;
dir: string;
width: number;
height: number;
transform: number[];
fontName: string;
hasEOL: boolean;
};
try {
const pdfjsLib = window['pdfjs-dist/build/pdf'];
pdfjsLib.workerSrc = '/js/pdf.worker.js';
const readPDFPage = async (doc: any, pageNo: number) => {
const page = await doc.getPage(pageNo);
const tokenizedText = await page.getTextContent();
const viewport = page.getViewport({ scale: 1 });
const pageHeight = viewport.height;
const headerThreshold = pageHeight * 0.07; // 假设页头在页面顶部5%的区域内
const footerThreshold = pageHeight * 0.93; // 假设页脚在页面底部5%的区域内
const pageTexts: TokenType[] = tokenizedText.items.filter((token: TokenType) => {
return (
!token.transform ||
(token.transform[5] > headerThreshold && token.transform[5] < footerThreshold)
);
});
// concat empty string 'hasEOL'
for (let i = 0; i < pageTexts.length; i++) {
const item = pageTexts[i];
if (item.str === '' && pageTexts[i - 1]) {
pageTexts[i - 1].hasEOL = item.hasEOL;
pageTexts.splice(i, 1);
i--;
}
}
return pageTexts
.map((token) => {
const paragraphEnd = token.hasEOL && /([。?!.?!\n\r]|(\r\n))$/.test(token.str);
return paragraphEnd ? `${token.str}\n` : token.str;
})
.join('');
};
let reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = async (event) => {
if (!event?.target?.result) return reject('解析 PDF 失败');
try {
const doc = await pdfjsLib.getDocument(event.target.result).promise;
const pageTextPromises = [];
for (let pageNo = 1; pageNo <= doc.numPages; pageNo++) {
pageTextPromises.push(readPDFPage(doc, pageNo));
}
const pageTexts = await Promise.all(pageTextPromises);
resolve(pageTexts.join(''));
const content = await readPdfFile({ pdf: event.target.result });
resolve(content);
} catch (err) {
console.log(err, 'pdf load error');
reject('解析 PDF 失败');
@@ -122,7 +51,7 @@ export const readDocContent = (file: File, metadata: Record<string, any>) =>
});
const md = htmlStr2Md(html);
const rawText = await formatMarkdown(md, metadata);
const rawText = await uploadMarkdownBase64(md, metadata);
resolve(rawText);
} catch (error) {
@@ -156,7 +85,7 @@ export const readDocContent = (file: File, metadata: Record<string, any>) =>
*/
export const readCsvContent = async (file: File) => {
try {
const textArr = await readTxtContent(file);
const textArr = await readFileRawText(file);
const csvArr = Papa.parse(textArr).data as string[][];
if (csvArr.length === 0) {
throw new Error('csv 解析失败');
@@ -175,7 +104,7 @@ export const readCsvContent = async (file: File) => {
* 1. upload base64
* 2. replace \
*/
export const formatMarkdown = async (rawText: string = '', metadata: Record<string, any>) => {
export const uploadMarkdownBase64 = async (rawText: string = '', metadata: Record<string, any>) => {
// match base64, upload and replace it
const base64Regex = /data:image\/.*;base64,([^\)]+)/g;
const base64Arr = rawText.match(base64Regex) || [];

View File

@@ -94,7 +94,7 @@ export const useConfirm = (props?: {
<ModalFooter>
{showCancel && (
<Button
variant={'base'}
variant={'whiteBase'}
onClick={() => {
onClose();
typeof cancelCb.current === 'function' && cancelCb.current();

View File

@@ -96,7 +96,7 @@ export const useEditTitle = ({
/>
</ModalBody>
<ModalFooter>
<Button mr={3} variant={'base'} onClick={onClose}>
<Button mr={3} variant={'whiteBase'} onClick={onClose}>
</Button>
<Button onClick={onclickConfirm}></Button>

View File

@@ -60,9 +60,7 @@ export function usePagination<T = any>({
isDisabled={pageNum === 1}
icon={<ArrowBackIcon />}
aria-label={'left'}
size={'sm'}
w={'28px'}
h={'28px'}
size={'smSquare'}
isLoading={isLoading}
onClick={() => mutate(pageNum - 1)}
/>

View File

@@ -1,4 +1,4 @@
import { GET, POST, PUT, DELETE } from '@/web/common/api/request';
import type { InitDateResponse } from '@/global/common/api/systemRes';
export const getSystemInitData = () => GET<InitDateResponse>('/system/getInitData');
export const getSystemInitData = () => GET<InitDateResponse>('/common/system/getInitData');

View File

@@ -1,7 +1,7 @@
import type { InitDateResponse } from '@/global/common/api/systemRes';
import { getSystemInitData } from '@/web/common/system/api';
import { delay } from '@fastgpt/global/common/system/utils';
import type { FeConfigsType } from '@fastgpt/global/common/system/types/index.d';
import type { FastGPTFeConfigsType } from '@fastgpt/global/common/system/types/index.d';
import { AppSimpleEditConfigTemplateType } from '@fastgpt/global/core/app/type';
import type {
ChatModelItemType,
@@ -12,7 +12,7 @@ import type {
AudioSpeechModelType
} from '@fastgpt/global/core/ai/model.d';
export let feConfigs: FeConfigsType = {};
export let feConfigs: FastGPTFeConfigsType = {};
export let priceMd = '';
export let systemVersion = '0.0.0';

View File

@@ -1,7 +1,11 @@
export enum EventNameEnum {
sendQuestion = 'sendQuestion',
editQuestion = 'editQuestion',
updaterNode = 'updaterNode'
// flow
requestFlowEvent = 'requestFlowEvent',
requestFlowStore = 'requestFlowStore',
receiveFlowStore = 'receiveFlowStore'
}
type EventNameType = `${EventNameEnum}`;