Greasy Fork

Greasy Fork is available in English.

百度网盘 - 更高级的重命名

你不知道的百度网盘重命名姿势~支持批量替换重命名、手动批量修改后一次提交、智能重命名,拒绝转圈圈!

当前为 2023-08-14 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name            百度网盘 - 更高级的重命名
// @version         1.0.5
// @description     你不知道的百度网盘重命名姿势~支持批量替换重命名、手动批量修改后一次提交、智能重命名,拒绝转圈圈!
// @author          Priate
// @match           https://pan.baidu.com/*
// @grant           GM_setValue
// @grant           GM_getValue
// @grant           GM_addStyle
// @icon            https://nd-static.bdstatic.com/m-static/v20-main/favicon-main.ico
// @require         https://unpkg.com/vue@2
// @require         https://unpkg.com/[email protected]/dist/sweetalert.min.js
// @require         https://unpkg.com/[email protected]/dist/jquery.min.js
// @require         http://greasyfork.icu/scripts/435476-priatelib/code/PriateLib.js?version=1202493
// @supportURL      http://greasyfork.icu/scripts/443771/feedback
// @homepageURL     http://greasyfork.icu/scripts/443771
// @contributionURL https://afdian.net/@cyberubbish
// @license         MIT
// @namespace       http://greasyfork.icu/users/219866
// ==/UserScript==

