feat:图片上传展示进度

This commit is contained in:
lililemon 2024-05-29 17:09:09 +08:00
parent 13fed127d7
commit 3bf051acc9
4 changed files with 191 additions and 115 deletions

View File

@ -0,0 +1,25 @@
@keyframes loading {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.loading-box{
width: 32px;
height: 32px;
position:absolute;
top:50%;
left:50%;
transform:translate(-16px,-16px);
}
.loading-icon{
width: 32px;
height: 32px;
animation: loading 1s linear infinite;
}
.loading-text{
font-size: 14px;
white-space: nowrap;
}

View File

@ -1,124 +1,172 @@
import { MediaMessageContent } from "wukongimjssdk" import WKSDK, { MediaMessageContent, Task } from "wukongimjssdk";
import React from "react" import React from "react";
import WKApp from "../../App" import WKApp from "../../App";
import { MessageContentTypeConst } from "../../Service/Const" import { MessageContentTypeConst } from "../../Service/Const";
import MessageBase from "../Base" import MessageBase from "../Base";
import { MessageCell } from "../MessageCell" import { MessageCell } from "../MessageCell";
import Viewer from 'react-viewer'; import Viewer from "react-viewer";
import "./index.css";
export class ImageContent extends MediaMessageContent { export class ImageContent extends MediaMessageContent {
width!: number width!: number;
height!: number height!: number;
url!: string url!: string;
imgData?: string imgData?: string;
constructor(file?: File, imgData?: string, width?: number, height?: number) { constructor(file?: File, imgData?: string, width?: number, height?: number) {
super() super();
this.file = file this.file = file;
this.imgData = imgData this.imgData = imgData;
this.width = width || 0 this.width = width || 0;
this.height = height || 0 this.height = height || 0;
} }
decodeJSON(content: any) { decodeJSON(content: any) {
this.width = content["width"] || 0 this.width = content["width"] || 0;
this.height = content["height"] || 0 this.height = content["height"] || 0;
this.url = content["url"] || '' this.url = content["url"] || "";
this.remoteUrl = this.url this.remoteUrl = this.url;
} }
encodeJSON() { encodeJSON() {
return { "width": this.width || 0, "height": this.height || 0, "url": this.remoteUrl || "" } return { width: this.width || 0, height: this.height || 0, url: this.remoteUrl || "" };
} }
get contentType() { get contentType() {
return MessageContentTypeConst.image return MessageContentTypeConst.image;
} }
get conversationDigest() { get conversationDigest() {
return "[图片]" return "[图片]";
} }
} }
interface ImageCellState { interface ImageCellState {
showPreview: boolean showPreview: boolean;
loading: boolean;
progress: number;
} }
export class ImageCell extends MessageCell<any, ImageCellState> { export class ImageCell extends MessageCell<any, ImageCellState> {
taskListener!: any;
constructor(props: any) {
super(props);
this.state = {
showPreview: false,
loading: false,
progress: 0,
};
}
constructor(props: any) { imageScale(orgWidth: number, orgHeight: number, maxWidth = 250, maxHeight = 250) {
super(props) let actSize = { width: orgWidth, height: orgHeight };
this.state = { if (orgWidth > orgHeight) {
showPreview: false, //横图
if (orgWidth > maxWidth) {
// 横图超过最大宽度
let rate = maxWidth / orgWidth; // 缩放比例
actSize.width = maxWidth;
actSize.height = orgHeight * rate;
}
} else if (orgWidth < orgHeight) {
//竖图
if (orgHeight > maxHeight) {
let rate = maxHeight / orgHeight; // 缩放比例
actSize.width = orgWidth * rate;
actSize.height = maxHeight;
}
} else if (orgWidth === orgHeight) {
if (orgWidth > maxWidth) {
let rate = maxWidth / orgWidth; // 缩放比例
actSize.width = maxWidth;
actSize.height = orgHeight * rate;
}
}
return actSize;
}
getImageSrc(content: ImageContent) {
if (content.url && content.url !== "") {
// 等待发送的消息
let downloadURL = WKApp.dataSource.commonDataSource.getImageURL(content.url, {
width: content.width,
height: content.height,
});
if (downloadURL.indexOf("?") != -1) {
downloadURL += "&filename=image.png";
} else {
downloadURL += "?filename=image.png";
}
return downloadURL;
}
return content.imgData;
}
getImageElement() {
const { message } = this.props;
const content = message.content as ImageContent;
let scaleSize = this.imageScale(content.width, content.height);
if (!this.taskListener && !content?.url) {
this.taskListener = (task: Task) => {
this.setState({
loading: true,
progress: Math.trunc(task.progress() * 100),
});
if (task.progress() === 1) {
this.setState({
loading: false,
progress: 100,
});
WKSDK.shared().taskManager.removeListener(this.taskListener);
} }
};
WKSDK.shared().taskManager.addListener(this.taskListener);
} }
return (
<div style={{ position: "relative" }}>
<img
alt=""
src={this.getImageSrc(content)}
style={{ borderRadius: "5px", width: scaleSize.width, height: scaleSize.height }}
/>
{this.state.loading && scaleSize.width > 32 && (
<i className="loading-box">
<img className="loading-icon" src={require("../../assets/loading.png")} alt="" />
{scaleSize.height > 46 && <p className="loading-text">{this.state.progress}%</p>}
</i>
)}
</div>
);
}
imageScale(orgWidth: number, orgHeight: number, maxWidth = 250, maxHeight = 250) { render() {
let actSize = { width: orgWidth, height: orgHeight }; const { message, context } = this.props;
if (orgWidth > orgHeight) {//横图 const { showPreview } = this.state;
if (orgWidth > maxWidth) { // 横图超过最大宽度 const content = message.content as ImageContent;
let rate = maxWidth / orgWidth; // 缩放比例 let scaleSize = this.imageScale(content.width, content.height);
actSize.width = maxWidth; const imageURL = this.getImageSrc(content) || "";
actSize.height = orgHeight * rate; return (
} <MessageBase context={context} message={message}>
} else if (orgWidth < orgHeight) { //竖图 <div
if (orgHeight > maxHeight) { style={{ width: scaleSize.width, height: scaleSize.height, cursor: "pointer" }}
let rate = maxHeight / orgHeight; // 缩放比例 onClick={() => {
actSize.width = orgWidth * rate; this.setState({
actSize.height = maxHeight; showPreview: !this.state.showPreview,
} });
} else if (orgWidth === orgHeight) { }}
if (orgWidth > maxWidth) { >
let rate = maxWidth / orgWidth; // 缩放比例 {this.getImageElement()}
actSize.width = maxWidth; </div>
actSize.height = orgHeight * rate; <Viewer
} visible={showPreview}
} noImgDetails={true}
return actSize; downloadable={true}
} rotatable={false}
changeable={false}
getImageSrc(content: ImageContent) { showTotal={false}
if (content.url && content.url !== "") { // 等待发送的消息 onMaskClick={() => {
let downloadURL = WKApp.dataSource.commonDataSource.getImageURL(content.url, { width: content.width, height: content.height }) this.setState({ showPreview: false });
if (downloadURL.indexOf("?") != -1) { }}
downloadURL += "&filename=image.png" onClose={() => {
} else { this.setState({ showPreview: false });
downloadURL += "?filename=image.png" }}
} images={[{ src: imageURL, alt: "", downloadUrl: imageURL }]}
return downloadURL />
} </MessageBase>
return content.imgData );
} }
}
getImageElement() {
const { message } = this.props
const content = message.content as ImageContent
let scaleSize = this.imageScale(content.width, content.height);
return <img alt="" src={this.getImageSrc(content)} style={{ borderRadius: '5px', width: scaleSize.width, height: scaleSize.height }} />
}
render() {
const { message, context } = this.props
const { showPreview } = this.state
const content = message.content as ImageContent
let scaleSize = this.imageScale(content.width, content.height);
const imageURL = this.getImageSrc(content) || ""
return <MessageBase context={context} message={message}>
<div style={{ width: scaleSize.width, height: scaleSize.height, cursor: "pointer" }} onClick={() => {
this.setState({
showPreview: !this.state.showPreview,
})
}}>
{this.getImageElement()}
</div>
<Viewer
visible={showPreview}
noImgDetails={true}
downloadable={true}
rotatable={false}
changeable={false}
showTotal={false}
onMaskClick={() => { this.setState({ showPreview: false }); }}
onClose={() => { this.setState({ showPreview: false }); }}
images={[{ src: imageURL, alt: '', downloadUrl: imageURL }]}
/>
</MessageBase>
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -18,10 +18,13 @@ export class MediaMessageUploadTask extends MessageTask {
async start(): Promise<void> { async start(): Promise<void> {
const mediaContent = this.message.content as MediaMessageContent const mediaContent = this.message.content as MediaMessageContent
if(mediaContent.file) { if(mediaContent.file) {
const fileNameSuffix = mediaContent.file.name.substring(
mediaContent.file.name.lastIndexOf(".")
);
const param = new FormData(); const param = new FormData();
param.append("file", mediaContent.file); param.append("file", mediaContent.file);
const fileName = this.getUUID(); const fileName = this.getUUID();
const path = `/${this.message.channel.channelType}/${this.message.channel.channelID}/${fileName}${mediaContent.extension??""}` const path = `/${this.message.channel.channelType}/${this.message.channel.channelID}/${fileName}${fileNameSuffix ?? ""}`;
const uploadURL = await this.getUploadURL(path) const uploadURL = await this.getUploadURL(path)
if(uploadURL) { if(uploadURL) {
this.uploadFile(mediaContent.file,uploadURL) this.uploadFile(mediaContent.file,uploadURL)
@ -52,7 +55,7 @@ export class MediaMessageUploadTask extends MessageTask {
this.canceler = c this.canceler = c
}), }),
onUploadProgress: e => { onUploadProgress: e => {
var completeProgress = ((e.loaded / e.total) | 0); var completeProgress = ((e.loaded / e.total) || 0);
this._progress = completeProgress this._progress = completeProgress
this.update() this.update()
} }