mirror of https://github.com/openspug/spug
pull/592/head
parent
e7921e4171
commit
baf2d8c5d3
|
@ -26,6 +26,7 @@ class FileManager extends React.Component {
|
||||||
super(props);
|
super(props);
|
||||||
this.input = null;
|
this.input = null;
|
||||||
this.input2 = null
|
this.input2 = null
|
||||||
|
this.pwdHistoryCaches = new Map()
|
||||||
this.state = {
|
this.state = {
|
||||||
fetching: false,
|
fetching: false,
|
||||||
showDot: false,
|
showDot: false,
|
||||||
|
@ -100,12 +101,18 @@ class FileManager extends React.Component {
|
||||||
|
|
||||||
fetchFiles = (pwd) => {
|
fetchFiles = (pwd) => {
|
||||||
this.setState({ fetching: true });
|
this.setState({ fetching: true });
|
||||||
pwd = pwd || this.state.pwd;
|
pwd = pwd || (this.pwdHistoryCaches.get(this.props.id) || []);
|
||||||
|
if (this.pwdHistoryCaches.has(this.props.id)) {
|
||||||
|
let pwdCache = this.pwdHistoryCaches.get(this.props.id)
|
||||||
|
pwdCache.push(pwd.length > 0 ? pwd.splice(-1) : null)
|
||||||
|
pwd = pwdCache.filter(x => !!x)
|
||||||
|
}
|
||||||
const path = '/' + pwd.join('/');
|
const path = '/' + pwd.join('/');
|
||||||
return http.get('/api/file/', { params: { id: this.props.id, path } })
|
return http.get('/api/file/', { params: { id: this.props.id, path } })
|
||||||
.then(res => {
|
.then(res => {
|
||||||
const objects = lds.orderBy(res, [this._kindSort, 'name'], ['desc', 'asc']);
|
const objects = lds.orderBy(res, [this._kindSort, 'name'], ['desc', 'asc']);
|
||||||
this.setState({ objects, pwd })
|
this.setState({ objects, pwd })
|
||||||
|
this.pwdHistoryCaches.set(this.props.id, pwd)
|
||||||
this.state.inputPath !== null && this.setState({ inputPath: path })
|
this.state.inputPath !== null && this.setState({ inputPath: path })
|
||||||
})
|
})
|
||||||
.finally(() => this.setState({ fetching: false }))
|
.finally(() => this.setState({ fetching: false }))
|
||||||
|
@ -118,122 +125,154 @@ class FileManager extends React.Component {
|
||||||
this.setState({ inputPath: null })
|
this.setState({ inputPath: null })
|
||||||
} else if (action === '2') {
|
} else if (action === '2') {
|
||||||
const index = pwd.indexOf(name);
|
const index = pwd.indexOf(name);
|
||||||
pwd = pwd.splice(0, index + 1)
|
pwd = pwd.splice(0, index + 1);
|
||||||
} else {
|
} else {
|
||||||
pwd = []
|
pwd = [];
|
||||||
}
|
}
|
||||||
this.fetchFiles(pwd)
|
this.fetchFiles(pwd);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleInputEnter = () => {
|
handleInputEnter = () => {
|
||||||
if (this.state.inputPath === null) {
|
if (this.state.inputPath === null) {
|
||||||
if (this.state.pwd.length > 0) {
|
if (this.state.pwd.length > 0) {
|
||||||
this.setState({ inputPath: `/${this.state.pwd.join('/')}/` })
|
this.setState({ inputPath: `/${this.state.pwd.join("/")}/` });
|
||||||
} else {
|
} else {
|
||||||
this.setState({ inputPath: '/' })
|
this.setState({ inputPath: "/" });
|
||||||
}
|
}
|
||||||
setTimeout(() => this.input2.focus(), 100)
|
setTimeout(() => this.input2.focus(), 100);
|
||||||
} else {
|
} else {
|
||||||
let pwdStr = this.state.inputPath.replace(/^\/+/, '')
|
let pwdStr = this.state.inputPath.replace(/^\/+/, "");
|
||||||
pwdStr = pwdStr.replace(/\/+$/, '')
|
pwdStr = pwdStr.replace(/\/+$/, "");
|
||||||
this.fetchFiles(pwdStr.split('/'))
|
this.fetchFiles(pwdStr.split("/")).then(() =>
|
||||||
.then(() => this.setState({ inputPath: null }))
|
this.setState({ inputPath: null })
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
handleUpload = () => {
|
handleUpload = () => {
|
||||||
this.input.click();
|
this.input.click();
|
||||||
this.input.onchange = e => {
|
this.input.onchange = (e) => {
|
||||||
this.setState({ uploading: true, uploadStatus: 'active', percent: 0 });
|
this.setState({ uploading: true, uploadStatus: "active", percent: 0 });
|
||||||
const file = e.target['files'][0];
|
const file = e.target["files"][0];
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
const token = uniqueId();
|
const token = uniqueId();
|
||||||
this._updatePercent(token);
|
this._updatePercent(token);
|
||||||
formData.append('file', file);
|
formData.append("file", file);
|
||||||
formData.append('id', this.props.id);
|
formData.append("id", this.props.id);
|
||||||
formData.append('token', token);
|
formData.append("token", token);
|
||||||
formData.append('path', '/' + this.state.pwd.join('/'));
|
formData.append("path", "/" + this.state.pwd.join("/"));
|
||||||
this.input.value = '';
|
this.input.value = "";
|
||||||
http.post('/api/file/object/', formData, { timeout: 600000, onUploadProgress: this._updateLocal })
|
http
|
||||||
.then(() => {
|
.post("/api/file/object/", formData, {
|
||||||
this.setState({ uploadStatus: 'success' });
|
timeout: 600000,
|
||||||
this.fetchFiles()
|
onUploadProgress: this._updateLocal,
|
||||||
}, () => this.setState({ uploadStatus: 'exception' }))
|
})
|
||||||
.finally(() => setTimeout(() => this.setState({ uploading: false }), 2000))
|
.then(
|
||||||
}
|
() => {
|
||||||
|
this.setState({ uploadStatus: "success" });
|
||||||
|
this.fetchFiles();
|
||||||
|
},
|
||||||
|
() => this.setState({ uploadStatus: "exception" })
|
||||||
|
)
|
||||||
|
.finally(() =>
|
||||||
|
setTimeout(() => this.setState({ uploading: false }), 2000)
|
||||||
|
);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
_updateLocal = (e) => {
|
_updateLocal = (e) => {
|
||||||
const percent = e.loaded / e.total * 100 / 2
|
const percent = ((e.loaded / e.total) * 100) / 2;
|
||||||
this.setState({ percent: Number(percent.toFixed(1)) })
|
this.setState({ percent: Number(percent.toFixed(1)) });
|
||||||
}
|
};
|
||||||
|
|
||||||
_updatePercent = token => {
|
_updatePercent = (token) => {
|
||||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
||||||
this.socket = new WebSocket(`${protocol}//${window.location.host}/api/ws/subscribe/${token}/?x-token=${X_TOKEN}`);
|
this.socket = new WebSocket(
|
||||||
this.socket.onopen = () => this.socket.send('ok');
|
`${protocol}//${window.location.host}/api/ws/subscribe/${token}/?x-token=${X_TOKEN}`
|
||||||
this.socket.onmessage = e => {
|
);
|
||||||
if (e.data === 'pong') {
|
this.socket.onopen = () => this.socket.send("ok");
|
||||||
this.socket.send('ping')
|
this.socket.onmessage = (e) => {
|
||||||
|
if (e.data === "pong") {
|
||||||
|
this.socket.send("ping");
|
||||||
} else {
|
} else {
|
||||||
const percent = this.state.percent + Number(e.data) / 2;
|
const percent = this.state.percent + Number(e.data) / 2;
|
||||||
if (percent > this.state.percent) this.setState({ percent: Number(percent.toFixed(1)) });
|
if (percent > this.state.percent)
|
||||||
|
this.setState({ percent: Number(percent.toFixed(1)) });
|
||||||
if (percent === 100) {
|
if (percent === 100) {
|
||||||
this.socket.close()
|
this.socket.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
handleDownload = (name) => {
|
handleDownload = (name) => {
|
||||||
const file = `/${this.state.pwd.join('/')}/${name}`;
|
const file = `/${this.state.pwd.join("/")}/${name}`;
|
||||||
const link = document.createElement('a');
|
const link = document.createElement("a");
|
||||||
link.download = name;
|
link.download = name;
|
||||||
link.href = `/api/file/object/?id=${this.props.id}&file=${file}&x-token=${X_TOKEN}`;
|
link.href = `/api/file/object/?id=${this.props.id}&file=${file}&x-token=${X_TOKEN}`;
|
||||||
document.body.appendChild(link);
|
document.body.appendChild(link);
|
||||||
link.click();
|
link.click();
|
||||||
document.body.removeChild(link);
|
document.body.removeChild(link);
|
||||||
message.warning('即将开始下载,请勿重复点击。')
|
message.warning("即将开始下载,请勿重复点击。");
|
||||||
};
|
};
|
||||||
|
|
||||||
handleDelete = (name) => {
|
handleDelete = (name) => {
|
||||||
const file = `/${this.state.pwd.join('/')}/${name}`;
|
const file = `/${this.state.pwd.join("/")}/${name}`;
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: '删除文件确认',
|
title: "删除文件确认",
|
||||||
content: `确认删除文件:${file} ?`,
|
content: `确认删除文件:${file} ?`,
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
return http.delete('/api/file/object/', { params: { id: this.props.id, file } })
|
return http
|
||||||
|
.delete("/api/file/object/", { params: { id: this.props.id, file } })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
message.success('删除成功');
|
message.success("删除成功");
|
||||||
this.fetchFiles()
|
this.fetchFiles();
|
||||||
})
|
});
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let objects = this.state.objects;
|
let objects = this.state.objects;
|
||||||
if (!this.state.showDot) {
|
if (!this.state.showDot) {
|
||||||
objects = objects.filter(x => !x.name.startsWith('.'))
|
objects = objects.filter((x) => !x.name.startsWith("."));
|
||||||
}
|
}
|
||||||
const scrollY = document.body.clientHeight - 168;
|
const scrollY = document.body.clientHeight - 168;
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<input style={{ display: 'none' }} type="file" ref={ref => this.input = ref} />
|
<input
|
||||||
|
style={{ display: "none" }}
|
||||||
|
type="file"
|
||||||
|
ref={(ref) => (this.input = ref)}
|
||||||
|
/>
|
||||||
<div className={styles.drawerHeader}>
|
<div className={styles.drawerHeader}>
|
||||||
{this.state.inputPath !== null ? (
|
{this.state.inputPath !== null ? (
|
||||||
<Input ref={ref => this.input2 = ref} size="small" className={styles.input}
|
<Input
|
||||||
suffix={<div style={{ color: '#999', fontSize: 12 }}>回车确认</div>}
|
ref={(ref) => (this.input2 = ref)}
|
||||||
value={this.state.inputPath} onChange={e => this.setState({ inputPath: e.target.value })}
|
size="small"
|
||||||
|
className={styles.input}
|
||||||
|
suffix={
|
||||||
|
<div style={{ color: "#999", fontSize: 12 }}>回车确认</div>
|
||||||
|
}
|
||||||
|
value={this.state.inputPath}
|
||||||
|
onChange={(e) => this.setState({ inputPath: e.target.value })}
|
||||||
onBlur={this.handleInputEnter}
|
onBlur={this.handleInputEnter}
|
||||||
onPressEnter={this.handleInputEnter} />
|
onPressEnter={this.handleInputEnter}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Breadcrumb className={styles.bread}>
|
<Breadcrumb className={styles.bread}>
|
||||||
<Breadcrumb.Item href="#" onClick={() => this.handleChdir('', '0')}>
|
<Breadcrumb.Item
|
||||||
|
href="#"
|
||||||
|
onClick={() => this.handleChdir("", "0")}
|
||||||
|
>
|
||||||
<HomeOutlined style={{ fontSize: 16 }} />
|
<HomeOutlined style={{ fontSize: 16 }} />
|
||||||
</Breadcrumb.Item>
|
</Breadcrumb.Item>
|
||||||
{this.state.pwd.map(item => (
|
{this.state.pwd.map((item) => (
|
||||||
<Breadcrumb.Item key={item} href="#" onClick={() => this.handleChdir(item, '2')}>
|
<Breadcrumb.Item
|
||||||
|
key={item}
|
||||||
|
href="#"
|
||||||
|
onClick={() => this.handleChdir(item, "2")}
|
||||||
|
>
|
||||||
<span>{item}</span>
|
<span>{item}</span>
|
||||||
</Breadcrumb.Item>
|
</Breadcrumb.Item>
|
||||||
))}
|
))}
|
||||||
|
@ -249,10 +288,15 @@ class FileManager extends React.Component {
|
||||||
checked={this.state.showDot}
|
checked={this.state.showDot}
|
||||||
checkedChildren="开启"
|
checkedChildren="开启"
|
||||||
unCheckedChildren="关闭"
|
unCheckedChildren="关闭"
|
||||||
onChange={v => this.setState({ showDot: v })} />
|
onChange={(v) => this.setState({ showDot: v })}
|
||||||
|
/>
|
||||||
{this.state.uploading ? (
|
{this.state.uploading ? (
|
||||||
<Progress className={styles.progress} strokeWidth={14} status={this.state.uploadStatus}
|
<Progress
|
||||||
percent={this.state.percent} />
|
className={styles.progress}
|
||||||
|
strokeWidth={14}
|
||||||
|
status={this.state.uploadStatus}
|
||||||
|
percent={this.state.percent}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<AuthButton
|
<AuthButton
|
||||||
auth="host.console.upload"
|
auth="host.console.upload"
|
||||||
|
@ -260,7 +304,10 @@ class FileManager extends React.Component {
|
||||||
size="small"
|
size="small"
|
||||||
type="primary"
|
type="primary"
|
||||||
icon={<UploadOutlined />}
|
icon={<UploadOutlined />}
|
||||||
onClick={this.handleUpload}>上传文件</AuthButton>
|
onClick={this.handleUpload}
|
||||||
|
>
|
||||||
|
上传文件
|
||||||
|
</AuthButton>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -271,11 +318,15 @@ class FileManager extends React.Component {
|
||||||
pagination={false}
|
pagination={false}
|
||||||
columns={this.columns}
|
columns={this.columns}
|
||||||
scroll={{ y: scrollY }}
|
scroll={{ y: scrollY }}
|
||||||
style={{ fontFamily: 'Source Code Pro, Courier New, Courier, Monaco, monospace, PingFang SC, Microsoft YaHei' }}
|
style={{
|
||||||
dataSource={objects} />
|
fontFamily:
|
||||||
|
"Source Code Pro, Courier New, Courier, Monaco, monospace, PingFang SC, Microsoft YaHei",
|
||||||
|
}}
|
||||||
|
dataSource={objects}
|
||||||
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default FileManager
|
export default FileManager;
|
||||||
|
|
Loading…
Reference in New Issue