(function() {
	'use strict';

	function initSetting() {
		var setting;
		if (!GM_getValue('priate_script_bdwp_data')) {
			GM_setValue('priate_script_bdwp_data', {
				left: 20,
				top: 100,
			})
		}
		setting = GM_getValue('priate_script_bdwp_data')
		GM_setValue('priate_script_bdwp_data', setting)
	}

	function injectDiv() {
		var priate_script_div = document.createElement("div")
		priate_script_div.innerHTML = `
<div id="priate_script_div">
<b style='font-size:30px; font-weight:300; margin: 10px 20px'>更高级的重命名</b>
<p id='priate_script_setting' style='margin: 0 0'>
❤️ by <a @click='openDonate' style='color:#337ab7'>Priate</a> |
v <a href="//greasyfork.org/scripts/443771" target="_blank" style='color:#ff6666'>{{version}}</a> |
<a @click="switchDrag">📌</a> | <a @click="recoverText">♻️</a> | <a v-show="data.length > 0" @click="smartRename">🤖️ |</a> <a @click="clearData">❌</a>
<br>
文件夹重命名 : <a @click='todo' :style='"color:" + (false ? "#00947e" : "#CC0F35")'> 关闭 </a> |
正则 : <a @click='todo' :style='"color:" + (false ? "#00947e" : "#CC0F35")'> 关闭 </a>
<div v-show="data.length">
<a style='color:#946C00;' @click="changeOriginText" v-show="showOriginText">{{'【' + originText + '】'}}</a>
<textarea class="replaceArea" ref="originTextInput" v-show="!showOriginText" @blur="recoverOriginText" type="text" v-model="originText" ></textarea>
<a @click="autoRename">➡️ ➡️ ➡️</a>
<a style='color:#00947e' @click="changeReplaceText" v-show="showReplaceText">{{'【' + replaceText + '】' }}</a>
<textarea class="replaceArea" ref="replaceTextInput" v-show="!showReplaceText" @blur="recoverReplaceText" type="text" v-model="replaceText" ></textarea>
</div>
</p>
<button @click="loadData">{{data.length > 0 ? '重载数据' : '加载数据'}}</button>
<button @click="postRename" v-show="musicList.length > 0"> 确定修改 </button>
</br>
<table v-show="data.length > 0">
<thead><tr><th></th><th>原始文件名</th><th>修改后文件名</th></tr></thead>
<tbody id="priate_script_table">
<tr v-for="(item, index) in data" :key="index">
<td><input class="checkMusicBox" v-model="musicList" :value='item' type="checkbox" :disabled="item.replace == item.origin"></td>
<td><a @click="originText = item.origin" style='color:#337ab7'>{{item.origin}}</a></td>
<td><a v-show="!item.isChanging" @click="manualRename(item)" style='color:#C01D07'>{{item.replace}}</a><textarea class="replaceArea" :ref="item.id" @blur="modifyReplace(item)" v-show="item.isChanging" v-model="item.replace"></textarea></td>
</tr>
</tbody>
</table>
</div>
`
		GM_addStyle(`
#priate_script_div{
font-size : 15px;
position: fixed;
background-color: rgb(240, 223, 175);
color : #660000;
text-align : center;
padding: 10px;
z-index : 9999;
border-radius : 20px;
border:2px solid #660000;
font-weight: 300;
text-stroke: 0.5px;
box-shadow: 5px 15px 15px rgba(0,0,0,0.4);
user-select : none;
-webkit-user-select : none;
-moz-user-select : none;
-ms-user-select:none;
}
#priate_script_div:hover{
box-shadow: 5px 15px 15px rgba(0,0,0,0.8);
transition: box-shadow 0.3s;
}

#priate_script_div a{
margin-bottom: 2px !important;
}
.priate_script_hide{
padding: 0 !important;
border:none !important;
}
a{
cursor : pointer;
text-decoration : none;
}
/*表格样式*/
#priate_script_div table{
text-align: center;
// border:2px solid #660000;
margin: 5px auto;
padding: 2px;
border-collapse: collapse;
display: block;
height : 400px;
overflow-y: scroll;
}
/*表格框样式*/
#priate_script_div td{
border:2px solid #660000;
padding: 8px 12px;
max-width : 300px;
word-wrap : break-word;
}
/*表头样式*/
#priate_script_div th{
border:2px solid #660000;
padding: 8px 12px;
font-weight: 300;
-webkit-text-stroke: 0.5px;
text-stroke: 0.5px;
}

/*脚本按钮样式*/
#priate_script_div button{
display: inline-block;
border-radius: 4px;
border: 1px solid #660000;
background-color: transparent;
color: #660000;
text-decoration: none;
padding: 5px 10px;
margin : 5px 10px;
font-weight: 300;
-webkit-text-stroke: 0.5px;
text-stroke: 0.5px;
}
/*脚本按钮悬浮样式*/
#priate_script_div button:hover{
cursor : pointer;
color: rgb(240, 223, 175);
background-color: #660000;
transition: background-color 0.2s;
}
/*设置区域 p 标签*/
#priate_script_setting{
user-select : none;
-webkit-user-select : none;
-moz-user-select : none;
-ms-user-select:none;
}
/*swal按钮*/
.swal-button--1{
background-color: #FFFAEB !important;
color: #946C00;
}
.swal-button--2{
background-color: #ebfffc !important;
color: #00947e;
}
.swal-button--3{
background-color: #ECF6FD !important;
color: #55ACEE;
}
.checkMusicBox{
transform: scale(1.7,1.7);
cursor: pointer;
}
.replaceArea{
height : 100%;
width : 100%;
background-color: #fff;
border:1px solid #000000;
padding: 4px;
border-radius: 4px;
}
.replaceInput{
height : 100%;
width : 40%;
background-color: #fff;
border:1px solid #000000;
padding: 4px;
border-radius: 4px;
}
`);
		document.querySelector("html").appendChild(priate_script_div)
		var setting = GM_getValue('priate_script_bdwp_data')
		document.getElementById("priate_script_div").style.left = (setting.left || 20) + "px";
		document.getElementById("priate_script_div").style.top = (setting.top || 100) + "px";
	}

	function dragFunc(id) {
		var Drag = document.getElementById(id);
		var setting = GM_getValue('priate_script_bdwp_data')
		Drag.onmousedown = function(event) {
			var ev = event || window.event;
			event.stopPropagation();
			var disX = ev.clientX - Drag.offsetLeft;
			var disY = ev.clientY - Drag.offsetTop;
			document.onmousemove = function(event) {
				var ev = event || window.event;
				setting.left = ev.clientX - disX
				Drag.style.left = setting.left + "px";
				setting.top = ev.clientY - disY
				Drag.style.top = setting.top + "px";
				Drag.style.cursor = "move";
				GM_setValue('priate_script_bdwp_data', setting)
			};
		};
		Drag.onmouseup = function() {
			document.onmousemove = null;
			this.style.cursor = "default";
		};
	};

	function unDragFunc(id) {
		var Drag = document.getElementById(id);
		Drag.onmousedown = function(event) {
			var ev = event || window.event;
			event.stopPropagation();
		};
		Drag.onmouseup = function() {};
		Drag.onmousemove = function() {};
	};

	//初始化脚本设置
	initSetting()
	//注入脚本div
	injectDiv()

	function getToken() {
		return document.querySelector(".nd-main-list, .nd-new-main-list").__vue__.yunData.bdstoken;
	}

	function getLogid() {
		let ut = unsafeWindow.require("system-core:context/context.js").instanceForSystem.tools.baseService;
		return ut.base64Encode(base.getCookie("BAIDUID"));
	}

	function getPath() {
		var nowPath = location.href.match(/path=(.+?)(?:&|$)/);
		var pathValue;
		if (nowPath)
			pathValue = decodeURIComponent(nowPath[1]);
		else
			pathValue = "/";
		if (pathValue.charAt(0) !== "/")
			pathValue = "/" + pathValue; // 补齐路径前缀斜杠
		if (pathValue.charAt(pathValue.length - 1) !== "/")
			pathValue += "/"
		return pathValue
	}

	function reloadList() {
		document.querySelector(".nd-main-list, .nd-new-main-list").__vue__.reloadList();
	}

	// 处理数据等逻辑
	var vm = new Vue({
		el: '#priate_script_div',
		data: {
			version: "1.0.5",
			setting: GM_getValue('priate_script_bdwp_data'),
			data: [],
			musicList: [],
			showOriginText: true,
			showReplaceText: true,
			originText: "需要替换的内容",
			replaceText: "",
			path: '/',
			isDrag: true,
		},
		methods: {
			loadData() {
				const path = getPath()
				this.path = path
				const all_tr = document.querySelectorAll('table.wp-s-pan-table__body-table tbody>tr');
				var result = [];
				var _this = this
				all_tr.forEach((item) => {
					const type = item.querySelector('img[alt]') ? item.querySelector('img[alt]').getAttribute('alt') : 'unknow'
					if (!item.querySelector('a')) return
					const music = {
						id: item.getAttribute('data-id'),
						origin: item.querySelector('a').getAttribute('title'),
						replace: item.querySelector('a').getAttribute('title'),
						isChanging: false,
						type,
						isFolder: type == 'folder',
					}
					result.push(music)
				})
				// 如果仍未获取到数据
				if (result.length == 0) {
					swal("未获取到数据,请确认此目录下有文件或文件夹!", {
						icon: "error",
						buttons: false,
						timer: 3000,
					});
				}
				this.data = result
				this.musicList = []
			},
			clearData() {
				if (this.data.length == 0) swal(`已经是最简形态了!`, {
					buttons: false,
					timer: 2000,
				});
				this.data = []
				this.musicList = []
			},
			openDonate() {
				showDonate()
			},
			async manualRename(item) {
				this.unDrag()
				item.isChanging = true
				await Sleep(0.01)
				this.$refs[item.id][0].focus();
			},
			modifyReplace(item) {
				this.drag()
				item.isChanging = false
				item.replace = item.replace.trim()
				if (item.replace != item.origin) {
					if (!this.musicList.find(el => el.id == item.id)) {
						this.musicList.push(item)
					}
				} else {
					this.musicList = this.musicList.filter(el => el.id != item.id)
				}

			},
			autoRename() {
				var _this = this
				const origin = this.originText
				const replace = this.replaceText
				var hasChanged = false
				var hasEmpty = false
				this.data.forEach(item => {
					item.replace = item.replace.replace(origin, replace).trim()
					if (item.replace !== item.origin) {
						hasChanged = true
					}
					if (item.replace == "") {
						hasEmpty = true
						item.replace = item.origin
					}
					_this.modifyReplace(item)
				})
				if (!hasChanged) swal(`没有匹配到任何需要修改的文件!`, {
					icon: "error",
					buttons: false,
					timer: 3000,
				});
				if (hasEmpty) swal(`替换后某个文件名为空!`, {
					icon: "error",
					buttons: false,
					timer: 3000,
				});
			},
			async postRename() {
				var _this = this
				const token = getToken()
				// const logid = getLogid()
				const data = this.musicList.map(item => {
					return {
						id: item.id,
						path: `${_this.path}${item.origin}`,
						newname: item.replace,
					}
				})
				$.ajax(`https://pan.baidu.com/api/filemanager?async=2&onnest=fail&opera=rename&bdstoken=${getToken()}&clienttype=0&app_id=250528&web=1`, {
					type: 'post',
					data: {
						filelist: JSON.stringify(data)
					},
					complete: function(res) {
						const resp = res.responseJSON
						if (resp['errno'] == 0) {
							swal(`重命名已完成!\n如部分文件显示未修改请点击 ♻️ 按钮手动刷新!`, {
								icon: "success",
								buttons: false,
								timer: 3000,
							});
						} else {
							swal(`重命名失败!`, {
								icon: "error",
								buttons: false,
								timer: 3000,
							});
						}
						_this.clearData()
					}
				});
				await Sleep(3)
				reloadList()
			},
			switchDrag() {
				if (this.isDrag) {
					this.unDrag()
					swal(`悬浮窗已固定`, {
						buttons: false,
						timer: 2000,
					});
				} else {
					this.drag()
					swal(`悬浮窗可以拖动了`, {
						buttons: false,
						timer: 2000,
					});
				}
			},
			unDrag() {
				this.isDrag = false
				unDragFunc("priate_script_div")
			},
			drag() {
				this.isDrag = true
				dragFunc("priate_script_div")
			},
			async changeOriginText() {
				this.unDrag()
				this.showOriginText = false
				await Sleep(0.01)
				this.$refs.originTextInput.focus();
			},
			async changeReplaceText() {
				this.unDrag()
				this.showReplaceText = false
				await Sleep(0.01)
				this.$refs.replaceTextInput.focus();
			},
			recoverOriginText() {
				this.drag()
				this.showOriginText = true
			},
			recoverReplaceText() {
				this.drag()
				this.showReplaceText = true
			},
			recoverText() {
				reloadList()
			},
			smartRename() {
				var _this = this
				var hasChanged = false
				var hasEmpty = false
				var lengthStatistics = {}
				var maxLength = 0
				this.data.forEach(item => {
					const suffix = item.origin.split('.').length > 1 ? '.' + item.origin.split('.')[item.origin.split('.').length - 1] : ''
					item.numArr = item.origin.replace(suffix, '').match(/\d+/g) || []
					// 寻找出现次数最多的匹配项
					if (lengthStatistics[item.numArr.length] == undefined) lengthStatistics[item.numArr.length] = 1
					else lengthStatistics[item.numArr.length] += 1
				})
				for (var i in lengthStatistics) {
					maxLength = lengthStatistics[i] > maxLength ? i : maxLength
				}
				var seq = -1
				for (var index = 0; index < maxLength; index++) {
					const tempList = this.data.map(item => {
						if (item.numArr.length == maxLength) {
							return item.numArr[index]
						}
					}).filter(l => l != undefined)
					// 判断是否有重复元素
					if (Array.from(new Set(tempList)).length == tempList.length) {
						seq = index
						break
					}
				}
				if (seq < 0) return swal(`智能重命名失败,找不到唯一的数字序号!`, {
					icon: "error",
					buttons: false,
					timer: 3000,
				});
				this.data.forEach(item => {
					if (item.numArr.length == maxLength) {
						const suffix = item.origin.split('.').length > 1 ? '.' + item.origin.split('.')[item.origin.split('.').length - 1] : ''
						item.replace = `${item.numArr[seq]}${suffix}`.trim()
					}
					if (item.replace !== item.origin) {
						hasChanged = true
					}
					if (item.replace == "") {
						hasEmpty = true
						item.replace = item.origin
					}
					_this.modifyReplace(item)
				})

				if (!hasChanged) swal(`没有匹配到任何需要修改的文件!`, {
					icon: "error",
					buttons: false,
					timer: 3000,
				});
				if (hasEmpty) swal(`替换后某个文件名为空!`, {
					icon: "error",
					buttons: false,
					timer: 3000,
				});
			},
			todo() {
				swal(`🈲️🈲️🈲️ 此功能暂不可用,请等待版本更新 🔞🔞🔞`, {
					buttons: false,
					timer: 2000,
				});
			}
		},
		computed: {},
		mounted() {}
	})
	//设置div可拖动
	dragFunc("priate_script_div");
})();