解决v2.0.0公测版大家反馈的问题
This commit is contained in:
parent
78ab2ed495
commit
6a63ea8e85
@ -1,13 +1,13 @@
|
||||
var authConfig = {
|
||||
"siteName": "Achirou's Cloud", // 网站名称
|
||||
"version" : "1.1.0", // 程序版本
|
||||
"theme" : "acrou",
|
||||
siteName: "Achirou's Cloud", // 网站名称
|
||||
version: "1.1.0", // 程序版本
|
||||
theme: "acrou",
|
||||
/*"client_id": "202264815644.apps.googleusercontent.com",
|
||||
"client_secret": "X4Z3ca8xfWDb1Voo-F9a7ZxJ",*/
|
||||
// 强烈推荐使用自己的 client_id 和 client_secret
|
||||
"client_id": "",
|
||||
"client_secret": "",
|
||||
"refresh_token": "", // 授权 token
|
||||
client_id: "",
|
||||
client_secret: "",
|
||||
refresh_token: "", // 授权 token
|
||||
/**
|
||||
* 设置要显示的多个云端硬盘;按格式添加多个
|
||||
* [id]: 可以是 团队盘id、子文件夹id、或者"root"(代表个人盘根目录);
|
||||
@ -21,7 +21,7 @@ var authConfig = {
|
||||
* 不需要 Basic Auth 的盘,保持 user 和 pass 同时为空即可。(直接不设置也可以)
|
||||
* 【注意】对于id设置为为子文件夹id的盘将不支持搜索功能(不影响其他盘)。
|
||||
*/
|
||||
"roots": [
|
||||
roots: [
|
||||
{
|
||||
id: "",
|
||||
name: "TeamDrive",
|
||||
@ -30,45 +30,52 @@ var authConfig = {
|
||||
{
|
||||
id: "root",
|
||||
name: "PrivateDrive",
|
||||
user: '',
|
||||
user: "",
|
||||
pass: "",
|
||||
protect_file_link: true
|
||||
protect_file_link: true,
|
||||
},
|
||||
{
|
||||
id: "",
|
||||
name: "folder1",
|
||||
pass: "",
|
||||
}
|
||||
},
|
||||
],
|
||||
"default_gd": 0,
|
||||
default_gd: 0,
|
||||
/**
|
||||
* 文件列表页面每页显示的数量。【推荐设置值为 100 到 1000 之间】;
|
||||
* 如果设置大于1000,会导致请求 drive api 时出错;
|
||||
* 如果设置的值过小,会导致文件列表页面滚动条增量加载(分页加载)失效;
|
||||
* 此值的另一个作用是,如果目录内文件数大于此设置值(即需要多页展示的),将会对首次列目录结果进行缓存。
|
||||
*/
|
||||
"files_list_page_size": 50,
|
||||
files_list_page_size: 50,
|
||||
/**
|
||||
* 搜索结果页面每页显示的数量。【推荐设置值为 50 到 1000 之间】;
|
||||
* 如果设置大于1000,会导致请求 drive api 时出错;
|
||||
* 如果设置的值过小,会导致搜索结果页面滚动条增量加载(分页加载)失效;
|
||||
* 此值的大小影响搜索操作的响应速度。
|
||||
*/
|
||||
"search_result_list_page_size": 50,
|
||||
search_result_list_page_size: 50,
|
||||
// 确认有 cors 用途的可以开启
|
||||
"enable_cors_file_down": false,
|
||||
enable_cors_file_down: false,
|
||||
/**
|
||||
* 上面的 basic auth 已经包含了盘内全局保护的功能。所以默认不再去认证 .password 文件内的密码;
|
||||
* 如果在全局认证的基础上,仍需要给某些目录单独进行 .password 文件内的密码验证的话,将此选项设置为 true;
|
||||
* 【注意】如果开启了 .password 文件密码验证,每次列目录都会额外增加查询目录内 .password 文件是否存在的开销。
|
||||
*/
|
||||
"enable_password_file_verify": true
|
||||
enable_password_file_verify: true,
|
||||
};
|
||||
|
||||
var themeOptions = {
|
||||
//可选默认系统语言:en/zh-chs/zh-cht
|
||||
languages: 'en'
|
||||
}
|
||||
languages: "en",
|
||||
render: {
|
||||
head_md: false,
|
||||
readme_md: false,
|
||||
// 是否显示文件/文件夹描述(默认不显示)
|
||||
// Show file/folder description or not (not shown by default)
|
||||
desc: false
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* global functions
|
||||
@ -81,11 +88,11 @@ const FUNCS = {
|
||||
let nothing = "";
|
||||
let space = " ";
|
||||
if (!keyword) return nothing;
|
||||
return keyword.replace(/(!=)|['"=<>/\\:]/g, nothing)
|
||||
return keyword
|
||||
.replace(/(!=)|['"=<>/\\:]/g, nothing)
|
||||
.replace(/[,,|(){}]/g, space)
|
||||
.trim()
|
||||
}
|
||||
|
||||
.trim();
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
@ -93,16 +100,16 @@ const FUNCS = {
|
||||
* @type {{folder_mime_type: string, default_file_fields: string, gd_root_type: {share_drive: number, user_drive: number, sub_folder: number}}}
|
||||
*/
|
||||
const CONSTS = new (class {
|
||||
default_file_fields = 'parents,id,name,mimeType,modifiedTime,createdTime,fileExtension,size';
|
||||
default_file_fields =
|
||||
"parents,id,name,mimeType,modifiedTime,createdTime,fileExtension,size";
|
||||
gd_root_type = {
|
||||
user_drive: 0,
|
||||
share_drive: 1,
|
||||
sub_folder: 2
|
||||
sub_folder: 2,
|
||||
};
|
||||
folder_mime_type = 'application/vnd.google-apps.folder';
|
||||
folder_mime_type = "application/vnd.google-apps.folder";
|
||||
})();
|
||||
|
||||
|
||||
// gd instances
|
||||
var gds = [];
|
||||
|
||||
@ -118,8 +125,14 @@ function html(current_drive_order = 0, model = {}) {
|
||||
@import url(https://cloud.jsonpop.cn/go2index/v2.0.0_beta/dist/style.css);
|
||||
</style>
|
||||
<script>
|
||||
window.gdconfig = JSON.parse('${JSON.stringify({version: authConfig.version,themeOptions: themeOptions})}');
|
||||
window.gds = JSON.parse('${JSON.stringify(authConfig.roots.map(it => it.name))}');
|
||||
window.gdconfig = JSON.parse('${JSON.stringify({
|
||||
version: authConfig.version,
|
||||
themeOptions: themeOptions,
|
||||
})}');
|
||||
window.themeOptions = JSON.parse('${JSON.stringify(themeOptions)}');
|
||||
window.gds = JSON.parse('${JSON.stringify(
|
||||
authConfig.roots.map((it) => it.name)
|
||||
)}');
|
||||
window.MODEL = JSON.parse('${JSON.stringify(model)}');
|
||||
window.current_drive_order = ${current_drive_order};
|
||||
</script>
|
||||
@ -130,9 +143,9 @@ function html(current_drive_order = 0, model = {}) {
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
};
|
||||
}
|
||||
|
||||
addEventListener('fetch', event => {
|
||||
addEventListener("fetch", (event) => {
|
||||
event.respondWith(handleRequest(event.request));
|
||||
});
|
||||
|
||||
@ -145,11 +158,11 @@ async function handleRequest(request) {
|
||||
for (let i = 0; i < authConfig.roots.length; i++) {
|
||||
const gd = new googleDrive(authConfig, i);
|
||||
await gd.init();
|
||||
gds.push(gd)
|
||||
gds.push(gd);
|
||||
}
|
||||
// 这个操作并行,提高效率
|
||||
let tasks = [];
|
||||
gds.forEach(gd => {
|
||||
gds.forEach((gd) => {
|
||||
tasks.push(gd.initRootType());
|
||||
});
|
||||
for (let task of tasks) {
|
||||
@ -168,13 +181,16 @@ async function handleRequest(request) {
|
||||
* @returns {Response}
|
||||
*/
|
||||
function redirectToIndexPage() {
|
||||
return new Response('', {status: 301, headers: {'Location': `/${authConfig.default_gd}:/`}});
|
||||
return new Response("", {
|
||||
status: 301,
|
||||
headers: { Location: `/${authConfig.default_gd}:/` },
|
||||
});
|
||||
}
|
||||
|
||||
if (path == '/') return redirectToIndexPage();
|
||||
if (path.toLowerCase() == '/favicon.ico') {
|
||||
if (path == "/") return redirectToIndexPage();
|
||||
if (path.toLowerCase() == "/favicon.ico") {
|
||||
// 后面可以找一个 favicon
|
||||
return new Response('', {status: 404})
|
||||
return new Response("", { status: 404 });
|
||||
}
|
||||
|
||||
// 特殊命令格式
|
||||
@ -187,46 +203,48 @@ async function handleRequest(request) {
|
||||
if (order >= 0 && order < gds.length) {
|
||||
gd = gds[order];
|
||||
} else {
|
||||
return redirectToIndexPage()
|
||||
return redirectToIndexPage();
|
||||
}
|
||||
// basic auth
|
||||
for (const r = gd.basicAuthResponse(request); r; ) return r;
|
||||
command = match.groups.command;
|
||||
|
||||
// 搜索
|
||||
if (command === 'search') {
|
||||
if (request.method === 'POST') {
|
||||
if (command === "search") {
|
||||
if (request.method === "POST") {
|
||||
// 搜索结果
|
||||
return handleSearch(request, gd);
|
||||
} else {
|
||||
const params = url.searchParams;
|
||||
// 搜索页面
|
||||
return new Response(html(gd.order, {
|
||||
q: params.get("q") || '',
|
||||
return new Response(
|
||||
html(gd.order, {
|
||||
q: params.get("q") || "",
|
||||
is_search_page: true,
|
||||
root_type: gd.root_type
|
||||
root_type: gd.root_type,
|
||||
}),
|
||||
{
|
||||
status: 200,
|
||||
headers: {'Content-Type': 'text/html; charset=utf-8'}
|
||||
});
|
||||
headers: { "Content-Type": "text/html; charset=utf-8" },
|
||||
}
|
||||
} else if (command === 'id2path' && request.method === 'POST') {
|
||||
return handleId2Path(request, gd)
|
||||
} else if (command === 'view'){
|
||||
);
|
||||
}
|
||||
} else if (command === "id2path" && request.method === "POST") {
|
||||
return handleId2Path(request, gd);
|
||||
} else if (command === "view") {
|
||||
const params = url.searchParams;
|
||||
return gd.view(params.get("url"), request.headers.get('Range'));
|
||||
} else if (command!=='down' && request.method === 'GET'){
|
||||
return gd.view(params.get("url"), request.headers.get("Range"));
|
||||
} else if (command !== "down" && request.method === "GET") {
|
||||
return new Response(html(gd.order, { root_type: gd.root_type }), {
|
||||
status: 200,
|
||||
headers: {'Content-Type': 'text/html; charset=utf-8'}
|
||||
headers: { "Content-Type": "text/html; charset=utf-8" },
|
||||
});
|
||||
}
|
||||
}
|
||||
const reg = new RegExp(`^(/\\d+:)${command}/`, 'g');
|
||||
const reg = new RegExp(`^(/\\d+:)${command}/`, "g");
|
||||
path = path.replace(reg, (p1, p2) => {
|
||||
return p2+'/'
|
||||
})
|
||||
return p2 + "/";
|
||||
});
|
||||
// 期望的 path 格式
|
||||
const common_reg = /^\/\d+:\/.*$/g;
|
||||
try {
|
||||
@ -238,56 +256,67 @@ async function handleRequest(request) {
|
||||
if (order >= 0 && order < gds.length) {
|
||||
gd = gds[order];
|
||||
} else {
|
||||
return redirectToIndexPage()
|
||||
return redirectToIndexPage();
|
||||
}
|
||||
} catch (e) {
|
||||
return redirectToIndexPage()
|
||||
return redirectToIndexPage();
|
||||
}
|
||||
|
||||
// basic auth
|
||||
// for (const r = gd.basicAuthResponse(request); r;) return r;
|
||||
const basic_auth_res = gd.basicAuthResponse(request);
|
||||
path = path.replace(gd.url_path_prefix, '') || '/';
|
||||
if (request.method == 'POST') {
|
||||
path = path.replace(gd.url_path_prefix, "") || "/";
|
||||
if (request.method == "POST") {
|
||||
return basic_auth_res || apiRequest(request, gd);
|
||||
}
|
||||
|
||||
let action = url.searchParams.get('a');
|
||||
let action = url.searchParams.get("a");
|
||||
|
||||
if (path.substr(-1) == '/' || action != null) {
|
||||
return basic_auth_res || new Response(html(gd.order, {root_type: gd.root_type}), {
|
||||
if (path.substr(-1) == "/" || action != null) {
|
||||
return (
|
||||
basic_auth_res ||
|
||||
new Response(html(gd.order, { root_type: gd.root_type }), {
|
||||
status: 200,
|
||||
headers: {'Content-Type': 'text/html; charset=utf-8'}
|
||||
});
|
||||
headers: { "Content-Type": "text/html; charset=utf-8" },
|
||||
})
|
||||
);
|
||||
} else {
|
||||
if (path.split('/').pop().toLowerCase() == ".password") {
|
||||
if (
|
||||
path
|
||||
.split("/")
|
||||
.pop()
|
||||
.toLowerCase() == ".password"
|
||||
) {
|
||||
return basic_auth_res || new Response("", { status: 404 });
|
||||
}
|
||||
let file = await gd.file(path);
|
||||
let range = request.headers.get('Range');
|
||||
let range = request.headers.get("Range");
|
||||
if (gd.root.protect_file_link && basic_auth_res) return basic_auth_res;
|
||||
const is_down = !(command && command=='down');
|
||||
const is_down = !(command && command == "down");
|
||||
return gd.down(file.id, range, is_down);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function apiRequest(request, gd) {
|
||||
let url = new URL(request.url);
|
||||
let path = url.pathname;
|
||||
path = path.replace(gd.url_path_prefix, '') || '/';
|
||||
path = path.replace(gd.url_path_prefix, "") || "/";
|
||||
|
||||
let option = {status: 200, headers: {'Access-Control-Allow-Origin': '*'}}
|
||||
let option = { status: 200, headers: { "Access-Control-Allow-Origin": "*" } };
|
||||
|
||||
if (path.substr(-1) == '/') {
|
||||
if (path.substr(-1) == "/") {
|
||||
let deferred_pass = gd.password(path);
|
||||
let body = await request.text();
|
||||
body = JSON.parse(body);
|
||||
// 这样可以提升首次列目录时的速度。缺点是,如果password验证失败,也依然会产生列目录的开销
|
||||
let deferred_list_result = gd.list(path, body.page_token, Number(body.page_index));
|
||||
let deferred_list_result = gd.list(
|
||||
path,
|
||||
body.page_token,
|
||||
Number(body.page_index)
|
||||
);
|
||||
|
||||
// check .password file, if `enable_password_file_verify` is true
|
||||
if (authConfig['enable_password_file_verify']) {
|
||||
if (authConfig["enable_password_file_verify"]) {
|
||||
let password = await gd.password(path);
|
||||
// console.log("dir password", password);
|
||||
if (password && password.replace("\n", "") !== body.password) {
|
||||
@ -300,18 +329,24 @@ async function apiRequest(request, gd) {
|
||||
return new Response(JSON.stringify(list_result), option);
|
||||
} else {
|
||||
let file = await gd.file(path);
|
||||
let range = request.headers.get('Range');
|
||||
let range = request.headers.get("Range");
|
||||
return new Response(JSON.stringify(file));
|
||||
}
|
||||
}
|
||||
|
||||
// 处理 search
|
||||
async function handleSearch(request, gd) {
|
||||
const option = {status: 200, headers: {'Access-Control-Allow-Origin': '*'}};
|
||||
const option = {
|
||||
status: 200,
|
||||
headers: { "Access-Control-Allow-Origin": "*" },
|
||||
};
|
||||
let body = await request.text();
|
||||
body = JSON.parse(body);
|
||||
let search_result = await
|
||||
gd.search(body.q || '', body.page_token, Number(body.page_index));
|
||||
let search_result = await gd.search(
|
||||
body.q || "",
|
||||
body.page_token,
|
||||
Number(body.page_index)
|
||||
);
|
||||
return new Response(JSON.stringify(search_result), option);
|
||||
}
|
||||
|
||||
@ -322,11 +357,14 @@ async function handleSearch(request, gd) {
|
||||
* @returns {Promise<Response>} 【注意】如果从前台接收的id代表的项目不在目标gd盘下,那么response会返回给前台一个空字符串""
|
||||
*/
|
||||
async function handleId2Path(request, gd) {
|
||||
const option = {status: 200, headers: {'Access-Control-Allow-Origin': '*'}};
|
||||
const option = {
|
||||
status: 200,
|
||||
headers: { "Access-Control-Allow-Origin": "*" },
|
||||
};
|
||||
let body = await request.text();
|
||||
body = JSON.parse(body);
|
||||
let path = await gd.findPathById(body.id);
|
||||
return new Response(path || '', option);
|
||||
return new Response(path || "", option);
|
||||
}
|
||||
|
||||
class googleDrive {
|
||||
@ -346,8 +384,8 @@ class googleDrive {
|
||||
this.passwords = [];
|
||||
// id <-> path
|
||||
this.id_path_cache = {};
|
||||
this.id_path_cache[this.root['id']] = '/';
|
||||
this.paths["/"] = this.root['id'];
|
||||
this.id_path_cache[this.root["id"]] = "/";
|
||||
this.paths["/"] = this.root["id"];
|
||||
/*if (this.root['pass'] != "") {
|
||||
this.passwords['/'] = this.root['pass'];
|
||||
}*/
|
||||
@ -370,9 +408,9 @@ class googleDrive {
|
||||
})();*/
|
||||
// 等待 user_drive_real_root_id ,只获取1次
|
||||
if (authConfig.user_drive_real_root_id) return;
|
||||
const root_obj = await (gds[0] || this).findItemById('root');
|
||||
const root_obj = await (gds[0] || this).findItemById("root");
|
||||
if (root_obj && root_obj.id) {
|
||||
authConfig.user_drive_real_root_id = root_obj.id
|
||||
authConfig.user_drive_real_root_id = root_obj.id;
|
||||
}
|
||||
}
|
||||
|
||||
@ -381,9 +419,9 @@ class googleDrive {
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async initRootType() {
|
||||
const root_id = this.root['id'];
|
||||
const root_id = this.root["id"];
|
||||
const types = CONSTS.gd_root_type;
|
||||
if (root_id === 'root' || root_id === authConfig.user_drive_real_root_id) {
|
||||
if (root_id === "root" || root_id === authConfig.user_drive_real_root_id) {
|
||||
this.root_type = types.user_drive;
|
||||
} else {
|
||||
const obj = await this.getShareDriveObjById(root_id);
|
||||
@ -397,65 +435,72 @@ class googleDrive {
|
||||
* @returns {Response|null}
|
||||
*/
|
||||
basicAuthResponse(request) {
|
||||
const user = this.root.user || '',
|
||||
pass = this.root.pass || '',
|
||||
_401 = new Response('Unauthorized', {
|
||||
headers: {'WWW-Authenticate': `Basic realm="goindex:drive:${this.order}"`},
|
||||
status: 401
|
||||
const user = this.root.user || "",
|
||||
pass = this.root.pass || "",
|
||||
_401 = new Response("Unauthorized", {
|
||||
headers: {
|
||||
"WWW-Authenticate": `Basic realm="goindex:drive:${this.order}"`,
|
||||
},
|
||||
status: 401,
|
||||
});
|
||||
if (user || pass) {
|
||||
const auth = request.headers.get('Authorization')
|
||||
const auth = request.headers.get("Authorization");
|
||||
if (auth) {
|
||||
try {
|
||||
const [received_user, received_pass] = atob(auth.split(' ').pop()).split(':');
|
||||
return (received_user === user && received_pass === pass) ? null : _401;
|
||||
const [received_user, received_pass] = atob(
|
||||
auth.split(" ").pop()
|
||||
).split(":");
|
||||
return received_user === user && received_pass === pass ? null : _401;
|
||||
} catch (e) {}
|
||||
}
|
||||
} else return null;
|
||||
return _401;
|
||||
}
|
||||
|
||||
async view(url, range = '', inline = true) {
|
||||
async view(url, range = "", inline = true) {
|
||||
let requestOption = await this.requestOption();
|
||||
requestOption.headers['Range'] = range;
|
||||
requestOption.headers["Range"] = range;
|
||||
let res = await fetch(url, requestOption);
|
||||
const {headers} = res = new Response(res.body, res)
|
||||
this.authConfig.enable_cors_file_down && headers.append('Access-Control-Allow-Origin', '*');
|
||||
inline === true && headers.set('Content-Disposition', 'inline');
|
||||
const { headers } = (res = new Response(res.body, res));
|
||||
this.authConfig.enable_cors_file_down &&
|
||||
headers.append("Access-Control-Allow-Origin", "*");
|
||||
inline === true && headers.set("Content-Disposition", "inline");
|
||||
return res;
|
||||
}
|
||||
|
||||
async down(id, range = '', inline = false) {
|
||||
async down(id, range = "", inline = false) {
|
||||
let url = `https://www.googleapis.com/drive/v3/files/${id}?alt=media`;
|
||||
let requestOption = await this.requestOption();
|
||||
requestOption.headers['Range'] = range;
|
||||
requestOption.headers["Range"] = range;
|
||||
let res = await fetch(url, requestOption);
|
||||
const {headers} = res = new Response(res.body, res)
|
||||
this.authConfig.enable_cors_file_down && headers.append('Access-Control-Allow-Origin', '*');
|
||||
inline === true && headers.set('Content-Disposition', 'inline');
|
||||
const { headers } = (res = new Response(res.body, res));
|
||||
this.authConfig.enable_cors_file_down &&
|
||||
headers.append("Access-Control-Allow-Origin", "*");
|
||||
inline === true && headers.set("Content-Disposition", "inline");
|
||||
return res;
|
||||
}
|
||||
|
||||
async file(path) {
|
||||
if (typeof this.files[path] == 'undefined') {
|
||||
if (typeof this.files[path] == "undefined") {
|
||||
this.files[path] = await this._file(path);
|
||||
}
|
||||
return this.files[path];
|
||||
}
|
||||
|
||||
async _file(path) {
|
||||
let arr = path.split('/');
|
||||
let arr = path.split("/");
|
||||
let name = arr.pop();
|
||||
name = decodeURIComponent(name).replace(/\'/g, "\\'");
|
||||
let dir = arr.join('/') + '/';
|
||||
let dir = arr.join("/") + "/";
|
||||
// console.log(name, dir);
|
||||
let parent = await this.findPathId(dir);
|
||||
// console.log(parent);
|
||||
let url = 'https://www.googleapis.com/drive/v3/files';
|
||||
let params = {'includeItemsFromAllDrives': true, 'supportsAllDrives': true};
|
||||
let url = "https://www.googleapis.com/drive/v3/files";
|
||||
let params = { includeItemsFromAllDrives: true, supportsAllDrives: true };
|
||||
params.q = `'${parent}' in parents and name = '${name}' and trashed = false`;
|
||||
params.fields = "files(id, name, mimeType, size ,createdTime, modifiedTime, iconLink, thumbnailLink)";
|
||||
url += '?' + this.enQuery(params);
|
||||
params.fields =
|
||||
"files(id, name, mimeType, size ,createdTime, modifiedTime, iconLink, thumbnailLink)";
|
||||
url += "?" + this.enQuery(params);
|
||||
let requestOption = await this.requestOption();
|
||||
let response = await fetch(url, requestOption);
|
||||
let obj = await response.json();
|
||||
@ -470,15 +515,16 @@ class googleDrive {
|
||||
this.path_children_cache = {};
|
||||
}
|
||||
|
||||
if (this.path_children_cache[path]
|
||||
&& this.path_children_cache[path][page_index]
|
||||
&& this.path_children_cache[path][page_index].data
|
||||
if (
|
||||
this.path_children_cache[path] &&
|
||||
this.path_children_cache[path][page_index] &&
|
||||
this.path_children_cache[path][page_index].data
|
||||
) {
|
||||
let child_obj = this.path_children_cache[path][page_index];
|
||||
return {
|
||||
nextPageToken: child_obj.nextPageToken || null,
|
||||
curPageIndex: page_index,
|
||||
data: child_obj.data
|
||||
data: child_obj.data,
|
||||
};
|
||||
}
|
||||
|
||||
@ -488,18 +534,17 @@ class googleDrive {
|
||||
// 对有多页的,进行缓存
|
||||
if (result.nextPageToken && data.files) {
|
||||
if (!Array.isArray(this.path_children_cache[path])) {
|
||||
this.path_children_cache[path] = []
|
||||
this.path_children_cache[path] = [];
|
||||
}
|
||||
this.path_children_cache[path][Number(result.curPageIndex)] = {
|
||||
nextPageToken: result.nextPageToken,
|
||||
data: data
|
||||
data: data,
|
||||
};
|
||||
}
|
||||
|
||||
return result
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
async _ls(parent, page_token = null, page_index = 0) {
|
||||
// console.log("_ls", parent);
|
||||
|
||||
@ -507,17 +552,18 @@ class googleDrive {
|
||||
return null;
|
||||
}
|
||||
let obj;
|
||||
let params = {'includeItemsFromAllDrives': true, 'supportsAllDrives': true};
|
||||
let params = { includeItemsFromAllDrives: true, supportsAllDrives: true };
|
||||
params.q = `'${parent}' in parents and trashed = false AND name !='.password'`;
|
||||
params.orderBy = 'folder,name,modifiedTime desc';
|
||||
params.fields = "nextPageToken, files(id, name, mimeType, size , modifiedTime, thumbnailLink, description)";
|
||||
params.orderBy = "folder,name,modifiedTime desc";
|
||||
params.fields =
|
||||
"nextPageToken, files(id, name, mimeType, size , modifiedTime, thumbnailLink, description)";
|
||||
params.pageSize = this.authConfig.files_list_page_size;
|
||||
|
||||
if (page_token) {
|
||||
params.pageToken = page_token;
|
||||
}
|
||||
let url = 'https://www.googleapis.com/drive/v3/files';
|
||||
url += '?' + this.enQuery(params);
|
||||
let url = "https://www.googleapis.com/drive/v3/files";
|
||||
url += "?" + this.enQuery(params);
|
||||
let requestOption = await this.requestOption();
|
||||
let response = await fetch(url, requestOption);
|
||||
obj = await response.json();
|
||||
@ -525,7 +571,7 @@ class googleDrive {
|
||||
return {
|
||||
nextPageToken: obj.nextPageToken || null,
|
||||
curPageIndex: page_index,
|
||||
data: obj
|
||||
data: obj,
|
||||
};
|
||||
|
||||
/*do {
|
||||
@ -540,7 +586,6 @@ class googleDrive {
|
||||
files.push(...obj.files);
|
||||
pageToken = obj.nextPageToken;
|
||||
} while (pageToken);*/
|
||||
|
||||
}
|
||||
|
||||
async password(path) {
|
||||
@ -550,7 +595,7 @@ class googleDrive {
|
||||
|
||||
// console.log("load", path, ".password", this.passwords[path]);
|
||||
|
||||
let file = await this.file(path + '.password');
|
||||
let file = await this.file(path + ".password");
|
||||
if (file == undefined) {
|
||||
this.passwords[path] = null;
|
||||
} else {
|
||||
@ -563,7 +608,6 @@ class googleDrive {
|
||||
return this.passwords[path];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过 id 获取 share drive 信息
|
||||
* @param any_id
|
||||
@ -571,7 +615,7 @@ class googleDrive {
|
||||
*/
|
||||
async getShareDriveObjById(any_id) {
|
||||
if (!any_id) return null;
|
||||
if ('string' !== typeof any_id) return null;
|
||||
if ("string" !== typeof any_id) return null;
|
||||
|
||||
let url = `https://www.googleapis.com/drive/v3/drives/${any_id}`;
|
||||
let requestOption = await this.requestOption();
|
||||
@ -579,10 +623,9 @@ class googleDrive {
|
||||
let obj = await res.json();
|
||||
if (obj && obj.id) return obj;
|
||||
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
* @returns {Promise<{data: null, nextPageToken: null, curPageIndex: number}>}
|
||||
@ -595,7 +638,7 @@ class googleDrive {
|
||||
const empty_result = {
|
||||
nextPageToken: null,
|
||||
curPageIndex: page_index,
|
||||
data: null
|
||||
data: null,
|
||||
};
|
||||
|
||||
if (!is_user_drive && !is_share_drive) {
|
||||
@ -607,15 +650,17 @@ class googleDrive {
|
||||
return empty_result;
|
||||
}
|
||||
let words = keyword.split(/\s+/);
|
||||
let name_search_str = `name contains '${words.join("' AND name contains '")}'`;
|
||||
let name_search_str = `name contains '${words.join(
|
||||
"' AND name contains '"
|
||||
)}'`;
|
||||
|
||||
// corpora 为 user 是个人盘 ,为 drive 是团队盘。配合 driveId
|
||||
let params = {};
|
||||
if (is_user_drive) {
|
||||
params.corpora = 'user'
|
||||
params.corpora = "user";
|
||||
}
|
||||
if (is_share_drive) {
|
||||
params.corpora = 'drive';
|
||||
params.corpora = "drive";
|
||||
params.driveId = this.root.id;
|
||||
// This parameter will only be effective until June 1, 2020. Afterwards shared drive items will be included in the results.
|
||||
params.includeItemsFromAllDrives = true;
|
||||
@ -625,12 +670,13 @@ class googleDrive {
|
||||
params.pageToken = page_token;
|
||||
}
|
||||
params.q = `trashed = false AND name !='.password' AND (${name_search_str})`;
|
||||
params.fields = "nextPageToken, files(id, name, mimeType, size , modifiedTime, thumbnailLink, description)";
|
||||
params.fields =
|
||||
"nextPageToken, files(id, name, mimeType, size , modifiedTime, thumbnailLink, description)";
|
||||
params.pageSize = this.authConfig.search_result_list_page_size;
|
||||
// params.orderBy = 'folder,name,modifiedTime desc';
|
||||
|
||||
let url = 'https://www.googleapis.com/drive/v3/files';
|
||||
url += '?' + this.enQuery(params);
|
||||
let url = "https://www.googleapis.com/drive/v3/files";
|
||||
url += "?" + this.enQuery(params);
|
||||
// console.log(params)
|
||||
let requestOption = await this.requestOption();
|
||||
let response = await fetch(url, requestOption);
|
||||
@ -639,11 +685,10 @@ class googleDrive {
|
||||
return {
|
||||
nextPageToken: res_obj.nextPageToken || null,
|
||||
curPageIndex: page_index,
|
||||
data: res_obj
|
||||
data: res_obj,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 一层一层的向上获取这个文件或文件夹的上级文件夹的 file 对象。注意:会很慢!!!
|
||||
* 最多向上寻找到当前 gd 对象的根目录 (root id)
|
||||
@ -696,7 +741,7 @@ class googleDrive {
|
||||
}
|
||||
await addItsFirstParent(child_obj);
|
||||
|
||||
return meet_top ? parent_files : null
|
||||
return meet_top ? parent_files : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -710,20 +755,27 @@ class googleDrive {
|
||||
}
|
||||
|
||||
const p_files = await this.findParentFilesRecursion(child_id);
|
||||
if (!p_files || p_files.length < 1) return '';
|
||||
if (!p_files || p_files.length < 1) return "";
|
||||
|
||||
let cache = [];
|
||||
// 把查出来的每一级的path和id都缓存一下
|
||||
p_files.forEach((value, idx) => {
|
||||
const is_folder = idx === 0 ? (p_files[idx].mimeType === CONSTS.folder_mime_type) : true;
|
||||
let path = '/' + p_files.slice(idx).map(it => it.name).reverse().join('/');
|
||||
if (is_folder) path += '/';
|
||||
cache.push({id: p_files[idx].id, path: path})
|
||||
const is_folder =
|
||||
idx === 0 ? p_files[idx].mimeType === CONSTS.folder_mime_type : true;
|
||||
let path =
|
||||
"/" +
|
||||
p_files
|
||||
.slice(idx)
|
||||
.map((it) => it.name)
|
||||
.reverse()
|
||||
.join("/");
|
||||
if (is_folder) path += "/";
|
||||
cache.push({ id: p_files[idx].id, path: path });
|
||||
});
|
||||
|
||||
cache.forEach((obj) => {
|
||||
this.id_path_cache[obj.id] = obj.path;
|
||||
this.paths[obj.path] = obj.id
|
||||
this.paths[obj.path] = obj.id;
|
||||
});
|
||||
|
||||
/*const is_folder = p_files[0].mimeType === CONSTS.folder_mime_type;
|
||||
@ -733,25 +785,26 @@ class googleDrive {
|
||||
return cache[0].path;
|
||||
}
|
||||
|
||||
|
||||
// 根据id获取file item
|
||||
async findItemById(id) {
|
||||
const is_user_drive = this.root_type === CONSTS.gd_root_type.user_drive;
|
||||
let url = `https://www.googleapis.com/drive/v3/files/${id}?fields=${CONSTS.default_file_fields}${is_user_drive ? '' : '&supportsAllDrives=true'}`;
|
||||
let url = `https://www.googleapis.com/drive/v3/files/${id}?fields=${
|
||||
CONSTS.default_file_fields
|
||||
}${is_user_drive ? "" : "&supportsAllDrives=true"}`;
|
||||
let requestOption = await this.requestOption();
|
||||
let res = await fetch(url, requestOption);
|
||||
return await res.json()
|
||||
return await res.json();
|
||||
}
|
||||
|
||||
async findPathId(path) {
|
||||
let c_path = '/';
|
||||
let c_path = "/";
|
||||
let c_id = this.paths[c_path];
|
||||
|
||||
let arr = path.trim('/').split('/');
|
||||
let arr = path.trim("/").split("/");
|
||||
for (let name of arr) {
|
||||
c_path += name + '/';
|
||||
c_path += name + "/";
|
||||
|
||||
if (typeof this.paths[c_path] == 'undefined') {
|
||||
if (typeof this.paths[c_path] == "undefined") {
|
||||
let id = await this._findDirId(c_id, name);
|
||||
this.paths[c_path] = id;
|
||||
}
|
||||
@ -774,11 +827,11 @@ class googleDrive {
|
||||
return null;
|
||||
}
|
||||
|
||||
let url = 'https://www.googleapis.com/drive/v3/files';
|
||||
let params = {'includeItemsFromAllDrives': true, 'supportsAllDrives': true};
|
||||
let url = "https://www.googleapis.com/drive/v3/files";
|
||||
let params = { includeItemsFromAllDrives: true, supportsAllDrives: true };
|
||||
params.q = `'${parent}' in parents and mimeType = 'application/vnd.google-apps.folder' and name = '${name}' and trashed = false`;
|
||||
params.fields = "nextPageToken, files(id, name, mimeType)";
|
||||
url += '?' + this.enQuery(params);
|
||||
url += "?" + this.enQuery(params);
|
||||
let requestOption = await this.requestOption();
|
||||
let response = await fetch(url, requestOption);
|
||||
let obj = await response.json();
|
||||
@ -790,7 +843,10 @@ class googleDrive {
|
||||
|
||||
async accessToken() {
|
||||
console.log("accessToken");
|
||||
if (this.authConfig.expires == undefined || this.authConfig.expires < Date.now()) {
|
||||
if (
|
||||
this.authConfig.expires == undefined ||
|
||||
this.authConfig.expires < Date.now()
|
||||
) {
|
||||
const obj = await this.fetchAccessToken();
|
||||
if (obj.access_token != undefined) {
|
||||
this.authConfig.accessToken = obj.access_token;
|
||||
@ -804,19 +860,19 @@ class googleDrive {
|
||||
console.log("fetchAccessToken");
|
||||
const url = "https://www.googleapis.com/oauth2/v4/token";
|
||||
const headers = {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
};
|
||||
const post_data = {
|
||||
'client_id': this.authConfig.client_id,
|
||||
'client_secret': this.authConfig.client_secret,
|
||||
'refresh_token': this.authConfig.refresh_token,
|
||||
'grant_type': 'refresh_token'
|
||||
}
|
||||
client_id: this.authConfig.client_id,
|
||||
client_secret: this.authConfig.client_secret,
|
||||
refresh_token: this.authConfig.refresh_token,
|
||||
grant_type: "refresh_token",
|
||||
};
|
||||
|
||||
let requestOption = {
|
||||
'method': 'POST',
|
||||
'headers': headers,
|
||||
'body': this.enQuery(post_data)
|
||||
method: "POST",
|
||||
headers: headers,
|
||||
body: this.enQuery(post_data),
|
||||
};
|
||||
|
||||
const response = await fetch(url, requestOption);
|
||||
@ -836,36 +892,39 @@ class googleDrive {
|
||||
return response;
|
||||
}
|
||||
|
||||
async requestOption(headers = {}, method = 'GET') {
|
||||
async requestOption(headers = {}, method = "GET") {
|
||||
const accessToken = await this.accessToken();
|
||||
headers['authorization'] = 'Bearer ' + accessToken;
|
||||
return {'method': method, 'headers': headers};
|
||||
headers["authorization"] = "Bearer " + accessToken;
|
||||
return { method: method, headers: headers };
|
||||
}
|
||||
|
||||
enQuery(data) {
|
||||
const ret = [];
|
||||
for (let d in data) {
|
||||
ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d]));
|
||||
ret.push(encodeURIComponent(d) + "=" + encodeURIComponent(data[d]));
|
||||
}
|
||||
return ret.join('&');
|
||||
return ret.join("&");
|
||||
}
|
||||
|
||||
sleep(ms) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
let i = 0;
|
||||
setTimeout(function() {
|
||||
console.log('sleep' + ms);
|
||||
console.log("sleep" + ms);
|
||||
i++;
|
||||
if (i >= 2) reject(new Error('i>=2'));
|
||||
if (i >= 2) reject(new Error("i>=2"));
|
||||
else resolve(i);
|
||||
}, ms);
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
String.prototype.trim = function(char) {
|
||||
if (char) {
|
||||
return this.replace(new RegExp('^\\' + char + '+|\\' + char + '+$', 'g'), '');
|
||||
return this.replace(
|
||||
new RegExp("^\\" + char + "+|\\" + char + "+$", "g"),
|
||||
""
|
||||
);
|
||||
}
|
||||
return this.replace(/^\s+|\s+$/g, '');
|
||||
return this.replace(/^\s+|\s+$/g, "");
|
||||
};
|
||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -12677,7 +12677,7 @@
|
||||
},
|
||||
"webpack-bundle-analyzer": {
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npm.taobao.org/webpack-bundle-analyzer/download/webpack-bundle-analyzer-3.7.0.tgz?cache=0&sync_timestamp=1586846559504&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-bundle-analyzer%2Fdownload%2Fwebpack-bundle-analyzer-3.7.0.tgz",
|
||||
"resolved": "https://registry.npm.taobao.org/webpack-bundle-analyzer/download/webpack-bundle-analyzer-3.7.0.tgz?cache=0&sync_timestamp=1586846510646&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwebpack-bundle-analyzer%2Fdownload%2Fwebpack-bundle-analyzer-3.7.0.tgz",
|
||||
"integrity": "sha1-hNpDTolEKJm4hNmtOORm0NsCpW8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
@ -14,7 +14,7 @@
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
<script>
|
||||
var authConfig = {
|
||||
version: '1.0.0',
|
||||
version: '1.1.0',
|
||||
roots: [
|
||||
{
|
||||
id: "0AEofxddwF4bAUk9PVA",
|
||||
@ -26,18 +26,31 @@
|
||||
name: "PriveDrive",
|
||||
pass: "",
|
||||
},
|
||||
{
|
||||
id: "1ZUli0boWXTpAedKDzE_IF9CWT10G6V86",
|
||||
name: "folder1",
|
||||
pass: "",
|
||||
}
|
||||
],
|
||||
};
|
||||
var themeOptions = {
|
||||
// en/zh-chs/zh-cht
|
||||
languages: 'en'
|
||||
languages: 'en',
|
||||
render: {
|
||||
head_md: false,
|
||||
readme_md: false,
|
||||
// 是否显示文件/文件夹描述(默认不显示)
|
||||
// Show file/folder description or not (not shown by default)
|
||||
desc: false,
|
||||
}
|
||||
}
|
||||
window.gdconfig = JSON.parse(JSON.stringify({ version: authConfig.version, themeOptions: themeOptions }));
|
||||
window.themeOptions = themeOptions;
|
||||
window.gds = JSON.parse(
|
||||
JSON.stringify(authConfig.roots.map((it) => it.name))
|
||||
);
|
||||
window.current_drive_order = 0;
|
||||
// window.MODEL = { q: "the" };
|
||||
// window.MODEL = { q: "the",root_type: 1 };
|
||||
</script>
|
||||
<!-- 使用 CDN 加速的 JS 文件,配置在 vue.config.js 下 -->
|
||||
<% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
|
||||
|
@ -1,37 +1,34 @@
|
||||
import axios from "@utils/axios";
|
||||
let Base64 = require("js-base64").Base64;
|
||||
|
||||
// const exts = [
|
||||
// "html",
|
||||
// "php",
|
||||
// "css",
|
||||
// "go",
|
||||
// "java",
|
||||
// "js",
|
||||
// "json",
|
||||
// "py",
|
||||
// "txt",
|
||||
// "sh",
|
||||
// "md",
|
||||
// "mp4",
|
||||
// "webm",
|
||||
// "mkv",
|
||||
// "bmp",
|
||||
// "jpg",
|
||||
// "jpeg",
|
||||
// "png",
|
||||
// "gif",
|
||||
// ];
|
||||
const text_exts = [
|
||||
"html",
|
||||
"php",
|
||||
"css",
|
||||
"go",
|
||||
"java",
|
||||
"js",
|
||||
"json",
|
||||
"txt",
|
||||
"sh",
|
||||
"md",
|
||||
];
|
||||
const video_exts = ["mp4", "webm", "mkv", "m3u8"];
|
||||
const image_exts = ["bmp", "jpg", "jpeg", "png", "gif"];
|
||||
const pdf_exts = ["pdf"];
|
||||
|
||||
export const encodePath = (path) => {
|
||||
return path.replace(/(.*)/, (p1, p2) => {
|
||||
return p2.replace().replace(/\//g, "%2F").replace(/#/g, "%23")
|
||||
})
|
||||
return p2
|
||||
.replace()
|
||||
.replace(/\//g, "%2F")
|
||||
.replace(/#/g, "%23");
|
||||
});
|
||||
//return path.replace().replace("/", "%2F").replace("#", "%23")
|
||||
}
|
||||
};
|
||||
|
||||
export const checkoutPath = (path, file) => {
|
||||
path = encodePath(path)
|
||||
path = encodePath(path);
|
||||
if (file.mimeType === "application/vnd.google-apps.folder") {
|
||||
if (path.substr(-1) !== "/") {
|
||||
path += "/";
|
||||
@ -47,25 +44,25 @@ export const checkView = (path) => {
|
||||
.pop()
|
||||
.toLowerCase();
|
||||
let base64Path = encode64(path);
|
||||
if ("|html|php|css|go|java|js|json|txt|sh|md|".indexOf(`|${ext}|`) >= 0) {
|
||||
if (text_exts.indexOf(`${ext}`) != -1) {
|
||||
path = path.replace(/\/(\d+:)\/.*/, (p1, p2) => {
|
||||
return `/${p2}text/${base64Path}`;
|
||||
});
|
||||
}
|
||||
|
||||
if ("|pdf|".indexOf(`|${ext}|`) >= 0) {
|
||||
if (pdf_exts.indexOf(`${ext}`) != -1) {
|
||||
path = path.replace(/\/(\d+:)\/.*/, (p1, p2) => {
|
||||
return `/${p2}pdf/${base64Path}`;
|
||||
});
|
||||
}
|
||||
|
||||
if ("|mp4|webm|mkv|".indexOf(`|${ext}|`) >= 0) {
|
||||
if (video_exts.indexOf(`${ext}`) != -1) {
|
||||
path = path.replace(/\/(\d+:)\/.*/, (p1, p2) => {
|
||||
return `/${p2}video/${base64Path}`;
|
||||
});
|
||||
}
|
||||
|
||||
if ("|bmp|jpg|jpeg|png|gif|".indexOf(`|${ext}|`) >= 0) {
|
||||
if (image_exts.indexOf(`${ext}`) != -1) {
|
||||
path = path.replace(/\/(\d+:)\/.*/, (p1, p2) => {
|
||||
return `/${p2}image/${base64Path}`;
|
||||
});
|
||||
@ -73,27 +70,16 @@ export const checkView = (path) => {
|
||||
return path;
|
||||
};
|
||||
|
||||
export const getQueryString = (path, param) => {
|
||||
if (!path) {
|
||||
return "";
|
||||
}
|
||||
var args = getURLParameters(path);
|
||||
return args[param] ? args[param] : "";
|
||||
export const checkExtends = (path) => {
|
||||
let name = path.split("/").pop();
|
||||
let ext = name
|
||||
.split(".")
|
||||
.pop()
|
||||
.toLowerCase();
|
||||
let exts = text_exts.concat(...video_exts,...image_exts,...pdf_exts);
|
||||
return exts.indexOf(`${ext}`) != -1;
|
||||
};
|
||||
|
||||
export const getURLParameters = (url) =>
|
||||
url
|
||||
.match(/([^?=&]+)(=([^&]*))/g)
|
||||
.reduce(
|
||||
(a, v) => (
|
||||
(a[v.slice(0, v.indexOf("="))] = v.slice(v.indexOf("=") + 1)), a
|
||||
), {}
|
||||
);
|
||||
|
||||
// console.log(getURLParameters("/Movies/xx.mp4?a=view&y=123"));
|
||||
|
||||
//console.log(getQueryString("/Movies/xx.mp4?a=view&y=123", "y"));
|
||||
|
||||
export const encode64 = (str) => {
|
||||
return Base64.encodeURI(str);
|
||||
};
|
||||
@ -182,7 +168,6 @@ export function formatFileSize(bytes) {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
/** 日期格式化
|
||||
* @param {Number String Date}
|
||||
* @param {String} 'YYYY-MM-DD HH:mm:ss EEE' 年(Y)、月(M)、日(D)、12小时(h)、24小时(H)、分(m)、秒(s)、毫秒(S)、周(E)、季度(q)
|
||||
@ -190,42 +175,55 @@ export function formatFileSize(bytes) {
|
||||
* @example XDate.format(new Date(), "YYYY-MM-DD") ==> 2017-08-23
|
||||
*/
|
||||
export function formatDate(date, fmt) {
|
||||
fmt = fmt || 'YYYY-MM-DD HH:mm:ss';
|
||||
if (typeof date === 'string') {
|
||||
fmt = fmt || "YYYY-MM-DD HH:mm:ss";
|
||||
if (typeof date === "string") {
|
||||
// date = new Date(date.replace(/-/g, '/'))
|
||||
date = new Date(date)
|
||||
date = new Date(date);
|
||||
}
|
||||
if (typeof date === 'number') {
|
||||
date = new Date(date)
|
||||
if (typeof date === "number") {
|
||||
date = new Date(date);
|
||||
}
|
||||
var o = {
|
||||
'M+': date.getMonth() + 1,
|
||||
'D+': date.getDate(),
|
||||
'h+': date.getHours() % 12 === 0 ? 12 : date.getHours() % 12,
|
||||
'H+': date.getHours(),
|
||||
'm+': date.getMinutes(),
|
||||
's+': date.getSeconds(),
|
||||
'q+': Math.floor((date.getMonth() + 3) / 3),
|
||||
'S': date.getMilliseconds()
|
||||
}
|
||||
"M+": date.getMonth() + 1,
|
||||
"D+": date.getDate(),
|
||||
"h+": date.getHours() % 12 === 0 ? 12 : date.getHours() % 12,
|
||||
"H+": date.getHours(),
|
||||
"m+": date.getMinutes(),
|
||||
"s+": date.getSeconds(),
|
||||
"q+": Math.floor((date.getMonth() + 3) / 3),
|
||||
S: date.getMilliseconds(),
|
||||
};
|
||||
var week = {
|
||||
'0': '\u65e5',
|
||||
'1': '\u4e00',
|
||||
'2': '\u4e8c',
|
||||
'3': '\u4e09',
|
||||
'4': '\u56db',
|
||||
'5': '\u4e94',
|
||||
'6': '\u516d'
|
||||
}
|
||||
"0": "\u65e5",
|
||||
"1": "\u4e00",
|
||||
"2": "\u4e8c",
|
||||
"3": "\u4e09",
|
||||
"4": "\u56db",
|
||||
"5": "\u4e94",
|
||||
"6": "\u516d",
|
||||
};
|
||||
if (/(Y+)/.test(fmt)) {
|
||||
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
|
||||
fmt = fmt.replace(
|
||||
RegExp.$1,
|
||||
(date.getFullYear() + "").substr(4 - RegExp.$1.length)
|
||||
);
|
||||
}
|
||||
if (/(E+)/.test(fmt)) {
|
||||
fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? '\u661f\u671f' : '\u5468') : '') + week[date.getDay() + ''])
|
||||
fmt = fmt.replace(
|
||||
RegExp.$1,
|
||||
(RegExp.$1.length > 1
|
||||
? RegExp.$1.length > 2
|
||||
? "\u661f\u671f"
|
||||
: "\u5468"
|
||||
: "") + week[date.getDay() + ""]
|
||||
);
|
||||
}
|
||||
for (var k in o) {
|
||||
if (new RegExp('(' + k + ')').test(fmt)) {
|
||||
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
|
||||
if (new RegExp("(" + k + ")").test(fmt)) {
|
||||
fmt = fmt.replace(
|
||||
RegExp.$1,
|
||||
RegExp.$1.length === 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
|
||||
);
|
||||
}
|
||||
}
|
||||
return fmt;
|
||||
|
@ -108,6 +108,13 @@ export default {
|
||||
// height: 100%;
|
||||
padding: 10px 0.75em;
|
||||
}
|
||||
.level-left {
|
||||
width: 95%;
|
||||
.level-item {
|
||||
display: initial;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.level-right {
|
||||
.level-item {
|
||||
// border-radius: 50%;
|
||||
|
@ -42,7 +42,7 @@
|
||||
|
||||
<div class="navbar-end">
|
||||
<!-- is-hidden-desktop -->
|
||||
<div class="navbar-item">
|
||||
<div class="navbar-item" v-show="showSearch">
|
||||
<div class="field is-grouped">
|
||||
<p class="control has-icons-left is-dark" style="width:100%;">
|
||||
<input
|
||||
@ -71,7 +71,10 @@
|
||||
<i class="fab fa-github"></i>
|
||||
</a>
|
||||
<header-setting />
|
||||
<a class="navbar-item is-hidden-desktop" @click.stop="$refs.viewMode.toggleMode">
|
||||
<a
|
||||
class="navbar-item is-hidden-desktop"
|
||||
@click.stop="$refs.viewMode.toggleMode"
|
||||
>
|
||||
<view-mode ref="viewMode" />
|
||||
</a>
|
||||
</div>
|
||||
@ -144,6 +147,10 @@ export default {
|
||||
getCurrGD() {
|
||||
return this.gds.filter((item) => item.name !== this.currgd.name);
|
||||
},
|
||||
showSearch() {
|
||||
// 文件夹不支持搜索
|
||||
return window.MODEL ? window.MODEL.root_type < 2 : true
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
"$route.params.id": "chooseGD",
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<headmd :option="headmd" v-if="headmd.display"></headmd>
|
||||
<headmd :option="headmd" v-if="renderHeadMD && headmd.display"></headmd>
|
||||
<div
|
||||
class="golist"
|
||||
v-loading="loading"
|
||||
@ -8,7 +8,13 @@
|
||||
infinite-scroll-disabled="busy"
|
||||
infinite-scroll-distance="10"
|
||||
>
|
||||
<list-view :data="buildFiles" v-if="mode === 'list'" :icons="getIcon" :go="go" :copy="copy" />
|
||||
<list-view
|
||||
:data="buildFiles"
|
||||
v-if="mode === 'list'"
|
||||
:icons="getIcon"
|
||||
:go="go"
|
||||
:copy="copy"
|
||||
/>
|
||||
<grid-view
|
||||
class="g2-content"
|
||||
:data="buildFiles"
|
||||
@ -17,7 +23,10 @@
|
||||
:go="go"
|
||||
:thum="thum"
|
||||
/>
|
||||
<div v-show="files.length === 0" class="has-text-centered no-content"></div>
|
||||
<div
|
||||
v-show="files.length === 0"
|
||||
class="has-text-centered no-content"
|
||||
></div>
|
||||
<center>
|
||||
<div :class="!busy ? 'is-hidden' : ''">
|
||||
<i class="fa fa-spinner fa-pulse fa-2x fa-fw"></i>
|
||||
@ -28,8 +37,13 @@
|
||||
</span>-->
|
||||
</center>
|
||||
</div>
|
||||
<div class="is-divider" :data-content="$t('list.total')+' '+files.length+' ' + $t('list.item')"></div>
|
||||
<readmemd :option="readmemd" v-if="readmemd.display"></readmemd>
|
||||
<div
|
||||
class="is-divider"
|
||||
:data-content="
|
||||
$t('list.total') + ' ' + files.length + ' ' + $t('list.item')
|
||||
"
|
||||
></div>
|
||||
<readmemd :option="readmemd" v-if="renderReadMeMD && readmemd.display"></readmemd>
|
||||
|
||||
<viewer
|
||||
v-if="viewer && images && images.length > 0"
|
||||
@ -57,6 +71,7 @@ import {
|
||||
formatFileSize,
|
||||
checkoutPath,
|
||||
checkView,
|
||||
checkExtends,
|
||||
} from "@utils/AcrouUtil";
|
||||
import axios from "@/utils/axios";
|
||||
import { mapState } from "vuex";
|
||||
@ -139,6 +154,12 @@ export default {
|
||||
(file) => file.mimeType.indexOf("image") != -1
|
||||
);
|
||||
},
|
||||
renderHeadMD() {
|
||||
return window.themeOptions.render.head_md || false;
|
||||
},
|
||||
renderReadMeMD() {
|
||||
return window.themeOptions.render.readme_md || false;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.render();
|
||||
@ -238,7 +259,7 @@ export default {
|
||||
if (file.mimeType.indexOf("image") != -1) {
|
||||
this.viewer = true;
|
||||
this.$nextTick(() => {
|
||||
let index = this.images.findIndex(item => item.path === file.path)
|
||||
let index = this.images.findIndex((item) => item.path === file.path);
|
||||
this.$viewer.view(index);
|
||||
});
|
||||
return;
|
||||
@ -253,7 +274,7 @@ export default {
|
||||
window.open(path);
|
||||
return;
|
||||
}
|
||||
if (target === "down") {
|
||||
if (target === "down" || (!checkExtends(path) && !file.isFolder)) {
|
||||
let temp_path = this.$route.params.path ? this.$route.params.path : "";
|
||||
location.href = `/${this.$route.params.id}:down/${temp_path}/${file.name}`;
|
||||
return;
|
||||
|
@ -32,7 +32,11 @@
|
||||
<use :xlink:href="icons(file.mimeType)" />
|
||||
</svg>
|
||||
{{ file.name }}
|
||||
<span class="has-text-grey g2-file-desc" v-html="file.description"></span>
|
||||
<span
|
||||
class="has-text-grey g2-file-desc"
|
||||
v-if="isShowDesc"
|
||||
v-html="file.description"
|
||||
></span>
|
||||
</td>
|
||||
<td class="is-hidden-mobile is-hidden-touch">
|
||||
{{ file.modifiedTime }}
|
||||
@ -107,6 +111,9 @@ export default {
|
||||
},
|
||||
];
|
||||
},
|
||||
isShowDesc() {
|
||||
return window.themeOptions.render.desc || false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue
Block a user