This commit is contained in:
qsc 2023-06-27 15:23:39 +08:00
commit 43ea58b8c9
25 changed files with 287 additions and 294 deletions

View File

@ -1,7 +1,6 @@
import { EntityDict } from '../../../general-app-domain';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity';
import { ReactComponentProps } from 'oak-frontend-base/lib/types/Page';
declare type ImgUrlsOrigin = 'wechat' | 'others';
declare const _default: <ED2 extends EntityDict & BaseEntityDict, T2 extends keyof ED2>(props: ReactComponentProps<ED2, T2, true, {
type: string;
origin: string;
@ -10,6 +9,5 @@ declare const _default: <ED2 extends EntityDict & BaseEntityDict, T2 extends key
entity: keyof ED2;
entityId: string;
imgUrls: string[];
imgUrlsOrigin: ImgUrlsOrigin;
}>) => React.ReactElement;
export default _default;

View File

@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var uuid_1 = require("oak-domain/lib/utils/uuid");
var assert_1 = tslib_1.__importDefault(require("assert"));
var lodash_1 = require("oak-domain/lib/utils/lodash");
exports.default = OakComponent({
entity: 'extraFile',
isList: true,
@ -43,13 +44,15 @@ exports.default = OakComponent({
var _b, _c;
var originalFiles = _a.data, features = _a.features;
var file;
var notDeleteFiles = originalFiles === null || originalFiles === void 0 ? void 0 : originalFiles.filter(function (ele) { return !ele.$$deleteAt$$; });
if (this.props.tag1) {
file = (_b = originalFiles === null || originalFiles === void 0 ? void 0 : originalFiles.filter(function (ele) { return (ele === null || ele === void 0 ? void 0 : ele.tag1) === _this.props.tag1; })) === null || _b === void 0 ? void 0 : _b[0];
file = (_b = notDeleteFiles === null || notDeleteFiles === void 0 ? void 0 : notDeleteFiles.filter(function (ele) { return (ele === null || ele === void 0 ? void 0 : ele.tag1) === _this.props.tag1; })) === null || _b === void 0 ? void 0 : _b[0];
}
if (this.props.tag2) {
file = (_c = originalFiles === null || originalFiles === void 0 ? void 0 : originalFiles.filter(function (ele) { return (ele === null || ele === void 0 ? void 0 : ele.tag2) === _this.props.tag2; })) === null || _c === void 0 ? void 0 : _c[0];
file = (_c = notDeleteFiles === null || notDeleteFiles === void 0 ? void 0 : notDeleteFiles.filter(function (ele) { return (ele === null || ele === void 0 ? void 0 : ele.tag2) === _this.props.tag2; })) === null || _c === void 0 ? void 0 : _c[0];
}
return {
file: file,
src: features.extraFile.getUrl(file),
isBridge: file === null || file === void 0 ? void 0 : file.isBridge,
};
@ -60,7 +63,7 @@ exports.default = OakComponent({
renderImgs: [],
methodsType: '',
bridgeUrl: '',
originImgLoading: false,
selectedId: -1,
},
properties: {
type: '',
@ -69,47 +72,18 @@ exports.default = OakComponent({
entity: '',
entityId: '',
imgUrls: [],
imgUrlsOrigin: 'others',
},
lifetimes: {
// features.getBridgeUrl 中使用了URL.createObjectURL
attached: function () {
var imgUrlsOrigin = this.props.imgUrlsOrigin;
var renderImgs = this.state.renderImgs;
if (imgUrlsOrigin === 'wechat' && renderImgs && renderImgs.length) {
renderImgs.forEach(function (ele) {
URL.revokeObjectURL(ele.renderUrl);
});
}
}
},
lifetimes: {},
listeners: {
src: function (prev, next) {
imgUrls: function (prev, next) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var url, err_1;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(prev !== next && !!this.state.src)) return [3 /*break*/, 4];
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.features.extraFile.getBridgeUrl(this.state.src)];
case 2:
url = _a.sent();
this.setState({
bridgeUrl: url,
});
return [3 /*break*/, 4];
case 3:
err_1 = _a.sent();
this.setMessage({
content: '图片加载错误',
type: 'error'
});
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
// 因为imgUrls是从请求来的 它有可能比上边的src listener中的getBridgeUrl慢
// 所以此处增加前后项imgUrls里都有值且不等的条件再去clean
if ((prev === null || prev === void 0 ? void 0 : prev.imgUrls.length) && (next === null || next === void 0 ? void 0 : next.imgUrls.length) && !(0, lodash_1.isEqual)(prev.imgUrls, next.imgUrls)) {
this.clean();
}
return [2 /*return*/];
});
});
}
@ -117,21 +91,13 @@ exports.default = OakComponent({
methods: {
chooseMethod: function (method) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _a, fileInput_1, imgElement_1, _b, imgUrlsOrigin, imgUrls, renderImgs, i, renderUrl;
var fileInput_1, imgElement, imgUrls, renderImgs, renderImgs2, i, renderUrl, isWechatUrl;
var _this = this;
return tslib_1.__generator(this, function (_c) {
switch (_c.label) {
case 0:
_a = method;
switch (_a) {
case 'uploadLocalImg': return [3 /*break*/, 1];
case 'url': return [3 /*break*/, 2];
case 'original': return [3 /*break*/, 3];
}
return [3 /*break*/, 11];
case 1:
return tslib_1.__generator(this, function (_a) {
switch (method) {
case 'uploadLocalImg':
fileInput_1 = document.createElement('input');
imgElement_1 = document.getElementById('previewImg');
imgElement = document.getElementById('previewImg');
fileInput_1.type = 'file';
fileInput_1.accept = 'image/png, image/jpeg';
fileInput_1.style.display = 'none';
@ -139,85 +105,58 @@ exports.default = OakComponent({
if (!fileInput_1.files || fileInput_1.files.length === 0) {
return;
}
// 创建一个 FileReader 对象
var reader = new FileReader();
// 当文件读取完成后,显示预览图像
reader.addEventListener("load", function () {
imgElement_1.src = reader.result;
imgElement_1.style.display = 'block';
});
// 读取用户选择的文件
reader.readAsDataURL(fileInput_1.files[0]);
_this.myUpdateItem(fileInput_1.files[0]);
});
fileInput_1.click();
this.setState({
methodsType: method
});
return [3 /*break*/, 11];
case 2:
this.setSelectedId(-1);
break;
case 'url':
this.setState({
isModalOpen: true,
methodsType: method
});
return [3 /*break*/, 11];
case 3:
break;
case 'original':
this.setState({
isModalOpen1: true,
methodsType: method
});
_b = this.props, imgUrlsOrigin = _b.imgUrlsOrigin, imgUrls = _b.imgUrls;
imgUrls = this.props.imgUrls;
renderImgs = this.state.renderImgs;
if (!(imgUrls && imgUrls.length)) return [3 /*break*/, 10];
this.setState({
originImgLoading: true,
});
i = 0;
_c.label = 4;
case 4:
if (!(i < imgUrls.length)) return [3 /*break*/, 9];
if (renderImgs[i] && renderImgs[i].originUrl === imgUrls[i]) {
this.setState({
originImgLoading: false,
});
return [2 /*return*/];
}
else if (renderImgs[i] && renderImgs[i].originUrl !== imgUrls[i]) {
if (imgUrlsOrigin === 'wechat') {
URL.revokeObjectURL(renderImgs[i].renderUrl);
renderImgs2 = new (Array.bind.apply(Array, tslib_1.__spreadArray([void 0], tslib_1.__read(renderImgs), false)))();
if (imgUrls && imgUrls.length) {
for (i = 0; i < imgUrls.length; i++) {
if (renderImgs2[i] && renderImgs2[i].originUrl === imgUrls[i]) {
return [2 /*return*/];
}
else if (renderImgs2[i] && renderImgs2[i].originUrl !== imgUrls[i]) {
renderImgs2 = [];
}
renderUrl = void 0;
isWechatUrl = this.isWechatUrlFn(imgUrls[i]);
if (isWechatUrl) {
renderUrl = this.features.extraFile.getUrl({ isBridge: true, extra1: imgUrls[i] });
}
else {
renderUrl = imgUrls[i];
}
renderImgs2.push({
renderUrl: renderUrl,
originUrl: imgUrls[i],
id: i,
isBridge: isWechatUrl
});
}
this.setState({
renderImgs: [],
renderImgs: renderImgs2,
});
}
renderUrl = void 0;
if (!(imgUrlsOrigin === 'wechat')) return [3 /*break*/, 6];
return [4 /*yield*/, this.features.extraFile.getBridgeUrl(imgUrls[i])];
case 5:
renderUrl = _c.sent();
return [3 /*break*/, 7];
case 6:
renderUrl = imgUrls[i];
_c.label = 7;
case 7:
renderImgs.push({
renderUrl: renderUrl,
originUrl: imgUrls[i],
id: i,
});
_c.label = 8;
case 8:
i++;
return [3 /*break*/, 4];
case 9:
this.setState({
renderImgs: tslib_1.__spreadArray([], tslib_1.__read(renderImgs), false),
originImgLoading: false,
});
_c.label = 10;
case 10: return [3 /*break*/, 11];
case 11: return [2 /*return*/];
break;
}
return [2 /*return*/];
});
});
},
@ -233,7 +172,6 @@ exports.default = OakComponent({
},
createExtraFileData: function (params) {
var methodsType = this.state.methodsType;
var imgUrlsOrigin = this.props.imgUrlsOrigin;
var _a = this.props, tag1 = _a.tag1, tag2 = _a.tag2, entity = _a.entity, entityId = _a.entityId;
var extension = '';
var filename = '';
@ -267,7 +205,7 @@ exports.default = OakComponent({
origin: 'unknown',
extension: extension,
filename: filename,
isBridge: imgUrlsOrigin === 'wechat'
isBridge: this.isWechatUrlFn(params)
});
break;
case 'original':
@ -275,7 +213,7 @@ exports.default = OakComponent({
origin: 'unknown',
extension: extension,
filename: filename,
isBridge: imgUrlsOrigin === 'wechat',
isBridge: this.isWechatUrlFn(params)
});
break;
}
@ -315,20 +253,16 @@ exports.default = OakComponent({
},
myUpdateItem: function (params) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var files, createData;
var _this = this;
var file, createData;
return tslib_1.__generator(this, function (_a) {
files = this.state.files;
if (files && files.length) {
files.map(function (ele) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
this.removeItem(ele.id);
return [2 /*return*/];
});
}); });
file = this.state.file;
if (file) {
this.removeItem(file.id);
}
if (!!params) {
createData = this.createExtraFileData(params);
this.myAddItem(createData);
}
createData = this.createExtraFileData(params);
this.myAddItem(createData);
return [2 /*return*/];
});
});
@ -339,18 +273,21 @@ exports.default = OakComponent({
return;
}
this.myUpdateItem(value);
var imgElement = document.getElementById('previewImg');
imgElement.src = value;
imgElement.style.display = 'block';
this.setSelectedId(-1);
},
onModal1Confirm: function (value) {
var renderImgs = this.state.renderImgs;
var img = renderImgs.find(function (ele) { return ele.id === value; });
this.myUpdateItem(img.originUrl);
var imgElement = document.getElementById('previewImg');
imgElement.src = (img === null || img === void 0 ? void 0 : img.renderUrl) || '';
imgElement.style.display = 'block';
this.myUpdateItem(img === null || img === void 0 ? void 0 : img.originUrl);
this.closeModal1();
},
},
isWechatUrlFn: function (url) {
return (url.startsWith('https://mmbiz.qpic.cn') || url.startsWith('http://mmbiz.qpic.cn'));
},
setSelectedId: function (id) {
this.setState({
selectedId: id
});
}
}
});

