extraFile2 改 extraFile
This commit is contained in:
parent
8467b45c93
commit
a1bc6f9493
|
|
@ -70,18 +70,8 @@ export default OakComponent({
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
// async addExtraFile(
|
||||
// extraFile: EntityDict['extraFile']['CreateSingle']['data']
|
||||
// ) {
|
||||
// const result = await this.features.cache.operate('extraFile', {
|
||||
// action: 'create',
|
||||
// data: extraFile,
|
||||
// id: generateNewId(),
|
||||
// });
|
||||
// return result;
|
||||
// },
|
||||
async uploadFile(extraFile) {
|
||||
const result = await this.features.extraFile.createAndUpload(extraFile, extraFile.extra1);
|
||||
async uploadFile(extraFile, file) {
|
||||
const result = await this.features.extraFile.autoUpload(extraFile, file);
|
||||
return result;
|
||||
},
|
||||
setEditor(editor) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import "@wangeditor/editor/dist/css/style.css";
|
||||
import { EntityDict } from "./../../../oak-app-domain";
|
||||
import { WebComponentProps } from "oak-frontend-base";
|
||||
export default function Render(props: WebComponentProps<EntityDict, "article", false, {
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'article', false, {
|
||||
id: string;
|
||||
name: string;
|
||||
editor: any;
|
||||
|
|
@ -19,11 +19,7 @@ export default function Render(props: WebComponentProps<EntityDict, "article", f
|
|||
setEditor: (editor: any) => void;
|
||||
check: () => void;
|
||||
preview: () => void;
|
||||
addExtraFile: (file: EntityDict["extraFile"]["CreateSingle"]["data"]) => Promise<void>;
|
||||
uploadFile: (file: EntityDict["extraFile"]["CreateSingle"]["data"]) => Promise<{
|
||||
bucket: string;
|
||||
url: string;
|
||||
}>;
|
||||
uploadFile: (extraFile: EntityDict['extraFile']['CreateSingle']['data'], file: File) => Promise<string>;
|
||||
clearContentTip: () => void;
|
||||
gotoPreview: (content?: string, title?: string) => void;
|
||||
}>): import("react/jsx-runtime").JSX.Element;
|
||||
|
|
|
|||
|
|
@ -27,17 +27,17 @@ function customCheckImageFn(src, alt, url) {
|
|||
}
|
||||
export default function Render(props) {
|
||||
const { methods: method, data } = props;
|
||||
const { t, setEditor, check, preview, addExtraFile, uploadFile, update, setHtml, gotoPreview, } = method;
|
||||
const { id, content, editor, origin1, oakFullpath, html, oakId, articleMenuId, changeIsEdit } = data;
|
||||
const [articleId, setArticleId] = useState("");
|
||||
const { t, setEditor, check, preview, uploadFile, update, setHtml, gotoPreview, } = method;
|
||||
const { id, content, editor, origin1, oakFullpath, html, oakId, articleMenuId, changeIsEdit, } = data;
|
||||
const [articleId, setArticleId] = useState('');
|
||||
useEffect(() => {
|
||||
if (id) {
|
||||
setArticleId(id);
|
||||
}
|
||||
}, [id]);
|
||||
return (_jsxs("div", { className: Style.container, children: [_jsx("div", { style: { width: 'calc(100% - 20px)' }, children: _jsx(Toolbar, { editor: editor, defaultConfig: toolbarConfig, mode: "default" }) }), _jsxs(Row, { children: [_jsx(Col, { flex: 4 }), _jsx(Col, { flex: 16, children: _jsx("div", { className: Style.content, children: _jsxs("div", { className: Style.editorContainer, children: [data.contentTip && (_jsx(Alert, { type: "info", message: t("tips.content"), closable: true, onClose: () => method.clearContentTip() })), _jsx("div", { className: Style.titleContainer, children: _jsx(Input, { onChange: (e) => update({ name: e.target.value }), value: data.name, placeholder: "请输入文章标题", size: "large", maxLength: 32, suffix: `${[...(data.name || "")].length}/32`, className: Style.titleInput }) }), _jsx("div", { className: Style.editorContent, children: _jsx(Editor, { defaultConfig: {
|
||||
return (_jsxs("div", { className: Style.container, children: [_jsx("div", { style: { width: 'calc(100% - 20px)' }, children: _jsx(Toolbar, { editor: editor, defaultConfig: toolbarConfig, mode: "default" }) }), _jsxs(Row, { children: [_jsx(Col, { flex: 4 }), _jsx(Col, { flex: 16, children: _jsx("div", { className: Style.content, children: _jsxs("div", { className: Style.editorContainer, children: [data.contentTip && (_jsx(Alert, { type: "info", message: t('tips.content'), closable: true, onClose: () => method.clearContentTip() })), _jsx("div", { className: Style.titleContainer, children: _jsx(Input, { onChange: (e) => update({ name: e.target.value }), value: data.name, placeholder: '请输入文章标题', size: "large", maxLength: 32, suffix: `${[...(data.name || '')].length}/32`, className: Style.titleInput }) }), _jsx("div", { className: Style.editorContent, children: _jsx(Editor, { defaultConfig: {
|
||||
autoFocus: true,
|
||||
placeholder: "请输入文章内容...",
|
||||
placeholder: '请输入文章内容...',
|
||||
MENU_CONF: {
|
||||
checkImage: customCheckImageFn,
|
||||
uploadImage: {
|
||||
|
|
@ -46,33 +46,28 @@ export default function Render(props) {
|
|||
// TS 语法
|
||||
// file 即选中的文件
|
||||
const { name, size, type } = file;
|
||||
const extension = name.substring(name.lastIndexOf(".") + 1);
|
||||
const filename = name.substring(0, name.lastIndexOf("."));
|
||||
const extension = name.substring(name.lastIndexOf('.') + 1);
|
||||
const filename = name.substring(0, name.lastIndexOf('.'));
|
||||
const extraFile = {
|
||||
entity: "article",
|
||||
entity: 'article',
|
||||
entityId: articleId,
|
||||
extra1: file,
|
||||
origin: origin1,
|
||||
type: "image",
|
||||
tag1: "source",
|
||||
type: 'image',
|
||||
tag1: 'source',
|
||||
objectId: generateNewId(),
|
||||
filename,
|
||||
size,
|
||||
extension,
|
||||
bucket: "",
|
||||
bucket: '',
|
||||
id: generateNewId(),
|
||||
};
|
||||
try {
|
||||
// 自己实现上传,并得到图片 url alt href
|
||||
const { url, bucket } = await uploadFile(extraFile);
|
||||
extraFile.bucket = bucket;
|
||||
extraFile.extra1 = null;
|
||||
// await addExtraFile(extraFile);
|
||||
const url = await uploadFile(extraFile, file);
|
||||
// 最后插入图片
|
||||
insertFn("http://" + url, extraFile.filename);
|
||||
}
|
||||
catch (err) {
|
||||
insertFn(url, extraFile.filename);
|
||||
}
|
||||
catch (err) { }
|
||||
},
|
||||
},
|
||||
uploadVideo: {
|
||||
|
|
@ -81,30 +76,27 @@ export default function Render(props) {
|
|||
// TS 语法
|
||||
// file 即选中的文件
|
||||
const { name, size, type } = file;
|
||||
const extension = name.substring(name.lastIndexOf(".") + 1);
|
||||
const filename = name.substring(0, name.lastIndexOf("."));
|
||||
const extension = name.substring(name.lastIndexOf('.') + 1);
|
||||
const filename = name.substring(0, name.lastIndexOf('.'));
|
||||
const extraFile = {
|
||||
entity: "article",
|
||||
entity: 'article',
|
||||
entityId: articleId,
|
||||
extra1: file,
|
||||
origin: origin1,
|
||||
type: "video",
|
||||
tag1: "source",
|
||||
type: 'video',
|
||||
tag1: 'source',
|
||||
objectId: generateNewId(),
|
||||
filename,
|
||||
size,
|
||||
extension,
|
||||
bucket: "",
|
||||
bucket: '',
|
||||
id: generateNewId(),
|
||||
};
|
||||
try {
|
||||
// 自己实现上传,并得到图片 url alt href
|
||||
const { url, bucket } = await uploadFile(extraFile);
|
||||
extraFile.bucket = bucket;
|
||||
extraFile.extra1 = null;
|
||||
await addExtraFile(extraFile);
|
||||
const url = await uploadFile(extraFile, file);
|
||||
// 最后插入图片
|
||||
insertFn("http://" + url, "http://" + url + "?vframe/jpg/offset/0");
|
||||
insertFn(url, url +
|
||||
'?vframe/jpg/offset/0');
|
||||
}
|
||||
catch (err) { }
|
||||
},
|
||||
|
|
@ -114,7 +106,8 @@ export default function Render(props) {
|
|||
setHtml(editorDom.getHtml());
|
||||
}, style: {
|
||||
minHeight: 440,
|
||||
}, mode: "default" }) }), _jsx("div", { className: Style.footer, children: _jsx(Row, { align: "middle", children: _jsx(Col, { flex: "none", children: _jsxs(Space, { children: [_jsx(Button, { disabled: !data.oakDirty || data.oakExecuting, type: "primary", onClick: () => {
|
||||
}, mode: "default" }) }), _jsx("div", { className: Style.footer, children: _jsx(Row, { align: "middle", children: _jsx(Col, { flex: "none", children: _jsxs(Space, { children: [_jsx(Button, { disabled: !data.oakDirty ||
|
||||
data.oakExecuting, type: "primary", onClick: () => {
|
||||
check();
|
||||
}, children: "\u4FDD\u5B58" }), _jsxs(Button, { onClick: () => {
|
||||
gotoPreview(content, data.name);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { generateNewId } from 'oak-domain/lib/utils/uuid';
|
||||
import { OakUnloggedInException } from 'oak-domain/lib/types';
|
||||
export default OakComponent({
|
||||
isList: true,
|
||||
properties: {
|
||||
|
|
@ -49,26 +48,6 @@ export default OakComponent({
|
|||
this.triggerEvent('statuschange', e);
|
||||
}
|
||||
},
|
||||
async addExtraFile(extraFile) {
|
||||
try {
|
||||
const result = await this.features.cache.operate('extraFile', {
|
||||
action: 'create',
|
||||
data: extraFile,
|
||||
id: generateNewId(),
|
||||
});
|
||||
return result;
|
||||
}
|
||||
catch (error) {
|
||||
if (error.constructor.name ===
|
||||
OakUnloggedInException.name) {
|
||||
this.navigateTo({
|
||||
url: '/login',
|
||||
});
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
async onPickMp(event) {
|
||||
if (process.env.OAK_PLATFORM === 'wechatMp') {
|
||||
const { mediaType } = event.currentTarget.dataset;
|
||||
|
|
@ -90,7 +69,6 @@ export default OakComponent({
|
|||
const extension = tempFilePath.substring(tempFilePath.lastIndexOf('.') + 1);
|
||||
const filename = tempFilePath.substring(0, tempFilePath.lastIndexOf('.'));
|
||||
const extraFile = {
|
||||
extra1: tempFilePath,
|
||||
origin: 'qiniu',
|
||||
type: 'image',
|
||||
tag1: this.props.tag1 || 'editorImg',
|
||||
|
|
@ -104,11 +82,11 @@ export default OakComponent({
|
|||
entityId: this.props.entityId,
|
||||
bucket: '',
|
||||
id: generateNewId(),
|
||||
uploadState: 'uploading'
|
||||
};
|
||||
const { url } = await this.features.extraFile.createAndUpload(extraFile, extraFile.extra1);
|
||||
// await this.addExtraFile(extraFile);
|
||||
const url = await this.features.extraFile.autoUpload(extraFile, tempFilePath);
|
||||
this.editorCtx.insertImage({
|
||||
src: 'http://' + url,
|
||||
src: url,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,10 +20,10 @@ export default OakComponent({
|
|||
sort: 1,
|
||||
applicationId: 1,
|
||||
},
|
||||
features: ['extraFile2'],
|
||||
features: ['extraFile'],
|
||||
formData({ data: extraFiles, features }) {
|
||||
const avatar = extraFiles?.filter((ele) => !ele.$$deleteAt$$ && ele.tag1 === 'avatar')[0];
|
||||
const avatarUrl = features.extraFile2.getUrl(avatar);
|
||||
const avatarUrl = features.extraFile.getUrl(avatar);
|
||||
return {
|
||||
avatar,
|
||||
avatarUrl,
|
||||
|
|
@ -117,7 +117,7 @@ export default OakComponent({
|
|||
};
|
||||
// 如果autoUpload
|
||||
if (autoUpload) {
|
||||
await this.features.extraFile2.autoUpload(updateData, extra1);
|
||||
await this.features.extraFile.autoUpload(updateData, extra1);
|
||||
if (avatar) {
|
||||
this.removeItem(avatar.id);
|
||||
this.execute();
|
||||
|
|
@ -128,7 +128,7 @@ export default OakComponent({
|
|||
if (avatar) {
|
||||
this.removeItem(avatar.id);
|
||||
}
|
||||
this.features.extraFile2.addLocalFile(id, extra1);
|
||||
this.features.extraFile.addLocalFile(id, extra1);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import assert from 'assert';
|
|||
export default OakComponent({
|
||||
formData({ features }) {
|
||||
const ids = this.getEfIds();
|
||||
const states = ids.map((id) => features.extraFile2.getFileState(id));
|
||||
const states = ids.map((id) => features.extraFile.getFileState(id));
|
||||
let state = 'uploaded';
|
||||
states.forEach((ele) => {
|
||||
if (ele) {
|
||||
|
|
@ -60,7 +60,7 @@ export default OakComponent({
|
|||
assert(v[attr] instanceof Array);
|
||||
const [e2, fk2] = rel;
|
||||
if (e2 === 'extraFile') {
|
||||
efIds.push(...(v[attr].map((ele) => ele.id)));
|
||||
efIds.push(...v[attr].map((ele) => ele.id));
|
||||
}
|
||||
else {
|
||||
v[attr].forEach((ele) => getRecursive(e2, ele));
|
||||
|
|
@ -69,7 +69,7 @@ export default OakComponent({
|
|||
}
|
||||
};
|
||||
if (value instanceof Array) {
|
||||
value.forEach(ele => getRecursive(entity, ele));
|
||||
value.forEach((ele) => getRecursive(entity, ele));
|
||||
}
|
||||
getRecursive(entity, value);
|
||||
return efIds;
|
||||
|
|
@ -81,11 +81,11 @@ export default OakComponent({
|
|||
}
|
||||
const promises = [];
|
||||
ids.forEach((id) => {
|
||||
const fileState = this.features.extraFile2.getFileState(id);
|
||||
const fileState = this.features.extraFile.getFileState(id);
|
||||
if (fileState) {
|
||||
const { state } = fileState;
|
||||
if (['local', 'failed'].includes(state)) {
|
||||
promises.push(this.features.extraFile2.upload(id));
|
||||
promises.push(this.features.extraFile.upload(id));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -117,5 +117,5 @@ export default OakComponent({
|
|||
}
|
||||
},
|
||||
},
|
||||
features: ['extraFile2'],
|
||||
features: ['extraFile'],
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import { ButtonProps } from 'antd-mobile';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { FileState } from '../../../features/extraFile2';
|
||||
import { FileState } from '../../../features/extraFile';
|
||||
export default function render(props: WebComponentProps<EntityDict, any, true, {
|
||||
state: FileState;
|
||||
size?: ButtonProps['size'];
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import { ButtonProps } from 'antd';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { FileState } from '../../../features/extraFile2';
|
||||
import { FileState } from '../../../features/extraFile';
|
||||
export default function render(props: WebComponentProps<EntityDict, any, true, {
|
||||
state: FileState;
|
||||
size?: ButtonProps['size'];
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ export default OakComponent({
|
|||
extra1: null,
|
||||
uploadState: 'uploading',
|
||||
}));
|
||||
this.features.extraFile2.addLocalFile(id, file);
|
||||
this.features.extraFile.addLocalFile(id, file);
|
||||
},
|
||||
async myUpdateItem(params) {
|
||||
const { file } = this.state;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export default OakComponent({
|
|||
isBridge: 1,
|
||||
uploadState: 1,
|
||||
},
|
||||
features: ['extraFile2'],
|
||||
features: ['extraFile'],
|
||||
formData({ data, features }) {
|
||||
let files = data?.sort((ele1, ele2) => ele1.sort - ele2.sort);
|
||||
if (this.props.tag1) {
|
||||
|
|
@ -30,9 +30,9 @@ export default OakComponent({
|
|||
files = files?.filter((ele) => ele?.tag2 === this.props.tag2);
|
||||
}
|
||||
const files2 = files.map((ele) => {
|
||||
const url = features.extraFile2.getUrl(ele);
|
||||
const thumbUrl = features.extraFile2.getUrl(ele, this.props.style);
|
||||
const fileName = features.extraFile2.getFileName(ele);
|
||||
const url = features.extraFile.getUrl(ele);
|
||||
const thumbUrl = features.extraFile.getUrl(ele, this.props.style);
|
||||
const fileName = features.extraFile.getFileName(ele);
|
||||
return {
|
||||
url,
|
||||
thumbUrl,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { FileState } from '../../../features/extraFile2';
|
||||
import { FileState } from '../../../features/extraFile';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity';
|
||||
import { ReactComponentProps } from 'oak-frontend-base/lib/types/Page';
|
||||
type ExtraFile = EntityDict['extraFile']['OpSchema'];
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ export default OakComponent({
|
|||
}
|
||||
},
|
||||
},
|
||||
features: ['extraFile2'],
|
||||
features: ['extraFile'],
|
||||
formData({ data, features }) {
|
||||
let files = data
|
||||
?.filter((ele) => !ele.$$deleteAt$$)
|
||||
|
|
@ -107,10 +107,10 @@ export default OakComponent({
|
|||
files = files?.filter((ele) => ele?.tag2 === this.props.tag2);
|
||||
}
|
||||
const files2 = files.map((ele) => {
|
||||
const url = features.extraFile2.getUrl(ele);
|
||||
const thumbUrl = features.extraFile2.getUrl(ele, 'thumbnail');
|
||||
const fileState = features.extraFile2.getFileState(ele.id);
|
||||
const fileName = features.extraFile2.getFileName(ele);
|
||||
const url = features.extraFile.getUrl(ele);
|
||||
const thumbUrl = features.extraFile.getUrl(ele, 'thumbnail');
|
||||
const fileState = features.extraFile.getFileState(ele.id);
|
||||
const fileName = features.extraFile.getFileName(ele);
|
||||
return {
|
||||
url,
|
||||
thumbUrl,
|
||||
|
|
@ -127,7 +127,7 @@ export default OakComponent({
|
|||
methods: {
|
||||
onRemove(file) {
|
||||
this.removeItem(file.id);
|
||||
this.features.extraFile2.removeLocalFiles([file.id]);
|
||||
this.features.extraFile.removeLocalFiles([file.id]);
|
||||
},
|
||||
addExtraFileInner(options, file) {
|
||||
const { type, origin = 'qiniu', // 默认qiniu
|
||||
|
|
@ -154,7 +154,7 @@ export default OakComponent({
|
|||
sort,
|
||||
uploadState: 'uploading',
|
||||
});
|
||||
this.features.extraFile2.addLocalFile(id, file);
|
||||
this.features.extraFile.addLocalFile(id, file);
|
||||
},
|
||||
addFileByWeb(file) {
|
||||
const { size, type, name } = file;
|
||||
|
|
|
|||
|
|
@ -83,13 +83,13 @@ export default OakComponent({
|
|||
userId: session?.userId,
|
||||
userMobile: session?.user?.mobile$user &&
|
||||
session?.user?.mobile$user[0]?.mobile,
|
||||
userAvatar: features.extraFile2.getUrl(session?.user?.extraFile$entity &&
|
||||
userAvatar: features.extraFile.getUrl(session?.user?.extraFile$entity &&
|
||||
session?.user?.extraFile$entity[0]),
|
||||
};
|
||||
if (type === 'image') {
|
||||
const extraFile$entity = sessionMessage?.extraFile$entity;
|
||||
Object.assign(newSessionMessage, {
|
||||
picUrl: features.extraFile2.getUrl(extraFile$entity && extraFile$entity[0]),
|
||||
picUrl: features.extraFile.getUrl(extraFile$entity && extraFile$entity[0]),
|
||||
});
|
||||
}
|
||||
return newSessionMessage;
|
||||
|
|
|
|||
|
|
@ -285,7 +285,7 @@ export default OakComponent({
|
|||
entity: 'sessionMessage',
|
||||
entityId: sessionMessageId,
|
||||
};
|
||||
await this.features.extraFile2.autoUpload(extraFile, originFileObj);
|
||||
await this.features.extraFile.autoUpload(extraFile, originFileObj);
|
||||
try {
|
||||
this.updateItem({
|
||||
createTime: Date.now(),
|
||||
|
|
@ -298,12 +298,12 @@ export default OakComponent({
|
|||
// },
|
||||
// ],
|
||||
}, sessionMessageId);
|
||||
// this.features.extraFile2.addLocalFile(
|
||||
// this.features.extraFile.addLocalFile(
|
||||
// extraFile?.id,
|
||||
// originFileObj
|
||||
// );
|
||||
await this.execute(undefined, false);
|
||||
// this.features.extraFile2.upload(extraFile?.id);
|
||||
// this.features.extraFile.upload(extraFile?.id);
|
||||
this.pageScroll('comment');
|
||||
this.createItem();
|
||||
}
|
||||
|
|
@ -368,12 +368,12 @@ export default OakComponent({
|
|||
// },
|
||||
// ],
|
||||
// } as EntityDict['sessionMessage']['CreateSingle']['data']);
|
||||
// this.features.extraFile2.addLocalFile(
|
||||
// this.features.extraFile.addLocalFile(
|
||||
// extraFile?.id,
|
||||
// originFileObj
|
||||
// );
|
||||
// await this.execute(undefined, false);
|
||||
// this.features.extraFile2.upload(extraFile?.id);
|
||||
// this.features.extraFile.upload(extraFile?.id);
|
||||
// } catch (err) {
|
||||
// throw err;
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Feature } from 'oak-frontend-base';
|
||||
import { Cache } from 'oak-frontend-base/es/features/cache';
|
||||
import { RunningTree } from 'oak-frontend-base/es/features/runningTree';
|
||||
import { Locales } from 'oak-frontend-base/es/features/locales';
|
||||
import { CommonAspectDict } from 'oak-common-aspect';
|
||||
import AspectDict from '../aspects/AspectDict';
|
||||
|
|
@ -7,16 +8,25 @@ import { EntityDict } from '../oak-app-domain';
|
|||
import { BackendRuntimeContext } from '../context/BackendRuntimeContext';
|
||||
import { FrontendRuntimeContext } from '../context/FrontendRuntimeContext';
|
||||
import { Application } from './application';
|
||||
export type FileState = 'local' | 'uploading' | 'uploaded' | 'failed';
|
||||
export declare class ExtraFile<ED extends EntityDict, Cxt extends BackendRuntimeContext<ED>, FrontCxt extends FrontendRuntimeContext<ED, Cxt, AD>, AD extends AspectDict<ED, Cxt> & CommonAspectDict<ED, Cxt>> extends Feature {
|
||||
private cache;
|
||||
private application;
|
||||
private locales;
|
||||
constructor(cache: Cache<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>, application: Application<ED, Cxt, FrontCxt, AD>, locales: Locales<ED, Cxt, FrontCxt, AD>);
|
||||
createAndUpload(extraFile: EntityDict['extraFile']['CreateSingle']['data'], file: string | File): Promise<{
|
||||
url: string;
|
||||
}>;
|
||||
upload(extraFile: EntityDict['extraFile']['CreateSingle']['data'], file: string | File): Promise<void>;
|
||||
private files;
|
||||
private runningTree;
|
||||
constructor(cache: Cache<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>, application: Application<ED, Cxt, FrontCxt, AD>, locales: Locales<ED, Cxt, FrontCxt, AD>, runningTree: RunningTree<ED, Cxt, FrontCxt, AD>);
|
||||
addLocalFile(id: string, file: File | string): void;
|
||||
removeLocalFiles(ids: string[]): void;
|
||||
upload(id: string): Promise<void>;
|
||||
uploadCommit(efPaths: string[], oakFullpath: string): Promise<void>;
|
||||
getUrl(extraFile?: EntityDict['extraFile']['OpSchema'] | EntityDict['extraFile']['Schema'] | null, style?: string): string;
|
||||
getFileState(id: string): {
|
||||
state: FileState;
|
||||
percentage?: number;
|
||||
} | undefined;
|
||||
getFileName(extraFile: EntityDict['extraFile']['OpSchema']): string;
|
||||
formatBytes(size: number): string;
|
||||
autoUpload(extraFile: EntityDict['extraFile']['OpSchema'], file: File | string): Promise<string>;
|
||||
private uploadToAspect;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,115 +3,133 @@ import { Upload } from 'oak-frontend-base/es/utils/upload';
|
|||
import { bytesToSize, getFileURL } from '../utils/extraFile';
|
||||
import { assert } from 'oak-domain/lib/utils/assert';
|
||||
import { getCos } from '../utils/cos';
|
||||
import { generateNewId } from 'oak-domain/lib/utils/uuid';
|
||||
import { unset } from 'oak-domain/lib/utils/lodash';
|
||||
import { generateNewId, generateNewIdAsync } from 'oak-domain';
|
||||
import { extraFileProjection } from '../types/Projection';
|
||||
export class ExtraFile extends Feature {
|
||||
cache;
|
||||
application;
|
||||
locales;
|
||||
constructor(cache, application, locales) {
|
||||
files;
|
||||
runningTree;
|
||||
constructor(cache, application, locales, runningTree) {
|
||||
super();
|
||||
this.cache = cache;
|
||||
this.application = application;
|
||||
this.locales = locales;
|
||||
this.files = {};
|
||||
this.runningTree = runningTree;
|
||||
}
|
||||
async createAndUpload(extraFile, file) {
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'create',
|
||||
data: extraFile,
|
||||
id: generateNewId(),
|
||||
});
|
||||
await this.upload(extraFile, file);
|
||||
const application = this.application.getApplication();
|
||||
return {
|
||||
url: this.getUrl(extraFile),
|
||||
addLocalFile(id, file) {
|
||||
assert(!this.files[id]);
|
||||
this.files[id] = {
|
||||
file,
|
||||
state: 'local',
|
||||
};
|
||||
this.publish();
|
||||
}
|
||||
async upload(extraFile, file) {
|
||||
const { id, origin } = extraFile;
|
||||
assert(origin, '未设置上传方式');
|
||||
const [extraFileData] = this.cache.get('extraFile', {
|
||||
data: {
|
||||
origin: 1,
|
||||
type: 1,
|
||||
bucket: 1,
|
||||
objectId: 1,
|
||||
tag1: 1,
|
||||
tag2: 1,
|
||||
filename: 1,
|
||||
md5: 1,
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
extra1: 1,
|
||||
extension: 1,
|
||||
size: 1,
|
||||
sort: 1,
|
||||
fileType: 1,
|
||||
isBridge: 1,
|
||||
uploadState: 1,
|
||||
uploadMeta: 1,
|
||||
},
|
||||
removeLocalFiles(ids) {
|
||||
ids.forEach((id) => unset(this.files, id));
|
||||
this.publish();
|
||||
}
|
||||
async upload(id) {
|
||||
const [extraFile] = this.cache.get('extraFile', {
|
||||
data: extraFileProjection,
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
assert(extraFile && extraFile.uploadState === 'uploading');
|
||||
const item = this.files[id];
|
||||
assert(item);
|
||||
const { file, state } = item;
|
||||
assert(['local', 'failed'].includes(state));
|
||||
item.state = 'uploading';
|
||||
item.percentage = 0;
|
||||
const up = new Upload();
|
||||
try {
|
||||
const cos = getCos(origin);
|
||||
await cos.upload(extraFileData, up.uploadFile, file, async () => undefined);
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'update',
|
||||
data: {
|
||||
uploadState: 'success',
|
||||
},
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
id: generateNewId(),
|
||||
});
|
||||
const cos = getCos(extraFile.origin);
|
||||
await cos.upload(extraFile, up.uploadFile, file, this.uploadToAspect.bind(this));
|
||||
if (!cos.autoInform()) {
|
||||
await this.cache.exec('operate', {
|
||||
entity: 'extraFile',
|
||||
operation: {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'update',
|
||||
data: {
|
||||
uploadState: 'success',
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
item.state = 'uploaded';
|
||||
item.percentage = undefined;
|
||||
this.publish();
|
||||
}
|
||||
catch (err) {
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'update',
|
||||
data: {
|
||||
uploadState: 'failed',
|
||||
},
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
id: generateNewId(),
|
||||
});
|
||||
item.state = 'failed';
|
||||
item.percentage = undefined;
|
||||
this.publish();
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
async uploadCommit(efPaths, oakFullpath) {
|
||||
assert(false, '方法已经废弃');
|
||||
assert(efPaths && efPaths.length > 0);
|
||||
let ids = [];
|
||||
if (oakFullpath) {
|
||||
ids = efPaths
|
||||
.map((path) => {
|
||||
const path2 = path ? `${oakFullpath}.${path}` : oakFullpath;
|
||||
const data = this.runningTree.getFreshValue(path2);
|
||||
assert(data, `efPath为${path}的路径上取不到extraFile数据,请设置正确的相对路径`);
|
||||
return data.map((ele) => ele.id);
|
||||
})
|
||||
.flat()
|
||||
.filter((ele) => !!ele);
|
||||
}
|
||||
assert(ids.length > 0);
|
||||
const promises = [];
|
||||
ids.forEach((id) => {
|
||||
const fileState = this.getFileState(id);
|
||||
if (fileState) {
|
||||
const { state } = fileState;
|
||||
if (['local', 'failed'].includes(state)) {
|
||||
promises.push(this.upload(id));
|
||||
}
|
||||
}
|
||||
});
|
||||
if (promises.length > 0) {
|
||||
await Promise.all(promises);
|
||||
}
|
||||
}
|
||||
getUrl(extraFile, style) {
|
||||
if (!extraFile) {
|
||||
return '';
|
||||
}
|
||||
let url;
|
||||
if (extraFile?.isBridge && extraFile?.extra1) {
|
||||
if (typeof extraFile?.extra1 === 'string') {
|
||||
url = this.locales.makeBridgeUrl(extraFile?.extra1);
|
||||
return url;
|
||||
}
|
||||
return this.locales.makeBridgeUrl(extraFile?.extra1);
|
||||
}
|
||||
if (extraFile?.extra1) {
|
||||
// 有extra1就用extra1 可能File对象 可能外部链接
|
||||
if (typeof extraFile?.extra1 === 'string') {
|
||||
return extraFile?.extra1;
|
||||
const { id } = extraFile;
|
||||
if (this.files[id]) {
|
||||
const { file } = this.files[id];
|
||||
if (typeof file === 'string') {
|
||||
return file;
|
||||
}
|
||||
if (extraFile?.extra1 instanceof File) {
|
||||
return getFileURL(extraFile?.extra1) || '';
|
||||
if (file instanceof File) {
|
||||
return getFileURL(file);
|
||||
}
|
||||
return extraFile?.extra1 || '';
|
||||
assert(false, 'the incoming file is not supported');
|
||||
}
|
||||
const { origin } = extraFile;
|
||||
const cos = getCos(origin);
|
||||
const context = this.cache.begin();
|
||||
this.cache.commit();
|
||||
url = cos.composeFileUrl(extraFile, context, style);
|
||||
return url;
|
||||
return cos.composeFileUrl(extraFile, context, style);
|
||||
}
|
||||
getFileState(id) {
|
||||
if (this.files[id]) {
|
||||
return this.files[id];
|
||||
}
|
||||
}
|
||||
getFileName(extraFile) {
|
||||
const name = extraFile.filename +
|
||||
|
|
@ -121,4 +139,53 @@ export class ExtraFile extends Feature {
|
|||
formatBytes(size) {
|
||||
return bytesToSize(size);
|
||||
}
|
||||
async autoUpload(extraFile, file) {
|
||||
const extraFileId = extraFile.id || generateNewId();
|
||||
const applicationId = extraFile.applicationId || this.application.getApplicationId();
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'create',
|
||||
data: Object.assign(extraFile, {
|
||||
id: extraFileId,
|
||||
applicationId,
|
||||
}),
|
||||
id: await generateNewIdAsync(),
|
||||
});
|
||||
const [newExtraFile] = this.cache.get('extraFile', {
|
||||
data: extraFileProjection,
|
||||
filter: {
|
||||
id: extraFileId,
|
||||
},
|
||||
});
|
||||
const up = new Upload();
|
||||
try {
|
||||
const cos = getCos(newExtraFile.origin);
|
||||
await cos.upload(newExtraFile, up.uploadFile, file, this.uploadToAspect.bind(this));
|
||||
return this.getUrl(newExtraFile);
|
||||
}
|
||||
catch (err) {
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'remove',
|
||||
data: {},
|
||||
filter: {
|
||||
id: extraFileId,
|
||||
},
|
||||
id: await generateNewIdAsync(),
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
// 私有
|
||||
async uploadToAspect(file, name, // 文件的part name
|
||||
aspectName, // 上传的aspect名
|
||||
formData, // 上传的其它part参数
|
||||
autoInform // 上传成功是否会自动通知server(若不会则需要前台显式通知)
|
||||
) {
|
||||
const formData2 = new FormData();
|
||||
for (const key of Object.keys(formData)) {
|
||||
formData2.append(key, formData[key]);
|
||||
}
|
||||
formData2.append(name || 'file', file);
|
||||
const { result } = await this.cache.exec(aspectName, formData2);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
import { Feature } from 'oak-frontend-base';
|
||||
import { Cache } from 'oak-frontend-base/es/features/cache';
|
||||
import { RunningTree } from 'oak-frontend-base/es/features/runningTree';
|
||||
import { Locales } from 'oak-frontend-base/es/features/locales';
|
||||
import { CommonAspectDict } from 'oak-common-aspect';
|
||||
import AspectDict from '../aspects/AspectDict';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
import { BackendRuntimeContext } from '../context/BackendRuntimeContext';
|
||||
import { FrontendRuntimeContext } from '../context/FrontendRuntimeContext';
|
||||
import { Application } from './application';
|
||||
export type FileState = 'local' | 'uploading' | 'uploaded' | 'failed';
|
||||
export declare class ExtraFile2<ED extends EntityDict, Cxt extends BackendRuntimeContext<ED>, FrontCxt extends FrontendRuntimeContext<ED, Cxt, AD>, AD extends AspectDict<ED, Cxt> & CommonAspectDict<ED, Cxt>> extends Feature {
|
||||
private cache;
|
||||
private application;
|
||||
private locales;
|
||||
private files;
|
||||
private runningTree;
|
||||
constructor(cache: Cache<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>, application: Application<ED, Cxt, FrontCxt, AD>, locales: Locales<ED, Cxt, FrontCxt, AD>, runningTree: RunningTree<ED, Cxt, FrontCxt, AD>);
|
||||
addLocalFile(id: string, file: File | string): void;
|
||||
removeLocalFiles(ids: string[]): void;
|
||||
upload(id: string): Promise<void>;
|
||||
uploadCommit(efPaths: string[], oakFullpath: string): Promise<void>;
|
||||
getUrl(extraFile?: EntityDict['extraFile']['OpSchema'] | EntityDict['extraFile']['Schema'] | null, style?: string): string;
|
||||
getFileState(id: string): {
|
||||
state: FileState;
|
||||
percentage?: number;
|
||||
} | undefined;
|
||||
getFileName(extraFile: EntityDict['extraFile']['OpSchema']): string;
|
||||
formatBytes(size: number): string;
|
||||
autoUpload(extraFile: EntityDict['extraFile']['OpSchema'], file: File | string): Promise<string>;
|
||||
private uploadToAspect;
|
||||
}
|
||||
|
|
@ -1,193 +0,0 @@
|
|||
import { Feature } from 'oak-frontend-base';
|
||||
import { Upload } from 'oak-frontend-base/es/utils/upload';
|
||||
import { bytesToSize, getFileURL } from '../utils/extraFile';
|
||||
import { assert } from 'oak-domain/lib/utils/assert';
|
||||
import { getCos } from '../utils/cos';
|
||||
import { unset } from 'oak-domain/lib/utils/lodash';
|
||||
import { generateNewId, generateNewIdAsync } from 'oak-domain';
|
||||
import { extraFileProjection } from '../types/Projection';
|
||||
export class ExtraFile2 extends Feature {
|
||||
cache;
|
||||
application;
|
||||
locales;
|
||||
files;
|
||||
runningTree;
|
||||
constructor(cache, application, locales, runningTree) {
|
||||
super();
|
||||
this.cache = cache;
|
||||
this.application = application;
|
||||
this.locales = locales;
|
||||
this.files = {};
|
||||
this.runningTree = runningTree;
|
||||
}
|
||||
addLocalFile(id, file) {
|
||||
assert(!this.files[id]);
|
||||
this.files[id] = {
|
||||
file,
|
||||
state: 'local',
|
||||
};
|
||||
this.publish();
|
||||
}
|
||||
removeLocalFiles(ids) {
|
||||
ids.forEach((id) => unset(this.files, id));
|
||||
this.publish();
|
||||
}
|
||||
async upload(id) {
|
||||
const [extraFile] = this.cache.get('extraFile', {
|
||||
data: extraFileProjection,
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
assert(extraFile && extraFile.uploadState === 'uploading');
|
||||
const item = this.files[id];
|
||||
assert(item);
|
||||
const { file, state } = item;
|
||||
assert(['local', 'failed'].includes(state));
|
||||
item.state = 'uploading';
|
||||
item.percentage = 0;
|
||||
const up = new Upload();
|
||||
try {
|
||||
const cos = getCos(extraFile.origin);
|
||||
await cos.upload(extraFile, up.uploadFile, file, this.uploadToAspect.bind(this));
|
||||
if (!cos.autoInform()) {
|
||||
await this.cache.exec('operate', {
|
||||
entity: 'extraFile',
|
||||
operation: {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'update',
|
||||
data: {
|
||||
uploadState: 'success',
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
item.state = 'uploaded';
|
||||
item.percentage = undefined;
|
||||
this.publish();
|
||||
}
|
||||
catch (err) {
|
||||
item.state = 'failed';
|
||||
item.percentage = undefined;
|
||||
this.publish();
|
||||
}
|
||||
}
|
||||
async uploadCommit(efPaths, oakFullpath) {
|
||||
assert(false, '方法已经废弃');
|
||||
assert(efPaths && efPaths.length > 0);
|
||||
let ids = [];
|
||||
if (oakFullpath) {
|
||||
ids = efPaths
|
||||
.map((path) => {
|
||||
const path2 = path
|
||||
? `${oakFullpath}.${path}`
|
||||
: oakFullpath;
|
||||
const data = this.runningTree.getFreshValue(path2);
|
||||
assert(data, `efPath为${path}的路径上取不到extraFile数据,请设置正确的相对路径`);
|
||||
return data.map((ele) => ele.id);
|
||||
})
|
||||
.flat()
|
||||
.filter((ele) => !!ele);
|
||||
}
|
||||
assert(ids.length > 0);
|
||||
const promises = [];
|
||||
ids.forEach((id) => {
|
||||
const fileState = this.getFileState(id);
|
||||
if (fileState) {
|
||||
const { state } = fileState;
|
||||
if (['local', 'failed'].includes(state)) {
|
||||
promises.push(this.upload(id));
|
||||
}
|
||||
}
|
||||
});
|
||||
if (promises.length > 0) {
|
||||
await Promise.all(promises);
|
||||
}
|
||||
}
|
||||
getUrl(extraFile, style) {
|
||||
if (!extraFile) {
|
||||
return '';
|
||||
}
|
||||
if (extraFile?.isBridge && extraFile?.extra1) {
|
||||
return this.locales.makeBridgeUrl(extraFile?.extra1);
|
||||
}
|
||||
const { id } = extraFile;
|
||||
if (this.files[id]) {
|
||||
const { file } = this.files[id];
|
||||
if (typeof file === 'string') {
|
||||
return file;
|
||||
}
|
||||
if (file instanceof File) {
|
||||
return getFileURL(file);
|
||||
}
|
||||
assert(false, 'the incoming file is not supported');
|
||||
}
|
||||
const { origin } = extraFile;
|
||||
const cos = getCos(origin);
|
||||
const context = this.cache.begin();
|
||||
this.cache.commit();
|
||||
return cos.composeFileUrl(extraFile, context, style);
|
||||
}
|
||||
getFileState(id) {
|
||||
if (this.files[id]) {
|
||||
return this.files[id];
|
||||
}
|
||||
}
|
||||
getFileName(extraFile) {
|
||||
const name = extraFile.filename +
|
||||
(extraFile.extension ? `.${extraFile.extension}` : '');
|
||||
return name;
|
||||
}
|
||||
formatBytes(size) {
|
||||
return bytesToSize(size);
|
||||
}
|
||||
async autoUpload(extraFile, file) {
|
||||
const extraFileId = extraFile.id || generateNewId();
|
||||
const applicationId = extraFile.applicationId || this.application.getApplicationId();
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'create',
|
||||
data: Object.assign(extraFile, {
|
||||
id: extraFileId,
|
||||
applicationId,
|
||||
}),
|
||||
id: await generateNewIdAsync(),
|
||||
});
|
||||
const [newExtraFile] = this.cache.get('extraFile', {
|
||||
data: extraFileProjection,
|
||||
filter: {
|
||||
id: extraFileId,
|
||||
},
|
||||
});
|
||||
const up = new Upload();
|
||||
try {
|
||||
const cos = getCos(newExtraFile.origin);
|
||||
await cos.upload(newExtraFile, up.uploadFile, file, this.uploadToAspect.bind(this));
|
||||
return this.getUrl(newExtraFile);
|
||||
}
|
||||
catch (err) {
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'remove',
|
||||
data: {},
|
||||
filter: {
|
||||
id: extraFileId,
|
||||
},
|
||||
id: await generateNewIdAsync(),
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
// 私有
|
||||
async uploadToAspect(file, name, // 文件的part name
|
||||
aspectName, // 上传的aspect名
|
||||
formData, // 上传的其它part参数
|
||||
autoInform // 上传成功是否会自动通知server(若不会则需要前台显式通知)
|
||||
) {
|
||||
const formData2 = new FormData();
|
||||
for (const key of Object.keys(formData)) {
|
||||
formData2.append(key, formData[key]);
|
||||
}
|
||||
formData2.append(name || 'file', file);
|
||||
const { result } = await this.cache.exec(aspectName, formData2);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
import { CommonAspectDict } from 'oak-common-aspect';
|
||||
import { Token } from './token';
|
||||
import { ExtraFile } from './extraFile';
|
||||
import { ExtraFile2 } from './extraFile2';
|
||||
import { Application } from './application';
|
||||
import { Config } from './config';
|
||||
import { Template } from './template';
|
||||
|
|
@ -20,7 +19,6 @@ export declare function initialize<ED extends EntityDict, Cxt extends BackendRun
|
|||
export type GeneralFeatures<ED extends EntityDict, Cxt extends BackendRuntimeContext<ED>, FrontCxt extends FrontendRuntimeContext<ED, Cxt, AD>, AD extends AspectDict<ED, Cxt> & CommonAspectDict<ED, Cxt>> = {
|
||||
token: Token<ED, Cxt, FrontCxt, AD>;
|
||||
extraFile: ExtraFile<ED, Cxt, FrontCxt, AD>;
|
||||
extraFile2: ExtraFile2<ED, Cxt, FrontCxt, AD>;
|
||||
application: Application<ED, Cxt, FrontCxt, AD>;
|
||||
config: Config<ED, Cxt, FrontCxt, AD>;
|
||||
template: Template<ED, Cxt, FrontCxt, AD>;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { Token } from './token';
|
||||
import { ExtraFile } from './extraFile';
|
||||
import { ExtraFile2 } from './extraFile2';
|
||||
import { Application } from './application';
|
||||
import { Config } from './config';
|
||||
import { Template } from './template';
|
||||
|
|
@ -15,9 +14,7 @@ export function initialize(basicFeatures, type, domain) {
|
|||
const wechatMenu = new WechatMenu(basicFeatures.cache, basicFeatures.localStorage);
|
||||
const wechatPublicTag = new WechatPublicTag(basicFeatures.cache, basicFeatures.localStorage);
|
||||
const userWechatPublicTag = new UserWechatPublicTag(basicFeatures.cache, basicFeatures.localStorage);
|
||||
// 临时代码,合并后再删
|
||||
const extraFile = new ExtraFile(basicFeatures.cache, application, basicFeatures.locales);
|
||||
const extraFile2 = new ExtraFile2(basicFeatures.cache, application, basicFeatures.locales, basicFeatures.runningTree);
|
||||
const extraFile = new ExtraFile(basicFeatures.cache, application, basicFeatures.locales, basicFeatures.runningTree);
|
||||
const config = new Config(basicFeatures.cache);
|
||||
const template = new Template(basicFeatures.cache);
|
||||
const weiXinJsSdk = new WeiXinJsSdk(basicFeatures.cache, basicFeatures.localStorage, basicFeatures.environment);
|
||||
|
|
@ -25,7 +22,6 @@ export function initialize(basicFeatures, type, domain) {
|
|||
return {
|
||||
token,
|
||||
extraFile,
|
||||
extraFile2,
|
||||
application,
|
||||
config,
|
||||
template,
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ export default OakComponent({
|
|||
}
|
||||
},
|
||||
uploadFile(extraFile) {
|
||||
return this.features.extraFile.createAndUpload(extraFile, extraFile.extra1);
|
||||
return this.features.extraFile.autoUpload(extraFile, extraFile.extra1);
|
||||
},
|
||||
setEditor(editor) {
|
||||
this.setState({
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Feature } from 'oak-frontend-base';
|
||||
import { Cache } from 'oak-frontend-base/es/features/cache';
|
||||
import { RunningTree } from 'oak-frontend-base/es/features/runningTree';
|
||||
import { Locales } from 'oak-frontend-base/es/features/locales';
|
||||
import { CommonAspectDict } from 'oak-common-aspect';
|
||||
import AspectDict from '../aspects/AspectDict';
|
||||
|
|
@ -7,16 +8,25 @@ import { EntityDict } from '../oak-app-domain';
|
|||
import { BackendRuntimeContext } from '../context/BackendRuntimeContext';
|
||||
import { FrontendRuntimeContext } from '../context/FrontendRuntimeContext';
|
||||
import { Application } from './application';
|
||||
export type FileState = 'local' | 'uploading' | 'uploaded' | 'failed';
|
||||
export declare class ExtraFile<ED extends EntityDict, Cxt extends BackendRuntimeContext<ED>, FrontCxt extends FrontendRuntimeContext<ED, Cxt, AD>, AD extends AspectDict<ED, Cxt> & CommonAspectDict<ED, Cxt>> extends Feature {
|
||||
private cache;
|
||||
private application;
|
||||
private locales;
|
||||
constructor(cache: Cache<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>, application: Application<ED, Cxt, FrontCxt, AD>, locales: Locales<ED, Cxt, FrontCxt, AD>);
|
||||
createAndUpload(extraFile: EntityDict['extraFile']['CreateSingle']['data'], file: string | File): Promise<{
|
||||
url: string;
|
||||
}>;
|
||||
upload(extraFile: EntityDict['extraFile']['CreateSingle']['data'], file: string | File): Promise<void>;
|
||||
private files;
|
||||
private runningTree;
|
||||
constructor(cache: Cache<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>, application: Application<ED, Cxt, FrontCxt, AD>, locales: Locales<ED, Cxt, FrontCxt, AD>, runningTree: RunningTree<ED, Cxt, FrontCxt, AD>);
|
||||
addLocalFile(id: string, file: File | string): void;
|
||||
removeLocalFiles(ids: string[]): void;
|
||||
upload(id: string): Promise<void>;
|
||||
uploadCommit(efPaths: string[], oakFullpath: string): Promise<void>;
|
||||
getUrl(extraFile?: EntityDict['extraFile']['OpSchema'] | EntityDict['extraFile']['Schema'] | null, style?: string): string;
|
||||
getFileState(id: string): {
|
||||
state: FileState;
|
||||
percentage?: number;
|
||||
} | undefined;
|
||||
getFileName(extraFile: EntityDict['extraFile']['OpSchema']): string;
|
||||
formatBytes(size: number): string;
|
||||
autoUpload(extraFile: EntityDict['extraFile']['OpSchema'], file: File | string): Promise<string>;
|
||||
private uploadToAspect;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,115 +6,133 @@ const upload_1 = require("oak-frontend-base/es/utils/upload");
|
|||
const extraFile_1 = require("../utils/extraFile");
|
||||
const assert_1 = require("oak-domain/lib/utils/assert");
|
||||
const cos_1 = require("../utils/cos");
|
||||
const uuid_1 = require("oak-domain/lib/utils/uuid");
|
||||
const lodash_1 = require("oak-domain/lib/utils/lodash");
|
||||
const oak_domain_1 = require("oak-domain");
|
||||
const Projection_1 = require("../types/Projection");
|
||||
class ExtraFile extends oak_frontend_base_1.Feature {
|
||||
cache;
|
||||
application;
|
||||
locales;
|
||||
constructor(cache, application, locales) {
|
||||
files;
|
||||
runningTree;
|
||||
constructor(cache, application, locales, runningTree) {
|
||||
super();
|
||||
this.cache = cache;
|
||||
this.application = application;
|
||||
this.locales = locales;
|
||||
this.files = {};
|
||||
this.runningTree = runningTree;
|
||||
}
|
||||
async createAndUpload(extraFile, file) {
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'create',
|
||||
data: extraFile,
|
||||
id: (0, uuid_1.generateNewId)(),
|
||||
});
|
||||
await this.upload(extraFile, file);
|
||||
const application = this.application.getApplication();
|
||||
return {
|
||||
url: this.getUrl(extraFile),
|
||||
addLocalFile(id, file) {
|
||||
(0, assert_1.assert)(!this.files[id]);
|
||||
this.files[id] = {
|
||||
file,
|
||||
state: 'local',
|
||||
};
|
||||
this.publish();
|
||||
}
|
||||
async upload(extraFile, file) {
|
||||
const { id, origin } = extraFile;
|
||||
(0, assert_1.assert)(origin, '未设置上传方式');
|
||||
const [extraFileData] = this.cache.get('extraFile', {
|
||||
data: {
|
||||
origin: 1,
|
||||
type: 1,
|
||||
bucket: 1,
|
||||
objectId: 1,
|
||||
tag1: 1,
|
||||
tag2: 1,
|
||||
filename: 1,
|
||||
md5: 1,
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
extra1: 1,
|
||||
extension: 1,
|
||||
size: 1,
|
||||
sort: 1,
|
||||
fileType: 1,
|
||||
isBridge: 1,
|
||||
uploadState: 1,
|
||||
uploadMeta: 1,
|
||||
},
|
||||
removeLocalFiles(ids) {
|
||||
ids.forEach((id) => (0, lodash_1.unset)(this.files, id));
|
||||
this.publish();
|
||||
}
|
||||
async upload(id) {
|
||||
const [extraFile] = this.cache.get('extraFile', {
|
||||
data: Projection_1.extraFileProjection,
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
(0, assert_1.assert)(extraFile && extraFile.uploadState === 'uploading');
|
||||
const item = this.files[id];
|
||||
(0, assert_1.assert)(item);
|
||||
const { file, state } = item;
|
||||
(0, assert_1.assert)(['local', 'failed'].includes(state));
|
||||
item.state = 'uploading';
|
||||
item.percentage = 0;
|
||||
const up = new upload_1.Upload();
|
||||
try {
|
||||
const cos = (0, cos_1.getCos)(origin);
|
||||
await cos.upload(extraFileData, up.uploadFile, file, async () => undefined);
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'update',
|
||||
data: {
|
||||
uploadState: 'success',
|
||||
},
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
id: (0, uuid_1.generateNewId)(),
|
||||
});
|
||||
const cos = (0, cos_1.getCos)(extraFile.origin);
|
||||
await cos.upload(extraFile, up.uploadFile, file, this.uploadToAspect.bind(this));
|
||||
if (!cos.autoInform()) {
|
||||
await this.cache.exec('operate', {
|
||||
entity: 'extraFile',
|
||||
operation: {
|
||||
id: await (0, oak_domain_1.generateNewIdAsync)(),
|
||||
action: 'update',
|
||||
data: {
|
||||
uploadState: 'success',
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
item.state = 'uploaded';
|
||||
item.percentage = undefined;
|
||||
this.publish();
|
||||
}
|
||||
catch (err) {
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'update',
|
||||
data: {
|
||||
uploadState: 'failed',
|
||||
},
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
id: (0, uuid_1.generateNewId)(),
|
||||
});
|
||||
item.state = 'failed';
|
||||
item.percentage = undefined;
|
||||
this.publish();
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
async uploadCommit(efPaths, oakFullpath) {
|
||||
(0, assert_1.assert)(false, '方法已经废弃');
|
||||
(0, assert_1.assert)(efPaths && efPaths.length > 0);
|
||||
let ids = [];
|
||||
if (oakFullpath) {
|
||||
ids = efPaths
|
||||
.map((path) => {
|
||||
const path2 = path ? `${oakFullpath}.${path}` : oakFullpath;
|
||||
const data = this.runningTree.getFreshValue(path2);
|
||||
(0, assert_1.assert)(data, `efPath为${path}的路径上取不到extraFile数据,请设置正确的相对路径`);
|
||||
return data.map((ele) => ele.id);
|
||||
})
|
||||
.flat()
|
||||
.filter((ele) => !!ele);
|
||||
}
|
||||
(0, assert_1.assert)(ids.length > 0);
|
||||
const promises = [];
|
||||
ids.forEach((id) => {
|
||||
const fileState = this.getFileState(id);
|
||||
if (fileState) {
|
||||
const { state } = fileState;
|
||||
if (['local', 'failed'].includes(state)) {
|
||||
promises.push(this.upload(id));
|
||||
}
|
||||
}
|
||||
});
|
||||
if (promises.length > 0) {
|
||||
await Promise.all(promises);
|
||||
}
|
||||
}
|
||||
getUrl(extraFile, style) {
|
||||
if (!extraFile) {
|
||||
return '';
|
||||
}
|
||||
let url;
|
||||
if (extraFile?.isBridge && extraFile?.extra1) {
|
||||
if (typeof extraFile?.extra1 === 'string') {
|
||||
url = this.locales.makeBridgeUrl(extraFile?.extra1);
|
||||
return url;
|
||||
}
|
||||
return this.locales.makeBridgeUrl(extraFile?.extra1);
|
||||
}
|
||||
if (extraFile?.extra1) {
|
||||
// 有extra1就用extra1 可能File对象 可能外部链接
|
||||
if (typeof extraFile?.extra1 === 'string') {
|
||||
return extraFile?.extra1;
|
||||
const { id } = extraFile;
|
||||
if (this.files[id]) {
|
||||
const { file } = this.files[id];
|
||||
if (typeof file === 'string') {
|
||||
return file;
|
||||
}
|
||||
if (extraFile?.extra1 instanceof File) {
|
||||
return (0, extraFile_1.getFileURL)(extraFile?.extra1) || '';
|
||||
if (file instanceof File) {
|
||||
return (0, extraFile_1.getFileURL)(file);
|
||||
}
|
||||
return extraFile?.extra1 || '';
|
||||
(0, assert_1.assert)(false, 'the incoming file is not supported');
|
||||
}
|
||||
const { origin } = extraFile;
|
||||
const cos = (0, cos_1.getCos)(origin);
|
||||
const context = this.cache.begin();
|
||||
this.cache.commit();
|
||||
url = cos.composeFileUrl(extraFile, context, style);
|
||||
return url;
|
||||
return cos.composeFileUrl(extraFile, context, style);
|
||||
}
|
||||
getFileState(id) {
|
||||
if (this.files[id]) {
|
||||
return this.files[id];
|
||||
}
|
||||
}
|
||||
getFileName(extraFile) {
|
||||
const name = extraFile.filename +
|
||||
|
|
@ -124,5 +142,54 @@ class ExtraFile extends oak_frontend_base_1.Feature {
|
|||
formatBytes(size) {
|
||||
return (0, extraFile_1.bytesToSize)(size);
|
||||
}
|
||||
async autoUpload(extraFile, file) {
|
||||
const extraFileId = extraFile.id || (0, oak_domain_1.generateNewId)();
|
||||
const applicationId = extraFile.applicationId || this.application.getApplicationId();
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'create',
|
||||
data: Object.assign(extraFile, {
|
||||
id: extraFileId,
|
||||
applicationId,
|
||||
}),
|
||||
id: await (0, oak_domain_1.generateNewIdAsync)(),
|
||||
});
|
||||
const [newExtraFile] = this.cache.get('extraFile', {
|
||||
data: Projection_1.extraFileProjection,
|
||||
filter: {
|
||||
id: extraFileId,
|
||||
},
|
||||
});
|
||||
const up = new upload_1.Upload();
|
||||
try {
|
||||
const cos = (0, cos_1.getCos)(newExtraFile.origin);
|
||||
await cos.upload(newExtraFile, up.uploadFile, file, this.uploadToAspect.bind(this));
|
||||
return this.getUrl(newExtraFile);
|
||||
}
|
||||
catch (err) {
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'remove',
|
||||
data: {},
|
||||
filter: {
|
||||
id: extraFileId,
|
||||
},
|
||||
id: await (0, oak_domain_1.generateNewIdAsync)(),
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
// 私有
|
||||
async uploadToAspect(file, name, // 文件的part name
|
||||
aspectName, // 上传的aspect名
|
||||
formData, // 上传的其它part参数
|
||||
autoInform // 上传成功是否会自动通知server(若不会则需要前台显式通知)
|
||||
) {
|
||||
const formData2 = new FormData();
|
||||
for (const key of Object.keys(formData)) {
|
||||
formData2.append(key, formData[key]);
|
||||
}
|
||||
formData2.append(name || 'file', file);
|
||||
const { result } = await this.cache.exec(aspectName, formData2);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
exports.ExtraFile = ExtraFile;
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
import { Feature } from 'oak-frontend-base';
|
||||
import { Cache } from 'oak-frontend-base/es/features/cache';
|
||||
import { RunningTree } from 'oak-frontend-base/es/features/runningTree';
|
||||
import { Locales } from 'oak-frontend-base/es/features/locales';
|
||||
import { CommonAspectDict } from 'oak-common-aspect';
|
||||
import AspectDict from '../aspects/AspectDict';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
import { BackendRuntimeContext } from '../context/BackendRuntimeContext';
|
||||
import { FrontendRuntimeContext } from '../context/FrontendRuntimeContext';
|
||||
import { Application } from './application';
|
||||
export type FileState = 'local' | 'uploading' | 'uploaded' | 'failed';
|
||||
export declare class ExtraFile2<ED extends EntityDict, Cxt extends BackendRuntimeContext<ED>, FrontCxt extends FrontendRuntimeContext<ED, Cxt, AD>, AD extends AspectDict<ED, Cxt> & CommonAspectDict<ED, Cxt>> extends Feature {
|
||||
private cache;
|
||||
private application;
|
||||
private locales;
|
||||
private files;
|
||||
private runningTree;
|
||||
constructor(cache: Cache<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>, application: Application<ED, Cxt, FrontCxt, AD>, locales: Locales<ED, Cxt, FrontCxt, AD>, runningTree: RunningTree<ED, Cxt, FrontCxt, AD>);
|
||||
addLocalFile(id: string, file: File | string): void;
|
||||
removeLocalFiles(ids: string[]): void;
|
||||
upload(id: string): Promise<void>;
|
||||
uploadCommit(efPaths: string[], oakFullpath: string): Promise<void>;
|
||||
getUrl(extraFile?: EntityDict['extraFile']['OpSchema'] | EntityDict['extraFile']['Schema'] | null, style?: string): string;
|
||||
getFileState(id: string): {
|
||||
state: FileState;
|
||||
percentage?: number;
|
||||
} | undefined;
|
||||
getFileName(extraFile: EntityDict['extraFile']['OpSchema']): string;
|
||||
formatBytes(size: number): string;
|
||||
autoUpload(extraFile: EntityDict['extraFile']['OpSchema'], file: File | string): Promise<string>;
|
||||
private uploadToAspect;
|
||||
}
|
||||
|
|
@ -1,197 +0,0 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ExtraFile2 = void 0;
|
||||
const oak_frontend_base_1 = require("oak-frontend-base");
|
||||
const upload_1 = require("oak-frontend-base/es/utils/upload");
|
||||
const extraFile_1 = require("../utils/extraFile");
|
||||
const assert_1 = require("oak-domain/lib/utils/assert");
|
||||
const cos_1 = require("../utils/cos");
|
||||
const lodash_1 = require("oak-domain/lib/utils/lodash");
|
||||
const oak_domain_1 = require("oak-domain");
|
||||
const Projection_1 = require("../types/Projection");
|
||||
class ExtraFile2 extends oak_frontend_base_1.Feature {
|
||||
cache;
|
||||
application;
|
||||
locales;
|
||||
files;
|
||||
runningTree;
|
||||
constructor(cache, application, locales, runningTree) {
|
||||
super();
|
||||
this.cache = cache;
|
||||
this.application = application;
|
||||
this.locales = locales;
|
||||
this.files = {};
|
||||
this.runningTree = runningTree;
|
||||
}
|
||||
addLocalFile(id, file) {
|
||||
(0, assert_1.assert)(!this.files[id]);
|
||||
this.files[id] = {
|
||||
file,
|
||||
state: 'local',
|
||||
};
|
||||
this.publish();
|
||||
}
|
||||
removeLocalFiles(ids) {
|
||||
ids.forEach((id) => (0, lodash_1.unset)(this.files, id));
|
||||
this.publish();
|
||||
}
|
||||
async upload(id) {
|
||||
const [extraFile] = this.cache.get('extraFile', {
|
||||
data: Projection_1.extraFileProjection,
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
(0, assert_1.assert)(extraFile && extraFile.uploadState === 'uploading');
|
||||
const item = this.files[id];
|
||||
(0, assert_1.assert)(item);
|
||||
const { file, state } = item;
|
||||
(0, assert_1.assert)(['local', 'failed'].includes(state));
|
||||
item.state = 'uploading';
|
||||
item.percentage = 0;
|
||||
const up = new upload_1.Upload();
|
||||
try {
|
||||
const cos = (0, cos_1.getCos)(extraFile.origin);
|
||||
await cos.upload(extraFile, up.uploadFile, file, this.uploadToAspect.bind(this));
|
||||
if (!cos.autoInform()) {
|
||||
await this.cache.exec('operate', {
|
||||
entity: 'extraFile',
|
||||
operation: {
|
||||
id: await (0, oak_domain_1.generateNewIdAsync)(),
|
||||
action: 'update',
|
||||
data: {
|
||||
uploadState: 'success',
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
item.state = 'uploaded';
|
||||
item.percentage = undefined;
|
||||
this.publish();
|
||||
}
|
||||
catch (err) {
|
||||
item.state = 'failed';
|
||||
item.percentage = undefined;
|
||||
this.publish();
|
||||
}
|
||||
}
|
||||
async uploadCommit(efPaths, oakFullpath) {
|
||||
(0, assert_1.assert)(false, '方法已经废弃');
|
||||
(0, assert_1.assert)(efPaths && efPaths.length > 0);
|
||||
let ids = [];
|
||||
if (oakFullpath) {
|
||||
ids = efPaths
|
||||
.map((path) => {
|
||||
const path2 = path
|
||||
? `${oakFullpath}.${path}`
|
||||
: oakFullpath;
|
||||
const data = this.runningTree.getFreshValue(path2);
|
||||
(0, assert_1.assert)(data, `efPath为${path}的路径上取不到extraFile数据,请设置正确的相对路径`);
|
||||
return data.map((ele) => ele.id);
|
||||
})
|
||||
.flat()
|
||||
.filter((ele) => !!ele);
|
||||
}
|
||||
(0, assert_1.assert)(ids.length > 0);
|
||||
const promises = [];
|
||||
ids.forEach((id) => {
|
||||
const fileState = this.getFileState(id);
|
||||
if (fileState) {
|
||||
const { state } = fileState;
|
||||
if (['local', 'failed'].includes(state)) {
|
||||
promises.push(this.upload(id));
|
||||
}
|
||||
}
|
||||
});
|
||||
if (promises.length > 0) {
|
||||
await Promise.all(promises);
|
||||
}
|
||||
}
|
||||
getUrl(extraFile, style) {
|
||||
if (!extraFile) {
|
||||
return '';
|
||||
}
|
||||
if (extraFile?.isBridge && extraFile?.extra1) {
|
||||
return this.locales.makeBridgeUrl(extraFile?.extra1);
|
||||
}
|
||||
const { id } = extraFile;
|
||||
if (this.files[id]) {
|
||||
const { file } = this.files[id];
|
||||
if (typeof file === 'string') {
|
||||
return file;
|
||||
}
|
||||
if (file instanceof File) {
|
||||
return (0, extraFile_1.getFileURL)(file);
|
||||
}
|
||||
(0, assert_1.assert)(false, 'the incoming file is not supported');
|
||||
}
|
||||
const { origin } = extraFile;
|
||||
const cos = (0, cos_1.getCos)(origin);
|
||||
const context = this.cache.begin();
|
||||
this.cache.commit();
|
||||
return cos.composeFileUrl(extraFile, context, style);
|
||||
}
|
||||
getFileState(id) {
|
||||
if (this.files[id]) {
|
||||
return this.files[id];
|
||||
}
|
||||
}
|
||||
getFileName(extraFile) {
|
||||
const name = extraFile.filename +
|
||||
(extraFile.extension ? `.${extraFile.extension}` : '');
|
||||
return name;
|
||||
}
|
||||
formatBytes(size) {
|
||||
return (0, extraFile_1.bytesToSize)(size);
|
||||
}
|
||||
async autoUpload(extraFile, file) {
|
||||
const extraFileId = extraFile.id || (0, oak_domain_1.generateNewId)();
|
||||
const applicationId = extraFile.applicationId || this.application.getApplicationId();
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'create',
|
||||
data: Object.assign(extraFile, {
|
||||
id: extraFileId,
|
||||
applicationId,
|
||||
}),
|
||||
id: await (0, oak_domain_1.generateNewIdAsync)(),
|
||||
});
|
||||
const [newExtraFile] = this.cache.get('extraFile', {
|
||||
data: Projection_1.extraFileProjection,
|
||||
filter: {
|
||||
id: extraFileId,
|
||||
},
|
||||
});
|
||||
const up = new upload_1.Upload();
|
||||
try {
|
||||
const cos = (0, cos_1.getCos)(newExtraFile.origin);
|
||||
await cos.upload(newExtraFile, up.uploadFile, file, this.uploadToAspect.bind(this));
|
||||
return this.getUrl(newExtraFile);
|
||||
}
|
||||
catch (err) {
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'remove',
|
||||
data: {},
|
||||
filter: {
|
||||
id: extraFileId,
|
||||
},
|
||||
id: await (0, oak_domain_1.generateNewIdAsync)(),
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
// 私有
|
||||
async uploadToAspect(file, name, // 文件的part name
|
||||
aspectName, // 上传的aspect名
|
||||
formData, // 上传的其它part参数
|
||||
autoInform // 上传成功是否会自动通知server(若不会则需要前台显式通知)
|
||||
) {
|
||||
const formData2 = new FormData();
|
||||
for (const key of Object.keys(formData)) {
|
||||
formData2.append(key, formData[key]);
|
||||
}
|
||||
formData2.append(name || 'file', file);
|
||||
const { result } = await this.cache.exec(aspectName, formData2);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
exports.ExtraFile2 = ExtraFile2;
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
import { CommonAspectDict } from 'oak-common-aspect';
|
||||
import { Token } from './token';
|
||||
import { ExtraFile } from './extraFile';
|
||||
import { ExtraFile2 } from './extraFile2';
|
||||
import { Application } from './application';
|
||||
import { Config } from './config';
|
||||
import { Template } from './template';
|
||||
|
|
@ -20,7 +19,6 @@ export declare function initialize<ED extends EntityDict, Cxt extends BackendRun
|
|||
export type GeneralFeatures<ED extends EntityDict, Cxt extends BackendRuntimeContext<ED>, FrontCxt extends FrontendRuntimeContext<ED, Cxt, AD>, AD extends AspectDict<ED, Cxt> & CommonAspectDict<ED, Cxt>> = {
|
||||
token: Token<ED, Cxt, FrontCxt, AD>;
|
||||
extraFile: ExtraFile<ED, Cxt, FrontCxt, AD>;
|
||||
extraFile2: ExtraFile2<ED, Cxt, FrontCxt, AD>;
|
||||
application: Application<ED, Cxt, FrontCxt, AD>;
|
||||
config: Config<ED, Cxt, FrontCxt, AD>;
|
||||
template: Template<ED, Cxt, FrontCxt, AD>;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ exports.initialize = void 0;
|
|||
const tslib_1 = require("tslib");
|
||||
const token_1 = require("./token");
|
||||
const extraFile_1 = require("./extraFile");
|
||||
const extraFile2_1 = require("./extraFile2");
|
||||
const application_1 = require("./application");
|
||||
const config_1 = require("./config");
|
||||
const template_1 = require("./template");
|
||||
|
|
@ -19,9 +18,7 @@ function initialize(basicFeatures, type, domain) {
|
|||
const wechatMenu = new wechatMenu_1.WechatMenu(basicFeatures.cache, basicFeatures.localStorage);
|
||||
const wechatPublicTag = new wechatPublicTag_1.WechatPublicTag(basicFeatures.cache, basicFeatures.localStorage);
|
||||
const userWechatPublicTag = new userWechatPublicTag_1.UserWechatPublicTag(basicFeatures.cache, basicFeatures.localStorage);
|
||||
// 临时代码,合并后再删
|
||||
const extraFile = new extraFile_1.ExtraFile(basicFeatures.cache, application, basicFeatures.locales);
|
||||
const extraFile2 = new extraFile2_1.ExtraFile2(basicFeatures.cache, application, basicFeatures.locales, basicFeatures.runningTree);
|
||||
const extraFile = new extraFile_1.ExtraFile(basicFeatures.cache, application, basicFeatures.locales, basicFeatures.runningTree);
|
||||
const config = new config_1.Config(basicFeatures.cache);
|
||||
const template = new template_1.Template(basicFeatures.cache);
|
||||
const weiXinJsSdk = new weiXinJsSdk_1.WeiXinJsSdk(basicFeatures.cache, basicFeatures.localStorage, basicFeatures.environment);
|
||||
|
|
@ -29,7 +26,6 @@ function initialize(basicFeatures, type, domain) {
|
|||
return {
|
||||
token,
|
||||
extraFile,
|
||||
extraFile2,
|
||||
application,
|
||||
config,
|
||||
template,
|
||||
|
|
|
|||
|
|
@ -76,21 +76,14 @@ export default OakComponent({
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
// async addExtraFile(
|
||||
// extraFile: EntityDict['extraFile']['CreateSingle']['data']
|
||||
// ) {
|
||||
// const result = await this.features.cache.operate('extraFile', {
|
||||
// action: 'create',
|
||||
// data: extraFile,
|
||||
// id: generateNewId(),
|
||||
// });
|
||||
// return result;
|
||||
// },
|
||||
|
||||
async uploadFile(
|
||||
extraFile: EntityDict['extraFile']['CreateSingle']['data']
|
||||
extraFile: EntityDict['extraFile']['CreateSingle']['data'],
|
||||
file: File | string
|
||||
) {
|
||||
const result = await this.features.extraFile.createAndUpload(extraFile, extraFile.extra1!);
|
||||
const result = await this.features.extraFile.autoUpload(
|
||||
extraFile as EntityDict['extraFile']['OpSchema'],
|
||||
file!
|
||||
);
|
||||
return result;
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ function customCheckImageFn(
|
|||
export default function Render(
|
||||
props: WebComponentProps<
|
||||
EntityDict,
|
||||
"article",
|
||||
'article',
|
||||
false,
|
||||
{
|
||||
id: string;
|
||||
|
|
@ -73,12 +73,10 @@ export default function Render(
|
|||
setEditor: (editor: any) => void;
|
||||
check: () => void;
|
||||
preview: () => void;
|
||||
addExtraFile: (
|
||||
file: EntityDict["extraFile"]["CreateSingle"]["data"]
|
||||
) => Promise<void>;
|
||||
uploadFile: (
|
||||
file: EntityDict["extraFile"]["CreateSingle"]["data"]
|
||||
) => Promise<{ bucket: string; url: string }>;
|
||||
extraFile: EntityDict['extraFile']['CreateSingle']['data'],
|
||||
file: File
|
||||
) => Promise<string>;
|
||||
clearContentTip: () => void;
|
||||
gotoPreview: (content?: string, title?: string) => void;
|
||||
}
|
||||
|
|
@ -90,14 +88,23 @@ export default function Render(
|
|||
setEditor,
|
||||
check,
|
||||
preview,
|
||||
addExtraFile,
|
||||
uploadFile,
|
||||
update,
|
||||
setHtml,
|
||||
gotoPreview,
|
||||
} = method;
|
||||
const { id, content, editor, origin1, oakFullpath, html, oakId, articleMenuId, changeIsEdit } = data;
|
||||
const [articleId, setArticleId] = useState("");
|
||||
const {
|
||||
id,
|
||||
content,
|
||||
editor,
|
||||
origin1,
|
||||
oakFullpath,
|
||||
html,
|
||||
oakId,
|
||||
articleMenuId,
|
||||
changeIsEdit,
|
||||
} = data;
|
||||
const [articleId, setArticleId] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
if (id) {
|
||||
|
|
@ -106,7 +113,13 @@ export default function Render(
|
|||
}, [id]);
|
||||
return (
|
||||
<div className={Style.container}>
|
||||
<div style={{ width: 'calc(100% - 20px)' }}><Toolbar editor={editor} defaultConfig={toolbarConfig} mode="default" /></div>
|
||||
<div style={{ width: 'calc(100% - 20px)' }}>
|
||||
<Toolbar
|
||||
editor={editor}
|
||||
defaultConfig={toolbarConfig}
|
||||
mode="default"
|
||||
/>
|
||||
</div>
|
||||
<Row>
|
||||
<Col flex={4} />
|
||||
<Col flex={16}>
|
||||
|
|
@ -115,19 +128,23 @@ export default function Render(
|
|||
{data.contentTip && (
|
||||
<Alert
|
||||
type="info"
|
||||
message={t("tips.content")}
|
||||
message={t('tips.content')}
|
||||
closable
|
||||
onClose={() => method.clearContentTip()}
|
||||
/>
|
||||
)}
|
||||
<div className={Style.titleContainer}>
|
||||
<Input
|
||||
onChange={(e) => update({ name: e.target.value })}
|
||||
onChange={(e) =>
|
||||
update({ name: e.target.value })
|
||||
}
|
||||
value={data.name}
|
||||
placeholder={"请输入文章标题"}
|
||||
placeholder={'请输入文章标题'}
|
||||
size="large"
|
||||
maxLength={32}
|
||||
suffix={`${[...(data.name || "")].length}/32`}
|
||||
suffix={`${
|
||||
[...(data.name || '')].length
|
||||
}/32`}
|
||||
className={Style.titleInput}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -135,47 +152,60 @@ export default function Render(
|
|||
<Editor
|
||||
defaultConfig={{
|
||||
autoFocus: true,
|
||||
placeholder: "请输入文章内容...",
|
||||
placeholder: '请输入文章内容...',
|
||||
MENU_CONF: {
|
||||
checkImage: customCheckImageFn,
|
||||
uploadImage: {
|
||||
// 自定义上传
|
||||
async customUpload(file: File, insertFn: InsertFnType) {
|
||||
async customUpload(
|
||||
file: File,
|
||||
insertFn: InsertFnType
|
||||
) {
|
||||
// TS 语法
|
||||
// file 即选中的文件
|
||||
const { name, size, type } = file;
|
||||
const extension = name.substring(
|
||||
name.lastIndexOf(".") + 1
|
||||
);
|
||||
const filename = name.substring(
|
||||
0,
|
||||
name.lastIndexOf(".")
|
||||
);
|
||||
const { name, size, type } =
|
||||
file;
|
||||
const extension =
|
||||
name.substring(
|
||||
name.lastIndexOf(
|
||||
'.'
|
||||
) + 1
|
||||
);
|
||||
const filename =
|
||||
name.substring(
|
||||
0,
|
||||
name.lastIndexOf(
|
||||
'.'
|
||||
)
|
||||
);
|
||||
const extraFile = {
|
||||
entity: "article",
|
||||
entity: 'article',
|
||||
entityId: articleId,
|
||||
extra1: file as any,
|
||||
origin: origin1,
|
||||
type: "image",
|
||||
tag1: "source",
|
||||
objectId: generateNewId(),
|
||||
type: 'image',
|
||||
tag1: 'source',
|
||||
objectId:
|
||||
generateNewId(),
|
||||
filename,
|
||||
size,
|
||||
extension,
|
||||
bucket: "",
|
||||
bucket: '',
|
||||
id: generateNewId(),
|
||||
} as EntityDict["extraFile"]["CreateSingle"]["data"];
|
||||
} as EntityDict['extraFile']['CreateSingle']['data'];
|
||||
|
||||
try {
|
||||
// 自己实现上传,并得到图片 url alt href
|
||||
const { url, bucket } = await uploadFile(extraFile);
|
||||
extraFile.bucket = bucket;
|
||||
extraFile.extra1 = null;
|
||||
// await addExtraFile(extraFile);
|
||||
const url =
|
||||
await uploadFile(
|
||||
extraFile,
|
||||
file
|
||||
);
|
||||
// 最后插入图片
|
||||
insertFn("http://" + url, extraFile.filename);
|
||||
} catch (err) {
|
||||
}
|
||||
insertFn(
|
||||
url,
|
||||
extraFile.filename
|
||||
);
|
||||
} catch (err) {}
|
||||
},
|
||||
},
|
||||
uploadVideo: {
|
||||
|
|
@ -186,41 +216,50 @@ export default function Render(
|
|||
) {
|
||||
// TS 语法
|
||||
// file 即选中的文件
|
||||
const { name, size, type } = file;
|
||||
const extension = name.substring(
|
||||
name.lastIndexOf(".") + 1
|
||||
);
|
||||
const filename = name.substring(
|
||||
0,
|
||||
name.lastIndexOf(".")
|
||||
);
|
||||
const { name, size, type } =
|
||||
file;
|
||||
const extension =
|
||||
name.substring(
|
||||
name.lastIndexOf(
|
||||
'.'
|
||||
) + 1
|
||||
);
|
||||
const filename =
|
||||
name.substring(
|
||||
0,
|
||||
name.lastIndexOf(
|
||||
'.'
|
||||
)
|
||||
);
|
||||
const extraFile = {
|
||||
entity: "article",
|
||||
entity: 'article',
|
||||
entityId: articleId,
|
||||
extra1: file as any,
|
||||
origin: origin1,
|
||||
type: "video",
|
||||
tag1: "source",
|
||||
objectId: generateNewId(),
|
||||
type: 'video',
|
||||
tag1: 'source',
|
||||
objectId:
|
||||
generateNewId(),
|
||||
filename,
|
||||
size,
|
||||
extension,
|
||||
bucket: "",
|
||||
bucket: '',
|
||||
id: generateNewId(),
|
||||
} as EntityDict["extraFile"]["CreateSingle"]["data"];
|
||||
} as EntityDict['extraFile']['CreateSingle']['data'];
|
||||
|
||||
try {
|
||||
// 自己实现上传,并得到图片 url alt href
|
||||
const { url, bucket } = await uploadFile(extraFile);
|
||||
extraFile.bucket = bucket;
|
||||
extraFile.extra1 = null;
|
||||
await addExtraFile(extraFile);
|
||||
const url =
|
||||
await uploadFile(
|
||||
extraFile,
|
||||
file
|
||||
);
|
||||
// 最后插入图片
|
||||
insertFn(
|
||||
"http://" + url,
|
||||
"http://" + url + "?vframe/jpg/offset/0"
|
||||
url,
|
||||
url +
|
||||
'?vframe/jpg/offset/0'
|
||||
);
|
||||
} catch (err) { }
|
||||
} catch (err) {}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -240,7 +279,10 @@ export default function Render(
|
|||
<Col flex="none">
|
||||
<Space>
|
||||
<Button
|
||||
disabled={!data.oakDirty || data.oakExecuting}
|
||||
disabled={
|
||||
!data.oakDirty ||
|
||||
data.oakExecuting
|
||||
}
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
check();
|
||||
|
|
@ -250,7 +292,10 @@ export default function Render(
|
|||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
gotoPreview(content, data.name);
|
||||
gotoPreview(
|
||||
content,
|
||||
data.name
|
||||
);
|
||||
}}
|
||||
>
|
||||
<EyeOutlined />
|
||||
|
|
@ -265,6 +310,6 @@ export default function Render(
|
|||
</Col>
|
||||
<Col flex={4} />
|
||||
</Row>
|
||||
</div >
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,29 +51,7 @@ export default OakComponent({
|
|||
this.triggerEvent('statuschange', e);
|
||||
}
|
||||
},
|
||||
async addExtraFile(
|
||||
extraFile: EntityDict['extraFile']['CreateSingle']['data']
|
||||
) {
|
||||
try {
|
||||
const result = await this.features.cache.operate('extraFile', {
|
||||
action: 'create',
|
||||
data: extraFile,
|
||||
id: generateNewId(),
|
||||
});
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (
|
||||
(error as OakException<EntityDict>).constructor.name ===
|
||||
OakUnloggedInException.name
|
||||
) {
|
||||
this.navigateTo({
|
||||
url: '/login',
|
||||
});
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
async onPickMp(event: WechatMiniprogram.Touch) {
|
||||
if (process.env.OAK_PLATFORM === 'wechatMp') {
|
||||
const { mediaType } = event.currentTarget.dataset;
|
||||
|
|
@ -99,7 +77,6 @@ export default OakComponent({
|
|||
tempFilePath.lastIndexOf('.')
|
||||
);
|
||||
const extraFile = {
|
||||
extra1: tempFilePath,
|
||||
origin: 'qiniu',
|
||||
type: 'image',
|
||||
tag1: this.props.tag1 || 'editorImg',
|
||||
|
|
@ -113,13 +90,15 @@ export default OakComponent({
|
|||
entityId: this.props.entityId,
|
||||
bucket: '',
|
||||
id: generateNewId(),
|
||||
uploadState: 'uploading'
|
||||
} as EntityDict['extraFile']['CreateSingle']['data'];
|
||||
const { url } =
|
||||
await this.features.extraFile.createAndUpload(extraFile, extraFile.extra1!);
|
||||
const url = await this.features.extraFile.autoUpload(
|
||||
extraFile as EntityDict['extraFile']['OpSchema'],
|
||||
tempFilePath!
|
||||
);
|
||||
|
||||
// await this.addExtraFile(extraFile);
|
||||
(this as any).editorCtx.insertImage({
|
||||
src: 'http://' + url,
|
||||
src: url,
|
||||
});
|
||||
}
|
||||
} catch (err: any) {
|
||||
|
|
|
|||
|
|
@ -22,12 +22,12 @@ export default OakComponent({
|
|||
sort: 1,
|
||||
applicationId: 1,
|
||||
},
|
||||
features: ['extraFile2'],
|
||||
features: ['extraFile'],
|
||||
formData({ data: extraFiles, features }) {
|
||||
const avatar = extraFiles?.filter(
|
||||
(ele) => !ele.$$deleteAt$$ && ele.tag1 === 'avatar'
|
||||
)[0];
|
||||
const avatarUrl = features.extraFile2.getUrl(
|
||||
const avatarUrl = features.extraFile.getUrl(
|
||||
avatar as EntityDict['extraFile']['OpSchema']
|
||||
);
|
||||
return {
|
||||
|
|
@ -137,7 +137,7 @@ export default OakComponent({
|
|||
|
||||
// 如果autoUpload
|
||||
if (autoUpload) {
|
||||
await this.features.extraFile2.autoUpload(
|
||||
await this.features.extraFile.autoUpload(
|
||||
updateData as EntityDict['extraFile']['OpSchema'],
|
||||
extra1
|
||||
);
|
||||
|
|
@ -150,7 +150,7 @@ export default OakComponent({
|
|||
if (avatar) {
|
||||
this.removeItem(avatar.id as string);
|
||||
}
|
||||
this.features.extraFile2.addLocalFile(id, extra1);
|
||||
this.features.extraFile.addLocalFile(id, extra1);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import assert from 'assert';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { FileState } from '../../../features/extraFile2';
|
||||
import { FileState } from '../../../features/extraFile';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity';
|
||||
import { ReactComponentProps } from 'oak-frontend-base/lib/types/Page';
|
||||
import { ButtonProps } from 'antd';
|
||||
|
|
@ -9,7 +9,7 @@ import { ButtonProps as AmButtonProps } from 'antd-mobile';
|
|||
export default OakComponent({
|
||||
formData({ features }) {
|
||||
const ids: string[] = this.getEfIds();
|
||||
const states = ids.map((id) => features.extraFile2.getFileState(id));
|
||||
const states = ids.map((id) => features.extraFile.getFileState(id));
|
||||
let state: FileState = 'uploaded';
|
||||
states.forEach((ele) => {
|
||||
if (ele) {
|
||||
|
|
@ -31,47 +31,54 @@ export default OakComponent({
|
|||
type: 'primary',
|
||||
executeText: '',
|
||||
buttonProps: {},
|
||||
afterCommit: () => { },
|
||||
beforeCommit: (() => true) as () => boolean | undefined | Promise<boolean | undefined>,
|
||||
afterCommit: () => {},
|
||||
beforeCommit: (() => true) as () =>
|
||||
| boolean
|
||||
| undefined
|
||||
| Promise<boolean | undefined>,
|
||||
},
|
||||
methods: {
|
||||
getEfIds() {
|
||||
const entity = this.features.runningTree.getEntity(this.state.oakFullpath);
|
||||
const value = this.features.runningTree.getFreshValue(this.state.oakFullpath);
|
||||
const entity = this.features.runningTree.getEntity(
|
||||
this.state.oakFullpath
|
||||
);
|
||||
const value = this.features.runningTree.getFreshValue(
|
||||
this.state.oakFullpath
|
||||
);
|
||||
const efIds = [] as string[];
|
||||
|
||||
const getRecursive = (e: string, v: Record<string, any>) => {
|
||||
for (const attr in v) {
|
||||
const rel = this.features.cache.judgeRelation(e as keyof EntityDict, attr);
|
||||
const rel = this.features.cache.judgeRelation(
|
||||
e as keyof EntityDict,
|
||||
attr
|
||||
);
|
||||
if (rel === 2) {
|
||||
assert(typeof v[attr] === 'object');
|
||||
if (attr === 'extraFile') {
|
||||
assert(v[attr].id);
|
||||
efIds.push(v[attr].id);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
getRecursive(attr, v[attr]);
|
||||
}
|
||||
}
|
||||
else if (typeof rel === 'string') {
|
||||
} else if (typeof rel === 'string') {
|
||||
assert(typeof v[attr] === 'object');
|
||||
if (rel === 'extraFile') {
|
||||
assert(v[attr].id);
|
||||
efIds.push(v[attr].id);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
getRecursive(rel, v[attr]);
|
||||
}
|
||||
}
|
||||
else if (rel instanceof Array) {
|
||||
} else if (rel instanceof Array) {
|
||||
assert(v[attr] instanceof Array);
|
||||
const [e2, fk2] = rel;
|
||||
if (e2 === 'extraFile') {
|
||||
efIds.push(...(v[attr].map((ele: { id: string }) => ele.id)));
|
||||
}
|
||||
else {
|
||||
v[attr].forEach(
|
||||
(ele: any) => getRecursive(e2, ele)
|
||||
efIds.push(
|
||||
...v[attr].map((ele: { id: string }) => ele.id)
|
||||
);
|
||||
} else {
|
||||
v[attr].forEach((ele: any) =>
|
||||
getRecursive(e2, ele)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -79,9 +86,7 @@ export default OakComponent({
|
|||
};
|
||||
|
||||
if (value instanceof Array) {
|
||||
value.forEach(
|
||||
ele => getRecursive(entity, ele)
|
||||
);
|
||||
value.forEach((ele) => getRecursive(entity, ele));
|
||||
}
|
||||
getRecursive(entity, value as any);
|
||||
return efIds;
|
||||
|
|
@ -94,11 +99,11 @@ export default OakComponent({
|
|||
|
||||
const promises: Promise<void>[] = [];
|
||||
ids.forEach((id) => {
|
||||
const fileState = this.features.extraFile2.getFileState(id);
|
||||
const fileState = this.features.extraFile.getFileState(id);
|
||||
if (fileState) {
|
||||
const { state } = fileState;
|
||||
if (['local', 'failed'].includes(state)) {
|
||||
promises.push(this.features.extraFile2.upload(id));
|
||||
promises.push(this.features.extraFile.upload(id));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -130,21 +135,24 @@ export default OakComponent({
|
|||
}
|
||||
},
|
||||
},
|
||||
features: ['extraFile2'],
|
||||
features: ['extraFile'],
|
||||
}) as <ED2 extends EntityDict & BaseEntityDict, T2 extends keyof ED2>(
|
||||
props: ReactComponentProps<
|
||||
ED2,
|
||||
T2,
|
||||
true,
|
||||
{
|
||||
action?: string;
|
||||
size?: ButtonProps['size'] | AmButtonProps['size'],
|
||||
block?: boolean,
|
||||
type?: ButtonProps['type'] | AmButtonProps['type'],
|
||||
executeText?: string,
|
||||
buttonProps?: ButtonProps & AmButtonProps,
|
||||
afterCommit?: () => any,
|
||||
beforeCommit?: () => boolean | undefined | Promise<boolean | undefined>,
|
||||
}
|
||||
>
|
||||
) => React.ReactElement;
|
||||
props: ReactComponentProps<
|
||||
ED2,
|
||||
T2,
|
||||
true,
|
||||
{
|
||||
action?: string;
|
||||
size?: ButtonProps['size'] | AmButtonProps['size'];
|
||||
block?: boolean;
|
||||
type?: ButtonProps['type'] | AmButtonProps['type'];
|
||||
executeText?: string;
|
||||
buttonProps?: ButtonProps & AmButtonProps;
|
||||
afterCommit?: () => any;
|
||||
beforeCommit?: () =>
|
||||
| boolean
|
||||
| undefined
|
||||
| Promise<boolean | undefined>;
|
||||
}
|
||||
>
|
||||
) => React.ReactElement;
|
||||
|
|
@ -2,7 +2,7 @@ import { WebComponentProps } from 'oak-frontend-base';
|
|||
import React from 'react';
|
||||
import { Button, ButtonProps } from 'antd';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { FileState } from '../../../features/extraFile2';
|
||||
import { FileState } from '../../../features/extraFile';
|
||||
|
||||
export default function render(
|
||||
props: WebComponentProps<
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { WebComponentProps } from 'oak-frontend-base';
|
|||
import React from 'react';
|
||||
import { Button, ButtonProps } from 'antd-mobile';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { FileState } from '../../../features/extraFile2';
|
||||
import { FileState } from '../../../features/extraFile';
|
||||
|
||||
export default function render(
|
||||
props: WebComponentProps<
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ export default OakComponent({
|
|||
uploadState: 'uploading',
|
||||
})
|
||||
);
|
||||
this.features.extraFile2.addLocalFile(id, file as any);
|
||||
this.features.extraFile.addLocalFile(id, file as any);
|
||||
},
|
||||
async myUpdateItem(params: File | string) {
|
||||
const { file } = this.state;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export default OakComponent({
|
|||
isBridge: 1,
|
||||
uploadState: 1,
|
||||
},
|
||||
features: ['extraFile2'],
|
||||
features: ['extraFile'],
|
||||
formData({ data, features }) {
|
||||
let files = data?.sort((ele1, ele2) => ele1.sort! - ele2.sort!);
|
||||
if (this.props.tag1) {
|
||||
|
|
@ -45,12 +45,12 @@ export default OakComponent({
|
|||
}
|
||||
|
||||
const files2 = files.map((ele) => {
|
||||
const url = features.extraFile2.getUrl(ele as ExtraFile);
|
||||
const thumbUrl = features.extraFile2.getUrl(
|
||||
const url = features.extraFile.getUrl(ele as ExtraFile);
|
||||
const thumbUrl = features.extraFile.getUrl(
|
||||
ele as ExtraFile,
|
||||
this.props.style
|
||||
);
|
||||
const fileName = features.extraFile2.getFileName(ele as ExtraFile);
|
||||
const fileName = features.extraFile.getFileName(ele as ExtraFile);
|
||||
return {
|
||||
url,
|
||||
thumbUrl,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { FileState } from '../../../features/extraFile2';
|
||||
import { FileState } from '../../../features/extraFile';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity';
|
||||
import { ReactComponentProps } from 'oak-frontend-base/lib/types/Page';
|
||||
import { generateNewId } from 'oak-domain';
|
||||
|
|
@ -132,7 +132,7 @@ export default OakComponent({
|
|||
}
|
||||
},
|
||||
},
|
||||
features: ['extraFile2'],
|
||||
features: ['extraFile'],
|
||||
formData({ data, features }) {
|
||||
let files = data
|
||||
?.filter((ele) => !ele.$$deleteAt$$)
|
||||
|
|
@ -145,13 +145,13 @@ export default OakComponent({
|
|||
}
|
||||
|
||||
const files2 = files.map((ele) => {
|
||||
const url = features.extraFile2.getUrl(ele as ExtraFile);
|
||||
const thumbUrl = features.extraFile2.getUrl(
|
||||
const url = features.extraFile.getUrl(ele as ExtraFile);
|
||||
const thumbUrl = features.extraFile.getUrl(
|
||||
ele as ExtraFile,
|
||||
'thumbnail'
|
||||
);
|
||||
const fileState = features.extraFile2.getFileState(ele.id!);
|
||||
const fileName = features.extraFile2.getFileName(ele as ExtraFile);
|
||||
const fileState = features.extraFile.getFileState(ele.id!);
|
||||
const fileName = features.extraFile.getFileName(ele as ExtraFile);
|
||||
return {
|
||||
url,
|
||||
thumbUrl,
|
||||
|
|
@ -168,7 +168,7 @@ export default OakComponent({
|
|||
methods: {
|
||||
onRemove(file: EnhancedExtraFile) {
|
||||
this.removeItem(file.id);
|
||||
this.features.extraFile2.removeLocalFiles([file.id]);
|
||||
this.features.extraFile.removeLocalFiles([file.id]);
|
||||
},
|
||||
addExtraFileInner(
|
||||
options: {
|
||||
|
|
@ -201,7 +201,7 @@ export default OakComponent({
|
|||
type,
|
||||
tag1,
|
||||
tag2,
|
||||
objectId: generateNewId(), // 这个域用来标识唯一性
|
||||
objectId: generateNewId(), // 这个域用来标识唯一性
|
||||
entity,
|
||||
filename,
|
||||
size,
|
||||
|
|
@ -211,7 +211,7 @@ export default OakComponent({
|
|||
sort,
|
||||
uploadState: 'uploading',
|
||||
});
|
||||
this.features.extraFile2.addLocalFile(id, file);
|
||||
this.features.extraFile.addLocalFile(id, file);
|
||||
},
|
||||
addFileByWeb(file: File) {
|
||||
const { size, type, name } = file;
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ export default OakComponent({
|
|||
userMobile:
|
||||
session?.user?.mobile$user &&
|
||||
session?.user?.mobile$user[0]?.mobile,
|
||||
userAvatar: features.extraFile2.getUrl(
|
||||
userAvatar: features.extraFile.getUrl(
|
||||
session?.user?.extraFile$entity &&
|
||||
session?.user?.extraFile$entity[0]
|
||||
),
|
||||
|
|
@ -96,7 +96,7 @@ export default OakComponent({
|
|||
const extraFile$entity = sessionMessage?.extraFile$entity;
|
||||
|
||||
Object.assign(newSessionMessage, {
|
||||
picUrl: features.extraFile2.getUrl(
|
||||
picUrl: features.extraFile.getUrl(
|
||||
extraFile$entity && extraFile$entity[0]
|
||||
),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -102,10 +102,8 @@ export default OakComponent({
|
|||
},
|
||||
},
|
||||
formData({ data, features }) {
|
||||
const sessionMessages = data?.filter(
|
||||
(ele) => ele.$$createAt$$ !== 1
|
||||
)
|
||||
|
||||
const sessionMessages = data?.filter((ele) => ele.$$createAt$$ !== 1);
|
||||
|
||||
// 获取用户最后一条sessionMessage
|
||||
const userLastMessage = this.getUserLastMessage() as RowWithActions<
|
||||
EntityDict,
|
||||
|
|
@ -328,7 +326,7 @@ export default OakComponent({
|
|||
entityId: sessionMessageId,
|
||||
} as EntityDict['extraFile']['CreateSingle']['data'];
|
||||
|
||||
await this.features.extraFile2.autoUpload(
|
||||
await this.features.extraFile.autoUpload(
|
||||
extraFile as EntityDict['extraFile']['OpSchema'],
|
||||
originFileObj
|
||||
);
|
||||
|
|
@ -348,12 +346,12 @@ export default OakComponent({
|
|||
},
|
||||
sessionMessageId
|
||||
);
|
||||
// this.features.extraFile2.addLocalFile(
|
||||
// this.features.extraFile.addLocalFile(
|
||||
// extraFile?.id,
|
||||
// originFileObj
|
||||
// );
|
||||
await this.execute(undefined, false);
|
||||
// this.features.extraFile2.upload(extraFile?.id);
|
||||
// this.features.extraFile.upload(extraFile?.id);
|
||||
this.pageScroll('comment');
|
||||
this.createItem();
|
||||
} catch (err) {
|
||||
|
|
@ -424,12 +422,12 @@ export default OakComponent({
|
|||
// },
|
||||
// ],
|
||||
// } as EntityDict['sessionMessage']['CreateSingle']['data']);
|
||||
// this.features.extraFile2.addLocalFile(
|
||||
// this.features.extraFile.addLocalFile(
|
||||
// extraFile?.id,
|
||||
// originFileObj
|
||||
// );
|
||||
// await this.execute(undefined, false);
|
||||
// this.features.extraFile2.upload(extraFile?.id);
|
||||
// this.features.extraFile.upload(extraFile?.id);
|
||||
// } catch (err) {
|
||||
// throw err;
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { Feature } from 'oak-frontend-base';
|
||||
import { Upload } from 'oak-frontend-base/es/utils/upload';
|
||||
import { Cache } from 'oak-frontend-base/es/features/cache';
|
||||
import { RunningTree } from 'oak-frontend-base/es/features/runningTree';
|
||||
import { Locales } from 'oak-frontend-base/es/features/locales';
|
||||
import { CommonAspectDict } from 'oak-common-aspect';
|
||||
import AspectDict from '../aspects/AspectDict';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
import { Config, Origin } from '../types/Config';
|
||||
import { BackendRuntimeContext } from '../context/BackendRuntimeContext';
|
||||
import { FrontendRuntimeContext } from '../context/FrontendRuntimeContext';
|
||||
import { Application } from './application'
|
||||
|
|
@ -13,7 +13,11 @@ import { bytesToSize, getFileURL } from '../utils/extraFile';
|
|||
import { assert } from 'oak-domain/lib/utils/assert';
|
||||
import { getCos } from '../utils/cos';
|
||||
import { OpSchema } from '../oak-app-domain/ExtraFile/Schema';
|
||||
import { generateNewId } from 'oak-domain/lib/utils/uuid';
|
||||
import { unset } from 'oak-domain/lib/utils/lodash';
|
||||
import { generateNewId, generateNewIdAsync } from 'oak-domain';
|
||||
import { extraFileProjection } from '../types/Projection';
|
||||
|
||||
export type FileState = 'local' | 'uploading' | 'uploaded' | 'failed';
|
||||
|
||||
export class ExtraFile<
|
||||
ED extends EntityDict,
|
||||
|
|
@ -24,102 +28,125 @@ export class ExtraFile<
|
|||
private cache: Cache<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>;
|
||||
private application: Application<ED, Cxt, FrontCxt, AD>;
|
||||
private locales: Locales<ED, Cxt, FrontCxt, AD>;
|
||||
private files: Record<
|
||||
string,
|
||||
{
|
||||
file: File | string;
|
||||
state: FileState;
|
||||
percentage?: number;
|
||||
}
|
||||
>;
|
||||
private runningTree: RunningTree<ED, Cxt, FrontCxt, AD>;
|
||||
|
||||
constructor(
|
||||
cache: Cache<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>,
|
||||
application: Application<ED, Cxt, FrontCxt, AD>,
|
||||
locales: Locales<ED, Cxt, FrontCxt, AD>
|
||||
locales: Locales<ED, Cxt, FrontCxt, AD>,
|
||||
runningTree: RunningTree<ED, Cxt, FrontCxt, AD>
|
||||
) {
|
||||
super();
|
||||
this.cache = cache;
|
||||
this.application = application;
|
||||
this.locales = locales;
|
||||
this.files = {};
|
||||
this.runningTree = runningTree;
|
||||
}
|
||||
|
||||
async createAndUpload(
|
||||
extraFile: EntityDict['extraFile']['CreateSingle']['data'],
|
||||
file: string | File,
|
||||
) {
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'create',
|
||||
data: extraFile,
|
||||
id: generateNewId(),
|
||||
} as EntityDict['extraFile']['Operation']);
|
||||
await this.upload(
|
||||
extraFile,
|
||||
file
|
||||
);
|
||||
const application = this.application.getApplication();
|
||||
return {
|
||||
url: this.getUrl(
|
||||
extraFile as EntityDict['extraFile']['OpSchema']
|
||||
),
|
||||
addLocalFile(id: string, file: File | string) {
|
||||
assert(!this.files[id]);
|
||||
this.files[id] = {
|
||||
file,
|
||||
state: 'local',
|
||||
};
|
||||
this.publish();
|
||||
}
|
||||
|
||||
async upload(
|
||||
extraFile: EntityDict['extraFile']['CreateSingle']['data'],
|
||||
file: string | File
|
||||
) {
|
||||
const { id, origin } = extraFile;
|
||||
assert(origin, '未设置上传方式');
|
||||
const [extraFileData] = this.cache.get('extraFile', {
|
||||
data: {
|
||||
origin: 1,
|
||||
type: 1,
|
||||
bucket: 1,
|
||||
objectId: 1,
|
||||
tag1: 1,
|
||||
tag2: 1,
|
||||
filename: 1,
|
||||
md5: 1,
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
extra1: 1,
|
||||
extension: 1,
|
||||
size: 1,
|
||||
sort: 1,
|
||||
fileType: 1,
|
||||
isBridge: 1,
|
||||
uploadState: 1,
|
||||
uploadMeta: 1,
|
||||
},
|
||||
removeLocalFiles(ids: string[]) {
|
||||
ids.forEach((id) => unset(this.files, id));
|
||||
this.publish();
|
||||
}
|
||||
|
||||
async upload(id: string) {
|
||||
const [extraFile] = this.cache.get('extraFile', {
|
||||
data: extraFileProjection,
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
assert(extraFile && extraFile.uploadState === 'uploading');
|
||||
const item = this.files[id];
|
||||
assert(item);
|
||||
const { file, state } = item;
|
||||
assert(['local', 'failed'].includes(state));
|
||||
item.state = 'uploading';
|
||||
item.percentage = 0;
|
||||
|
||||
const up = new Upload();
|
||||
try {
|
||||
const cos = getCos<ED, Cxt, FrontCxt>(origin);
|
||||
const cos = getCos<ED, Cxt, FrontCxt>(extraFile.origin!);
|
||||
await cos.upload(
|
||||
extraFileData as OpSchema,
|
||||
extraFile as OpSchema,
|
||||
up.uploadFile,
|
||||
file,
|
||||
async () => undefined
|
||||
this.uploadToAspect.bind(this)
|
||||
);
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'update',
|
||||
data: {
|
||||
uploadState: 'success',
|
||||
},
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
id: generateNewId(),
|
||||
} as EntityDict['extraFile']['Operation']);
|
||||
if (!cos.autoInform()) {
|
||||
await this.cache.exec('operate', {
|
||||
entity: 'extraFile',
|
||||
operation: {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'update',
|
||||
data: {
|
||||
uploadState: 'success',
|
||||
},
|
||||
} as ED['extraFile']['Operation'],
|
||||
});
|
||||
}
|
||||
item.state = 'uploaded';
|
||||
item.percentage = undefined;
|
||||
this.publish();
|
||||
} catch (err) {
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'update',
|
||||
data: {
|
||||
uploadState: 'failed',
|
||||
},
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
id: generateNewId(),
|
||||
} as EntityDict['extraFile']['Operation']);
|
||||
item.state = 'failed';
|
||||
item.percentage = undefined;
|
||||
this.publish();
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async uploadCommit(efPaths: string[], oakFullpath: string) {
|
||||
assert(false, '方法已经废弃');
|
||||
assert(efPaths && efPaths.length > 0);
|
||||
let ids = [] as string[];
|
||||
if (oakFullpath) {
|
||||
ids = efPaths
|
||||
.map((path) => {
|
||||
const path2 = path ? `${oakFullpath}.${path}` : oakFullpath;
|
||||
const data = this.runningTree.getFreshValue(path2);
|
||||
assert(
|
||||
data,
|
||||
`efPath为${path}的路径上取不到extraFile数据,请设置正确的相对路径`
|
||||
);
|
||||
return (
|
||||
data as Partial<EntityDict['extraFile']['OpSchema']>[]
|
||||
).map((ele) => ele.id);
|
||||
})
|
||||
.flat()
|
||||
.filter((ele) => !!ele) as string[];
|
||||
}
|
||||
assert(ids.length > 0);
|
||||
|
||||
const promises: Promise<void>[] = [];
|
||||
ids.forEach((id) => {
|
||||
const fileState = this.getFileState(id);
|
||||
if (fileState) {
|
||||
const { state } = fileState;
|
||||
if (['local', 'failed'].includes(state)) {
|
||||
promises.push(this.upload(id));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (promises.length > 0) {
|
||||
await Promise.all(promises);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -133,29 +160,37 @@ export class ExtraFile<
|
|||
if (!extraFile) {
|
||||
return '';
|
||||
}
|
||||
let url;
|
||||
|
||||
if (extraFile?.isBridge && extraFile?.extra1) {
|
||||
if (typeof extraFile?.extra1 === 'string') {
|
||||
url = this.locales.makeBridgeUrl(extraFile?.extra1);
|
||||
return url;
|
||||
}
|
||||
return this.locales.makeBridgeUrl(extraFile?.extra1);
|
||||
}
|
||||
if (extraFile?.extra1) {
|
||||
// 有extra1就用extra1 可能File对象 可能外部链接
|
||||
if (typeof extraFile?.extra1 === 'string') {
|
||||
return extraFile?.extra1;
|
||||
const { id } = extraFile;
|
||||
if (this.files[id]) {
|
||||
const { file } = this.files[id];
|
||||
if (typeof file === 'string') {
|
||||
return file;
|
||||
}
|
||||
if ((extraFile?.extra1 as File) instanceof File) {
|
||||
return getFileURL(extraFile?.extra1) || '';
|
||||
if (file instanceof File) {
|
||||
return getFileURL(file);
|
||||
}
|
||||
return extraFile?.extra1 || '';
|
||||
assert(false, 'the incoming file is not supported');
|
||||
}
|
||||
const { origin } = extraFile;
|
||||
const cos = getCos<ED, Cxt, FrontCxt>(origin);
|
||||
const context = this.cache.begin();
|
||||
this.cache.commit();
|
||||
url = cos.composeFileUrl(extraFile, context, style);
|
||||
return url;
|
||||
return cos.composeFileUrl(extraFile, context, style);
|
||||
}
|
||||
|
||||
getFileState(id: string):
|
||||
| {
|
||||
state: FileState;
|
||||
percentage?: number;
|
||||
}
|
||||
| undefined {
|
||||
if (this.files[id]) {
|
||||
return this.files[id];
|
||||
}
|
||||
}
|
||||
|
||||
getFileName(extraFile: EntityDict['extraFile']['OpSchema']) {
|
||||
|
|
@ -169,4 +204,71 @@ export class ExtraFile<
|
|||
formatBytes(size: number) {
|
||||
return bytesToSize(size);
|
||||
}
|
||||
}
|
||||
|
||||
async autoUpload(
|
||||
extraFile: EntityDict['extraFile']['OpSchema'],
|
||||
file: File | string
|
||||
) {
|
||||
const extraFileId = extraFile.id || generateNewId();
|
||||
const applicationId =
|
||||
extraFile.applicationId || this.application.getApplicationId();
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'create',
|
||||
data: Object.assign(extraFile, {
|
||||
id: extraFileId,
|
||||
applicationId,
|
||||
}),
|
||||
id: await generateNewIdAsync(),
|
||||
} as EntityDict['extraFile']['Operation']);
|
||||
const [newExtraFile] = this.cache.get('extraFile', {
|
||||
data: extraFileProjection,
|
||||
filter: {
|
||||
id: extraFileId,
|
||||
},
|
||||
});
|
||||
const up = new Upload();
|
||||
try {
|
||||
const cos = getCos<ED, Cxt, FrontCxt>(newExtraFile.origin!);
|
||||
await cos.upload(
|
||||
newExtraFile as OpSchema,
|
||||
up.uploadFile,
|
||||
file,
|
||||
this.uploadToAspect.bind(this)
|
||||
);
|
||||
return this.getUrl(
|
||||
newExtraFile as EntityDict['extraFile']['Schema']
|
||||
);
|
||||
} catch (err) {
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'remove',
|
||||
data: {},
|
||||
filter: {
|
||||
id: extraFileId,
|
||||
},
|
||||
id: await generateNewIdAsync(),
|
||||
} as EntityDict['extraFile']['Operation']);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// 私有
|
||||
private async uploadToAspect(
|
||||
file: File | string,
|
||||
name: string, // 文件的part name
|
||||
aspectName: string, // 上传的aspect名
|
||||
formData: Record<string, any>, // 上传的其它part参数
|
||||
autoInform?: boolean // 上传成功是否会自动通知server(若不会则需要前台显式通知)
|
||||
) {
|
||||
const formData2 = new FormData();
|
||||
for (const key of Object.keys(formData)) {
|
||||
formData2.append(key, formData[key]);
|
||||
}
|
||||
formData2.append(name || 'file', file as File);
|
||||
|
||||
const { result } = await this.cache.exec(
|
||||
aspectName as keyof CommonAspectDict<ED, Cxt>,
|
||||
formData2
|
||||
);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,277 +0,0 @@
|
|||
import { Feature } from 'oak-frontend-base';
|
||||
import { Upload } from 'oak-frontend-base/es/utils/upload';
|
||||
import { Cache } from 'oak-frontend-base/es/features/cache';
|
||||
import { RunningTree } from 'oak-frontend-base/es/features/runningTree';
|
||||
import { Locales } from 'oak-frontend-base/es/features/locales';
|
||||
import { CommonAspectDict } from 'oak-common-aspect';
|
||||
import AspectDict from '../aspects/AspectDict';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
import { BackendRuntimeContext } from '../context/BackendRuntimeContext';
|
||||
import { FrontendRuntimeContext } from '../context/FrontendRuntimeContext';
|
||||
import { Application } from './application'
|
||||
import { bytesToSize, getFileURL } from '../utils/extraFile';
|
||||
import { assert } from 'oak-domain/lib/utils/assert';
|
||||
import { getCos } from '../utils/cos';
|
||||
import { OpSchema } from '../oak-app-domain/ExtraFile/Schema';
|
||||
import { unset } from 'oak-domain/lib/utils/lodash';
|
||||
import { generateNewId, generateNewIdAsync } from 'oak-domain';
|
||||
import { extraFileProjection } from '../types/Projection';
|
||||
|
||||
export type FileState = 'local' | 'uploading' | 'uploaded' | 'failed';
|
||||
|
||||
export class ExtraFile2<
|
||||
ED extends EntityDict,
|
||||
Cxt extends BackendRuntimeContext<ED>,
|
||||
FrontCxt extends FrontendRuntimeContext<ED, Cxt, AD>,
|
||||
AD extends AspectDict<ED, Cxt> & CommonAspectDict<ED, Cxt>
|
||||
> extends Feature {
|
||||
private cache: Cache<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>;
|
||||
private application: Application<ED, Cxt, FrontCxt, AD>;
|
||||
private locales: Locales<ED, Cxt, FrontCxt, AD>;
|
||||
private files: Record<
|
||||
string,
|
||||
{
|
||||
file: File | string;
|
||||
state: FileState;
|
||||
percentage?: number;
|
||||
}
|
||||
>;
|
||||
private runningTree: RunningTree<ED, Cxt, FrontCxt, AD>;
|
||||
|
||||
constructor(
|
||||
cache: Cache<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>,
|
||||
application: Application<ED, Cxt, FrontCxt, AD>,
|
||||
locales: Locales<ED, Cxt, FrontCxt, AD>,
|
||||
runningTree: RunningTree<ED, Cxt, FrontCxt, AD>,
|
||||
) {
|
||||
super();
|
||||
this.cache = cache;
|
||||
this.application = application;
|
||||
this.locales = locales;
|
||||
this.files = {};
|
||||
this.runningTree = runningTree;
|
||||
}
|
||||
|
||||
addLocalFile(id: string, file: File | string) {
|
||||
assert(!this.files[id]);
|
||||
this.files[id] = {
|
||||
file,
|
||||
state: 'local',
|
||||
};
|
||||
this.publish();
|
||||
}
|
||||
|
||||
removeLocalFiles(ids: string[]) {
|
||||
ids.forEach((id) => unset(this.files, id));
|
||||
this.publish();
|
||||
}
|
||||
|
||||
async upload(id: string) {
|
||||
const [extraFile] = this.cache.get('extraFile', {
|
||||
data: extraFileProjection,
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
assert(extraFile && extraFile.uploadState === 'uploading');
|
||||
const item = this.files[id];
|
||||
assert(item);
|
||||
const { file, state } = item;
|
||||
assert(['local', 'failed'].includes(state));
|
||||
item.state = 'uploading';
|
||||
item.percentage = 0;
|
||||
|
||||
const up = new Upload();
|
||||
try {
|
||||
const cos = getCos<ED, Cxt, FrontCxt>(extraFile.origin!);
|
||||
await cos.upload(
|
||||
extraFile as OpSchema,
|
||||
up.uploadFile,
|
||||
file,
|
||||
this.uploadToAspect.bind(this)
|
||||
);
|
||||
if (!cos.autoInform()) {
|
||||
await this.cache.exec('operate', {
|
||||
entity: 'extraFile',
|
||||
operation: {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'update',
|
||||
data: {
|
||||
uploadState: 'success',
|
||||
},
|
||||
} as ED['extraFile']['Operation'],
|
||||
});
|
||||
}
|
||||
item.state = 'uploaded';
|
||||
item.percentage = undefined;
|
||||
this.publish();
|
||||
} catch (err) {
|
||||
item.state = 'failed';
|
||||
item.percentage = undefined;
|
||||
this.publish();
|
||||
}
|
||||
}
|
||||
|
||||
async uploadCommit(efPaths: string[], oakFullpath: string) {
|
||||
assert(false, '方法已经废弃');
|
||||
assert(efPaths && efPaths.length > 0);
|
||||
let ids = [] as string[];
|
||||
if (oakFullpath) {
|
||||
ids = efPaths
|
||||
.map((path) => {
|
||||
const path2 = path
|
||||
? `${oakFullpath}.${path}`
|
||||
: oakFullpath;
|
||||
const data =
|
||||
this.runningTree.getFreshValue(path2);
|
||||
assert(
|
||||
data,
|
||||
`efPath为${path}的路径上取不到extraFile数据,请设置正确的相对路径`
|
||||
);
|
||||
return (
|
||||
data as Partial<EntityDict['extraFile']['OpSchema']>[]
|
||||
).map((ele) => ele.id);
|
||||
})
|
||||
.flat()
|
||||
.filter((ele) => !!ele) as string[];
|
||||
}
|
||||
assert(ids.length > 0);
|
||||
|
||||
const promises: Promise<void>[] = [];
|
||||
ids.forEach((id) => {
|
||||
const fileState = this.getFileState(id);
|
||||
if (fileState) {
|
||||
const { state } = fileState;
|
||||
if (['local', 'failed'].includes(state)) {
|
||||
promises.push(this.upload(id));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (promises.length > 0) {
|
||||
await Promise.all(promises);
|
||||
}
|
||||
}
|
||||
|
||||
getUrl(
|
||||
extraFile?:
|
||||
| EntityDict['extraFile']['OpSchema']
|
||||
| EntityDict['extraFile']['Schema']
|
||||
| null,
|
||||
style?: string
|
||||
) {
|
||||
if (!extraFile) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (extraFile?.isBridge && extraFile?.extra1) {
|
||||
return this.locales.makeBridgeUrl(extraFile?.extra1);
|
||||
}
|
||||
const { id } = extraFile;
|
||||
if (this.files[id]) {
|
||||
const { file } = this.files[id];
|
||||
if (typeof file === 'string') {
|
||||
return file
|
||||
}
|
||||
if (file instanceof File) {
|
||||
return getFileURL(file);
|
||||
}
|
||||
assert(false, 'the incoming file is not supported');
|
||||
}
|
||||
const { origin } = extraFile;
|
||||
const cos = getCos<ED, Cxt, FrontCxt>(origin);
|
||||
const context = this.cache.begin();
|
||||
this.cache.commit();
|
||||
return cos.composeFileUrl(extraFile, context, style);
|
||||
}
|
||||
|
||||
getFileState(id: string):
|
||||
| {
|
||||
state: FileState;
|
||||
percentage?: number;
|
||||
}
|
||||
| undefined {
|
||||
if (this.files[id]) {
|
||||
return this.files[id];
|
||||
}
|
||||
}
|
||||
|
||||
getFileName(extraFile: EntityDict['extraFile']['OpSchema']) {
|
||||
const name =
|
||||
extraFile.filename +
|
||||
(extraFile.extension ? `.${extraFile.extension}` : '');
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
formatBytes(size: number) {
|
||||
return bytesToSize(size);
|
||||
}
|
||||
|
||||
async autoUpload(
|
||||
extraFile: EntityDict['extraFile']['OpSchema'],
|
||||
file: File | string
|
||||
) {
|
||||
const extraFileId = extraFile.id || generateNewId();
|
||||
const applicationId =
|
||||
extraFile.applicationId || this.application.getApplicationId();
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'create',
|
||||
data: Object.assign(extraFile, {
|
||||
id: extraFileId,
|
||||
applicationId,
|
||||
}),
|
||||
id: await generateNewIdAsync(),
|
||||
} as EntityDict['extraFile']['Operation']);
|
||||
const [newExtraFile] = this.cache.get('extraFile', {
|
||||
data: extraFileProjection,
|
||||
filter: {
|
||||
id: extraFileId,
|
||||
},
|
||||
});
|
||||
const up = new Upload();
|
||||
try {
|
||||
const cos = getCos<ED, Cxt, FrontCxt>(newExtraFile.origin!);
|
||||
await cos.upload(
|
||||
newExtraFile as OpSchema,
|
||||
up.uploadFile,
|
||||
file,
|
||||
this.uploadToAspect.bind(this)
|
||||
);
|
||||
return this.getUrl(
|
||||
newExtraFile as EntityDict['extraFile']['Schema']
|
||||
);
|
||||
} catch (err) {
|
||||
await this.cache.operate('extraFile', {
|
||||
action: 'remove',
|
||||
data: {},
|
||||
filter: {
|
||||
id: extraFileId,
|
||||
},
|
||||
id: await generateNewIdAsync(),
|
||||
} as EntityDict['extraFile']['Operation']);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// 私有
|
||||
private async uploadToAspect(
|
||||
file: File | string,
|
||||
name: string, // 文件的part name
|
||||
aspectName: string, // 上传的aspect名
|
||||
formData: Record<string, any>, // 上传的其它part参数
|
||||
autoInform?: boolean // 上传成功是否会自动通知server(若不会则需要前台显式通知)
|
||||
) {
|
||||
const formData2 = new FormData();
|
||||
for (const key of Object.keys(formData)) {
|
||||
formData2.append(key, formData[key]);
|
||||
}
|
||||
formData2.append(name || 'file', file as File);
|
||||
|
||||
const { result } = await this.cache.exec(
|
||||
aspectName as keyof CommonAspectDict<ED, Cxt>,
|
||||
formData2
|
||||
);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
import { CommonAspectDict } from 'oak-common-aspect';
|
||||
import { Token } from './token';
|
||||
import { ExtraFile } from './extraFile';
|
||||
import { ExtraFile2 } from './extraFile2';
|
||||
import { Application } from './application';
|
||||
import { Config } from './config';
|
||||
import { Template } from './template';
|
||||
|
|
@ -54,9 +53,12 @@ export function initialize<
|
|||
basicFeatures.localStorage,
|
||||
)
|
||||
|
||||
// 临时代码,合并后再删
|
||||
const extraFile = new ExtraFile<ED, Cxt, FrontCxt, AD>(basicFeatures.cache, application, basicFeatures.locales);
|
||||
const extraFile2 = new ExtraFile2<ED, Cxt, FrontCxt, AD>(basicFeatures.cache, application, basicFeatures.locales, basicFeatures.runningTree);
|
||||
const extraFile = new ExtraFile<ED, Cxt, FrontCxt, AD>(
|
||||
basicFeatures.cache,
|
||||
application,
|
||||
basicFeatures.locales,
|
||||
basicFeatures.runningTree
|
||||
);
|
||||
const config = new Config<ED, Cxt, FrontCxt, AD>(basicFeatures.cache);
|
||||
const template = new Template<ED, Cxt, FrontCxt, AD>(basicFeatures.cache);
|
||||
const weiXinJsSdk = new WeiXinJsSdk<ED, Cxt, FrontCxt, AD>(
|
||||
|
|
@ -69,7 +71,6 @@ export function initialize<
|
|||
return {
|
||||
token,
|
||||
extraFile,
|
||||
extraFile2,
|
||||
application,
|
||||
config,
|
||||
template,
|
||||
|
|
@ -89,7 +90,6 @@ export type GeneralFeatures<
|
|||
> = {
|
||||
token: Token<ED, Cxt, FrontCxt, AD>;
|
||||
extraFile: ExtraFile<ED, Cxt, FrontCxt, AD>;
|
||||
extraFile2: ExtraFile2<ED, Cxt, FrontCxt, AD>;
|
||||
application: Application<ED, Cxt, FrontCxt, AD>;
|
||||
config: Config<ED, Cxt, FrontCxt, AD>;
|
||||
template: Template<ED, Cxt, FrontCxt, AD>;
|
||||
|
|
|
|||
|
|
@ -90,7 +90,10 @@ export default OakComponent({
|
|||
},
|
||||
|
||||
uploadFile(extraFile: EntityDict['extraFile']['CreateSingle']['data']) {
|
||||
return this.features.extraFile.createAndUpload(extraFile, extraFile.extra1!);
|
||||
return this.features.extraFile.autoUpload(
|
||||
extraFile as EntityDict['extraFile']['OpSchema'],
|
||||
extraFile.extra1!
|
||||
);
|
||||
},
|
||||
|
||||
setEditor(editor: IDomEditor | null) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue