Merge branch 'dev' of codeup.aliyun.com:61c14a7efa282c88e103c23f/oak-general-business into dev
This commit is contained in:
commit
48784ed889
|
|
@ -0,0 +1,10 @@
|
|||
/// <reference types="react" />
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, keyof EntityDict, boolean, {
|
||||
efPaths: string[];
|
||||
size: import("antd/es/button").ButtonSize | "mini";
|
||||
block: boolean | undefined;
|
||||
type: "primary" | "text" | "default" | "link" | "button" | "dashed" | "submit" | "reset" | undefined;
|
||||
executeText: string;
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
export default _default;
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import assert from 'assert';
|
||||
export default OakComponent({
|
||||
formData({ features }) {
|
||||
const ids = this.getEfIds();
|
||||
const states = ids.map(id => features.extraFile2.getFileState(id));
|
||||
let state = 'uploaded';
|
||||
states.forEach((ele) => {
|
||||
if (ele) {
|
||||
if (['failed', 'local'].includes(ele.state)) {
|
||||
state = ele.state;
|
||||
}
|
||||
else if (ele.state === 'uploading' && state === 'uploaded') {
|
||||
state = 'uploading';
|
||||
}
|
||||
}
|
||||
});
|
||||
return {
|
||||
state,
|
||||
};
|
||||
},
|
||||
properties: {
|
||||
efPaths: [],
|
||||
size: 'middle',
|
||||
block: false,
|
||||
type: 'primary',
|
||||
executeText: '',
|
||||
},
|
||||
methods: {
|
||||
getEfIds() {
|
||||
const { efPaths } = this.props;
|
||||
const { oakFullpath } = this.state;
|
||||
assert(efPaths);
|
||||
if (oakFullpath) {
|
||||
const ids = efPaths.map((path) => {
|
||||
const path2 = path ? `${oakFullpath}.path` : oakFullpath;
|
||||
const data = this.features.runningTree.getFreshValue(path2);
|
||||
if (data) {
|
||||
return data.map(ele => ele.id);
|
||||
}
|
||||
}).flat().filter(ele => !!ele);
|
||||
return ids;
|
||||
}
|
||||
return [];
|
||||
},
|
||||
upload() {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"l-icon": "@oak-frontend-base/miniprogram_npm/lin-ui/icon/index",
|
||||
"l-button": "@oak-frontend-base/miniprogram_npm/lin-ui/button/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"executing": "%{text}中...",
|
||||
"upload": "上传",
|
||||
"uploading": "上传中"
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import { ButtonProps } from 'antd-mobile';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { FileState } from '../../../features/extraFile2';
|
||||
export default function render(props: WebComponentProps<EntityDict, any, true, {
|
||||
state: FileState;
|
||||
size?: ButtonProps['size'];
|
||||
block?: ButtonProps['block'];
|
||||
type?: ButtonProps['type'];
|
||||
executeText?: string;
|
||||
}, {
|
||||
upload: () => Promise<void>;
|
||||
}>): JSX.Element;
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { Button } from 'antd-mobile';
|
||||
export default function render(props) {
|
||||
const { state, oakExecutable, oakExecuting, oakDirty, size, block, type, executeText } = props.data;
|
||||
const { t, upload, execute } = props.methods;
|
||||
const disabled = oakExecuting || ['uploading'].includes(state) || (oakExecutable === false && ['uploaded'].includes(state));
|
||||
let text = executeText || t('common::action.confirm');
|
||||
if (oakExecuting) {
|
||||
text = t('executing', { text });
|
||||
}
|
||||
else if (oakExecutable === false) {
|
||||
if (state === 'uploading') {
|
||||
text = t('uploading');
|
||||
}
|
||||
else if (['failed', 'local'].includes(state)) {
|
||||
text = t('upload');
|
||||
}
|
||||
}
|
||||
return (_jsx(Button, { type: type, size: size, block: block, disabled: disabled, onClick: async () => {
|
||||
if (oakExecutable) {
|
||||
await execute();
|
||||
await upload();
|
||||
}
|
||||
else {
|
||||
await upload();
|
||||
}
|
||||
}, children: text }));
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import { ButtonProps } from 'antd';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { FileState } from '../../../features/extraFile2';
|
||||
export default function render(props: WebComponentProps<EntityDict, any, true, {
|
||||
state: FileState;
|
||||
size?: ButtonProps['size'];
|
||||
block?: ButtonProps['block'];
|
||||
type?: ButtonProps['type'];
|
||||
executeText?: string;
|
||||
}, {
|
||||
upload: () => Promise<void>;
|
||||
}>): JSX.Element;
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { Button } from 'antd';
|
||||
export default function render(props) {
|
||||
const { state, oakExecutable, oakExecuting, oakDirty, size, block, type, executeText } = props.data;
|
||||
const { t, upload, execute } = props.methods;
|
||||
const disabled = oakExecuting || ['uploading'].includes(state) || (oakExecutable === false && ['uploaded'].includes(state));
|
||||
let text = executeText || t('common::action.confirm');
|
||||
if (oakExecuting) {
|
||||
text = t('executing', { text });
|
||||
}
|
||||
else if (oakExecutable === false) {
|
||||
if (state === 'uploading') {
|
||||
text = t('uploading');
|
||||
}
|
||||
else if (['failed', 'local'].includes(state)) {
|
||||
text = t('upload');
|
||||
}
|
||||
}
|
||||
return (_jsx(Button, { type: type, size: size, block: block, disabled: disabled, onClick: async () => {
|
||||
if (oakExecutable) {
|
||||
await execute();
|
||||
await upload();
|
||||
}
|
||||
else {
|
||||
await upload();
|
||||
}
|
||||
}, children: text }));
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { FileState } from '../../../features/extraFile2';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity';
|
||||
import { ReactComponentProps } from 'oak-frontend-base/lib/types/Page';
|
||||
type ExtraFile = EntityDict['extraFile']['OpSchema'];
|
||||
export interface EnhancedExtraFile extends ExtraFile {
|
||||
url: string;
|
||||
thumbUrl: string;
|
||||
filename: string;
|
||||
fileState?: FileState;
|
||||
percentage?: number;
|
||||
}
|
||||
type SourceType = 'album' | 'camera';
|
||||
export type Theme = 'file' | 'image' | 'image-flow' | 'custom';
|
||||
type FileType = 'all' | 'video' | 'image' | 'file';
|
||||
type ImgMode = 'scaleToFill' | 'aspectFit' | 'aspectFill' | 'widthFix' | "heightFix" | 'top' | 'bottom' | 'left' | 'right' | 'center' | 'top left' | 'top right' | 'bottom left' | 'bottom right';
|
||||
declare const _default: <ED2 extends EntityDict & BaseEntityDict, T2 extends keyof ED2>(props: ReactComponentProps<ED2, T2, true, {
|
||||
bucket: string;
|
||||
removeLater: boolean;
|
||||
autoUpload: boolean;
|
||||
maxNumber: number;
|
||||
extension: string[];
|
||||
fileType: FileType;
|
||||
selectCount: number;
|
||||
sourceType: SourceType[];
|
||||
mediaType: ('image' | 'video')[];
|
||||
mode: ImgMode;
|
||||
size: number;
|
||||
showUploadList: boolean;
|
||||
accept: string;
|
||||
preview: boolean;
|
||||
disableDelete: boolean;
|
||||
disableAdd: boolean;
|
||||
disableDownload: boolean;
|
||||
disabled: boolean;
|
||||
type: string;
|
||||
origin: string;
|
||||
tag1: string;
|
||||
tag2: string;
|
||||
entity: keyof ED2;
|
||||
entityId: string;
|
||||
theme: Theme;
|
||||
showUploadProgress: boolean;
|
||||
children?: React.ReactNode;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
import { generateNewId } from 'oak-domain/lib/utils/uuid';
|
||||
;
|
||||
export default OakComponent({
|
||||
entity: 'extraFile',
|
||||
isList: true,
|
||||
projection: {
|
||||
id: 1,
|
||||
tag1: 1,
|
||||
tag2: 1,
|
||||
origin: 1,
|
||||
bucket: 1,
|
||||
objectId: 1,
|
||||
filename: 1,
|
||||
extra1: 1,
|
||||
extension: 1,
|
||||
type: 1,
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
fileType: 1,
|
||||
sort: 1,
|
||||
isBridge: 1,
|
||||
uploadState: 1,
|
||||
},
|
||||
data: {
|
||||
// 根据 size 不同,计算的图片显示大小不同
|
||||
itemSizePercentage: '',
|
||||
},
|
||||
wechatMp: {
|
||||
externalClasses: ['oak-class', 'oak-item-class'],
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
filter() {
|
||||
const { tag1, tag2 } = this.props;
|
||||
const filter1 = {};
|
||||
if (tag1) {
|
||||
Object.assign(filter1, { tag1 });
|
||||
}
|
||||
if (tag2) {
|
||||
Object.assign(filter1, { tag2 });
|
||||
}
|
||||
return filter1;
|
||||
},
|
||||
},
|
||||
],
|
||||
properties: {
|
||||
bucket: '',
|
||||
removeLater: true,
|
||||
autoUpload: false,
|
||||
maxNumber: 20,
|
||||
extension: [],
|
||||
fileType: 'all',
|
||||
selectCount: 1,
|
||||
sourceType: ['album', 'camera'],
|
||||
mediaType: ['image'],
|
||||
// 图片显示模式
|
||||
mode: 'aspectFit',
|
||||
// 每行可显示的个数
|
||||
size: 3,
|
||||
showUploadList: true,
|
||||
accept: 'image/*',
|
||||
// 图片是否可预览
|
||||
preview: true,
|
||||
// 图片是否可删除
|
||||
disableDelete: false,
|
||||
// 上传按钮隐藏
|
||||
disableAdd: false,
|
||||
// 下按按钮隐藏
|
||||
disableDownload: false,
|
||||
type: 'file',
|
||||
origin: 'qiniu',
|
||||
tag1: '',
|
||||
tag2: '',
|
||||
entity: '',
|
||||
entityId: '',
|
||||
theme: 'image',
|
||||
showUploadProgress: false,
|
||||
},
|
||||
listeners: {
|
||||
maxNumber(prev, next) {
|
||||
if (this.state.oakFullpath) {
|
||||
if (prev.maxNumber !== next.maxNumber) {
|
||||
this.reRender();
|
||||
}
|
||||
}
|
||||
},
|
||||
async size(prev, next) {
|
||||
if (process.env.OAK_PLATFORM === 'wechatMp') {
|
||||
const size = next.size;
|
||||
if (!size) {
|
||||
this.setState({ itemSizePercentage: '' });
|
||||
return;
|
||||
}
|
||||
// 获取 .file-list__container 容器宽度
|
||||
const res = await this.getNodeRectFromComponent(this, '.file-list__container');
|
||||
const widthRpx = this.px2rpx(res.right - res.left);
|
||||
// 根据容器宽度计算单张图片宽度百分比
|
||||
const itemSizePercentage = (10 / size) * 10 - (20 / widthRpx) * 100 + '%;';
|
||||
this.setState({
|
||||
itemSizePercentage: itemSizePercentage,
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
features: ['extraFile2'],
|
||||
formData({ data, features }) {
|
||||
const files = data.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);
|
||||
return {
|
||||
url,
|
||||
thumbUrl,
|
||||
filename,
|
||||
fileState: fileState?.state,
|
||||
percentage: fileState?.percentage,
|
||||
...ele,
|
||||
};
|
||||
});
|
||||
return {
|
||||
files,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onRemove(file) {
|
||||
this.removeItem(file.id);
|
||||
this.features.extraFile2.removeLocalFiles([file.id]);
|
||||
},
|
||||
addExtraFileInner(options, file) {
|
||||
const { type, origin, tag1, tag2, entity, entityId, bucket } = this.props;
|
||||
const { name, fileType, size } = options;
|
||||
const extension = name.substring(name.lastIndexOf('.') + 1);
|
||||
const filename = name.substring(0, name.lastIndexOf('.'));
|
||||
const { files } = this.state;
|
||||
const sort = files.length * 10000;
|
||||
const id = this.addItem({
|
||||
bucket,
|
||||
origin,
|
||||
type,
|
||||
tag1,
|
||||
tag2,
|
||||
objectId: generateNewId(),
|
||||
entity,
|
||||
filename,
|
||||
size,
|
||||
extension,
|
||||
fileType,
|
||||
entityId,
|
||||
sort
|
||||
});
|
||||
this.features.extraFile2.addLocalFile(id, file);
|
||||
},
|
||||
addFileByWeb(file) {
|
||||
const { size, type, name } = file;
|
||||
this.addExtraFileInner({
|
||||
name,
|
||||
fileType: type,
|
||||
size,
|
||||
}, file);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"choosePicture": "请选择图片",
|
||||
"chooseFile": "请选择文件"
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import { UploadFile } from "antd";
|
||||
import { WebComponentProps } from "oak-frontend-base";
|
||||
import { EntityDict } from "../../../oak-app-domain";
|
||||
import { EnhancedExtraFile, Theme } from './index';
|
||||
export default function render(props: WebComponentProps<EntityDict, 'extraFile', true, {
|
||||
files: EnhancedExtraFile[];
|
||||
accept?: string;
|
||||
maxNumber?: number;
|
||||
multiple?: boolean;
|
||||
draggable?: boolean;
|
||||
theme?: Theme;
|
||||
tips?: string;
|
||||
beforeUpload?: (file: File) => Promise<boolean>;
|
||||
style?: Record<string, string>;
|
||||
className?: string;
|
||||
directory?: boolean;
|
||||
onPreview?: (file: UploadFile<any>) => void;
|
||||
onDownload?: (file: UploadFile<any>) => void;
|
||||
showUploadList?: boolean;
|
||||
children?: JSX.Element;
|
||||
disableInsert?: boolean;
|
||||
disableDownload?: boolean;
|
||||
disableDelete?: boolean;
|
||||
preview?: boolean;
|
||||
}, {
|
||||
onRemove: (file: UploadFile) => void;
|
||||
addFileByWeb: (file: UploadFile) => void;
|
||||
}>): JSX.Element;
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import React, { useCallback } from 'react';
|
||||
import { Space, Upload, Button } from "antd";
|
||||
import { PlusOutlined } from "@ant-design/icons";
|
||||
import classNames from "classnames";
|
||||
import { DndProvider, useDrag, useDrop } from "react-dnd";
|
||||
import { HTML5Backend } from "react-dnd-html5-backend";
|
||||
import { TouchBackend } from "react-dnd-touch-backend";
|
||||
import { isPc } from "oak-frontend-base/es/utils/utils";
|
||||
import Style from "./web.module.less";
|
||||
function getListType(theme) {
|
||||
const themeMap = {
|
||||
file: "text",
|
||||
image: "picture-card",
|
||||
"image-flow": "picture",
|
||||
custom: "text",
|
||||
};
|
||||
return themeMap[theme];
|
||||
}
|
||||
const type = "DragableUploadList";
|
||||
const DragableUploadListItem = ({ originNode, moveRow, file, fileList, }) => {
|
||||
const ref = React.useRef(null);
|
||||
const index = fileList.indexOf(file);
|
||||
const [{ isOver, dropClassName }, drop] = useDrop({
|
||||
accept: type,
|
||||
collect: (monitor) => {
|
||||
const { index: dragIndex } = monitor.getItem() || {};
|
||||
if (dragIndex === index) {
|
||||
return {};
|
||||
}
|
||||
return {
|
||||
isOver: monitor.isOver(),
|
||||
dropClassName: dragIndex < index ? " drop-over-downward" : " drop-over-upward",
|
||||
};
|
||||
},
|
||||
drop: (item) => {
|
||||
moveRow(item.index, index);
|
||||
},
|
||||
});
|
||||
const [, drag] = useDrag({
|
||||
type,
|
||||
item: { index },
|
||||
collect: (monitor) => ({
|
||||
isDragging: monitor.isDragging(),
|
||||
}),
|
||||
});
|
||||
drop(drag(ref));
|
||||
return (_jsx("div", { ref: ref, className: `ant-upload-draggable-list-item ${isOver ? dropClassName : ""}`, style: { cursor: "move", height: "100%" }, children: originNode }));
|
||||
};
|
||||
export default function render(props) {
|
||||
const { accept = "image/*", maxNumber = 20, multiple = maxNumber !== 1, draggable = false, theme = "image", tips, beforeUpload, style, className, directory = false, onPreview, onDownload, children, showUploadList = true, files = [], disableInsert = false, disableDownload = false, disableDelete = false, preview = true, } = props.data;
|
||||
const { t, onRemove, addFileByWeb } = props.methods;
|
||||
const listType = getListType(theme);
|
||||
const getUploadButton = () => {
|
||||
if (children) {
|
||||
return children;
|
||||
}
|
||||
if (listType === "picture-card") {
|
||||
return (_jsxs("div", { children: [_jsx(PlusOutlined, {}), _jsx("div", { style: { marginTop: 8 }, children: t('choosePicture') })] }));
|
||||
}
|
||||
return _jsx(Button, { type: "default", children: t('chooseFile') });
|
||||
};
|
||||
const transformToUploadFile = () => {
|
||||
return files.map((file) => {
|
||||
let status = undefined;
|
||||
if (file.$$deleteAt$$) {
|
||||
status = 'removed';
|
||||
}
|
||||
else if (file.fileState) {
|
||||
switch (file.fileState) {
|
||||
case 'failed': {
|
||||
status = 'error';
|
||||
break;
|
||||
}
|
||||
case 'local': {
|
||||
break;
|
||||
}
|
||||
case 'uploaded': {
|
||||
status = 'done';
|
||||
break;
|
||||
}
|
||||
case 'uploading': {
|
||||
status = 'uploading';
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (file.uploadState) {
|
||||
case 'uploading': {
|
||||
status = 'uploading';
|
||||
break;
|
||||
}
|
||||
case 'failed': {
|
||||
status = 'error';
|
||||
break;
|
||||
}
|
||||
case 'success': {
|
||||
status = 'done';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
...file,
|
||||
status,
|
||||
name: file.filename,
|
||||
uid: file.id,
|
||||
size: file.size,
|
||||
};
|
||||
});
|
||||
};
|
||||
const moveRow = useCallback((dragIndex, hoverIndex) => {
|
||||
console.log('dragIndex', dragIndex, 'hoverIndex', hoverIndex);
|
||||
}, [files]);
|
||||
return (_jsxs(Space, { direction: "vertical", className: Style["oak-upload"], style: { width: "100%" }, children: [_jsx(DndProvider, { backend: isPc ? HTML5Backend : TouchBackend, children: _jsx(Upload, { className: classNames(Style["oak-upload__upload"], className), style: style, directory: directory, showUploadList: showUploadList
|
||||
? {
|
||||
showPreviewIcon: preview,
|
||||
showRemoveIcon: !disableDelete,
|
||||
showDownloadIcon: !disableDownload,
|
||||
}
|
||||
: false, beforeUpload: async (file) => {
|
||||
if (typeof beforeUpload === "function") {
|
||||
const result = await beforeUpload(file);
|
||||
if (result) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}, multiple: multiple, accept: accept, listType: listType, fileList: transformToUploadFile(), onChange: ({ file, fileList, event }) => {
|
||||
if (file instanceof File) {
|
||||
addFileByWeb(file);
|
||||
}
|
||||
}, onRemove: onRemove, onPreview: onPreview, onDownload: onDownload, itemRender: (originNode, currentFile, currentFileList) => {
|
||||
return (_jsx(DragableUploadListItem, { originNode: originNode, file: currentFile, fileList: currentFileList, moveRow: moveRow }));
|
||||
}, children: !disableInsert && files.length < maxNumber ? getUploadButton() : null }) }), tips && _jsx("small", { className: Style["oak-upload__tips"], children: tips })] }));
|
||||
}
|
||||
|
|
@ -135,6 +135,18 @@ const i18ns = [
|
|||
"weChat-authorization-login-successful": "微信授权登录成功"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "d294bc3cfdc260f1bcc6b96b4b9b49b0",
|
||||
namespace: "oak-general-business-c-extraFile-commit",
|
||||
language: "zh-CN",
|
||||
module: "oak-general-business",
|
||||
position: "src/components/extraFile/commit",
|
||||
data: {
|
||||
"executing": "%{text}中...",
|
||||
"upload": "上传",
|
||||
"uploading": "上传中"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "5c2e6feed554bc476664f2a80e09677b",
|
||||
namespace: "oak-general-business-c-extraFile-forUrl",
|
||||
|
|
@ -162,11 +174,11 @@ const i18ns = [
|
|||
}
|
||||
},
|
||||
{
|
||||
id: "d30e4a47c1d768d74efae1fade371595",
|
||||
namespace: "oak-general-business-c-extraFile-gallery2",
|
||||
id: "a0e4461f6283d6ecd0b6bba64c0560c2",
|
||||
namespace: "oak-general-business-c-extraFile-upload",
|
||||
language: "zh-CN",
|
||||
module: "oak-general-business",
|
||||
position: "src/components/extraFile/gallery2",
|
||||
position: "src/components/extraFile/upload",
|
||||
data: {
|
||||
"choosePicture": "请选择图片",
|
||||
"chooseFile": "请选择文件"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
/// <reference types="react" />
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, keyof EntityDict, boolean, {
|
||||
efPaths: string[];
|
||||
size: import("antd/es/button").ButtonSize | "mini";
|
||||
block: boolean | undefined;
|
||||
type: "primary" | "text" | "default" | "link" | "button" | "dashed" | "submit" | "reset" | undefined;
|
||||
executeText: string;
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
export default _default;
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const tslib_1 = require("tslib");
|
||||
const assert_1 = tslib_1.__importDefault(require("assert"));
|
||||
exports.default = OakComponent({
|
||||
formData({ features }) {
|
||||
const ids = this.getEfIds();
|
||||
const states = ids.map(id => features.extraFile2.getFileState(id));
|
||||
let state = 'uploaded';
|
||||
states.forEach((ele) => {
|
||||
if (ele) {
|
||||
if (['failed', 'local'].includes(ele.state)) {
|
||||
state = ele.state;
|
||||
}
|
||||
else if (ele.state === 'uploading' && state === 'uploaded') {
|
||||
state = 'uploading';
|
||||
}
|
||||
}
|
||||
});
|
||||
return {
|
||||
state,
|
||||
};
|
||||
},
|
||||
properties: {
|
||||
efPaths: [],
|
||||
size: 'middle',
|
||||
block: false,
|
||||
type: 'primary',
|
||||
executeText: '',
|
||||
},
|
||||
methods: {
|
||||
getEfIds() {
|
||||
const { efPaths } = this.props;
|
||||
const { oakFullpath } = this.state;
|
||||
(0, assert_1.default)(efPaths);
|
||||
if (oakFullpath) {
|
||||
const ids = efPaths.map((path) => {
|
||||
const path2 = path ? `${oakFullpath}.path` : oakFullpath;
|
||||
const data = this.features.runningTree.getFreshValue(path2);
|
||||
if (data) {
|
||||
return data.map(ele => ele.id);
|
||||
}
|
||||
}).flat().filter(ele => !!ele);
|
||||
return ids;
|
||||
}
|
||||
return [];
|
||||
},
|
||||
upload() {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"l-icon": "@oak-frontend-base/miniprogram_npm/lin-ui/icon/index",
|
||||
"l-button": "@oak-frontend-base/miniprogram_npm/lin-ui/button/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"executing": "%{text}中...",
|
||||
"upload": "上传",
|
||||
"uploading": "上传中"
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import { ButtonProps } from 'antd-mobile';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { FileState } from '../../../features/extraFile2';
|
||||
export default function render(props: WebComponentProps<EntityDict, any, true, {
|
||||
state: FileState;
|
||||
size?: ButtonProps['size'];
|
||||
block?: ButtonProps['block'];
|
||||
type?: ButtonProps['type'];
|
||||
executeText?: string;
|
||||
}, {
|
||||
upload: () => Promise<void>;
|
||||
}>): JSX.Element;
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const jsx_runtime_1 = require("react/jsx-runtime");
|
||||
const antd_mobile_1 = require("antd-mobile");
|
||||
function render(props) {
|
||||
const { state, oakExecutable, oakExecuting, oakDirty, size, block, type, executeText } = props.data;
|
||||
const { t, upload, execute } = props.methods;
|
||||
const disabled = oakExecuting || ['uploading'].includes(state) || (oakExecutable === false && ['uploaded'].includes(state));
|
||||
let text = executeText || t('common::action.confirm');
|
||||
if (oakExecuting) {
|
||||
text = t('executing', { text });
|
||||
}
|
||||
else if (oakExecutable === false) {
|
||||
if (state === 'uploading') {
|
||||
text = t('uploading');
|
||||
}
|
||||
else if (['failed', 'local'].includes(state)) {
|
||||
text = t('upload');
|
||||
}
|
||||
}
|
||||
return ((0, jsx_runtime_1.jsx)(antd_mobile_1.Button, { type: type, size: size, block: block, disabled: disabled, onClick: async () => {
|
||||
if (oakExecutable) {
|
||||
await execute();
|
||||
await upload();
|
||||
}
|
||||
else {
|
||||
await upload();
|
||||
}
|
||||
}, children: text }));
|
||||
}
|
||||
exports.default = render;
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import { ButtonProps } from 'antd';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { FileState } from '../../../features/extraFile2';
|
||||
export default function render(props: WebComponentProps<EntityDict, any, true, {
|
||||
state: FileState;
|
||||
size?: ButtonProps['size'];
|
||||
block?: ButtonProps['block'];
|
||||
type?: ButtonProps['type'];
|
||||
executeText?: string;
|
||||
}, {
|
||||
upload: () => Promise<void>;
|
||||
}>): JSX.Element;
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const jsx_runtime_1 = require("react/jsx-runtime");
|
||||
const antd_1 = require("antd");
|
||||
function render(props) {
|
||||
const { state, oakExecutable, oakExecuting, oakDirty, size, block, type, executeText } = props.data;
|
||||
const { t, upload, execute } = props.methods;
|
||||
const disabled = oakExecuting || ['uploading'].includes(state) || (oakExecutable === false && ['uploaded'].includes(state));
|
||||
let text = executeText || t('common::action.confirm');
|
||||
if (oakExecuting) {
|
||||
text = t('executing', { text });
|
||||
}
|
||||
else if (oakExecutable === false) {
|
||||
if (state === 'uploading') {
|
||||
text = t('uploading');
|
||||
}
|
||||
else if (['failed', 'local'].includes(state)) {
|
||||
text = t('upload');
|
||||
}
|
||||
}
|
||||
return ((0, jsx_runtime_1.jsx)(antd_1.Button, { type: type, size: size, block: block, disabled: disabled, onClick: async () => {
|
||||
if (oakExecutable) {
|
||||
await execute();
|
||||
await upload();
|
||||
}
|
||||
else {
|
||||
await upload();
|
||||
}
|
||||
}, children: text }));
|
||||
}
|
||||
exports.default = render;
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { FileState } from '../../../features/extraFile2';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity';
|
||||
import { ReactComponentProps } from 'oak-frontend-base/lib/types/Page';
|
||||
type ExtraFile = EntityDict['extraFile']['OpSchema'];
|
||||
export interface EnhancedExtraFile extends ExtraFile {
|
||||
url: string;
|
||||
thumbUrl: string;
|
||||
filename: string;
|
||||
fileState?: FileState;
|
||||
percentage?: number;
|
||||
}
|
||||
type SourceType = 'album' | 'camera';
|
||||
export type Theme = 'file' | 'image' | 'image-flow' | 'custom';
|
||||
type FileType = 'all' | 'video' | 'image' | 'file';
|
||||
type ImgMode = 'scaleToFill' | 'aspectFit' | 'aspectFill' | 'widthFix' | "heightFix" | 'top' | 'bottom' | 'left' | 'right' | 'center' | 'top left' | 'top right' | 'bottom left' | 'bottom right';
|
||||
declare const _default: <ED2 extends EntityDict & BaseEntityDict, T2 extends keyof ED2>(props: ReactComponentProps<ED2, T2, true, {
|
||||
bucket: string;
|
||||
removeLater: boolean;
|
||||
autoUpload: boolean;
|
||||
maxNumber: number;
|
||||
extension: string[];
|
||||
fileType: FileType;
|
||||
selectCount: number;
|
||||
sourceType: SourceType[];
|
||||
mediaType: ('image' | 'video')[];
|
||||
mode: ImgMode;
|
||||
size: number;
|
||||
showUploadList: boolean;
|
||||
accept: string;
|
||||
preview: boolean;
|
||||
disableDelete: boolean;
|
||||
disableAdd: boolean;
|
||||
disableDownload: boolean;
|
||||
disabled: boolean;
|
||||
type: string;
|
||||
origin: string;
|
||||
tag1: string;
|
||||
tag2: string;
|
||||
entity: keyof ED2;
|
||||
entityId: string;
|
||||
theme: Theme;
|
||||
showUploadProgress: boolean;
|
||||
children?: React.ReactNode;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const uuid_1 = require("oak-domain/lib/utils/uuid");
|
||||
;
|
||||
exports.default = OakComponent({
|
||||
entity: 'extraFile',
|
||||
isList: true,
|
||||
projection: {
|
||||
id: 1,
|
||||
tag1: 1,
|
||||
tag2: 1,
|
||||
origin: 1,
|
||||
bucket: 1,
|
||||
objectId: 1,
|
||||
filename: 1,
|
||||
extra1: 1,
|
||||
extension: 1,
|
||||
type: 1,
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
fileType: 1,
|
||||
sort: 1,
|
||||
isBridge: 1,
|
||||
uploadState: 1,
|
||||
},
|
||||
data: {
|
||||
// 根据 size 不同,计算的图片显示大小不同
|
||||
itemSizePercentage: '',
|
||||
},
|
||||
wechatMp: {
|
||||
externalClasses: ['oak-class', 'oak-item-class'],
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
filter() {
|
||||
const { tag1, tag2 } = this.props;
|
||||
const filter1 = {};
|
||||
if (tag1) {
|
||||
Object.assign(filter1, { tag1 });
|
||||
}
|
||||
if (tag2) {
|
||||
Object.assign(filter1, { tag2 });
|
||||
}
|
||||
return filter1;
|
||||
},
|
||||
},
|
||||
],
|
||||
properties: {
|
||||
bucket: '',
|
||||
removeLater: true,
|
||||
autoUpload: false,
|
||||
maxNumber: 20,
|
||||
extension: [],
|
||||
fileType: 'all',
|
||||
selectCount: 1,
|
||||
sourceType: ['album', 'camera'],
|
||||
mediaType: ['image'],
|
||||
// 图片显示模式
|
||||
mode: 'aspectFit',
|
||||
// 每行可显示的个数
|
||||
size: 3,
|
||||
showUploadList: true,
|
||||
accept: 'image/*',
|
||||
// 图片是否可预览
|
||||
preview: true,
|
||||
// 图片是否可删除
|
||||
disableDelete: false,
|
||||
// 上传按钮隐藏
|
||||
disableAdd: false,
|
||||
// 下按按钮隐藏
|
||||
disableDownload: false,
|
||||
type: 'file',
|
||||
origin: 'qiniu',
|
||||
tag1: '',
|
||||
tag2: '',
|
||||
entity: '',
|
||||
entityId: '',
|
||||
theme: 'image',
|
||||
showUploadProgress: false,
|
||||
},
|
||||
listeners: {
|
||||
maxNumber(prev, next) {
|
||||
if (this.state.oakFullpath) {
|
||||
if (prev.maxNumber !== next.maxNumber) {
|
||||
this.reRender();
|
||||
}
|
||||
}
|
||||
},
|
||||
async size(prev, next) {
|
||||
if (process.env.OAK_PLATFORM === 'wechatMp') {
|
||||
const size = next.size;
|
||||
if (!size) {
|
||||
this.setState({ itemSizePercentage: '' });
|
||||
return;
|
||||
}
|
||||
// 获取 .file-list__container 容器宽度
|
||||
const res = await this.getNodeRectFromComponent(this, '.file-list__container');
|
||||
const widthRpx = this.px2rpx(res.right - res.left);
|
||||
// 根据容器宽度计算单张图片宽度百分比
|
||||
const itemSizePercentage = (10 / size) * 10 - (20 / widthRpx) * 100 + '%;';
|
||||
this.setState({
|
||||
itemSizePercentage: itemSizePercentage,
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
features: ['extraFile2'],
|
||||
formData({ data, features }) {
|
||||
const files = data.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);
|
||||
return {
|
||||
url,
|
||||
thumbUrl,
|
||||
filename,
|
||||
fileState: fileState?.state,
|
||||
percentage: fileState?.percentage,
|
||||
...ele,
|
||||
};
|
||||
});
|
||||
return {
|
||||
files,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onRemove(file) {
|
||||
this.removeItem(file.id);
|
||||
this.features.extraFile2.removeLocalFiles([file.id]);
|
||||
},
|
||||
addExtraFileInner(options, file) {
|
||||
const { type, origin, tag1, tag2, entity, entityId, bucket } = this.props;
|
||||
const { name, fileType, size } = options;
|
||||
const extension = name.substring(name.lastIndexOf('.') + 1);
|
||||
const filename = name.substring(0, name.lastIndexOf('.'));
|
||||
const { files } = this.state;
|
||||
const sort = files.length * 10000;
|
||||
const id = this.addItem({
|
||||
bucket,
|
||||
origin,
|
||||
type,
|
||||
tag1,
|
||||
tag2,
|
||||
objectId: (0, uuid_1.generateNewId)(),
|
||||
entity,
|
||||
filename,
|
||||
size,
|
||||
extension,
|
||||
fileType,
|
||||
entityId,
|
||||
sort
|
||||
});
|
||||
this.features.extraFile2.addLocalFile(id, file);
|
||||
},
|
||||
addFileByWeb(file) {
|
||||
const { size, type, name } = file;
|
||||
this.addExtraFileInner({
|
||||
name,
|
||||
fileType: type,
|
||||
size,
|
||||
}, file);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"l-icon": "@oak-frontend-base/miniprogram_npm/lin-ui/icon/index",
|
||||
"l-button": "@oak-frontend-base/miniprogram_npm/lin-ui/button/index",
|
||||
"oak-display": "../display/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"choosePicture": "请选择图片",
|
||||
"chooseFile": "请选择文件"
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import { UploadFile } from "antd";
|
||||
import { WebComponentProps } from "oak-frontend-base";
|
||||
import { EntityDict } from "../../../oak-app-domain";
|
||||
import { EnhancedExtraFile, Theme } from './index';
|
||||
export default function render(props: WebComponentProps<EntityDict, 'extraFile', true, {
|
||||
files: EnhancedExtraFile[];
|
||||
accept?: string;
|
||||
maxNumber?: number;
|
||||
multiple?: boolean;
|
||||
draggable?: boolean;
|
||||
theme?: Theme;
|
||||
tips?: string;
|
||||
beforeUpload?: (file: File) => Promise<boolean>;
|
||||
style?: Record<string, string>;
|
||||
className?: string;
|
||||
directory?: boolean;
|
||||
onPreview?: (file: UploadFile<any>) => void;
|
||||
onDownload?: (file: UploadFile<any>) => void;
|
||||
showUploadList?: boolean;
|
||||
children?: JSX.Element;
|
||||
disableInsert?: boolean;
|
||||
disableDownload?: boolean;
|
||||
disableDelete?: boolean;
|
||||
preview?: boolean;
|
||||
}, {
|
||||
onRemove: (file: UploadFile) => void;
|
||||
addFileByWeb: (file: UploadFile) => void;
|
||||
}>): JSX.Element;
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const tslib_1 = require("tslib");
|
||||
const jsx_runtime_1 = require("react/jsx-runtime");
|
||||
const react_1 = tslib_1.__importStar(require("react"));
|
||||
const antd_1 = require("antd");
|
||||
const icons_1 = require("@ant-design/icons");
|
||||
const classnames_1 = tslib_1.__importDefault(require("classnames"));
|
||||
const react_dnd_1 = require("react-dnd");
|
||||
const react_dnd_html5_backend_1 = require("react-dnd-html5-backend");
|
||||
const react_dnd_touch_backend_1 = require("react-dnd-touch-backend");
|
||||
const utils_1 = require("oak-frontend-base/es/utils/utils");
|
||||
const web_module_less_1 = tslib_1.__importDefault(require("./web.module.less"));
|
||||
function getListType(theme) {
|
||||
const themeMap = {
|
||||
file: "text",
|
||||
image: "picture-card",
|
||||
"image-flow": "picture",
|
||||
custom: "text",
|
||||
};
|
||||
return themeMap[theme];
|
||||
}
|
||||
const type = "DragableUploadList";
|
||||
const DragableUploadListItem = ({ originNode, moveRow, file, fileList, }) => {
|
||||
const ref = react_1.default.useRef(null);
|
||||
const index = fileList.indexOf(file);
|
||||
const [{ isOver, dropClassName }, drop] = (0, react_dnd_1.useDrop)({
|
||||
accept: type,
|
||||
collect: (monitor) => {
|
||||
const { index: dragIndex } = monitor.getItem() || {};
|
||||
if (dragIndex === index) {
|
||||
return {};
|
||||
}
|
||||
return {
|
||||
isOver: monitor.isOver(),
|
||||
dropClassName: dragIndex < index ? " drop-over-downward" : " drop-over-upward",
|
||||
};
|
||||
},
|
||||
drop: (item) => {
|
||||
moveRow(item.index, index);
|
||||
},
|
||||
});
|
||||
const [, drag] = (0, react_dnd_1.useDrag)({
|
||||
type,
|
||||
item: { index },
|
||||
collect: (monitor) => ({
|
||||
isDragging: monitor.isDragging(),
|
||||
}),
|
||||
});
|
||||
drop(drag(ref));
|
||||
return ((0, jsx_runtime_1.jsx)("div", { ref: ref, className: `ant-upload-draggable-list-item ${isOver ? dropClassName : ""}`, style: { cursor: "move", height: "100%" }, children: originNode }));
|
||||
};
|
||||
function render(props) {
|
||||
const { accept = "image/*", maxNumber = 20, multiple = maxNumber !== 1, draggable = false, theme = "image", tips, beforeUpload, style, className, directory = false, onPreview, onDownload, children, showUploadList = true, files = [], disableInsert = false, disableDownload = false, disableDelete = false, preview = true, } = props.data;
|
||||
const { t, onRemove, addFileByWeb } = props.methods;
|
||||
const listType = getListType(theme);
|
||||
const getUploadButton = () => {
|
||||
if (children) {
|
||||
return children;
|
||||
}
|
||||
if (listType === "picture-card") {
|
||||
return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(icons_1.PlusOutlined, {}), (0, jsx_runtime_1.jsx)("div", { style: { marginTop: 8 }, children: t('choosePicture') })] }));
|
||||
}
|
||||
return (0, jsx_runtime_1.jsx)(antd_1.Button, { type: "default", children: t('chooseFile') });
|
||||
};
|
||||
const transformToUploadFile = () => {
|
||||
return files.map((file) => {
|
||||
let status = undefined;
|
||||
if (file.$$deleteAt$$) {
|
||||
status = 'removed';
|
||||
}
|
||||
else if (file.fileState) {
|
||||
switch (file.fileState) {
|
||||
case 'failed': {
|
||||
status = 'error';
|
||||
break;
|
||||
}
|
||||
case 'local': {
|
||||
break;
|
||||
}
|
||||
case 'uploaded': {
|
||||
status = 'done';
|
||||
break;
|
||||
}
|
||||
case 'uploading': {
|
||||
status = 'uploading';
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (file.uploadState) {
|
||||
case 'uploading': {
|
||||
status = 'uploading';
|
||||
break;
|
||||
}
|
||||
case 'failed': {
|
||||
status = 'error';
|
||||
break;
|
||||
}
|
||||
case 'success': {
|
||||
status = 'done';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
...file,
|
||||
status,
|
||||
name: file.filename,
|
||||
uid: file.id,
|
||||
size: file.size,
|
||||
};
|
||||
});
|
||||
};
|
||||
const moveRow = (0, react_1.useCallback)((dragIndex, hoverIndex) => {
|
||||
console.log('dragIndex', dragIndex, 'hoverIndex', hoverIndex);
|
||||
}, [files]);
|
||||
return ((0, jsx_runtime_1.jsxs)(antd_1.Space, { direction: "vertical", className: web_module_less_1.default["oak-upload"], style: { width: "100%" }, children: [(0, jsx_runtime_1.jsx)(react_dnd_1.DndProvider, { backend: utils_1.isPc ? react_dnd_html5_backend_1.HTML5Backend : react_dnd_touch_backend_1.TouchBackend, children: (0, jsx_runtime_1.jsx)(antd_1.Upload, { className: (0, classnames_1.default)(web_module_less_1.default["oak-upload__upload"], className), style: style, directory: directory, showUploadList: showUploadList
|
||||
? {
|
||||
showPreviewIcon: preview,
|
||||
showRemoveIcon: !disableDelete,
|
||||
showDownloadIcon: !disableDownload,
|
||||
}
|
||||
: false, beforeUpload: async (file) => {
|
||||
if (typeof beforeUpload === "function") {
|
||||
const result = await beforeUpload(file);
|
||||
if (result) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}, multiple: multiple, accept: accept, listType: listType, fileList: transformToUploadFile(), onChange: ({ file, fileList, event }) => {
|
||||
if (file instanceof File) {
|
||||
addFileByWeb(file);
|
||||
}
|
||||
}, onRemove: onRemove, onPreview: onPreview, onDownload: onDownload, itemRender: (originNode, currentFile, currentFileList) => {
|
||||
return ((0, jsx_runtime_1.jsx)(DragableUploadListItem, { originNode: originNode, file: currentFile, fileList: currentFileList, moveRow: moveRow }));
|
||||
}, children: !disableInsert && files.length < maxNumber ? getUploadButton() : null }) }), tips && (0, jsx_runtime_1.jsx)("small", { className: web_module_less_1.default["oak-upload__tips"], children: tips })] }));
|
||||
}
|
||||
exports.default = render;
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
.oak-upload {
|
||||
&__tips {
|
||||
display: block;
|
||||
color: var(--oak-text-color-placeholder);
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
|
|
@ -137,6 +137,18 @@ const i18ns = [
|
|||
"weChat-authorization-login-successful": "微信授权登录成功"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "d294bc3cfdc260f1bcc6b96b4b9b49b0",
|
||||
namespace: "oak-general-business-c-extraFile-commit",
|
||||
language: "zh-CN",
|
||||
module: "oak-general-business",
|
||||
position: "src/components/extraFile/commit",
|
||||
data: {
|
||||
"executing": "%{text}中...",
|
||||
"upload": "上传",
|
||||
"uploading": "上传中"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "5c2e6feed554bc476664f2a80e09677b",
|
||||
namespace: "oak-general-business-c-extraFile-forUrl",
|
||||
|
|
@ -164,11 +176,11 @@ const i18ns = [
|
|||
}
|
||||
},
|
||||
{
|
||||
id: "d30e4a47c1d768d74efae1fade371595",
|
||||
namespace: "oak-general-business-c-extraFile-gallery2",
|
||||
id: "a0e4461f6283d6ecd0b6bba64c0560c2",
|
||||
namespace: "oak-general-business-c-extraFile-upload",
|
||||
language: "zh-CN",
|
||||
module: "oak-general-business",
|
||||
position: "src/components/extraFile/gallery2",
|
||||
position: "src/components/extraFile/upload",
|
||||
data: {
|
||||
"choosePicture": "请选择图片",
|
||||
"chooseFile": "请选择文件"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"l-icon": "@oak-frontend-base/miniprogram_npm/lin-ui/icon/index",
|
||||
"l-button": "@oak-frontend-base/miniprogram_npm/lin-ui/button/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
import assert from 'assert';
|
||||
import { ButtonProps } from 'antd';
|
||||
import { ButtonProps as MobileButtonProps } from 'antd-mobile';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { FileState } from '../../../features/extraFile2';
|
||||
|
||||
export default OakComponent({
|
||||
formData({ features }) {
|
||||
const ids: string[] = this.getEfIds();
|
||||
const states = ids.map(
|
||||
id => features.extraFile2.getFileState(id)
|
||||
);
|
||||
let state: FileState = 'uploaded';
|
||||
states.forEach(
|
||||
(ele) => {
|
||||
if (ele) {
|
||||
if (['failed', 'local'].includes(ele.state)) {
|
||||
state = ele.state;
|
||||
}
|
||||
else if (ele.state === 'uploading' && state === 'uploaded') {
|
||||
state = 'uploading';
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
return {
|
||||
state,
|
||||
};
|
||||
},
|
||||
properties: {
|
||||
efPaths: [] as string[],
|
||||
size: 'middle' as ButtonProps['size'] | MobileButtonProps['size'],
|
||||
block: false as ButtonProps['block'] | MobileButtonProps['block'],
|
||||
type: 'primary' as ButtonProps['type'] | MobileButtonProps['type'],
|
||||
executeText: '',
|
||||
},
|
||||
methods: {
|
||||
getEfIds() {
|
||||
const { efPaths } = this.props;
|
||||
const { oakFullpath } = this.state;
|
||||
assert(efPaths);
|
||||
if (oakFullpath) {
|
||||
const ids = efPaths.map(
|
||||
(path) => {
|
||||
const path2 = path ? `${oakFullpath}.path` : oakFullpath;
|
||||
const data = this.features.runningTree.getFreshValue(path2);
|
||||
if (data) {
|
||||
return (data as EntityDict['extraFile']['OpSchema'][]).map(
|
||||
ele => ele.id
|
||||
);
|
||||
}
|
||||
}
|
||||
).flat().filter(
|
||||
ele => !!ele
|
||||
) as string[];
|
||||
return ids;
|
||||
}
|
||||
return [];
|
||||
},
|
||||
upload() {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"executing": "%{text}中...",
|
||||
"upload": "上传",
|
||||
"uploading": "上传中"
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
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';
|
||||
|
||||
export default function render(props: WebComponentProps<EntityDict, any, true, {
|
||||
state: FileState;
|
||||
size?: ButtonProps['size'];
|
||||
block?: ButtonProps['block'];
|
||||
type?: ButtonProps['type'];
|
||||
executeText?: string;
|
||||
}, {
|
||||
upload: () => Promise<void>
|
||||
}>) {
|
||||
const { state, oakExecutable, oakExecuting, oakDirty,
|
||||
size, block, type, executeText } = props.data;
|
||||
const { t, upload, execute } = props.methods;
|
||||
|
||||
const disabled = oakExecuting || ['uploading'].includes(state) || (oakExecutable === false && ['uploaded'].includes(state));
|
||||
let text = executeText || t('common::action.confirm');
|
||||
if (oakExecuting) {
|
||||
text = t('executing', { text });
|
||||
}
|
||||
else if (oakExecutable === false) {
|
||||
if (state === 'uploading') {
|
||||
text = t('uploading');
|
||||
}
|
||||
else if (['failed', 'local'].includes(state)) {
|
||||
text = t('upload');
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
type={type}
|
||||
size={size}
|
||||
block={block}
|
||||
disabled={disabled}
|
||||
onClick={async () => {
|
||||
if (oakExecutable) {
|
||||
await execute();
|
||||
await upload();
|
||||
}
|
||||
else {
|
||||
await upload();
|
||||
}
|
||||
}}
|
||||
>
|
||||
{text}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
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';
|
||||
|
||||
export default function render(props: WebComponentProps<EntityDict, any, true, {
|
||||
state: FileState;
|
||||
size?: ButtonProps['size'];
|
||||
block?: ButtonProps['block'];
|
||||
type?: ButtonProps['type'];
|
||||
executeText?: string;
|
||||
}, {
|
||||
upload: () => Promise<void>
|
||||
}>) {
|
||||
const { state, oakExecutable, oakExecuting, oakDirty,
|
||||
size, block, type, executeText } = props.data;
|
||||
const { t, upload, execute } = props.methods;
|
||||
|
||||
const disabled = oakExecuting || ['uploading'].includes(state) || (oakExecutable === false && ['uploaded'].includes(state));
|
||||
let text = executeText || t('common::action.confirm');
|
||||
if (oakExecuting) {
|
||||
text = t('executing', { text });
|
||||
}
|
||||
else if (oakExecutable === false) {
|
||||
if (state === 'uploading') {
|
||||
text = t('uploading');
|
||||
}
|
||||
else if (['failed', 'local'].includes(state)) {
|
||||
text = t('upload');
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
type={type}
|
||||
size={size}
|
||||
block={block}
|
||||
disabled={disabled}
|
||||
onClick={async () => {
|
||||
if (oakExecutable) {
|
||||
await execute();
|
||||
await upload();
|
||||
}
|
||||
else {
|
||||
await upload();
|
||||
}
|
||||
}}
|
||||
>
|
||||
{text}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"l-icon": "@oak-frontend-base/miniprogram_npm/lin-ui/icon/index",
|
||||
"l-button": "@oak-frontend-base/miniprogram_npm/lin-ui/button/index",
|
||||
"oak-display": "../display/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import { generateNewId } from 'oak-domain/lib/utils/uuid';
|
||||
import { pull } from 'oak-domain/lib/utils/lodash';
|
||||
import assert from 'assert';
|
||||
import Dialog from '../../../utils/dialog/index';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
|
|
@ -65,6 +66,7 @@ export default OakComponent({
|
|||
},
|
||||
],
|
||||
properties: {
|
||||
bucket: '',
|
||||
removeLater: true,
|
||||
autoUpload: false,
|
||||
maxNumber: 20,
|
||||
|
|
@ -87,7 +89,6 @@ export default OakComponent({
|
|||
disableAdd: false,
|
||||
// 下按按钮隐藏
|
||||
disableDownload: false,
|
||||
disabled: false,
|
||||
type: 'file' as ExtraFile['type'],
|
||||
origin: 'qiniu' as ExtraFile['origin'],
|
||||
tag1: '',
|
||||
|
|
@ -152,15 +153,16 @@ export default OakComponent({
|
|||
};
|
||||
},
|
||||
methods: {
|
||||
onDeleteByWeb(file: EnhancedExtraFile) {
|
||||
console.log(file);
|
||||
onRemove(file: EnhancedExtraFile) {
|
||||
this.removeItem(file.id);
|
||||
this.features.extraFile2.removeLocalFiles([file.id]);
|
||||
},
|
||||
addExtraFileInner(options: {
|
||||
name: string;
|
||||
fileType: string;
|
||||
size: number;
|
||||
}, file: File | string) {
|
||||
const { type, origin, tag1, tag2, entity, entityId, autoUpload } = this.props;
|
||||
const { type, origin, tag1, tag2, entity, entityId, bucket } = this.props;
|
||||
const { name, fileType, size } = options;
|
||||
const extension = name.substring(name.lastIndexOf('.') + 1);
|
||||
const filename = name.substring(0, name.lastIndexOf('.'));
|
||||
|
|
@ -168,6 +170,7 @@ export default OakComponent({
|
|||
const sort = files.length * 10000;
|
||||
|
||||
const id = this.addItem({
|
||||
bucket,
|
||||
origin,
|
||||
type,
|
||||
tag1,
|
||||
|
|
@ -198,6 +201,7 @@ export default OakComponent({
|
|||
T2,
|
||||
true,
|
||||
{
|
||||
bucket: string, // 上传的存储桶位置
|
||||
removeLater: boolean,
|
||||
autoUpload: boolean,
|
||||
maxNumber: number,
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
.oak-upload {
|
||||
&__tips {
|
||||
display: block;
|
||||
color: var(--oak-text-color-placeholder);
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
|
|
@ -79,7 +79,6 @@ export default function render(props: WebComponentProps<
|
|||
theme?: Theme;
|
||||
tips?: string;
|
||||
beforeUpload?: (file: File) => Promise<boolean>;
|
||||
disabled?: boolean;
|
||||
style?: Record<string, string>;
|
||||
className?: string;
|
||||
directory?: boolean;
|
||||
|
|
@ -88,12 +87,11 @@ export default function render(props: WebComponentProps<
|
|||
showUploadList?: boolean;
|
||||
children?: JSX.Element;
|
||||
disableInsert?: boolean;
|
||||
disableAdd?: boolean;
|
||||
disableDownload?: boolean;
|
||||
disableDelete?: boolean;
|
||||
preview?: boolean;
|
||||
}, {
|
||||
onDeleteByWeb: (file: UploadFile) => void;
|
||||
onRemove: (file: UploadFile) => void;
|
||||
addFileByWeb: (file: UploadFile) => void;
|
||||
}>) {
|
||||
const {
|
||||
|
|
@ -104,7 +102,6 @@ export default function render(props: WebComponentProps<
|
|||
theme = "image",
|
||||
tips,
|
||||
beforeUpload,
|
||||
disabled,
|
||||
style,
|
||||
className,
|
||||
directory = false,
|
||||
|
|
@ -114,13 +111,12 @@ export default function render(props: WebComponentProps<
|
|||
showUploadList = true,
|
||||
files = [],
|
||||
disableInsert = false,
|
||||
disableAdd = false,
|
||||
disableDownload = false,
|
||||
disableDelete = false,
|
||||
preview = true,
|
||||
} = props.data;
|
||||
|
||||
const { t, onDeleteByWeb, addFileByWeb } = props.methods;
|
||||
const { t, onRemove, addFileByWeb } = props.methods;
|
||||
|
||||
const listType = getListType(theme);
|
||||
const getUploadButton = () => {
|
||||
|
|
@ -211,7 +207,6 @@ export default function render(props: WebComponentProps<
|
|||
<Upload
|
||||
className={classNames(Style["oak-upload__upload"], className)}
|
||||
style={style}
|
||||
disabled={disabled}
|
||||
directory={directory}
|
||||
showUploadList={
|
||||
showUploadList
|
||||
|
|
@ -232,14 +227,15 @@ export default function render(props: WebComponentProps<
|
|||
return false;
|
||||
}}
|
||||
multiple={multiple}
|
||||
maxCount={maxNumber}
|
||||
accept={accept}
|
||||
listType={listType}
|
||||
fileList={transformToUploadFile()}
|
||||
onChange={({ file, fileList, event }) => {
|
||||
addFileByWeb(file);
|
||||
if (file instanceof File) {
|
||||
addFileByWeb(file);
|
||||
}
|
||||
}}
|
||||
onRemove={onDeleteByWeb}
|
||||
onRemove={onRemove}
|
||||
onPreview={onPreview}
|
||||
onDownload={onDownload}
|
||||
itemRender={(originNode, currentFile, currentFileList) => {
|
||||
|
|
@ -253,7 +249,7 @@ export default function render(props: WebComponentProps<
|
|||
);
|
||||
}}
|
||||
>
|
||||
{!disableInsert && !disableAdd ? getUploadButton() : null}
|
||||
{!disableInsert && files.length < maxNumber ? getUploadButton() : null}
|
||||
</Upload>
|
||||
</DndProvider>
|
||||
|
||||
|
|
@ -137,6 +137,18 @@ const i18ns: I18n[] = [
|
|||
"weChat-authorization-login-successful": "微信授权登录成功"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "d294bc3cfdc260f1bcc6b96b4b9b49b0",
|
||||
namespace: "oak-general-business-c-extraFile-commit",
|
||||
language: "zh-CN",
|
||||
module: "oak-general-business",
|
||||
position: "src/components/extraFile/commit",
|
||||
data: {
|
||||
"executing": "%{text}中...",
|
||||
"upload": "上传",
|
||||
"uploading": "上传中"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "5c2e6feed554bc476664f2a80e09677b",
|
||||
namespace: "oak-general-business-c-extraFile-forUrl",
|
||||
|
|
@ -164,11 +176,11 @@ const i18ns: I18n[] = [
|
|||
}
|
||||
},
|
||||
{
|
||||
id: "d30e4a47c1d768d74efae1fade371595",
|
||||
namespace: "oak-general-business-c-extraFile-gallery2",
|
||||
id: "a0e4461f6283d6ecd0b6bba64c0560c2",
|
||||
namespace: "oak-general-business-c-extraFile-upload",
|
||||
language: "zh-CN",
|
||||
module: "oak-general-business",
|
||||
position: "src/components/extraFile/gallery2",
|
||||
position: "src/components/extraFile/upload",
|
||||
data: {
|
||||
"choosePicture": "请选择图片",
|
||||
"chooseFile": "请选择文件"
|
||||
|
|
|
|||
Loading…
Reference in New Issue