View File

@ -11,12 +11,13 @@ export default function render(props: WebComponentProps<EntityDict, "extraFile",
originUrl: string;
id: number;
}[];
originImgLoading: boolean;
selectedId: number;
}, {
onModalConfirm: (value: string) => void;
chooseMethod: (method: MethodsType) => void;
closeModal1: () => void;
closeModal: () => void;
onModal1Confirm: (value: number) => void;
}>): import("react/jsx-runtime").JSX.Element;
setSelectedId: (id: number) => void;
}>): JSX.Element;
export {};

View File

@ -2,24 +2,21 @@
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var jsx_runtime_1 = require("react/jsx-runtime");
var react_1 = require("react");
var antd_1 = require("antd");
var icons_1 = require("@ant-design/icons");
var web_module_less_1 = tslib_1.__importDefault(require("./web.module.less"));
var imgBox_1 = tslib_1.__importDefault(require("oak-frontend-base/src/components/imgBox"));
function render(props) {
var _a = props.data, isModalOpen = _a.isModalOpen, isModalOpen1 = _a.isModalOpen1, renderImgs = _a.renderImgs, src = _a.src, bridgeUrl = _a.bridgeUrl, originImgLoading = _a.originImgLoading;
var _b = props.methods, t = _b.t, onModalConfirm = _b.onModalConfirm, chooseMethod = _b.chooseMethod, closeModal1 = _b.closeModal1, closeModal = _b.closeModal, onModal1Confirm = _b.onModal1Confirm;
var _a = props.data, isModalOpen = _a.isModalOpen, isModalOpen1 = _a.isModalOpen1, renderImgs = _a.renderImgs, src = _a.src, bridgeUrl = _a.bridgeUrl, selectedId = _a.selectedId;
var _b = props.methods, t = _b.t, onModalConfirm = _b.onModalConfirm, chooseMethod = _b.chooseMethod, closeModal1 = _b.closeModal1, closeModal = _b.closeModal, onModal1Confirm = _b.onModal1Confirm, setSelectedId = _b.setSelectedId;
var methods = ['original', 'url', 'uploadLocalImg'];
var _c = tslib_1.__read((0, react_1.useState)(-1), 2), selectedId = _c[0], setSelectedId = _c[1];
var _d = tslib_1.__read(antd_1.Form.useForm(), 1), form = _d[0];
var renderUrl = bridgeUrl || src; // 用户选图预览
var _c = tslib_1.__read(antd_1.Form.useForm(), 1), form = _c[0];
var handleOk = function () {
onModalConfirm(form.getFieldValue('url'));
form.setFieldValue('url', '');
closeModal();
};
return ((0, jsx_runtime_1.jsxs)("div", tslib_1.__assign({ className: web_module_less_1.default.imgBox }, { children: [(0, jsx_runtime_1.jsxs)(antd_1.Space, tslib_1.__assign({ direction: "vertical", size: 4 }, { children: [(0, jsx_runtime_1.jsx)(icons_1.PlusOutlined, {}), (0, jsx_runtime_1.jsx)("div", { children: "\u9009\u62E9\u5C01\u9762" })] })), (0, jsx_runtime_1.jsx)("img", { id: "previewImg", src: renderUrl, alt: "previewImg", className: web_module_less_1.default.previewImg, style: { display: renderUrl ? 'inline-block' : 'none' } }), (0, jsx_runtime_1.jsx)("div", tslib_1.__assign({ className: web_module_less_1.default.methodList }, { children: methods && methods.map(function (ele) { return ((0, jsx_runtime_1.jsx)("div", tslib_1.__assign({ className: web_module_less_1.default.methodListItem, onClick: function () {
return ((0, jsx_runtime_1.jsxs)("div", tslib_1.__assign({ className: web_module_less_1.default.imgBox }, { children: [(0, jsx_runtime_1.jsxs)(antd_1.Space, tslib_1.__assign({ direction: "vertical", size: 4 }, { children: [(0, jsx_runtime_1.jsx)(icons_1.PlusOutlined, {}), (0, jsx_runtime_1.jsx)("div", { children: "\u9009\u62E9\u5C01\u9762" })] })), (0, jsx_runtime_1.jsx)("img", { id: "previewImg", src: src, alt: "previewImg", className: web_module_less_1.default.previewImg, style: { display: src ? 'inline-block' : 'none' } }), (0, jsx_runtime_1.jsx)("div", tslib_1.__assign({ className: web_module_less_1.default.methodList }, { children: methods && methods.map(function (ele) { return ((0, jsx_runtime_1.jsx)("div", tslib_1.__assign({ className: web_module_less_1.default.methodListItem, onClick: function () {
chooseMethod(ele);
} }, { children: t(ele) }))); }) })), (0, jsx_runtime_1.jsx)(antd_1.Modal, tslib_1.__assign({ title: t('fillInImageLink'), open: isModalOpen, onOk: handleOk, onCancel: closeModal }, { children: (0, jsx_runtime_1.jsx)(antd_1.Form, tslib_1.__assign({ form: form, className: web_module_less_1.default.formMT }, { children: (0, jsx_runtime_1.jsx)(antd_1.Form.Item, tslib_1.__assign({ name: "url", rules: [
{
@ -33,15 +30,15 @@ function render(props) {
] }, { children: (0, jsx_runtime_1.jsx)(antd_1.Input, { onChange: function (_a) {
var value = _a.target.value;
form.setFieldValue('url', value);
}, placeholder: '\u5982\uFF1Ahttps://www.xxx.com' }) })) })) })), (0, jsx_runtime_1.jsx)(antd_1.Modal, tslib_1.__assign({ width: 800, title: t('chooseImage'), open: isModalOpen1, onOk: function () { return onModal1Confirm(selectedId); }, onCancel: closeModal1 }, { children: (0, jsx_runtime_1.jsx)(antd_1.Spin, tslib_1.__assign({ spinning: originImgLoading }, { children: (renderImgs && renderImgs.length) ? ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(antd_1.Row, tslib_1.__assign({ gutter: [4, 4] }, { children: renderImgs.map(function (img) {
return (0, jsx_runtime_1.jsx)(antd_1.Col, tslib_1.__assign({ span: 4 }, { children: (0, jsx_runtime_1.jsx)(imgBox_1.default, { width: "100%", bordered: true, mode: "select", src: img.renderUrl, selected: selectedId === img.id, onClick: function () {
if (selectedId === img.id) {
setSelectedId(-1);
}
else {
setSelectedId(img.id);
}
} }, img.id) }));
}) })) })) : ((0, jsx_runtime_1.jsx)(antd_1.Empty, { image: antd_1.Empty.PRESENTED_IMAGE_SIMPLE })) })) }))] })));
}, placeholder: '\u5982\uFF1Ahttps://www.xxx.com' }) })) })) })), (0, jsx_runtime_1.jsx)(antd_1.Modal, tslib_1.__assign({ width: 800, title: t('chooseImage'), open: isModalOpen1, onOk: function () { return onModal1Confirm(selectedId); }, onCancel: closeModal1 }, { children: (renderImgs && renderImgs.length) ? ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(antd_1.Row, tslib_1.__assign({ gutter: [4, 4] }, { children: renderImgs.map(function (img) {
return (0, jsx_runtime_1.jsx)(antd_1.Col, tslib_1.__assign({ span: 4 }, { children: (0, jsx_runtime_1.jsx)(imgBox_1.default, { width: "100%", bordered: true, mode: "select", src: img.renderUrl, selected: selectedId === img.id, onClick: function () {
if (selectedId === img.id) {
setSelectedId(-1);
}
else {
setSelectedId(img.id);
}
} }, img.id) }));
}) })) })) : ((0, jsx_runtime_1.jsx)(antd_1.Empty, { image: antd_1.Empty.PRESENTED_IMAGE_SIMPLE })) }))] })));
}
exports.default = render;

View File

@ -0,0 +1,59 @@
.imgBox {
width: 220px;
height: 100px;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
color: #888;
box-sizing: border-box;
border: 2px dashed #EBEBEB;
border-radius: 8px;
text-align: center;
transition: all 0.1s;
}
.methodList {
width: 160px;
padding: 8px 0px;
border-radius: 8px;
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%);
display: none;
flex-direction: column;
box-shadow: 0px 3px 3px -2px rgba(0,0,0,0.2),0px 3px 4px 0px rgba(0,0,0,0.14),0px 1px 8px 0px rgba(0,0,0,0.12);
background-color: #fff;
z-index: 10;
.methodListItem {
cursor: pointer;
padding: 4px 0px;
}
.methodListItem:hover {
background-color: #f6f7f8;
}
}
.imgBox:hover .methodList,
.methodList:hover {
display: flex;
}
.previewImg {
width: 100%;
height: 100px;
object-fit: contain;
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 0;
left: 0;
bottom: 0;
}
.formMT {
margin-top: 16px;
}

View File

@ -22,6 +22,7 @@ exports.default = OakComponent({
entityId: 1,
fileType: 1,
sort: 1,
isBridge: 1,
},
formData: function (_a) {
var _this = this;

View File

@ -14,7 +14,7 @@ export interface Schema extends EntityShape {
extra1?: Text;
extension: String<16>;
size?: Int<4>;
sort?: Float<4, 2>;
sort?: Float<22, 10>;
fileType?: String<128>;
isBridge?: Boolean;
}

View File

@ -6,10 +6,12 @@ import { BackendRuntimeContext } from '../context/BackendRuntimeContext';
import { FrontendRuntimeContext } from '../context/FrontendRuntimeContext';
import { Cache } from 'oak-frontend-base/lib/features/cache';
import { Application } from './application';
import { Locales } from 'oak-frontend-base/lib/features/locales';
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;
constructor(cache: Cache<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>, application: Application<ED, Cxt, FrontCxt, AD>);
private locales;
constructor(cache: Cache<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>, application: Application<ED, Cxt, FrontCxt, AD>, locales: Locales<ED, Cxt, AD>);
private getUploadInfo;
upload(extraFile: EntityDict['extraFile']['CreateSingle']['data']): Promise<{
url: string;

View File

@ -8,10 +8,11 @@ var extraFile_1 = require("../utils/extraFile");
var assert_1 = tslib_1.__importDefault(require("assert"));
var ExtraFile = /** @class */ (function (_super) {
tslib_1.__extends(ExtraFile, _super);
function ExtraFile(cache, application) {
function ExtraFile(cache, application, locales) {
var _this = _super.call(this) || this;
_this.cache = cache;
_this.application = application;
_this.locales = locales;
return _this;
}
ExtraFile.prototype.getUploadInfo = function (origin, key) {
@ -66,7 +67,14 @@ var ExtraFile = /** @class */ (function (_super) {
var application = this.application.getApplication();
var config = ((_a = application === null || application === void 0 ? void 0 : application.system) === null || _a === void 0 ? void 0 : _a.config) ||
((_c = (_b = application === null || application === void 0 ? void 0 : application.system) === null || _b === void 0 ? void 0 : _b.platform) === null || _c === void 0 ? void 0 : _c.config);
var url = (0, extraFile_1.composeFileUrl)(extraFile, config, style);
var url;
if ((extraFile === null || extraFile === void 0 ? void 0 : extraFile.isBridge) && (extraFile === null || extraFile === void 0 ? void 0 : extraFile.extra1)) {
if (typeof (extraFile === null || extraFile === void 0 ? void 0 : extraFile.extra1) === 'string') {
url = this.locales.makeBridgeUrl(extraFile === null || extraFile === void 0 ? void 0 : extraFile.extra1);
return url;
}
}
url = (0, extraFile_1.composeFileUrl)(extraFile, config, style);
return url;
};
/**

View File

@ -11,7 +11,8 @@ var theme_1 = tslib_1.__importDefault(require("./theme"));
function initialize(basicFeatures, type, domain) {
var application = new application_1.Application(type, domain, basicFeatures.cache, basicFeatures.localStorage);
var token = new token_1.Token(basicFeatures.cache, basicFeatures.localStorage);
var extraFile = new extraFile_1.ExtraFile(basicFeatures.cache, application);
// 临时代码,合并后再删
var extraFile = new extraFile_1.ExtraFile(basicFeatures.cache, application, basicFeatures.locales);
var config = new config_1.Config(basicFeatures.cache);
var weiXinJsSdk = new weiXinJsSdk_1.WeiXinJsSdk(basicFeatures.cache, basicFeatures.localStorage);
var theme = new theme_1.default(basicFeatures.cache, basicFeatures.localStorage);

View File

@ -15,7 +15,10 @@
"grant": "授权",
"revoke": "回收",
"tip": "提示",
"detail": "详情"
"detail": "详情",
"editor": "编辑",
"newAdd": "新增",
"add": "添加"
},
"reset": "重置",
"select": "查询",

View File

@ -118,6 +118,8 @@ exports.default = OakComponent({
relations: [],
redirectToAfterConfirm: {},
qrCodeType: '',
showTitle: true,
showBack: false,
},
data: {
searchValue: '',

View File

@ -11,6 +11,7 @@ export default function Render(props: WebComponentProps<EntityDict, 'user', true
entity: string;
entityId: string;
showBack: boolean;
showTitle: boolean;
}, {
goUpsert: () => void;
goUpdate: (id: string) => void;

View File

@ -9,12 +9,12 @@ var pageHeader_1 = tslib_1.__importDefault(require("../../../components/common/p
var web_module_less_1 = tslib_1.__importDefault(require("./web.module.less"));
function Render(props) {
var _this = this;
var _a = props.data, pagination = _a.pagination, _b = _a.users, users = _b === void 0 ? [] : _b, entity = _a.entity, entityId = _a.entityId, oakLoading = _a.oakLoading, _c = _a.showBack, showBack = _c === void 0 ? false : _c;
var _d = pagination || {}, pageSize = _d.pageSize, total = _d.total, currentPage = _d.currentPage;
var _e = props.methods, goUpsert = _e.goUpsert, t = _e.t, setCurrentPage = _e.setCurrentPage, setPageSize = _e.setPageSize, confirmDelete = _e.confirmDelete, goUpdate = _e.goUpdate;
var _f = tslib_1.__read((0, react_1.useState)(undefined), 2), idRemove = _f[0], setIdRemove = _f[1];
var _g = tslib_1.__read((0, react_1.useState)(false), 2), inviteVisible = _g[0], setInviteVisible = _g[1];
return ((0, jsx_runtime_1.jsxs)(pageHeader_1.default, tslib_1.__assign({ title: "\u6743\u9650\u5217\u8868", showBack: showBack }, { children: [(0, jsx_runtime_1.jsxs)("div", tslib_1.__assign({ className: web_module_less_1.default.container }, { children: [(0, jsx_runtime_1.jsx)(antd_1.Space, tslib_1.__assign({ style: { marginBottom: 16 } }, { children: (0, jsx_runtime_1.jsx)(antd_1.Button, tslib_1.__assign({ type: "primary", onClick: function () { return goUpsert(); } }, { children: "\u6DFB\u52A0" })) })), (0, jsx_runtime_1.jsx)(antd_1.Table, { loading: oakLoading, rowKey: "id", columns: [
var _a = props.data, pagination = _a.pagination, _b = _a.users, users = _b === void 0 ? [] : _b, entity = _a.entity, entityId = _a.entityId, oakLoading = _a.oakLoading, _c = _a.showBack, showBack = _c === void 0 ? false : _c, _d = _a.showTitle, showTitle = _d === void 0 ? true : _d;
var _e = pagination || {}, pageSize = _e.pageSize, total = _e.total, currentPage = _e.currentPage;
var _f = props.methods, goUpsert = _f.goUpsert, t = _f.t, setCurrentPage = _f.setCurrentPage, setPageSize = _f.setPageSize, confirmDelete = _f.confirmDelete, goUpdate = _f.goUpdate;
var _g = tslib_1.__read((0, react_1.useState)(undefined), 2), idRemove = _g[0], setIdRemove = _g[1];
var _h = tslib_1.__read((0, react_1.useState)(false), 2), inviteVisible = _h[0], setInviteVisible = _h[1];
return ((0, jsx_runtime_1.jsxs)(pageHeader_1.default, tslib_1.__assign({ title: showTitle ? '权限列表' : undefined, showBack: showBack }, { children: [(0, jsx_runtime_1.jsxs)("div", tslib_1.__assign({ className: web_module_less_1.default.container }, { children: [(0, jsx_runtime_1.jsx)(antd_1.Space, tslib_1.__assign({ style: { marginBottom: 16 } }, { children: (0, jsx_runtime_1.jsx)(antd_1.Button, tslib_1.__assign({ type: "primary", onClick: function () { return goUpsert(); } }, { children: "\u6DFB\u52A0" })) })), (0, jsx_runtime_1.jsx)(antd_1.Table, { loading: oakLoading, rowKey: "id", columns: [
{
width: 100,
dataIndex: 'index',

View File

@ -1,6 +1,6 @@
{
"name": "oak-general-business",
"version": "2.5.10",
"version": "2.5.11",
"description": "oak框架中公共业务逻辑的实现",
"author": {
"name": "XuChang"

View File

@ -2,11 +2,11 @@ import { generateNewId } from 'oak-domain/lib/utils/uuid';
import assert from 'assert';
import { EntityDict } from '../../../general-app-domain';
import { OpSchema as ExtraFile } from '../../../general-app-domain/ExtraFile/Schema';
import { isEqual } from 'oak-domain/lib/utils/lodash';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity';
import { ReactComponentProps } from 'oak-frontend-base/lib/types/Page';
type MethodsType = 'original' | 'url' | 'uploadLocalImg';
type ImgUrlsOrigin = 'wechat' | 'others'; // 原文链接来源
type RenderImgItem = { renderUrl: any, originUrl: string, id: number, isBridge: boolean };
export default OakComponent({
entity: 'extraFile',
isList: true,
@ -44,13 +44,15 @@ export default OakComponent({
],
formData({ data: originalFiles, features }) {
let file;
const notDeleteFiles = originalFiles?.filter((ele) => !ele.$$deleteAt$$);
if (this.props.tag1) {
file = originalFiles?.filter((ele) => ele?.tag1 === this.props.tag1)?.[0];
file = notDeleteFiles?.filter((ele) => ele?.tag1 === this.props.tag1)?.[0];
}
if (this.props.tag2) {
file = originalFiles?.filter((ele) => ele?.tag2 === this.props.tag2)?.[0];
file = notDeleteFiles?.filter((ele) => ele?.tag2 === this.props.tag2)?.[0];
}
return {
file,
src: features.extraFile.getUrl(file as ExtraFile),
isBridge: file?.isBridge,
};
@ -58,10 +60,10 @@ export default OakComponent({
data: {
isModalOpen: false,
isModalOpen1: false,
renderImgs: [] as { renderUrl: any, originUrl: string, id: number }[], // 读取的原文图片在modal使用
renderImgs: [] as RenderImgItem[], // 读取的原文图片在modal使用
methodsType: '' as MethodsType,
bridgeUrl: '', // 通过桥接方式获得的url
originImgLoading: false,
selectedId: -1,
},
properties: {
type: '',
@ -70,35 +72,15 @@ export default OakComponent({
entity: '' as keyof EntityDict,
entityId: '',
imgUrls: [] as string[],
imgUrlsOrigin: 'others' as ImgUrlsOrigin,
},
lifetimes: {
// features.getBridgeUrl 中使用了URL.createObjectURL
attached() {
const { imgUrlsOrigin } = this.props;
const { renderImgs } = this.state;
if (imgUrlsOrigin === 'wechat' && renderImgs && renderImgs.length) {
renderImgs.forEach((ele) => {
URL.revokeObjectURL(ele.renderUrl);
})
}
}
},
listeners: {
async src(prev, next) {
if (prev !== next && !!this.state.src) {
try {
const url = await this.features.extraFile.getBridgeUrl(this.state.src);
this.setState({
bridgeUrl: url,
})
}
catch (err) {
this.setMessage({
content: '图片加载错误',
type: 'error'
})
}
async imgUrls(prev, next) {
// 因为imgUrls是从请求来的 它有可能比上边的src listener中的getBridgeUrl慢
// 所以此处增加前后项imgUrls里都有值且不等的条件再去clean
if (prev?.imgUrls.length && next?.imgUrls.length && !isEqual(prev.imgUrls, next.imgUrls)) {
this.clean();
}
}
},
@ -115,23 +97,13 @@ export default OakComponent({
if (!fileInput.files || fileInput.files.length === 0) {
return;
}
// 创建一个 FileReader 对象
const reader = new FileReader();
// 当文件读取完成后,显示预览图像
reader.addEventListener("load", function () {
imgElement!.src = reader.result as string;
imgElement.style.display = 'block';
});
// 读取用户选择的文件
reader.readAsDataURL(fileInput.files[0]);
this.myUpdateItem(fileInput.files[0]);
});
fileInput.click();
this.setState({
methodsType: method
})
this.setSelectedId(-1);
break;
case 'url':
this.setState({
@ -144,43 +116,34 @@ export default OakComponent({
isModalOpen1: true,
methodsType: method
})
const { imgUrlsOrigin, imgUrls } = this.props;
const { imgUrls } = this.props;
const { renderImgs } = this.state;
let renderImgs2: RenderImgItem[] = new Array(...renderImgs);
if (imgUrls && imgUrls.length) {
this.setState({
originImgLoading: true,
})
for (let i = 0; i < imgUrls.length; i++) {
if (renderImgs[i] && renderImgs[i].originUrl === imgUrls[i]) {
this.setState({
originImgLoading: false,
})
if (renderImgs2[i] && renderImgs2[i].originUrl === imgUrls[i]) {
return;
}
else if (renderImgs[i] && renderImgs[i].originUrl !== imgUrls[i]) {
if (imgUrlsOrigin === 'wechat') {
URL.revokeObjectURL(renderImgs[i].renderUrl);
}
this.setState({
renderImgs: [],
})
else if (renderImgs2[i] && renderImgs2[i].originUrl !== imgUrls[i]) {
renderImgs2 = [];
}
let renderUrl: string;
if (imgUrlsOrigin === 'wechat') {
renderUrl = await this.features.extraFile.getBridgeUrl(imgUrls[i]);
const isWechatUrl = this.isWechatUrlFn(imgUrls[i]);
if (isWechatUrl) {
renderUrl = this.features.extraFile.getUrl({isBridge: true, extra1: imgUrls[i]} as ExtraFile);
}
else {
renderUrl = imgUrls[i]
}
renderImgs.push({
renderImgs2.push({
renderUrl,
originUrl: imgUrls[i],
id: i,
isBridge: isWechatUrl
});
}
this.setState({
renderImgs: [...renderImgs],
originImgLoading: false,
renderImgs: renderImgs2,
})
}
break;
@ -199,7 +162,6 @@ export default OakComponent({
createExtraFileData(params: File | string) {
const { methodsType } = this.state;
const { imgUrlsOrigin } = this.props;
const { tag1, tag2, entity, entityId } = this.props;
let extension = '';
let filename = '';
@ -233,7 +195,7 @@ export default OakComponent({
origin: 'unknown',
extension,
filename,
isBridge: imgUrlsOrigin === 'wechat'
isBridge: this.isWechatUrlFn(params)
});
break;
case 'original':
@ -241,7 +203,7 @@ export default OakComponent({
origin: 'unknown',
extension,
filename,
isBridge: imgUrlsOrigin === 'wechat',
isBridge: this.isWechatUrlFn(params)
})
break;
}
@ -249,7 +211,7 @@ export default OakComponent({
},
async myAddItem(createData: EntityDict['extraFile']['CreateSingle']['data']) {
// 目前只支持七牛上传
// 目前只支持七牛上传
const { methodsType } = this.state;
this.addItem(createData, async () => {
if (createData.bucket) {
@ -268,35 +230,38 @@ export default OakComponent({
});
},
async myUpdateItem(params: File | string) {
const { files } = this.state;
if (files && files.length) {
files.map(async (ele: EntityDict['extraFile']['OpSchema']) => {
this.removeItem(ele.id);
})
const { file } = this.state;
if (file) {
this.removeItem(file.id);
}
if (!!params) {
const createData = this.createExtraFileData(params);
this.myAddItem(createData);
}
const createData = this.createExtraFileData(params);
this.myAddItem(createData);
},
onModalConfirm(value: string){
onModalConfirm(value: string) {
const reg = new RegExp(/(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/);
if (!reg.test(value)) {
return
}
this.myUpdateItem(value);
const imgElement = document.getElementById('previewImg') as HTMLImageElement;
imgElement!.src = value;
imgElement.style.display = 'block';
this.setSelectedId(-1);
},
onModal1Confirm(value: number) {
const { renderImgs } = this.state;
const img = renderImgs.find((ele) => ele.id === value);
this.myUpdateItem(img!.originUrl);
const imgElement = document.getElementById('previewImg') as HTMLImageElement;
imgElement!.src = img?.renderUrl || '';
imgElement.style.display = 'block';
this.myUpdateItem(img?.originUrl);
this.closeModal1();
},
},
isWechatUrlFn(url: string) {
return (url.startsWith('https://mmbiz.qpic.cn') || url.startsWith('http://mmbiz.qpic.cn'));
},
setSelectedId(id :number) {
this.setState({
selectedId: id
});
}
}
}) as <ED2 extends EntityDict & BaseEntityDict, T2 extends keyof ED2>(
props: ReactComponentProps<
ED2,
@ -310,7 +275,6 @@ export default OakComponent({
entity: keyof ED2,
entityId: string,
imgUrls: string[],
imgUrlsOrigin: ImgUrlsOrigin,
}
>
) => React.ReactElement;

View File

@ -44,13 +44,14 @@
.previewImg {
width: 100%;
height: 100px;
object-fit: contain;
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 0;
left: 0;
bottom: 0;
display: none;
}
.formMT {

View File

@ -20,7 +20,7 @@ export default function render(
isModalOpen: boolean;
isModalOpen1: boolean;
renderImgs: { renderUrl: string, originUrl: string, id: number }[];
originImgLoading: boolean;
selectedId: number;
},
{
onModalConfirm: (value: string) => void;
@ -28,6 +28,7 @@ export default function render(
closeModal1: () => void;
closeModal: () => void;
onModal1Confirm: (value: number) => void;
setSelectedId: (id: number) => void;
}
>
) {
@ -37,14 +38,12 @@ export default function render(
renderImgs,
src,
bridgeUrl,
originImgLoading,
selectedId,
} = props.data;
const { t, onModalConfirm, chooseMethod, closeModal1, closeModal, onModal1Confirm } = props.methods;
const { t, onModalConfirm, chooseMethod, closeModal1, closeModal, onModal1Confirm, setSelectedId } = props.methods;
const methods: MethodsType[] = ['original', 'url', 'uploadLocalImg'];
const [selectedId, setSelectedId] = useState(-1);
const [form] = Form.useForm();
const renderUrl = bridgeUrl || src; // 用户选图预览
const handleOk = () => {
onModalConfirm(form.getFieldValue('url'));
@ -57,7 +56,7 @@ export default function render(
<PlusOutlined />
<div></div>
</Space>
<img id="previewImg" src={renderUrl} alt="previewImg" className={Style.previewImg} style={{ display: renderUrl ? 'inline-block' : 'none'}} />
<img id="previewImg" src={src} alt="previewImg" className={Style.previewImg} style={{ display: src ? 'inline-block' : 'none' }} />
<div className={Style.methodList}>
{methods && methods.map((ele) => (
<div
@ -109,35 +108,33 @@ export default function render(
onOk={() => onModal1Confirm(selectedId)}
onCancel={closeModal1}
>
<Spin spinning={originImgLoading}>
{(renderImgs && renderImgs.length) ? (
<>
<Row gutter={[4,4]}>
{renderImgs.map((img: { renderUrl: string, originUrl: string, id: number }) =>
<Col span={4}>
<ImgBox
width={"100%"}
bordered={true}
mode="select"
src={img.renderUrl}
key={img.id}
selected={selectedId === img.id}
onClick={() => {
if (selectedId === img.id) {
setSelectedId(-1);
} else {
setSelectedId(img.id);
}
}}
/>
</Col>
)}
</Row>
</>
) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
)}
</Spin>
{(renderImgs && renderImgs.length) ? (
<>
<Row gutter={[4, 4]}>
{renderImgs.map((img: { renderUrl: string, originUrl: string, id: number }) =>
<Col span={4}>
<ImgBox
width={"100%"}
bordered={true}
mode="select"
src={img.renderUrl}
key={img.id}
selected={selectedId === img.id}
onClick={() => {
if (selectedId === img.id) {
setSelectedId(-1);
} else {
setSelectedId(img.id);
}
}}
/>
</Col>
)}
</Row>
</>
) : (
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
)}
</Modal>
</div>
);

View File

@ -28,6 +28,7 @@ export default OakComponent({
entityId: 1,
fileType: 1,
sort:1,
isBridge: 1,
},
formData({ data: originalFiles, features }) {
let files = (

View File

@ -16,7 +16,7 @@ export interface Schema extends EntityShape {
extra1?: Text;
extension: String<16>;
size?: Int<4>;
sort?: Float<4,2>;
sort?: Float<22,10>;
fileType?: String<128>;
isBridge?: Boolean;
};

View File

@ -10,6 +10,7 @@ import { Cache } from 'oak-frontend-base/lib/features/cache';
import { Application } from './application'
import { composeFileUrl, bytesToSize } from '../utils/extraFile'
import assert from 'assert';
import { Locales } from 'oak-frontend-base/lib/features/locales';
export class ExtraFile<
ED extends EntityDict,
@ -19,13 +20,16 @@ export class ExtraFile<
> extends Feature {
private cache: Cache<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>;
private application: Application<ED, Cxt, FrontCxt, AD>;
private locales: Locales<ED, Cxt, AD>;
constructor(
cache: Cache<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>,
application: Application<ED, Cxt, FrontCxt, AD>
application: Application<ED, Cxt, FrontCxt, AD>,
locales: Locales<ED, Cxt, AD>,
) {
super();
this.cache = cache;
this.application = application;
this.locales = locales;
}
private async getUploadInfo(origin: Origin, key?: string) {
@ -67,8 +71,14 @@ export class ExtraFile<
const config =
application?.system?.config ||
application?.system?.platform?.config;
const url = composeFileUrl(extraFile, config, style);
let url;
if(extraFile?.isBridge && extraFile?.extra1) {
if(typeof extraFile?.extra1 === 'string') {
url = this.locales.makeBridgeUrl(extraFile?.extra1);
return url;
}
}
url = composeFileUrl(extraFile, config, style);
return url;
}

View File

@ -33,13 +33,16 @@ export function initialize<
basicFeatures.cache,
basicFeatures.localStorage
);
const extraFile = new ExtraFile<ED, Cxt, FrontCxt, AD>(basicFeatures.cache, application);
// 临时代码,合并后再删
const extraFile = new ExtraFile<ED, Cxt, FrontCxt, AD>(basicFeatures.cache, application, basicFeatures.locales);
const config = new Config<ED, Cxt, FrontCxt, AD>(basicFeatures.cache);
const weiXinJsSdk = new WeiXinJsSdk<ED, Cxt, FrontCxt, AD>(
basicFeatures.cache,
basicFeatures.localStorage
);
const theme = new Theme(basicFeatures.cache, basicFeatures.localStorage);
return {
token,
extraFile,

View File

@ -15,7 +15,10 @@
"grant": "授权",
"revoke": "回收",
"tip": "提示",
"detail": "详情"
"detail": "详情",
"editor": "编辑",
"newAdd": "新增",
"add": "添加"
},
"reset": "重置",
"select": "查询",

View File

@ -117,6 +117,8 @@ export default OakComponent({
relations: [] as string[],
redirectToAfterConfirm: {} as EntityDict['userEntityGrant']['Schema']['redirectTo'],
qrCodeType: '' as string,
showTitle: true,
showBack: false,
},
data: {
searchValue: '',

View File

@ -32,6 +32,7 @@ export default function Render(
entity: string;
entityId: string;
showBack: boolean;
showTitle: boolean;
},
{
goUpsert: () => void;
@ -47,6 +48,7 @@ export default function Render(
entityId,
oakLoading,
showBack = false,
showTitle = true,
} = props.data;
const { pageSize, total, currentPage } = pagination || {};
const {
@ -62,7 +64,7 @@ export default function Render(
const [inviteVisible, setInviteVisible] = useState(false);
return (
<PageHeader title="权限列表" showBack={showBack}>
<PageHeader title={showTitle ? '权限列表' : undefined} showBack={showBack}>
<div className={Style.container}>
<Space style={{ marginBottom: 16 }}>
<Button type="primary" onClick={() => goUpsert()}>