// ==UserScript== // @name 访问码验证助手 // @author wangzijian0@vip.qq.com // @description 115网盘访问码验证助手:内容查重、批量验证/接收/分享,智能存储(115分享/磁力/ED2K)、元素屏蔽、自动填写、数据导入导出等。 // @description:en 115 Access Code Helper: content deduplication, batch verify/receive/share, smart storage (115 share/magnet/ED2K), element blocking, autofill, import/export. // @version 1.8.9.20250826 // @icon data:image/gif;base64,R0lGODlhgAGAAZECAPr7/ERNVv///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo5OTk5ODkxZS0wMWE2LTRlMTItYWM1Mi00YTIzMzI1MTViYjQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MkU2QTk5NkYxM0UzMTFFQzg5RkRCRTMwRTcyQUZCRjIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MkU2QTk5NkUxM0UzMTFFQzg5RkRCRTMwRTcyQUZCRjIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoxOTQyMDFlMi00OGRjLTQ3OTgtOTFlNi05ZjkyNzhjNTJlZTUiIHN0UmVmOmRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDplMjk3YTUwZC00MTM4LWVmNDYtYTY3Ni1kZTkzNDU1ZjNmOTkiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQJEAACACwAAAAAgAGAAQAC/5SPqcvtD6OctNqLs968+w+G4kiW5omm6sq27gvH8kzX9o3n+s73/g8MCofEovGITCqXzKbzCY1Kp9Sq9YrNarfcrvcLDovH5LL5jE6r1+y2+w2Py+f0uv2Oz+v3/L7/DxgoOEhYaHiImKi4yNjo+AgZKTlJWWl5iZmpucnZ6fkJGhoRQFpqeoqaakql2up6Kmr1OtvKSnu7GmuLi7vLS6vr+/sqPFwbLGUMPKU8i5zc7Focnfv8RH0MjY1qDbWdOr3dff0Ny1xePb6Enu7NTqre9A5//h7PNB8Qjn2/Pr9PrZ+SfACjCUxCsB67g0gSalvI0EY+hzEm/otYwqK9Gf8aIWIc0REdjZDlPpIg+W0kSn4mRaxkKeNlwJYhZBrkaFMZzZo5jans+WsnCKDDfhK9JfTDUV5GlxJL2sEpUpxSn0LdUNUZ1ayqrnLgKm0rWHNeM4ztKvYsvbIY1HJLq5atWbftXtCtK1fC3VJN3ea9sLfohMBB/1YgzHQw4qmGFS/Wqvcx5MajJFutbDkbZQiZw0buDG4zZtBkR5PmK5rz6dKqV6NO7cA13gayX8NmUHut6dW3Y+emkFtfb9y/HcseTrw28OLIEwRfrry5c+a7T0ufHv3z8esHnht33Ti4eKIfx5u3Wf68epLp17uf2P69fJEY59svWf++/psR9/v/95nffwIu09+ABnrG0IEKhlbggg4K1+CDCsYnoYEUVijghRj6p+GGHuriYYisfSJiiRCGYqKIIKb4YSwstijKixuuKKOENNbo4I04Tujijjn26COPMQYpJIpEHqjjkRwCqeR/SX4DQJRSTklllVZeiWWWWm7JZZdWejfkO16OSWaZZp75JXWg5INmm26+2SaYRooJZ5123kmlnGvOg2effsapJol8/klooVvqKSidhi7KaJSIesJmo5IW+mgnkU6KKZ6VcnJppp6+uekmnX5KqpmhajJqqap2eWomqa4KK5atYvJqrLZOOesltd56a66W7MprrL4WAmywxmJ6FCXF/x7L7KLJTrJss9L6+awk0U6LbZ3VRnJttt6iuS0k3X5L7pjhPjJuuepqea4j6a4Lb5XtNvJuvPYCMC8j9d4Lb76L7Muvuv4qAnDA5A6cSMEGe4swIgovjG3DhzwMsbQSG0JxxcxeTOygrOKiMb4gUxsYIePyEjLKJO9lssdcqlwxzJqWPMjJI8d888ws1+zyoTkvLPOdhLWs6Ms/Gxy0nUPzXLTPt6R8tLY0C2Lz0xonLfXOVPfMbtT8Yg3n0ls33bXVOJut811Es2Ou1/eCDerUgVRNC9RoCy03IHTPYnfdK6vNNNtewm0v4YBqPTfXWRrer9tuip042Ys7Hi/jZ/9Crjfl4Gq+ruWGckyH52WKfjDnn5MXON9/q36236WCPgfpbd+NtOmUoj6262mzDrHsq6OX+it/+p4t8bsDnzvveNMesPHL97S28krbXjrzyOIeue7PS9889cNjn7n1cYtfuPe/yxS98Oe30jf31wOVvivfk1+5+X3CLofzZWtfO/2M4h8H/U3Of52z3/HQFzz5rU8V7VPf68D3BwHKyoDTkuD4oDeGo3xLg1fLGzmAskGiNDAuCslJCEHYQcS5A4XFE2EKAfcQEzLMha2jS0FCcsKejPAsN+xIDmVYQ7+U0CY/JOILbThEmRRRiUcUYgyN2EIW9s6DTuBgFHXYRBL/PpGJVwTiFFX4QSx2EYpfhGEUrBgxGpYRiVt8yRLdmEUeJhGOY+TiGp0YQAqGbI8DxGDyHMjHQF4wJ/FjnyAPeTg/Zs99iGzk/giZQEM6cpJGg18kGUjJTPYRkn9UoCY/mScI+sGCoPyaKPtAylKWz5KdlKQqPwlAOKTylQVk5SIBSUtKxvINs8xl9RQZPv75EpG7dEMvh1nHlxQSk8h0ZDG7kLFmztCWslScNPf4TC5E85oVPCUbtsnNZmVzC+AM57HGqYVymjNY6MyCOtfZK2+u4Z3wFJY81UDPeq6qnVjIpz4fSE1eWvOfqwSmQCVH0IJyMo8ITWjjAmrMgTpU/2D3TIM/Jzopfl7hohhtlEaNkBiXSBSjHxVASM/YC5CMdKIlPekKCcSThna0pSltI1pEKlOSVrQtNUUpY2IquI6mCaJR6elLJzOUlTqUpj896mWSmlOW7hQwRg0jUpWi1IQyFaZORRBUgyrUUBL1K1WtYlmLGtWlTtUCLrXqU7GaVq2u9TBnxUddsZJVgm71qmZtKlzBGlYp7fWtfeXqX9ERWHnNFTqGLSxf0QrYxA7Wq26lrAc4msnJauYgTdINd+Dio89KpLOirUFnT1RaGJw2taDdEWtjQtrXqja2snXBamtrW9ridgW33S1vdetbFPQ2uMIFLnEzYtzjqrRJyv8t7mn92tzqPPem0f3OdDdb3dZc17LZpc12Cdvd5HyXuuH1zXjJW17xnndE6VXAetHbXuy8dzbxNcB831LfBdyXvfk16X5t09/u/NezAfbvgAss3/1md8AWKS2D4SPaB1PkOhK+yGcrvJELY5g+Gt5wSiLs4Q93OMQzGTGJm+HgE5eYOypeMYVbjGIQwxhAJp7xXW9jYxqzOMeFqTGPwTucH7e1OUK+MWyKDF3kILmxSl4ykHvj5CfjOMrYJTKV4dvkK+N3x1rmb5C77GUog5m+Yh4zga1sZtRKJ82C+Qube5yXNw/ZK3I28k7qnOSr4JnJet6zlIXi5z/fOdBVpjP/obHc50NvWS6KZlCcGx3mpEA60oCeNIDZYulLl2XCD3hweCws3fV+OsOhPu+oPVLq8Z6aw6n+7qrxox0FG4bT5v3vq0Xc6u3eWhzWne+uYZLr6/7axZ1m8LD5E+zpHjvGsb7vsnXS6/c+W8falbWbQV1tZ8uYz/qdK629S+oX57nbYyU3qrONa3Fz273exnaxw71mOwu43OyGd61Zre7Hqhd5yYYzunnt40LvG4HNTve7zx3vcdfboPeGdb/n/GWFJ5jf/wZ2xYmN5nVPnOAPl7d93Z1xfZt7oRdHdsmZzWWNI4Bj3x44wFMu8oWT/OD4prnD8y3oeTMc3AhvuMFD0Z7zj9N74y8/ObQDjuiRU9zmP+d5zYHOXZevhLFPd/rNERztpGsA4r+VONaVHnW8ev0EXP+61B391ZinoOxml3nQ6Tp2E7C97Sv3ONxVTna7t33uVI07cv2+d71nHe12EfzX+c5WwwNV7XTXOeP7jne5Kx7BiL/74yUPeLNXnupvP8nkC7z5wS+68Jk//Od9LvCuR57uoS946lXQeqzH3uiabsHsQX96q4cd9rlvvO9/D/zgC3/4xC++8Y+P/OQrf/nMb77znw/96Et/+tRHQwEAACH5BAkQAAIALAAAAACAAYABAAL/lI+py+0Po5y02ouz3rz7D4biSJbmiabqyrbuC8fyTNf2jef6zvf+DwwKh8Si8YhMKpfMpvMJjUqn1Kr1is1qt9yu9wsOi8fksvmMTqvX7Lb7DY/L5/S6/Y7P6/f8vv8PGCg4SFhoeIiYqLjI2Oj4CBkpOUlZaXmJmam5ydnp+QkaKjpKWmp6ipqqusra6voKGys7S1tre4ubq7vL2+v7CxwsPExMEnCMnKy8zJxM1QwdrVw8I20N/Xyt7Uwds/0dkA1+3e09Tj51jl7uom4t7t7M/hIfDV8/Pd+CL5/Ov6xv3798UgYSDJjCILeCCo8hXNHQob+GD1VEDDdRYcWE/xHvDdyI4qLHfyBPiMxosKSJkwwpqjTWEeXHlxMusjRnU6PKnC5l8NRZ8mfKakJJ7izKjwbSpEeXxlPq9GnTqOegUq069eo3q1q3Zu26DidYbS/HevVpluzXtP3QspVW9i1conKxra2LjCvegxv3thXrN+/dvXoDYwxqeCFgw3ETS3TruLHjsxEmj5NsOSyEzJT7clYr4TNokKI1Pyj9bjDqx5VX20XsmhmF2H890+Z7+jbuh7p3N+it2Dbw2cBZC+9NvDhm3cmHq17dHPlz1NGZTy9d/fZy7TWLHybtPTttYt7Lm6VlPr1W9OrbL2XvPj5P+PLr94xlPz9Q/Pr74/+j71+A4AAoYIGpyWJggqa5omCDr/HnYISCIShhhQRWmOCFGBao4YYBduhhiKSESKJso5SI4oShpJjiiCyW6OKLIp4o44yi1GjjijhuGOOOEvboo4NABqngkEQaaOSRAiappH9MNqnfk/EAQGWVVl6JZZZabslll15+CWaW5UnpTphmnolmmmqKGR6NDa0JZ5xywjmmmwrNiWeeemJZ540R7QlooHS26eebgh6KqJd96mhooo4+SuWioFwEaaWJSvoJpZZuCiimnmjKaahzetoJqKKeqiapnJiKaqthqroJq67OyiWsmshKa65X2poJrrr+yismvv6aa7CHDEtsspz/jkUJsso++yizkzgLbbWCSisJtdZumye2kWjLbbiDdtXsn+Ke2ylY5TaKbrtyegsJuO7OuyW8j8hLb75W2usIvvrqy28j/v5Lb8CMDEywuwYvgnDC6C6sSMMOiwtxIhJPzG3FiFyMsbUaH2sumN90DMDIgWZGCL4mY7zynigPovI2JLes58uCxKzNzDKfbFnKIX9Jc8JB42lzIDhfo3POPE/mM7uK7swy1C73DPPPTysdNdZTM121010O/S/Y71J9s9VfS+2w2HEWDcjR1iSN9NKRdX3nq2gLfTfRZBttdq15h/332FyX7bXfWqcd+Np7t913vYkX/PiabP/htjRw/78td2JNx53u4Xh7vqy6dGPeOecTqw3px3agLnnkCrt+qeiEm14z7A/bfqjqdbCeKu4U+545VZuTvjXtnxsfOrmjWx58NJczj6rudPCeJvW3g76p9HNYfyb3v2NvqfZyeG83+PmSX/pVw0NfPPGIm5+67HzD3zr9r9sfu/Kzu98t8Bn73z7hLc95zYPG8wgYPfkxDn9oQt+2HFg7/c0PeaMCoMcs2D8JgmEs39PKAf0yEqd08CofJIxMojJCqpQQLyFcSgpR2LHJOYGD4aJh1ubWEg/WECwrrEsLkfJCEcZwcU+w4QN5OMTBRcGIF+xKD+Xyw6IE0YVJxOESkfg/J/9WUXMnFGIWdXhDLuaQhDvUYhgZ00UqfpGMZwxMFIUyRSBuEY1jVGEZwXg6IroBgiTro+HWM0AD+nGQetMg5TBIyESWTIGHZKAiH7kvRvqBj5D0o/jiQMlKPvEn60OgJj+ppUvCIZOgfB8g98e+UqpykYacJCJXSTBRvoGUsDyfJPtAy1rOS5Z7fKUuIddKXPryl/c75QT5R0xF8rINuUxmHIsyvcY505K3ZAPHpnk9Y45SmticY1SiWbhubnI+2+OmOE2pvnKG85x5DKY1zclOwLlzDdeMZ7WWyYV62vNZ+NyCPveZrH5q4Z8ABVY16QnPgrZLoFkgqEJpxVAsOPT/oa6K6BUmStEEzlMNGM2oqCxqhM58oKOwBKkARDrDbcBknR5lpTZHqtI0mkgEJF2lSVHaBJxyoKaqvGlM62iPEfC0lD4dDRR0uoGhgrKoC8rpT0Og1E8y9UBXNCpMWerRqc4FqA8CQVQ1qdWgcrU2V61bS9m00QwgVQlrVWtCHxrWrhbxqV59q0LjStaUWtUDX60kXmda1abu1K4F/StAZHpYmhIWoIb1DRPaioG+QrKxwckUlHJCk+5c9iaZdcBmbdLZ1nz2PqFlwGhjUtrfnHY/qVXAalnbWgS8diixde1sjVLbBNwWt7k9wG6Z0lvf/rYewZXtcKVS3JMe1x3J/zXAcpnb3OeqYzvSTacwqpsW8mDXpGTaLieH4d2D6iK8acUFeV/qi/NaNxjqFeB12+sU7cIXKfKdr1Dqa19yvje/390vfzEL3v/ql70Czu4sCmxgCiFYvKlYMHen5eDyniLCEjYFhdHbiguvFxYadi+EOkzfA4P4PSIeMTRLbOL+fjjFAFYwi1u84hejNsa83YyMjWNZ0ubmxt3FSmhu/J1JzdjGPLYTbUUr4x5fRrNJNvJMflzkQsHWs0BW8oCY/GIrQ1a4UWbUlFXbZSHrmMphzvGXTVtlJ9d4x02W8pGJ3GYvv5nNWUYxVeFcZxffmc4sBlFikZxnGsuVzHHmMP9d+ZxiPzt2AUAO8iu27Nw063mrgO6znSmNZ0tPWqyVTvSlOZ1pT2960GAu9KMPTehAG3qvpVb1qVmN5jIzCNWt1jR4xlxr7kD5zPrgLKLHg+Un35rXtlVOsNfMmyH/Ojbi+c91fNxpYO96zsnGdaydM21hH0fby3ZNs4n77CVnW9fRdjZsiK1bQpUb3Oemdq6lvW7kDtvd15bOuIE7b26n2jr3Nne+kf1uZh8b39sGeL35HW/otlvfAff2wP1dcIJ3GzoPZ3dxIa1cazNa2c2lB60PbvCNa7zjFvm4yNFt3JGTPCQmLzbKufzyla9UsCend80ZLnOOwPrmIXe5zXOBvpKWp1vlKY850Ou6c5/jnOcSPzrLkz50o/va6SYRetF/HnWsUx3pNFd6z7O+9K1D1eow13rZwy72su5531+/OtrT3gGMT73h8ob7zNdOd4UnfLp2DzrU3d72swe+74QvvOEPj/jEK37xjG+84x8P+chLfvKUr7zlL4/5zGu+7wUAACH5BAkQAAIALAAAAACAAYABAAL/lI+py+0Po5y02ouz3rz7D4biSJbmiabqyrbuC8fyTNf2jef6zvf+DwwKh8Si8YhMKpfMpvMJjUqn1Kr1is1qt9yu9wsOi8fksvmMTqvX7Lb7DY/L5/S6/Y7P6/f8vv8PGCg4SFhoeIiYqLjI2Oj4CBkpOUlZaXmJmam5ydnp+QkaKjpKWmp6ipqqusra6voKGys7S1tre4ubq7vL2+v7CxwsPExcbHyMnKy8zNzs/AwdLT1NXW19jZ2tvc3d7f0NHi4+Tl5ufo6err7O3u7+Dh8vP09fb3+Pn6+/Dx/g/w8woMCBAKkQPIgwIL2EDA8abAix4LyIFAM8rNhwIcaM/1M2cpTnkeHFkAQ1kizZ8SRKkCoHjmz5zyTMmCln0mRp09/LmTJt7oTZk2fNnEGBDvU5MafOo0JxEmVq1ClSKUqXSm0aparFcVq10uhalRpYpV/HTo1m9iyMtFihsY0a421LsXJPlq0bki5ej3f3YtTrt2LfwBEBE4Y4+LDIaYopJm7skDHkj3EnL5Zm+XLlzJExc+68+bNAw6Jvhi5t2i1qhTNWs/bs2urp1aRRPy5dO7ZmCLr/Su5deAJwx7+H735gHHHx5KB5M0+Y+3lq5NKbP6tu3QH2lWi3jxbu/XX38NO1ky/f7Dx6Buplq1ZPof1W2Ofjt49e3T785eH11//n751/5OEnnYD9AbidgQEOI1+Dh9HiYIR7QShhhWxRaGGGXWGoYYdqveJhiG2BKGKJJHFoYorByaJiiyvG4mKM0M0iY40u0Whjju6RqKONKPbo4o9AqijkkCYWaaSRpCTJpHigNAnlfKFE2eSSVCZp5ZVDZqllj1x2meOXYNYo5pgxlmlmi2immeKabJbo5pshxilnh3TWmeGdGwHAZ59+/glooIIOSmihhh6KaKDy6YlRoo4+Cmmkkip63yhaTYpppppiuqilVW0KaqiiAtqpKJeOimqqk5Y65aeqvgqroaw+6Wqstt7K56yfnIprr6/q6gmvvg4rKrCdCEtsspn/GssJsso+CymzmzgLbbWHSqsJtdZuKyi2mWjLbbh9eosJuOKGS+4l5p67bbqGrMtuvL4qRgm88t4bK72T2Itvv6jqKwm//g68KcCRCExwwpIaDAnCCj+cKMOPOAxxxYRK7AjFFm/8J8aNaMxxyB4zAnLIG4+8SMkmV4yyIiqv/HDLibwMc8IyI0JzzQPffEjOOvfL87u1/kx0rg/uO7SsERUNAEWqAkcIwk4XPfW/vUWddKFV/7x1sVcPIvXSVItttW5YK+Vo1zWrDSrUYGd9Mdlcy+212W+jHTHda+vd9teChA0R02wX7HcggDckON+E2/033IMObjLkyxYOyOEM/yUeeKpuN443opJz/PmqlP9heUKYI6756H6UjtDpl6fOuOGOd6t45LVPHnvls1OaOdGhL6x6F8RJ8HukxUN8/K/BMzF8BMmnfTvo0d+6eVYvOtf7qM/bPL2t1UPRPPaolz3+3Nkr+/0T4VN3fqjbE/y+9ssvsb557fd9/8rx1x3bT9k1sD+tdY9lA4RV+pxQPwAW8FEBxFcDF9c/qPyPPQuEXv5sd8FeHbAJCaRgBjlVQe59kHrzU0IHF/BA2o3QYinEXQSpcj32lY9/r/NdCMnnGv9xR3w1lN8KCfhDA5YwCSdUQAtJdcOdJZGGtJHgDmXYQya2bmxBVF7u1BdD+//N0H1LBFoX8ffCMPgMV4px3YTmMEYSEsaMeKFDGr13GDbWxY27Y1cZqRgYOnZOiWvEo1/0mBOF3dGGhAGkTQQZRz+eUQ5vzFciCZlHNNbxXIM0XyQZOUlxVVJnQStDI4XYR0j+UZJ79Ncm91ZIUgZShIGRo1wMORNEhtKSo8RkKb04S04ezZarhN8jablI2VWRacTMWyo5t8ViKlN0xxRmMpcJTQte0plRjKY1PbdLaprumtzEZjN1N8xuQrOTsJyiOM/Ju2mC85noFCc5VVnNdp7znbyMpzy7Sc84HPGeJ8vmOu3JT2vmEw77DCjy/Em6LxpUet9MaDgXCrOBvqH/oBD1ZUO9cMqKLnODzPulRsc5RCRk9KPE5Cj9PErSYprUhChNqSs/o8O3uBSkV0RgS2cKTNs4UaY4VWlIjzDSnkb0p0YIqlAxGEbw3fSoSM3hTtnCVEXqFIa5jKr+iFoEo1oViEnFYlW3ytCu2vSrYGUhVsvZkrLG7aKt+CQ/JRqsTFoVrseSa1Tp2iy7MhWv09LrUfmaLb8KFbDfEmxPCVsuw+IUsepS7EwZawm33hOylZCsPClbL8e6FLNIu6Vax4VQV1i2nZwNmGZTWtqD4UlNnlptm1rrWjjBNrZzmi1t7WTb2+Ypt7qtEKN6OyDeAtdBvx1ugoRr3EqZKrkW/youc5/j3OcmJ7rSHQ51q3vWzmL3tabdLndV690jaTe8te0uecsL3vN6KLPqXe9429vc98JXQuydb3zNa1/6yje/7ioEf++b3v82qL4C7u/ZCmzguyFYuQFecHDx6+ADQTjCx50whfOz3wtDN8Mani6HO2zdD4M4u8gc8YYtbOKVzizFBRIxi6fa4BeTWJsyrunHamyc6/5XQXNBLoh5rBId8xfIdvFxh4l8IiNrGMl5UfKFmcwXJ1MYyhsRcn6p7Jvl4hjLgpFyhLlcxMJuGTxk8bKDwZzFuo6ZeGEx84LRrBwt1xjOlKHVmp3XZmG4lh8erBOfUbjaPxsx0IJGwEWeC32AQyNaAIpGdKML/WhBR/rPk+Zzpflx6X1kWh+bzkenFw3qUIt61KQutalPjepUq3rVrG61q18N61jLeta0rnUiCgAAIfkECRAAAgAsAAAAAIABgAEAAv+Uj6nL7Q+jnLTai7PevPsPhuJIluaJpurKtu4Lx/JM1/aN5/rO9/4PDAqHxKLxiEwql8ym8wmNSqfUqvWKzWq33K73Cw6Lx+Sy+YxOq9fstvsNj8vn9Lr9js/r9/y+/w8YKDhIWGh4iJiouMjY6PgIGSk5SVlpeYmZqbnJ2en5CRoaEUBaanqKmmpKpdrqeipq9Trbykp7uxpri4u7y0ur6/v7KjxcGyxlDDylPIuc3OxaHJ37/ER9DI2Nag21nTq93X39DctcXj2+hJ7uzU6q3vQOf/4ezzQfEI59vz6/T62fknwAowlMQrAeu4NIEmpbyNBGPocxJv6LWMKivRn/GiFiHNERHY2Q5T6SIPltJEp+JkWsZCnjZcCWIWQa5GhTGc2aOY2p7PlrJwigw34SvSX0w1FeRpcSS9rBKVKcUp9C3VDVGdWsqq5y4CptK1hzXjOM7Sr2LL2yGNRyS6uWrVm37V7QrStXwt1STd3mvbC36ITAQf9WIMx0MOKphhUv1qr3MeTGoyRbrWw5G2UImcNG7gxuM2bQZEeT5iua8+nSqlejTu3ANd4Gsl/DZlB7renVt2PnppBbX2/cvx3LHk68NvDiyBMEX668uXPmu09Lnx798/HrB54bd904uHiiH8ebt1n+vHqS6de7n9j+vXyRGOfbL1n/vv6bEff7//eZ338CLtPfgAZ6xtCBCoZW4IIOCtfggwrGJ6GBFFYo4IUY+qfhhh7q4mGIrH0iYokQhmKiiCCm+GEsLLYoyosbriijhDTW6OCNOE7o4o459ugjjzEGKSSKRB6o45EcAqnkf0l+A0CUUk5JZZVWXollllpuyWWXVno35DtejklmmWae+SV1oOSDZptuvtkmmEaKCWeddt5JpZxrzoNnn37GqSaJfP5JaKFb6ikonYYuymiUiHrCZqOSFvpoJ5FOiimelXJyaaaevrnpJp1+SqqZoWoyaqmqdnlqJqmuCiuWrWLyaqy2TjnrJbXeemuuluzKa6y+FgJssMZiehQlxf8ey+yiyU6ybLPS+vmsJNFOi22d1UZybbbeorktJN1+S+6Y4T4ybrnqanmuI+muC2+V7Tbybrz2AjAvI/XeC2++i+zLr7r+KgJwwOQOnEjBBnuLMCIKL4xtw4c8DLG0EhtCccXMXkzsoKziojG+IFMbGCHj8hIyyiTvZbLHXKpcMcyaljzIySPHfPPMLNfs8qE5LyzznYS1rOjLPxsctJ1D81y0z7ekfLS2NAti89MaJy31zlT3zG7U/GIN59JbN9211TibrfNdRLNjrtf3gg3q1IFUTQvUaAstNyB0z2J33SurzTTbXsJtL+GAaj0311ka3q/bboqdONmLOx4v42f/Qq435eBqvq7lhnJMh+dlin4w55+TFzjff6t+tt+lgj4H6W3fjbTplKI+tutpsw6x7Kujl/orf/qeLfG7A58773jTHrDxy/e0tvJK214688jiHrnuz0vfPPXDY5+59XGLX7j3v8sUvfDnt9I399cDlb4r35Nfufl9wi6H82VrXzv9jOIfB/1Nzn+ds9/x0Bc8+a1PFe1T3+vA9wcBysqA05Lg+KAXO8VtjCgNRGD+NHiso3TwJaEDobFEeDUIuiFjjUJh63JSQsltECgjXEkMBVc8DqYQfhmUYQh1+ELkBdCEwXJh71TYBhb+D4hH5OEHfXhCJgINiWxQorOk2D8M/z4RhxHDYvecOEQoFtGLX6PiGqx4OhruUIth5GIFyfg2M6oBjbdTYxA9GIbEaMd9cRRj4xDnDsZUh31rREcNwVKQEfmGgAIj4h8B95DJtIZ/X3RjFumSyNkkh5Jl9GMBAUkOQU6Sj+XzZCNB6QQ9DpKBhSzHIbmSSduM0oFNtGQlMakQST7AglE0ZbkwF0oCrTIVr2xGMasSS93MUoF33MYxpZLMEy2TkM3ExjOdEk3ocLKPtuwkJKOgymmysprUuOZSsvkdWk7Rl9X7ZiCFKU5ithJK8zzLDUkZsnxuDozh26Y+/zk6OeaBlwDVJwDhQNCCmpMi/cSnQh96pYO+If+hEF0nGxuqzopqNKICxQNFN8pNGCaQmiAtKa46eoePmvSTF40gBVdqUZEmL6Mw1ahEV/jSmnpTptlzqE4NilI7qPSnOeSnSxlJVHKyp4fw3KUjkzq4oAognBPtRTrpCdUL8jSeb9miLhfZzaySiWNUxakoncpOsXLUqGD9ahKtukdXqvVwLW3rZRAK12FGY6503Spam2pWwNLmqXxda10He9bAunWThiysqaRa1rcmFrFhdewAD8vYu1Z1spnFqmWjylbKLvaMeeWqMT87O8wuILJVLO1fG4vaj4W2s5rBK2dXS9jYimy2uL3tHF1rV8/q9rJ+DW5tNytY2lpzuE7/U60CWEta32Knssx1FGSB2wXo/nY/RNAuQrDbWu4OwbsNAW909dNd8w5EvWlw0njZW17posG9QiDvEexrBvoGAb9F4C8Z9AsE/75XvmcA8A8EXF/4FnhJCSawERCcRwbvV8EPpnAZDOwDCAfYwv+V8IYd3F8OjwHDPdDwgUUsBhLzwMQZRnGExdvg5PoDxB2G8YRpHCAlcecGTVLmjivS4x/XoMfSFLJdgmzkmCA5yTAgMpOB3KQnN3nJUmaBk6vcgitjeQVa3nIKuuzlE4A5zBmhMpnLHOUzi5nILj4zm9tM5jfjWM1TlfNo6axcO8sSz6a1M5+1qWcG/bnPch50/1wDrUlDIwDRx1X0cxktaEf3FtKJljSluyrpSV+6yJnuzqb33GkDfBrUoR61j0Nd51Gj+tGqXvWiTe3qV7c61qn+NK1FDetbm5rTpc41rXd961pvOtjA1rWvY13sXx/b1ckOtl5l5Oyr+ijah542tQmdomtj20Tafi2Rum3cHYFbtN8et6bLbe7pHindrNYxu2Xt7nfjOs3yFja65T3mdOfb3CWqtwX67W9AYyjgAq8QwaX9oINXO+EK37aKG+7pEEHc2wafOLkrbvFzYzzj6h44x9s9o493fOMitzfJRQ7wkv/bwypfuHtavnIbw/zZ55l5weVjc4S/POc0Nw/Pe4Q+np87PFBCHznOi37xoyNd40pfutHf43SmQz3qT9851SOO3quvmbdaz7JUu26Cm4LdA2If+1e+bnaXoD3tQ1k728nu9refnetyP0nc6z4XuuOdJ3rfu1Lu7vfDAD7wOl8q4bfu3MMrfvGMb7zjHw/5yEt+8pSvvOUvj/nMa37znN9BAQAAIfkECRAAAgAsAAAAAIABgAEAAv+Uj6nL7Q+jnLTai7PevPsPhuJIluaJpurKtu4Lx/JM1/aN5/rO9/4PDAqHxKLxiEwql8ym8wmNSqfUqvWKzWq33K73Cw6Lx+Sy+YxOq9fstvsNj8vnrID9js/r93gq/w+YRzc4EWj453eo2EfY6LAIGZAYeehouUCpOJkJeOl5wGm4Gbr3+UnaOYWKaHq5yjf6atfqKiuoastI25irG9V7t+sIPIsLLMxLHCuLTEgsadzbPPi8/DpNVx2diz2nLfXd/RYORS7O9Wzukq58/sR+PAMv7e40zy1/z1zfpL8v4+8aPyYBV9EoiGogQYShDjLkpHDJQ4j5JkaKqMQiJYf/GhdhTNIREseQoj4eIampIspUJousLAnwJcuWQ2TOhGGTFc2aOUup7BlsJ0+gvnASLSrUx1Gk65YWSwrE6dMYUqFB/VFVZKGsKa8q5VppK9hAXrGOJSv2LKyyPdTefOBWJ1sdcddKqOtzLl28t+7yZap35F8KfwEHjlnYaoTEUw/XYKwYAmTHOCanHUzZhmW/iTNrZkwYtGfBfEN3Hv2z9GXVqKmK5ly4NeLYq/HKDgE5t8bbknX7Rsgb7u/h+oI/Io6cnfEGyZu3W67AuXRb0DFNv06qenTs3DdqR9A9vMfvoMSbf1v9vPq85Ne7D0pewPv38Q3Md19f/n31+ffz/6/vX4DsOSZggfBRZqCBoyVY4IIMBujgg/tFKOF8FFaIn2cY3nfhhud16KF4IIbY3YgkYmfiidOlqKJzLLaY3IucAEBjjTbeiGOOOu7IY48+/ghkjpshSEyQRh6JZJJKCvkakcAsCWWUUkI5JIFFTollllreWOVhz2wJZphUNmnlk2KeiaaPXQb2ZZpuvlnjmnq1CWedZ8o5F5127qklnmzpyWegUfpZFqCCHookoV4ZimijPyp6FaOOTqojpFBJSmmmcZLp5ZWafsolp2x6CmqplnaDaamq2tnRTqmuCmuardL0aqy2gjlrS7XeyuuUuZq0a6/CKvnrR8EOi2yQxf9idGyyzvK4bETNPkttqBa5Smq12j66G63Zbgtupd3q+m245m56rbdmnssuuhNhu2677Ear0LTy9krvQPbee2u+/OzLb6z+1tMsJPIaHGZV0xS8yMENJyzVwuXuiPC8D+MacTMMK+IwxxA7JXG8al58bsVbKqzxxOJ6bDHLJ2eMzMaHdDzzx0uF3IuRJpu7c5Yox6wyky7zTHKfMAsjsyE0K23zUTjnonPR4faM5c9IB40j1dtqLaXVuyQdyNJhN03U07ZEPfTUUld99NdYW1tzy3G/DHLKIvfIdbV5j1k30Gmz/ffWa+85sCV7L3m4s4nLOu7VgXc9uLaLo1n4MJH/D3o5tZPf2bjbj2P+ueaZv1l5MqEjPrriqTOert9zG3266rGz/q7dr/u8OrKbi1m6M7kfuTu+v/PeOS3BA3l8v8OTDZztTGM8u+7LQ1+768/TfTu4ycNevePZ+zq98tFz3rr313N/vtrjE1++599Dvr7w8VP/kNmAsP++3uGjz1A2b2vaEbE1Tw4AE1QA29W7MhQwUAeUW/288b9MNbBkxXPDAvk0QaK1bxwRpFQG1dc9OFyQcBoRYEH8dzdYfVB7FWzDCFlVQgS2kA0vrNMKBbdBC3ZwUjeU3AzXUEM49VB/OXThDh01RNEVkYZHbFQSn5VAMgSRdDF0YP8gmMJV/z1RdiH8glZgkz4WZtGHffvFeMA4NivKwoQ5sYZdFrM/gTWRV157xxnhOD/x5UyGZSzHHXuTR1tNEYBts2NX8Jg/Je5RjT1x44CEE0g5jpGIN9sGWtB4Pz4ukoJ9NGRYMPkHNqJClDJxpB5Mk0gozlGPTrMkepgTRxWuUpCFtMcfIZlKLkJNk60Exy2PE0lZTlKRvTTjIQGZy2QNUoK17McvYRlMLc5SkpX05TFxGUYcblKD1YzD9gIGThtFEYvJDKc5hdbFVnzznAEbJwFjyc57udOb8IwnL69ovTTac58rS6cp1slPTvrzFPUMqBgH6gmAGvSgD8xnJhe60HmKsP+gECUmPs2nz4ruU6IcjKZGLTpAjD70o/bkqA49SlJl/rAWKE3psEzahS8icpcuhR9Ct3PNk35ypmerqU0bytNXMjGn0NymT5OUQJlOlKgMWKZGk/rMoe4UmTQ9KrFWmgCldnSq2OypVa+6ROswFYhRFatRv6osrIKnrGrQKjDPilZuhRWnXNUpTIL6irgiVa3lGWtb2ZrVaVoVqn5Ng1uLWlW9Io+v9gEsGg7bVMEelbB1NWJh1zpMxWaNsfq57Bkga9bEahZvnAXtXz3b2MyO1l1Apeol6YnazsJ1tZuda2Bja8q+wJY21qzsQnA7hlO5xLEnIa4ZhEsE04LEuAr/FJUzgSsE5T7Wub/1rUSYK0XqXhe6QZDuZ7WbEewOxbqn5a0xybtc7oIBueO9qx/V60Xwphe9SPDuceVbX/FGV79hYO9+4fsVAMcUv8UVMA/s29zT9Na9nmSwXVlzXgc/l77fVXCEX5sf13Iow2JQEIf726APrzfEIvaCh0s8YAGh2MQkXrEWTuziLMA4xleYMY2rYOMbu9JCOq5xi3u8Y/oAGcc/HvJ7IWTkIG8oye09EZP/26IndxdGkZHyDqhcZSvnAMtaDnCUu3xgKoM5zDAa85XFbOYtoznNN+Aym9u85jeThkRy/kyZ6zznEOE5zx7ac2ro7GfX3DnQL3Az/6GbMuhD1yHOilaBoRvtaEZD+gSPnjSlJW1pElQ605rGNKdx4+lPf2DTogYBqUvtgVOjmgOqXrUGWu1qDMA61haYNa1RqaJbjzrUuq6ArXutYT0DewO/HjZinWzsDBQ72XTNNbMvsOxn9/XL0sY1sqtdG2FjG5R93ja3l+xtvHY73F0FNLnf6uxzH9vc6g7ttdvd7HfDG7PUnje9023vaeM737Ldd76jXW2AS1vgzyY4v3PMb3FnKOG+LjLDgy3kh2c74hJX+HoqPvGFY7zcPN44xynu8ciqOOTonhDJ193xk8d7wypfecpbrm+Tw/zeMp95rQls81fjPOey3jnPb5Ru4Z+DOuhC3zXRi94B/yL9425Z+tDN63RW+zzqJbcN1ZM+9au72+pa1/nRu25troMd2lkfO9BvavYWwDTtRkc72yNt27enYO1yJzZn6z4CuuO953Hfe6f77ncR6D3wYT8h4dV+98NLHfCKxzrjG2/3x0Ne2YmfvOUvj/nMa37znO+85z8P+tCLfvSkL73pT496NBQAACH5BAkQAAIALAAAAACAAYABAAL/lI+py+0Po5y02ouz3rz7D4biSJbmiabqyrbuC8fyTNf2jef6zvf+DwwKh8Si8YhMKpfMpvMJjUqn1Kr1is1qt9yu9wsOi8fksvmMTqvX7Lb7DY/L56yA/Y7P6/d4Kv8PmEc3OBFo+Od3qNhH2OiwCBmQGHnoaLlAqTiZCXjpecBpuBm69/lJ2jmFimh6uco3+mrX6iorqGrLSNuYqxvVe7frCDyLCyzMSxwri0xILGnc2zz4vPw6TVcdnYs9py313f0WDkUuzvVs7pKufP7EfjwDL+3uNM8tf89c36S/L+PvGj8mAVfRKIhqIEGEoQ4y5KRwyUOI+SZGiqjEIiWH/xoXYUzSERLHkKI+HiGpqSLKVCaLrCwJ8CXLlkNkzoRhkxXNmjlLqewZbCdPoL5wEi0q1MdRpOuWFksKxOnTGFKhQf1RVWShrCmvKuVaaSvYQF6xjiUr9iyssj3U3nzgVidbHXHXSqjrcy5dvLfu8mWqd+RfCn8BB45Z2GqExFMP12CsGAJkxzgmpx1M2YZlv4kza2ZMGLRnwXxDdx79s/Rl1aipiuZcuDXi2Kvxyg4BObfG25J1+0bIG+7v4fqCPyKOnJ3xBsmbt1uuwLl0W9AxTb9Oqnp07Nw3akfQPbzH76DEm39b/bz6vOTXuw9KXsD79/ENzHdfX/599fn38/+v71+A7DkmYIHwUWaggaMlWOCCDAbo4IP7RSjhfBRWiJ9nGN534YbndeiheCCG2N2IJGJn4onTpaiicyy2mNyLnABAY4023ohjjjruyGOPPv4IZI6bIUhMkEYeiWSSSgr5GpHALAlllFJCOSSBRU6JZZZa3ljlYc9sCWaYVDZp5ZNinommj10G9mWabr5Z45p6tQlnnWfKOReddu6pJZ5s6clnoFH6WRaggh6KJKFeGYpooz8qehWjjk6qI6RQSUpppnGS6eWVmn7KJadsegpqqZZ2g2mpqtrZ0U6prgprmq3S9GqstoI5a0u13srrlLmatGuvwir560fBDotskMX/YnRsss7yuGxEzT5LbagWuUpqtdo+uhut2W4LbqXd6vptuOZueq23Zp7LLroTYbtuu+xGq9C08vZK70D23ntrvvzsy2+s/tbTLCTyGhxmVdMUvMjBDScs1cLl7ojwvA/jGnEzDCviMMcQOyVxvGpefG7FWyqs8cTiemwxyydnjMzGh3Q888dLhdyLkSabu3OWKMesMpMu80xynzALI7MhNCtt81E456Jz0eH2jOXPSAeNI9Xbai2l1bskHcjSYTdN1NO2RD301FJXffTXWFtbc8txvwxyyiL3yHW1eY9ZN9Bps/331mvvObAley95uLOJyzru1YF3Pbi2i6NZ+DCR/w96ObWT39m4249j/rnmmb9ZeTKhIz664qkznq7fcxt9uuqxs/6u3a/7vDqym4tZujO5H7k7vr/z3jktwQN5fL/Dkw2c7UxjPLvuy0Nfu+vP0307uMnDXr3j2fs6vfLRc96699dzf77a4xNfvuffQ76+8PFT/5DZgLD/vt7ho88QGR0J+792ee0dGgFgAQXYNgJaxIALRGDffnFAXgVQbk7bBkMYOBGxAcUaAcHgQzTYEw76w4MXdODNLIgQEqbQhBUERwTFl0EWlg2FBVFhDWW4QRp2UH4xpOAMXdhACb6QaA8sxxAFdkTtJdAeSVzVBEu2xH40UVVPJOIJgdhDGP9+EIch9Mb+kHg3JbbPeF+EFcBs1TtqlNGJb5Nd99yXPjHmjIsBsd8fQLgKPPrDjnzQIyn8eA8+7gGQM6LjHp03Nh/KgpDwEKQeGEkJSKbDkXmQ5PbA+EYyzk+LZzNkcRB5P0+GwpLPMV8ioRhGwY2xFZc0YxuTlcZsrJGKr5TeKk3RSjamUnLFc8MZAwZMG8VyDL8MZjCHKYZiGjNgyAyDMpd5r2aC4ZnQFOU8ZLnLampTmL1sAzW3qb5M+rKW4DxmN9nwzXLy8pboJKc6+SXNL6Tznc+KpxfmSU9YnnMN+MznsOzZhX76k4f182I2B8rMfapBoAhFo0KzoBURMPT/nQBlQEQh2BXcuLOh0HooBi5qxIyCYKLqrKh1RKrAsEh0oxxdmTg7ANKUwkSjB20p8jx6gZgyEaUeIGk5TbodnkpRqBzwKTiBmgCdDlWlNJ2jTfn20qKOB4szHSlLn8pNdm5AqQsh6lavilUaIRU8U8UoU61a07BSDKcW4KpEyopWp6oVeGytgFszAtcPGHWbYy2PV/H61wzsVZt9tU9ed3pWvYI1rIXVT2CRcFfBLharjY1sfj4qqsueIrOarcVpOqtJ2oCWlZwdre8+a1pPnCq140Qtay3n2teeVrSyNR1ta6vG2OJWDqvd7Rl669syADe4xCwtcbWgoONSdULK/zWrf5rrXOZCF7HPnS51pWvdtwoou0utLncBC6Hvgte74j1Jg8oL2fOi1wjJXa9L1OveoYQ3vvIlL32jAqPI3LcpMNrvbFTkX9f0N8AvyK9+CZwCAyOYvy1acAsU7OAVQDjCCc4vhVUw4QubIMMaJgGHO7zSAYPYwxYeMYlFbOLFGLiUGl4xiy/s4niAOMb0mDGNqTPiG+PYxjo2SI577GMeA7khPx4ykYVsZO8gOcmW9S+TKbLkJyeWwlJWcoerfJH4Ylkd393yi8XrZRmvN8w1HjOZd2zmMwvEvWr+R5rbnB0twzkhcp7zkd9sZyujN8933jOfM0HfPwO6zoI+bP+XC91k5SKay6xd9Jdf62gx4zbSZZ40pdFs6UuvebeadnOmOx1n34I6yJwedahLbWooozrVeq4tq1X96VcbutGyzrKoa53oyzL6pNcxTaVd/WiLcsfX+Li1pIWDotpsOtaYRnavlU1qZnva2SuCNp2N/evjJBs2xV51t3uzbRUfW7a7Duqzud1scgeb19VG97TVPW7mDNvap5b2sqktHWKnG9LrNne7xZ1tfsdb2OEGd8BpPXB255vefQZ2wv29cHffG94HV7iLGA7rFGt7vhovMHw7/uCPg1zCIh95hbdr8pCjPOUkXznLT87xl5+gvTKfeclrHuKY43wENN85z2+a7vOeAj3oUnU50eNq36MzuKASj7bSVR5Vi0/86Riua7mpXoI0Xh3rP9cqxN/NdZt7Pan9DnvOmQ7wb5td7FH/+tTX3vW2k/3hcFfs2MlK97rD1Opl13vR5Y73ivt973f3q+AH/9XCGzbviMes4h17+MY7HvCGV7vkL4/5zGt+85zvvOc/D/rQi370pC+96U+P+tSrfvWs10IBAAAh+QQJEAACACwAAAAAgAGAAQAC/5SPqcvtD6OctNqLs968+w+G4kiW5omm6sq27gvH8kzX9o3n+s73/g8MCofEovGITCqXzKbzCY1Kp9Sq9YrNarfcrvcLDovH5LL5jE6r1+y2+w2Py+e8gP2Oz+v3eCr/D5hHNzgRaPjnd6jYR9josAgZkBh56Gi5QKk4mQl46XnAabgZuvf5Sdo5hYpoernKN/pq1+oqK6hqy0jbmKsb1Xu36wg8iwsszEscK4tMSCxp3Ns8+Lz8Ok1XHZ2LPact9d39Fg5FLs71bO6Srnz+xH48Ay/t7jTPLX/PXN+kvy/j7xo/JgFX0SiIaiBBhKEOMuSkcMlDiPkmRoqoxCIlh/8aF2FM0hESx5CiPh4hqakiylQmi6wsCfAly5ZDZM6EYZMVzZo5S6nsGWwnT6C+cBItKtTHUaTrlhZLCsTp0xhSoUH9UVVkoawpryrlWmkr2EBesY4lK/YsrLI91N584FYnWx1x10qo63MuXby37vJlqnfkXwp/AQeOWdhqhMRTD9dgrBgCZMc4JqcdTNmGZb+JM2tmTBi0Z8F8Q3ce/bP0ZdWoqYrmXLg14tir8coOATm3xtuSdftGyBvu7+H6gj8ijpyd8QbJm7dbrsC5dFvQMU2/Tqp6dOzcN2pH0D28x++gxJt/W/28+rzk17sPSl7A+/fxDcx3X1/+ffX59/P/r+9fgOw5JmCB8FFmoIGjJVjgggwG6OCD+0Uo4XwUVoifZxjed+GG53XooXgghtjdiCRiZ+KJ06WoonMstpjci5wAQGONNt6IY4467shjjz7+CGSOmyFITJBGHolkkkoK+RqRwCwJZZRSQjkkgUVOiWWWWt5Y5WHPbAlmmFQ2aeWTYp6Jpo9dBvZlmm6+WeOaerUJZ51nyjkXnXbuqSWebOnJZ6BR+lkWoIIeiiShXhmKaKM/KnoVo45OqiOkUElKaaZxkunllZp+yiWnbHoKaqmWdoNpqara2dFOqa4Ka5qt0vRqrLaCOWtLtd7K65S5mrRrr8Iq+etHwQ6LbJDF/2J0bLLO8rhsRM0+S22oFrlKarXaProbrdluC26l3er6bbjmbnqtt2aeyy66E2G7brvsRqvQtPL2Su9A9t57a7787MtvrP7W0ywk8hocZlXTFLzIwQ0nLNXC5e6I8LwP4xpxMwwr4jDHEDslcbxqXnxuxVsqrPHE4npsMcsnZ4zMxod0PPPHS4Xci5Emm7tzlijHrDKTLvNMcp8wCyOzITQrbfNROOeic9Hh9ozlz0gHjSPV22otpdW7JB3I0mE3TdTTtkQ99NRSV33011hbW3PLcb8Mcsoi98h1tXmPWTfQabP999Zr7zmwJXsvebizics67tWBdz24toujWfgwkf8Pejm1k9/ZuNuPY/655pm/WXkyoSM+uuKpM56u33MbfbrqsbP+rt2v+7w6spuLWbozuR+5O76/8945LcEDeXy/w5MNnO1MYzy77stDX7vrz9N9O7jJw16949n7Or3y0XPeuvfXc3++2uMTX77n30O+vvDxU/+Q2YCw/77e4aPPEBkdCfu/dnntHRoBYAEF2DYCWsSAC0Rg335xQF4FUG5O2wZDGDgRsQHFGgHB4EM02BMO+sODF3TgzSyIEBKm0IQVBEcExZdBFpYNhQVRYQ1luEEadlB+MaTgDF3YQAm+kGgPLMcQBXZE7SXQHklc1QRLtsR+NFFVTyTiCYHYQxj/fhCHIfTG/gIGRhv1jhpfDGMYx5iNMpoxYGj04vzWaMY2ymF7cGRj8VpBxzreS45xyKMeuRgQ+/3hj4Sk2B1N4cdCqq977kufIgnJRzgk8pGSO+Qp1EjJSrbPeJjMpOg2icdOelJ2jOTkG0cpOFAiUpSoHFYkvwCwVupPlWyIpSyf9Uov2PKWycplF3bJS1dacg3ADCYP6+fGnBnzjMNUQzGXaStfouNt0NRkKd3wzGo6sZlpyKY2TcVNNHjzm5+S5hbGSc5MmVML6EznpNaZhXa6s1HwxII853moel7hnvgMlD6NoBUR8FOR/9RPVyB4UBAMtJAFDShCwyJQas6z/6HjwSJMcCNRd1I0oQqEKEbv1k+4ITOiHGViSTuwUEiG8wIONeJJOZDSP27Uoy6l6QdiqseZXrSmO71pRtOpU7RYVKgfVWZIV3ZNlFb0oT31AE7rGFT0SPGlG3gqHKMqF54SVaE/JSdW7cLUrfoUpEel0VcH1NGmKpWsZT2rHkT41hFYdY1u7Ut+ioqZu5qPNXo1JW366te8AnaVpxksYf9qWE+cKrHYFBVjyVjYx1ouspL1HWUrm8bLYnaOjt3sODrr2TYsNrRlGC1pdZih04aVQ6pdrYVaq1XWwtakEJotbf1j29tOKLcLERBve1vb34KkQcIdrm+LiwQFIfckxP9drkua69yhBDe6QlAudWcDI6peNwPZvch28dpdsX63quHV7ngrUF7znrc26Y3remHaXvG+1wLxle98TVNftN4XvfkF637p21/9/hc2AT7QgPFb4MYcmMAJXjCAE2xgB/cGwgreL4XhQd0LKye6Gk5Hhjv8nOWCOMTIHXE8nGtieqA4xdThMIv/IeIXC2TFMk6Ii2ucnRvjmCI03nEmPuzjH+s4yC0tLpExHNojb9izSvZwkptM4spCOcqSnfKJN2tlFWM5yy1mMpdhjNkvg1nKYjbIk8ucYy+juSFnXrOQ1exm78A5zkWusoYR3OUtXxjPY7bzntlr5jk3GNA2FnT/gfk8Yz1TGNGBVjSEGV1oRw+awX1+bIchnWZJH5rQmQ7znTnNZkMHGNOh1vSoQc1jU/eX1Kn29J8pnWhXLxrVb1a1gBnQXVZH2M82PQ6MdF1hSy91wi0CdmTIrN7y/JrWwWZsnZmTXWOT9tm4jjazj81rtVZ72bD2L7J7DW1uL2bY39a2dcRNbHMbltrnLva1p01uX7u727dOLLu3g27hJFuv905Art/dZnX729r0dq+tDZ7uE0k74PZtt4oWvuDFqkPCa0VswitNcfJqNtxazrhTQYvvjnscvhvftshHrgGJUxnlGFD5lVmecpAP/OUwb7nMwbPymht7gPLGh8653XtzZZ/859fmOcd9TvQHW1zfQ0/6xeuy83g7/elxifq+py50wVI90lgHr1RNjnSuXr3rEB83zT8+drIX3K5b7/RYwa32mF994iSHe9xtPveca9zud1e6wHF+9or/ve9rN4zD8yx2vhMe4IWvdeIHv3imQ96gTd/75CMP9oaHPOxvvzzmN6/5mVde7or/fM9DD/jRAz3tps866l2Pccu/vvWg//rhY096z9Oe8pOnu+xtv/vMA1/0nEd76YOP/OQrf/nMb77znw/96Et/+tSvvvWvj/3sa3/73O9+HAoAADs= // @match *://115cdn.com/* // @match *://115.com/* // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_listValues // @connect 115cdn.com // @connect webapi.115.com // @connect pmsg.115.com // @connect 115.com // @license MIT // @namespace https://greasyfork.org/users/1453515 // ==/UserScript== (function() { 'use strict'; const __GM_ORIG__ = { get: typeof GM_getValue === 'function' ? GM_getValue : undefined, set: typeof GM_setValue === 'function' ? GM_setValue : undefined, del: typeof GM_deleteValue === 'function' ? GM_deleteValue : undefined, keys: typeof GM_listValues === 'function' ? GM_listValues : undefined }; const __KV_MEM__ = new Map(); const __IDB_CFG__ = { name: 'VisitCodeHelperDB', version: 1, store: 'kv' }; let __idbDbPromise = null; function __openIDB__() { if (__idbDbPromise) return __idbDbPromise; __idbDbPromise = new Promise((resolve, reject) => { try { const req = indexedDB.open(__IDB_CFG__.name, __IDB_CFG__.version); req.onupgradeneeded = function (e) { const db = e.target.result; if (!db.objectStoreNames.contains(__IDB_CFG__.store)) { db.createObjectStore(__IDB_CFG__.store, { keyPath: 'key' }); } }; req.onsuccess = () => resolve(req.result); req.onerror = () => reject(req.error); } catch (err) { reject(err); } }); return __idbDbPromise; } async function __idbGetAll__() { const db = await __openIDB__(); return new Promise((resolve, reject) => { const tx = db.transaction(__IDB_CFG__.store, 'readonly'); const store = tx.objectStore(__IDB_CFG__.store); const req = store.openCursor(); const out = []; req.onsuccess = e => { const cursor = e.target.result; if (cursor) { out.push(cursor.value); cursor.continue(); } else { resolve(out); } }; req.onerror = () => reject(req.error); }); } async function __idbSet__(key, value) { const db = await __openIDB__(); return new Promise((resolve, reject) => { const tx = db.transaction(__IDB_CFG__.store, 'readwrite'); const store = tx.objectStore(__IDB_CFG__.store); const req = store.put({ key, value }); req.onsuccess = () => resolve(true); req.onerror = () => reject(req.error); }); } async function __idbDel__(key) { const db = await __openIDB__(); return new Promise((resolve, reject) => { const tx = db.transaction(__IDB_CFG__.store, 'readwrite'); const store = tx.objectStore(__IDB_CFG__.store); const req = store.delete(key); req.onsuccess = () => resolve(true); req.onerror = () => reject(req.error); }); } async function __idbBulkPut__(entries) { if (!entries.length) return; const db = await __openIDB__(); await new Promise((resolve, reject) => { const tx = db.transaction(__IDB_CFG__.store, 'readwrite'); const store = tx.objectStore(__IDB_CFG__.store); for (const [key, value] of entries) { store.put({ key, value }); } tx.oncomplete = () => resolve(true); tx.onerror = () => reject(tx.error); }); } (async function __initKV__() { try { const all = await __idbGetAll__(); if (all && all.length) { for (const row of all) { __KV_MEM__.set(row.key, row.value); } } else if (__GM_ORIG__.keys && __GM_ORIG__.get) { try { const keys = __GM_ORIG__.keys(); for (const k of keys) { try { const v = __GM_ORIG__.get(k); __KV_MEM__.set(k, v); } catch (e) {} } __idbBulkPut__(Array.from(__KV_MEM__.entries())).catch(console.error); } catch (e) { console.warn('GM storage migration skipped:', e); } } } catch (e) { console.warn('IndexedDB init failed, fallback to memory only:', e); } })(); function GM_getValue(key, defaultValue) { if (__KV_MEM__.has(key)) return __KV_MEM__.get(key); if (__GM_ORIG__.get) { try { const v = __GM_ORIG__.get(key, defaultValue); __KV_MEM__.set(key, v); __idbSet__(key, v).catch(() => {}); return v; } catch (_) {} } return defaultValue; } function GM_setValue(key, value) { __KV_MEM__.set(key, value); __idbSet__(key, value).catch(err => console.error('IDB set failed:', key, err)); } function GM_deleteValue(key) { __KV_MEM__.delete(key); __idbDel__(key).catch(err => console.error('IDB delete failed:', key, err)); } function GM_listValues() { return Array.from(__KV_MEM__.keys()); } const cssContent = ` .gear-icon { background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' width='24' height='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23666' d='M12 15.5A3.5 3.5 0 0 1 8.5 12A3.5 3.5 0 0 1 12 8.5A3.5 3.5 0 0 1 15.5 12A3.5 3.5 0 0 1 12 15.5M19.43 12.97C19.47 12.65 19.5 12.33 19.5 12C19.5 11.67 19.47 11.34 19.43 11L21.54 9.37C21.73 9.22 21.78 8.95 21.66 8.73L19.66 5.27C19.54 5.05 19.27 4.96 19.05 5.05L16.56 6.05C16.04 5.66 15.5 5.32 14.87 5.07L14.5 2.42C14.46 2.18 14.25 2 14 2H10C9.75 2 9.54 2.18 9.5 2.42L9.13 5.07C8.5 5.32 7.96 5.66 7.44 6.05L4.95 5.05C4.73 4.96 4.46 5.05 4.34 5.27L2.34 8.73C2.21 8.95 2.27 9.22 2.46 9.37L4.57 11C4.53 11.34 4.5 11.67 4.5 12C4.5 12.33 4.53 12.65 4.57 12.97L2.46 14.63C2.27 14.78 2.21 15.05 2.34 15.27L4.34 18.73C4.46 18.95 4.73 19.03 4.95 18.95L7.44 17.94C7.96 18.34 8.5 18.68 9.13 18.93L9.5 21.58C9.54 21.82 9.75 22 10 22H14C14.25 22 14.46 21.82 14.5 21.58L14.87 18.93C15.5 18.67 16.04 18.34 16.56 17.94L19.05 18.95C19.27 19.03 19.54 18.95 19.66 18.73L21.66 15.27C21.78 15.05 21.73 14.78 21.54 14.63L19.43 12.97Z'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-size: contain; width: 24px; height: 24px; display: inline-block; } .gear-icon.active { background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' width='24' height='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%234285f4' d='M12 15.5A3.5 3.5 0 0 1 8.5 12A3.5 3.5 0 0 1 12 8.5A3.5 3.5 0 0 1 15.5 12A3.5 3.5 0 0 1 12 15.5M19.43 12.97C19.47 12.65 19.5 12.33 19.5 12C19.5 11.67 19.47 11.34 19.43 11L21.54 9.37C21.73 9.22 21.78 8.95 21.66 8.73L19.66 5.27C19.54 5.05 19.27 4.96 19.05 5.05L16.56 6.05C16.04 5.66 15.5 5.32 14.87 5.07L14.5 2.42C14.46 2.18 14.25 2 14 2H10C9.75 2 9.54 2.18 9.5 2.42L9.13 5.07C8.5 5.32 7.96 5.66 7.44 6.05L4.95 5.05C4.73 4.96 4.46 5.05 4.34 5.27L2.34 8.73C2.21 8.95 2.27 9.22 2.46 9.37L4.57 11C4.53 11.34 4.5 11.67 4.5 12C4.5 12.33 4.53 12.65 4.57 12.97L2.46 14.63C2.27 14.78 2.21 15.05 2.34 15.27L4.34 18.73C4.46 18.95 4.73 19.03 4.95 18.95L7.44 17.94C7.96 18.34 8.5 18.68 9.13 18.93L9.5 21.58C9.54 21.82 9.75 22 10 22H14C14.25 22 14.46 21.82 14.5 21.58L14.87 18.93C15.5 18.67 16.04 18.34 16.56 17.94L19.05 18.95C19.27 19.03 19.54 18.95 19.66 18.73L21.66 15.27C21.78 15.05 21.73 14.78 21.54 14.63L19.43 12.97Z'/%3E%3C/svg%3E"); } .refresh-icon { background-image: url("data:image/svg+xml,%3Csvg width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M23 4v6h-6M1 20v-6h6'/%3E%3Cpath d='M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-size: contain; width: 14px; height: 14px; display: inline-block; transition: all 0.2s ease; } .api-refresh-btn:hover .refresh-icon, .refresh-btn:hover .refresh-icon { background-image: url("data:image/svg+xml,%3Csvg width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%234285f4' stroke-width='2' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M23 4v6h-6M1 20v-6h6'/%3E%3Cpath d='M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15'/%3E%3C/svg%3E"); } .internet-icon { -webkit-mask-image: url("data:image/svg+xml,%3Csvg width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M2 12h20'/%3E%3Cpath d='M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M2 12h20'/%3E%3Cpath d='M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z'/%3E%3C/svg%3E"); -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; -webkit-mask-size: contain; mask-size: contain; background-color: currentColor; width: 14px; height: 14px; display: inline-block; transition: all 0.2s ease; } .extract-btn:hover .internet-icon { background-color: #4caf50; } .success-icon { background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z' fill='%234caf50'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-size: contain; width: 16px; height: 16px; display: inline-block; } .error-icon { background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='12' cy='12' r='10' fill='%23f44336'/%3E%3Cpath d='M15 9L9 15M9 9l6 6' stroke='%23fff' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-size: contain; width: 16px; height: 16px; display: inline-block; } .processing-icon { background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z' fill='currentColor'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-size: contain; width: 16px; height: 16px; display: inline-block; animation: spin 1s linear infinite; } @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } .batch-share-file-icon { width: 16px; height: 16px; display: inline-block; vertical-align: middle; margin-right: 6px; object-fit: contain; object-position: center; } .batch-share-success-icon { background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z' fill='%234caf50'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-size: contain; width: 16px; height: 16px; display: inline-block; } .batch-share-error-icon { background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='12' cy='12' r='10' fill='%23f44336'/%3E%3Cpath d='M15 9L9 15M9 9l6 6' stroke='%23fff' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-size: contain; width: 16px; height: 16px; display: inline-block; } .batch-share-processing-icon { background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='12' cy='12' r='10' fill='%23ff9800'/%3E%3Cpath d='M12 6v6l4 2' stroke='%23fff' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-size: contain; width: 16px; height: 16px; display: inline-block; animation: spin 1s linear infinite; } .batch-share-status-icon { background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='12' cy='12' r='10' fill='%23f44336'/%3E%3Cpath d='M15 9L9 15M9 9l6 6' stroke='%23fff' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-size: contain; width: 16px; height: 16px; display: inline-block; color: #f44336; } .batch-share-status-icon.warning { background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 2L2 20h20L12 2z' fill='%23ff9800'/%3E%3Cpath d='M12 8v6M12 16h.01' stroke='%23fff' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); color: #ff9800; }`; const style = document.createElement('style'); style.textContent = cssContent; style.id = 'svg-icons-styles'; document.head.appendChild(style); })(); const style = document.createElement('style'); style.textContent = ` :root { --color-white: white; --color-text: #333; --color-primary: #4285f4; --color-success: #4caf50; --color-error: #f44336; --color-warning: #ff9800; --bg-overlay-light: rgba(0,0,0,0.05); --bg-overlay-medium: rgba(0,0,0,0.1); --bg-overlay-dark: rgba(0,0,0,0.15); --bg-overlay-darker: rgba(0,0,0,0.2); --bg-primary: rgba(66, 133, 244, 0.9); } .btn, .window { position: fixed; z-index: 9998; transition: all 0.3s ease; } .flex-between { display: flex; justify-content: space-between; align-items: center; } .flex-gap { display: flex; gap: 8px; } .clear-text-btn { position: absolute; top: 6px; right: 6px; width: 24px; height: 24px; border-radius: 50%; border: 1px solid #ddd; background: #fff; color: #888; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease; z-index: 1; } .clear-text-btn:hover { background: #f5f5f5; color: #555; border-color: #ccc; } .batch-share-copy-all-btn, .batch-share-export-btn { display: none; } .batch-share-status-display { display: none; margin-top: 8px; padding: 6px 12px; background: var(--bg-primary); color: var(--color-white); border-radius: 4px; font-size: 13px; font-weight: 500; text-align: center; box-shadow: 0 2px 8px var(--bg-overlay-darker); } .progress-bar, .progress-bar-dynamic, #batch-receive-progress-bar, #batch-share-progress-bar { --progress-width: 0%; } .search-clear-btn { display: none; } .extract-btn-progress { background: linear-gradient(90deg, var(--color-success) var(--progress-percent, 0%), var(--bg-overlay-light) var(--progress-percent, 0%)) !important; transition: background 0.3s ease, color 0.3s ease !important; } .extract-btn-progress.progress-high { color: var(--color-white) !important; } .extract-btn-progress.progress-low { color: var(--color-text) !important; } .status-display-text { color: var(--color-white); } .batch-receive-ready { text-align: center; margin-top: 60px; } .btn { left: 10px; bottom: 15px; width: 40px; height: 40px; border-radius: 50%; background: #fff; border: 1px solid #ddd; box-shadow: 0 4px 15px rgba(0,0,0,0.1); display: flex; justify-content: center; align-items: center; cursor: move; user-select: none; } .btn:hover { box-shadow: 0 6px 20px rgba(0,0,0,0.15); } .window { width: 680px; max-width: 90vw; background: #fff; border-radius: 12px; border: 1px solid #ddd; box-shadow: 0 12px 40px rgba(0,0,0,0.15); padding: 20px; display: none; overflow: hidden; color: #333; cursor: move; left: 20px; top: 20px; z-index: 9999; } .window.maximized { width: 100% !important; height: 100vh !important; max-width: 100% !important; max-height: 100vh !important; top: 0 !important; left: 0 !important; border-radius: 0 !important; box-sizing: border-box !important; overflow: hidden !important; } .window.maximized .modal-textarea, .window.maximized #batch-receive-textarea { height: calc(100vh - 320px) !important; min-height: 200px !important; max-height: calc(100vh - 320px) !important; } .window.maximized .batch-results-container { height: calc(100vh - 320px) !important; min-height: 450px !important; max-height: calc(100vh - 320px) !important; } .window.maximized .storage-container { height: calc(100vh - 370px) !important; min-height: 396px !important; max-height: calc(100vh - 370px) !important; } .window.maximized #batch-share-file-list-container { height: calc(100vh - 420px) !important; min-height: 290px !important; max-height: calc(100vh - 420px) !important; } .window-header, .modal-header { display: flex; justify-content: space-between; align-items: center; padding-bottom: 12px; border-bottom: 1px solid #eee; } .window-title, .modal-title { margin: 0; color: #333; font-size: 18px; font-weight: 600; flex: 1; } .status-tag-container { margin-right: auto; padding: 0 10px; } .gear-icon { width: 30px; height: 30px; color: #555; transition: transform 0.3s ease; } .btn:hover .gear-icon { transform: rotate(30deg); color: #4285f4; } .form-group, .modal-form-group { margin-bottom: 18px; } .label, .modal-label, .concurrent-label { display: block; color: #666; margin-bottom: 8px; font-size: 12px; font-weight: 500; height: 16px; line-height: 16px; } .modal-label { text-align: left; margin-bottom: 5px; } .input, .select, .modal-input, .concurrent-input { width: 100%; padding: 10px 12px; background: #fff; border: 1px solid #ddd; border-radius: 8px; color: #333; font-size: 14px; transition: all 0.3s; box-sizing: border-box; box-shadow: 0 1px 2px rgba(0,0,0,0.05); } .modal-input { padding: 8px 12px; margin: 0; } .input:focus, .select:focus, .modal-input:focus { outline: none; border-color: #bbb; background: #f9f9f9; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .select { appearance: none; background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23555'%3e%3cpath d='M7 10l5 5 5-5z'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: right 12px center; background-size: 14px; } .btn-primary, .modal-btn { width: 100%; padding: 12px; border: none; border-radius: 8px; color: white; font-size: 15px; font-weight: 500; cursor: pointer; transition: all 0.3s; margin-bottom: 15px; box-shadow: 0 2px 6px rgba(0,0,0,0.1); background: #42a5f5; } .btn-primary:hover, .modal-btn:hover { background-color: #3367d6; } .btn-primary.stop { background: #ff5252; } .storage-tab-content:not([data-tab-content="storage"]) .btn-primary, .storage-tab-content:not([data-tab-content="storage"]) .batch-result-item-btn, .storage-tab-content:not([data-tab-content="storage"]) .modal-btn { background-color: #4285f4 !important; color: white !important; border: none; border-radius: 4px; padding: 8px 16px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s ease; display: inline-flex; align-items: center; justify-content: center; min-width: 80px; height: 36px; width: auto; margin-bottom: 0; box-shadow: none; } .storage-tab-content:not([data-tab-content="storage"]) .btn-primary:hover, .storage-tab-content:not([data-tab-content="storage"]) .batch-result-item-btn:hover, .storage-tab-content:not([data-tab-content="storage"]) .modal-btn:hover { background-color: #3367d6 !important; } .btn-danger, .storage-tab-content:not([data-tab-content="storage"]):not([data-tab-content="dedupe"]) .delete-btn, .storage-tab-content:not([data-tab-content="storage"]) .stop-btn, .storage-tab-content:not([data-tab-content="storage"]) .cancel-btn, .storage-tab-content:not([data-tab-content="storage"]) .batch-share-cancel-btn { background-color: #f44336 !important; color: white !important; border: none; border-radius: 4px; padding: 8px 16px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s ease; display: inline-flex; align-items: center; justify-content: center; min-width: 80px; height: 36px; } .btn-danger:hover, .storage-tab-content:not([data-tab-content="storage"]):not([data-tab-content="dedupe"]) .delete-btn:hover, .storage-tab-content:not([data-tab-content="storage"]) .stop-btn:hover, .storage-tab-content:not([data-tab-content="storage"]) .cancel-btn:hover, .storage-tab-content:not([data-tab-content="storage"]) .batch-share-cancel-btn:hover { background-color: #d32f2f !important; } .btn-warning, .storage-tab-content:not([data-tab-content="storage"]) .pause-resume-btn.pause { background-color: #ff9800 !important; color: white !important; border: none; border-radius: 4px; padding: 8px 16px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s ease; display: inline-flex; align-items: center; justify-content: center; min-width: 80px; height: 36px; } .btn-warning:hover, .storage-tab-content:not([data-tab-content="storage"]) .pause-resume-btn.pause:hover { background-color: #f57c00 !important; } .btn-success, .storage-tab-content:not([data-tab-content="storage"]) .pause-resume-btn:not(.pause), .storage-tab-content:not([data-tab-content="storage"]) .batch-result-btn-exists, .storage-tab-content:not([data-tab-content="storage"]) .batch-result-btn-imported { background-color: #4caf50 !important; color: white !important; border: none; border-radius: 4px; padding: 8px 16px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s ease; display: inline-flex; align-items: center; justify-content: center; min-width: 80px; height: 36px; } .btn-success:hover, .storage-tab-content:not([data-tab-content="storage"]) .pause-resume-btn:not(.pause):hover, .storage-tab-content:not([data-tab-content="storage"]) .batch-result-btn-exists:hover, .storage-tab-content:not([data-tab-content="storage"]) .batch-result-btn-imported:hover { background-color: #388e3c !important; } .storage-tab-content:not([data-tab-content="storage"]) .batch-result-btn-no-password { background-color: #fbbc05 !important; color: white !important; border: none; border-radius: 4px; padding: 8px 16px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s ease; display: inline-flex; align-items: center; justify-content: center; min-width: 80px; height: 36px; } .storage-tab-content:not([data-tab-content="storage"]) .batch-result-btn-no-password:hover { background-color: #f4b400 !important; } .modal-btn { padding: 8px 16px; font-size: 14px; margin-bottom: 0; } .modal-btn-primary { background: #42a5f5; } .modal-btn-secondary { background: #f5f5f5; color: #333; } .status, .batch-results-container, .failed-items-container { font-size: 12px; line-height: 1.6; max-height: 360px; overflow-y: auto; padding: 12px; background: #f5f5f5; border-radius: 8px; border: 1px solid #eee; margin-top: 15px; color: #666; display: none; } .batch-results-container, .failed-items-container { height: 360px; margin-top: 0; padding: 5px; } .status.active, .failed-items-container.active { display: block; } .status.flex { display: flex !important; } .error { color: #ea4335; font-size: 12px; margin-top: 6px; padding-left: 5px; } .stats, .share-info { color: #666; font-size: 12px; margin-bottom: 18px; padding: 10px; background: #f5f5f5; border-radius: 8px; border: 1px solid #eee; } .btn-group, .modal-footer { display: flex; gap: 10px; } .btn-group { height: 35px; margin-bottom: 15px; justify-content: center; width: 100%; } .btn-group .btn-primary { flex: 1; max-width: none; padding: 12px; height: auto; line-height: normal; min-height: 40px; } .modal-footer { justify-content: flex-end; margin-top: 20px; } .pause-resume-btn { background-color: #4285f4 !important; color: white !important; height: 40px; display: flex; align-items: center; justify-content: center; border: none; border-radius: 4px; padding: 8px 16px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s ease; min-width: 120px; } .pause-resume-btn:hover { background-color: #3367d6 !important; } .pause-resume-btn.pause { background-color: #f44336 !important; } .pause-resume-btn.pause:hover { background-color: #d32f2f !important; } .stop-btn { height: 40px; display: flex; align-items: center; justify-content: center; background-color: #f44336; color: white; border: none; border-radius: 4px; padding: 8px 16px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.2s ease; min-width: 120px; } .stop-btn:hover { background-color: #d32f2f; } .status::-webkit-scrollbar, .batch-results-container::-webkit-scrollbar, .failed-items-container::-webkit-scrollbar { width: 6px; } .status::-webkit-scrollbar-track, .batch-results-container::-webkit-scrollbar-track, .failed-items-container::-webkit-scrollbar-track { background: rgba(0,0,0,0.05); border-radius: 3px; } .status::-webkit-scrollbar-thumb, .batch-results-container::-webkit-scrollbar-thumb, .failed-items-container::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.15); border-radius: 3px; } .status::-webkit-scrollbar-thumb:hover, .batch-results-container::-webkit-scrollbar-thumb:hover, .failed-items-container::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,0.2); } .highlight { color: #4285f4; font-weight: 500; } .highlight-success { color: #34a853; font-weight: 500; } .highlight-warning { color: #fbbc05; font-weight: 500; } .disabled-input { opacity: 0.7; pointer-events: none; background: #f5f5f5 !important; } .chars-input.disabled-digits { background: #f5f5f5 !important; } .share-avatar { flex-shrink: 0; width: 50px; height: 50px; border-radius: 50%; object-fit: cover; border: 1px solid #ddd; } .form-row { display: flex; gap: 15px; justify-content: center; align-items: flex-start; width: 100%; } .form-row .form-group { flex: 1; margin-bottom: 0; max-width: none; display: flex; flex-direction: column; align-items: center; text-align: center; justify-content: flex-start; } .concurrent-group { flex: 1; display: flex; flex-direction: column; max-width: none; align-items: center; text-align: center; justify-content: flex-start; } .window.maximized .form-row .form-group { max-width: none; min-width: 200px; } .window.maximized .concurrent-group { max-width: none; min-width: 200px; } .window.maximized .btn-group .btn-primary { min-width: 200px; } .window.maximized .pause-resume-btn, .window.maximized .stop-btn { min-width: 200px; } .settings-section { margin-bottom: 15px; } .settings-section-title { font-size: 14px; font-weight: 600; color: #333; margin-bottom: 6px; padding: 6px 10px; background: #f8f9fa; border-left: 3px solid #4285f4; border-radius: 4px; display: flex; justify-content: space-between; align-items: center; } .category-toggle-container { display: flex; align-items: center; } .status-info-grid { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 10px; } .status-info-column { flex: 1; min-width: 45%; } .status-info-item { margin-bottom: 5px; font-size: 13px; } .progress-container, .compact-progress-bar { width: 100%; background: #f5f7fa; border-radius: 6px; margin-bottom: 8px; overflow: hidden; display: none; padding: 8px; border: 1px solid #e1e8ed; box-sizing: border-box; } .progress-container .progress-bar { height: 8px; background: #42a5f5; border-radius: 4px; overflow: hidden; border: none; } #batch-share-progress { display: none; margin-bottom: 12px; } #batch-share-progress.show { display: block; } #batch-receive-progress { display: none; margin-bottom: 12px; } #batch-receive-progress.show { display: block; } #batch-receive-result { margin-bottom: 12px; } .batch-result-item-title { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; overflow: hidden; } .batch-result-item-actions { display: flex; gap: 4px; margin-left: auto; flex-shrink: 0; } .batch-result-item-title .storage-item-btn { width: auto; min-width: fit-content; padding: 4px 8px; white-space: nowrap; } .batch-result-item-status { margin-top: 4px; } .progress-bar, .compact-progress-fill { height: 100%; background: #3b82f6; border-radius: 4px; transition: width 0.3s ease; position: relative; overflow: hidden; } .progress-bar::before, .compact-progress-fill::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); animation: shimmer 1.5s infinite; } @keyframes shimmer { 0% { left: -100%; } 100% { left: 100%; } } .status-tag, .expired-tag, .valid-tag, .time-limited-tag, .auto-renewal-tag, .error-tag { display: inline-block; padding: 2px 6px; border-radius: 4px; font-size: 12px; font-weight: normal; margin-left: 5px; color: white; text-align: center; } .error-tag, .expired-tag { background: #f44336; } .status-tag { margin-bottom: 5px; } .status-stopped { background: #ea4335; } .valid-tag, .auto-renewal-tag { background: #4caf50; } .time-limited-tag { background: #2196f3; } .storage-tab-content .file-size, .batch-receive-file-size, .batch-recognize-file-size { display: inline-block; padding: 2px 6px; background: #333333 !important; color: white !important; border-radius: 4px; font-size: 12px; margin-right: 5px; font-family: normal; width: auto; min-width: fit-content; white-space: nowrap; } .storage-tab-content .ed2k-tag { display: inline-block; padding: 2px 6px; background: #9c27b0; color: white; border-radius: 4px; font-size: 12px; margin-right: 5px; font-family: normal; } .storage-tab-content .magnet-tag { display: inline-block; padding: 2px 6px; background: #349871fa; color: white; border-radius: 4px; font-size: 12px; margin-right: 5px; font-family: normal; } .correct-code { background-color: #e6f4ea; padding: 8px 12px; border-radius: 6px; border: 1px solid #34a853; margin-top: 10px; font-weight: bold; color: #34a853; display: flex; justify-content: space-between; align-items: center; } .correct-code-text { flex: 1; } .correct-code-actions { display: flex; gap: 5px; } .correct-code-btn { padding: 2px 8px; background: rgba(0,0,0,0.05); border: none; border-radius: 4px; cursor: pointer; font-size: 12px; } .correct-code-btn:hover { background: rgba(0,0,0,0.1); } .storage-container { max-height: 396px; overflow-y: auto; margin-top: 15px; background: #f5f5f5; border-radius: 8px; border: 1px solid #eee; } .storage-scroll-content { position: relative; width: 100%; } .storage-item { position: absolute; width: 100%; box-sizing: border-box; display: flex; flex-direction: column; padding: 10px; background: #fff; border-radius: 6px; border: 1px solid #eee; margin-bottom: 10px; cursor: pointer; transition: background-color 0.2s ease; height: 99px; min-height: 99px; max-height: 99px; overflow: hidden; } .dedupe-item-list { display: flex; flex-direction: column; gap: 8px; max-height: 396px; overflow-y: auto; } .dedupe-item-list .storage-item { position: relative; width: 100%; height: auto; min-height: 0; max-height: none; overflow: visible; margin-bottom: 0; } .batch-result-item { position: relative; margin-bottom: 4px; padding: 8px; background: #fff; border-radius: 6px; border: 1px solid #eee; cursor: pointer; transition: background-color 0.2s ease; } .storage-item:hover { background: #f8f9fa; } .storage-item.selected { background: #e3f2fd; border-color: #2196f3; } .storage-item-header, .batch-result-item-title { display: flex; justify-content: flex-start; margin-bottom: 5px; align-items: center; } .batch-result-item-title { font-weight: bold; color: #4285f4; word-break: break-word; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-right: 10px; cursor: pointer; display: flex; align-items: center; margin-bottom: 2px; } .storage-item-title { font-weight: bold; color: #4285f4; word-break: break-word; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-right: 10px; cursor: pointer; display: flex; align-items: center; } .storage-item-actions, .batch-result-item-actions { display: flex; gap: 5px; flex-shrink: 0; } .batch-result-item-actions { margin-top: 4px; } .btn-small, .storage-item-btn, .batch-result-item-btn { padding: 4px 8px; background: rgba(0,0,0,0.05); border: none; border-radius: 4px; cursor: pointer; font-size: 12px; white-space: nowrap; height: 24px; line-height: 16px; transition: all 0.2s ease; } .btn-small:hover, .storage-item-btn:hover, .batch-result-item-btn:hover { background: rgba(0,0,0,0.1); } .btn-small.active, .storage-item-btn.active { background: rgba(66,165,245,0.2); color: #4285f4; } .storage-item-btn.ed2k-btn.active { background: rgba(156,39,176,0.2); color: #9c27b0; } .storage-item-btn.magnet-btn.active { background: rgba(52,152,113,0.2); color: #349871fa; } .storage-item-content { display: flex; align-items: center; gap: 10px; margin-bottom: 5px; font-size: 13px; word-break: break-all; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; min-height: 0; } .batch-result-item-details { font-size: 12px; color: #666; margin-bottom: 0; } .storage-item-note { font-size: 12px; color: #666; margin-top: 3px; display: flex; align-items: center; gap: 5px; flex-shrink: 0; min-height: 0; } .note-display { display: inline-block; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; cursor: text; } .storage-item-title-input, .storage-item-note-input { display: none; padding: 2px 4px; border: 1px solid #ddd; border-radius: 3px; font-size: 12px; vertical-align: baseline; } .storage-item-title-input { width: 300px; font-weight: bold; color: #4285f4; font-size: 13px; } .storage-item-note-input { flex: 1; min-width: 0; } .storage-item-password-input { display: none; width: 40px; padding: 2px 4px; text-align: center; border: 1px solid #ddd; border-radius: 3px; font-size: 12px; vertical-align: baseline; } .storage-item-info { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; } .storage-item-password { display: flex; align-items: center; gap: 10px; margin-top: 3px; } .storage-item-sharer { font-size: 12px; color: #666; margin-right: 10px; } .password-display { font-size: 12px; color: #666; margin-right: 10px; } .password-value { font-size: 12px; color: #666; } .title-value { font-size: 13px; color: #4285f4; font-weight: bold; } .fill-error { color: #f44336; font-size: 12px; margin-top: 5px; display: none; } .storage-item-share-title { font-weight: bold; margin-bottom: 5px; color: #333; } .storage-item-expire-time { font-size: 12px; color: #666; margin-left: 5px; } .storage-item-input-hidden { display: none !important; } .storage-item-input-visible { display: inline-block !important; } .btn-hidden { display: none !important; } .btn-visible { display: inline-block !important; } .batch-recognize-btn-visible { display: inline-block !important; } .batch-recognize-btn-hidden { display: none !important; } .batch-recognize-container-visible { display: block !important; } .batch-recognize-container-hidden { display: none !important; } .batch-recognize-flex-visible { display: flex !important; } .batch-recognize-flex-hidden { display: none !important; } .batch-recognize-result-maximized { height: calc(100vh - 360px) !important; min-height: 200px !important; } .batch-recognize-result-dynamic { height: 360px !important; min-height: 200px !important; } .batch-receive-btn-visible { display: inline-block !important; } .batch-receive-btn-hidden { display: none !important; } .batch-receive-container-visible { display: block !important; } .batch-receive-container-hidden { display: none !important; } .batch-receive-flex-visible { display: flex !important; } .batch-receive-flex-hidden { display: none !important; } .batch-receive-result-maximized { height: calc(100vh - 360px) !important; min-height: 200px !important; } .batch-receive-result-dynamic { height: 360px !important; min-height: 200px !important; } .text-color-gray { color: #666 !important; font-size: 12px; } .text-color-primary { color: #4285f4 !important; font-size: 12px; } .text-color-custom { color: var(--text-color, #4285f4) !important; font-size: 12px; } .input-width-small { width: 80px !important; } .input-width-medium { width: 300px !important; } .input-width-large { width: 100% !important; max-width: 600px !important; } .storage-tabs { display: flex; border-bottom: 1px solid #eee; margin-bottom: 15px; } .storage-tab { padding: 8px 12px; cursor: pointer; border-bottom: 2px solid transparent; position: relative; display: inline-block; } .storage-tab.active { border-bottom: 2px solid #4285f5; color: #4285f4; font-weight: bold; } .storage-tab-content { display: none; } .storage-tab-content.active { display: block; } .storage-import-export { display: flex; gap: 10px; margin-top: 15px; } .btn-secondary, .storage-import-export-btn { padding: 8px 12px; background: rgba(0,0,0,0.05); border: none; border-radius: 4px; cursor: pointer; font-size: 13px; text-align: center; transition: all 0.2s ease; display: flex; align-items: center; justify-content: center; gap: 5px; position: relative; min-width: fit-content; } .storage-import-export-btn[data-text="导出结果"] { flex: none; width: auto; min-width: fit-content; padding: 8px 12px; } .btn-secondary:hover, .storage-import-export-btn:hover { background: rgba(0,0,0,0.1); transform: translateY(-1px); } .storage-batch-actions { display: none; gap: 10px; margin-top: 15px; padding: 10px; background: #f5f5f5; border-radius: 6px; border: 1px solid #ddd; } .storage-batch-actions.show { display: flex; } .storage-batch-actions button { padding: 8px 12px; background: rgba(0,0,0,0.05); border: none; border-radius: 4px; cursor: pointer; font-size: 13px; text-align: center; transition: all 0.2s ease; display: flex; align-items: center; justify-content: center; gap: 5px; position: relative; min-width: fit-content; } .storage-batch-actions button:hover { background: rgba(0,0,0,0.1); transform: translateY(-1px); } .storage-batch-actions button.delete-btn { background: #f44336; color: white; } .storage-batch-actions button.delete-btn:hover { background: #d32f2f; } .storage-batch-actions .selected-count { font-weight: bold; color: #333; margin-right: auto; } .storage-empty { text-align: center; padding: 20px; color: #666; font-size: 14px; } .storage-search { display: flex; gap: 8px; margin-bottom: 10px; align-items: center; } .storage-search-input { flex: 1; padding: 6px 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 13px; } .close-icon { background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' width='24' height='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23666' d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-size: contain; width: 16px; height: 16px; display: inline-block; transition: all 0.2s ease; } .search-input-container { position: relative; flex: 1; display: flex; align-items: center; } .search-clear-btn { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); background: none; border: none; cursor: pointer; padding: 2px; border-radius: 50%; display: flex; align-items: center; justify-content: center; transition: all 0.2s ease; } .search-clear-btn:hover { background-color: rgba(0, 0, 0, 0.1); } .search-clear-btn:hover .close-icon { background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' width='24' height='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23333' d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/%3E%3C/svg%3E"); } .storage-search-select { padding: 6px 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 13px; background: white; } .element-block-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; } .hidden-tabs-section .element-block-grid { grid-template-columns: 1fr 1fr 1fr; } .element-block-item { display: flex; flex-direction: column; padding: 4px; background: #fff; border-radius: 6px; border: 1px solid #eee; } .element-block-item-header { display: flex; align-items: center; margin-bottom: 1px; } .element-block-switch { position: relative; display: inline-block; width: 50px; height: 24px; margin-right: 10px; } .element-block-switch input { opacity: 0; width: 0; height: 0; } .element-block-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: .4s; border-radius: 24px; } .element-block-slider:before { position: absolute; content: ""; height: 16px; width: 16px; left: 4px; bottom: 4px; background-color: white; transition: .4s; border-radius: 50%; } input:checked + .element-block-slider { background-color: #42a5f5; } input:checked + .element-block-slider:before { transform: translateX(26px); } .element-block-name { flex: 1; font-size: 13px; color: #333; font-weight: bold; } .element-block-selector { font-size: 11px; color: #666; word-break: break-all; } .modal-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); display: flex; justify-content: center; align-items: center; z-index: 10000; } .modal-content { background: white; border-radius: 8px; padding: 20px; width: 400px; max-width: 90%; box-shadow: 0 5px 20px rgba(0,0,0,0.2); box-sizing: border-box; } .modal-textarea { width: 100%; height: 150px; padding: 8px 12px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; box-sizing: border-box; resize: vertical; } .batch-result-item.success { border-left: 4px solid #4caf50; } .batch-result-item.error { border-left: 4px solid #f44336; } .batch-result-item.warning { border-left: 4px solid #ff9800; } .failed-item { padding: 5px; margin-bottom: 5px; border-bottom: 1px solid #eee; font-size: 12px; word-break: break-all; } .compact-layout { font-size: 12px; line-height: 1.4; } .compact-layout .batch-result-item-title { margin-bottom: 1px; font-size: 12px; } .compact-layout .batch-result-item-details { font-size: 11px; margin-bottom: 1px; } .compact-layout .batch-result-item-actions { margin-top: 1px; } .compact-layout .batch-result-item { margin-bottom: 2px; padding: 6px; } .compact-layout .batch-result-item-btn { padding: 1px 4px; font-size: 11px; } .compact-progress { display: flex; align-items: center; margin-top: 5px; font-size: 11px; } .api-refresh-btn, .delete-expired-btn, .delete-invalid-btn { position: relative; } .api-refresh-badge, .expired-count-badge, .invalid-count-badge, .error-count-badge, .import-badge, .extract-badge { position: absolute; top: -6px; right: -6px; color: white; border-radius: 12px; min-width: 16px; height: 16px; padding: 0 4px; font-size: 10px; display: flex; align-items: center; justify-content: center; box-sizing: border-box; white-space: nowrap; } .api-refresh-badge { background-color: #4285f4; } .expired-count-badge, .invalid-count-badge, .error-count-badge { background-color: #f44336; } .import-badge { background-color: #4caf50; display: none; } .import-badge.show { display: flex; } .extract-badge { background-color: #ff9800; display: none; } .extract-badge.show { display: flex; } .extract-btn-progress { transition: all 0.3s ease; position: relative; overflow: hidden; } .extract-btn-progress::before { content: ''; position: absolute; top: 0; left: 0; height: 100%; background: linear-gradient(90deg, #4caf50, #45a049); transition: width 0.3s ease; z-index: 0; } .extract-btn-progress > * { position: relative; z-index: 1; } .expired-count-badge.large-count, .invalid-count-badge.large-count, .error-count-badge.large-count { right: -12px; padding: 0 6px; } .fetch-btn { background-color: rgba(66,133,244,0.1); color: #4285f4; } .fetch-btn:hover { background-color: rgba(66,133,244,0.2); } .fetch-btn:active { background-color: rgba(66,133,244,0.3); } .filter-buttons { display: flex; justify-content: space-between; margin-bottom: 6px; align-items: center; } .filter-group, .action-group { display: flex; gap: 8px; } .sort-buttons { display: flex; gap: 8px; margin-bottom: 4px; align-items: center; justify-content: center; height: 36px; min-height: 36px; max-height: 36px; } .batch-actions-container { margin-left: auto; display: flex; align-items: center; gap: 8px; height: 32px; min-height: 32px; max-height: 32px; overflow: visible; flex-shrink: 0; position: relative; } .batch-actions-container.has-selection { padding: 4px 8px; background: #f5f5f5; border-radius: 4px; border: 1px solid #ddd; } .chip-muted { display: inline-flex; align-items: center; gap: 6px; padding: 4px 6px; background: #f5f5f5; border: 1px solid #ddd; border-radius: 4px; color: #333; font-size: inherit; font-family: inherit; } .chip-muted .storage-search-select { border: none; background: transparent; padding-left: 2px; } .chip-muted .storage-search-select:focus { outline: 1px solid #bbb; border-radius: 3px; background: #fff; } .chip-muted label, .chip-muted .storage-search-select { font-size: inherit; font-family: inherit; color: inherit; } .dedupe-controls { font-size: 13px; color: #333; font-family: inherit; } .dedupe-controls #dedupe-scan-btn { width: 24px; height: 24px; min-width: 24px; min-height: 24px; padding: 0; border-radius: 50%; margin-bottom: 0; box-shadow: none; display: inline-flex; align-items: center; justify-content: center; line-height: 24px; } .dedupe-controls #dedupe-scan-btn[disabled] { opacity: 0.6; cursor: default; } .dedupe-controls #dedupe-scan-btn svg { width: 18px; height: 18px; display: block; } @keyframes dedupe-scan-rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } .dedupe-controls #dedupe-scan-btn.scanning svg .sweep { animation: dedupe-scan-rotate 0.8s linear infinite; transform-origin: 50% 50%; } .dedupe-pagination, .dedupe-pagination .dedupe-stats { font-size: 13px; color: #333; font-family: inherit; } .dedupe-group-title { font-size: 13px; color: #333; font-family: inherit; } .chip-muted .batch-actions-container.has-selection { padding: 0; background: transparent; border: none; } .batch-actions-container .selected-count { font-size: 12px; color: #333; font-weight: bold; } .batch-actions-container .selected-help-btn { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 50%; border: 1px solid #d0d0d0; background: #fff; cursor: pointer; padding: 0; color: #bdbdbd; } .batch-actions-container .selected-help-btn:hover { background: #f4f4f4; color: #8a8a8a; } .batch-actions-container .multi-select-hint { position: absolute; right: 8px; top: calc(100% + 6px); background: #fffef7; border: 1px solid #f0e6c8; box-shadow: 0 2px 8px rgba(0,0,0,0.12); border-radius: 6px; padding: 8px 10px; color: #5c4b00; font-size: 12px; line-height: 1.5; z-index: 1000; display: none; min-width: 360px; max-width: 560px; white-space: normal; pointer-events: auto; } .batch-actions-container .batch-result-item-btn, .batch-actions-container .storage-item-btn { display: inline-flex; align-items: center; justify-content: center; padding: 4px 8px; border: none; border-radius: 3px; cursor: pointer; font-size: 12px; font-weight: 500; transition: all 0.2s ease; height: 24px; width: auto; } .batch-actions-container .copy-btn { background-color: #4285f4; color: white; } .batch-actions-container .copy-btn:hover { background-color: #3367d6; } .batch-actions-container .delete-btn { background-color: #f44336; color: white; } .batch-actions-container .delete-btn:hover { background-color: #d32f2f; } .batch-actions-container .cancel-btn { background-color: #ff9800; color: white; } .batch-actions-container .cancel-btn:hover { background-color: #f57c00; } .btn-icon { background: none; border: none; color: #666; cursor: pointer; opacity: 0.7; transition: all 0.2s ease; padding: 0; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; border-radius: 50%; position: relative; } .btn-icon:hover { opacity: 1; background-color: rgba(0,0,0,0.05); } .ed2k-btn { background-color: rgba(156,39,176,0.1); color: #9c27b0; } .ed2k-btn:hover { background-color: rgba(156,39,176,0.2); } .ed2k-btn:active { background-color: rgba(156,39,176,0.3); } .magnet-btn { background-color: rgba(52,152,113,0.1); color: #349871fa; } .magnet-btn:hover { background-color: rgba(52,152,113,0.2); } .magnet-btn:active { background-color: rgba(52,152,113,0.3); } .storage-item-ed2k-input, .storage-item-magnet-input { display: none; width: 100%; max-width: 600px; padding: 2px 5px; margin-left: 5px; border: 1px solid #ddd; border-radius: 4px; font-size: 12px; box-sizing: border-box; } .window-close, .window-maximize { background: none; border: none; color: #666; cursor: pointer; opacity: 0.7; transition: all 0.2s ease; padding: 0; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; border-radius: 50%; position: relative; } .window-close:hover, .window-maximize:hover { opacity: 1; background-color: rgba(0,0,0,0.05); } .window-close::before, .window-maximize::before { content: ""; display: block; width: 16px; height: 16px; background-repeat: no-repeat; background-position: center; background-size: contain; position: absolute; transition: transform 0.3s cubic-bezier(.4,2,.6,1); } .window-close::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E"); } .window-maximize::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='4' width='16' height='16' rx='2' ry='2'%3E%3C/rect%3E%3C/svg%3E"); } .window.maximized .window-maximize::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3'%3E%3C/path%3E%3C/svg%3E"); } .window-close:hover::before, .window-maximize:hover::before { transform: rotate(90deg); } .window-title { margin: 0; color: #333; font-size: 16px; font-weight: 600; flex: 1; display: flex; align-items: center; gap: 6px; } .pro-tag { background: linear-gradient(135deg, #f0f0f0 0%, #e0e0e0 50%, #c9c9c9 100%); color: #5d5d5d; border: 1px solid #c9c9c9; box-shadow: inset 0 1px 1px rgba(255,255,255,0.2); font-size: 9px; font-weight: bold; padding: 1px 6px; border-radius: 3px; text-transform: uppercase; cursor: pointer; transition: all 0.2s ease; } .pro-tag.golden { background: linear-gradient(135deg, #fff4c1 0%, #ffd56b 50%, #ffb84c 100%); color: #8b4513; border: 1px solid #daa520; box-shadow: inset 0 1px 1px rgba(255,255,255,0.3), 0 1px 3px rgba(0,0,0,0.2); } .pro-tag:hover { background: linear-gradient(135deg, #e8e8e8 0%, #d8d8d8 50%, #c1c1c1 100%); box-shadow: inset 0 1px 1px rgba(255,255,255,0.3); } .pro-tag.golden:hover { background: linear-gradient(135deg, #ffe89a 0%, #ffc94c 50%, #ffa629 100%); box-shadow: inset 0 1px 1px rgba(255,255,255,0.4), 0 2px 4px rgba(0,0,0,0.3); } .pro-tag-input { display: none; background: linear-gradient(135deg, #f0f0f0 0%, #e0e0e0 50%, #c9c9c9 100%); color: #5d5d5d; border: 1px solid #c9c9c9; box-shadow: inset 0 1px 1px rgba(255,255,255,0.2); font-size: 9px; font-weight: bold; padding: 1px 6px; border-radius: 3px; text-transform: uppercase; width: 120px; min-width: 80px; max-width: 200px; box-sizing: border-box; } .pro-tag-input:focus { outline: none; border-color: #4285f4; box-shadow: 0 0 0 2px rgba(66, 133, 244, 0.2); } .open-tab-icon { display: inline-block; width: 14px; height: 14px; position: absolute; right: 0; top: 2px; cursor: pointer; background-color: transparent; vertical-align: middle; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/%3E%3Cpath d='M15 3h6v6'/%3E%3Cpath d='M10 14L21 3'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: center; background-size: contain; } .copy-btn.copied { background: #e6f4ea !important; color: #34a853 !important; } .delete-error-btn, .delete-expired-btn, .delete-invalid-btn { display: none; position: relative; } .storage-item-title-input, .storage-item-ed2k-input { display: none; } .share-info { display: flex; align-items: center; gap: 15px; } .share-avatar { flex-shrink: 0; } .share-text { flex: 1; } .share-row { display: block; } .share-left { flex: 1; min-width: 0; } .share-right { margin-left: 10px; white-space: nowrap; } .share-info { position: relative; } .share-status { position: absolute; top: 4px; right: 8px; white-space: nowrap; background: rgba(255, 251, 230, 0.96); border: 1px solid #ffe58f; padding: 2px 8px; border-radius: 4px; box-shadow: 0 1px 2px rgba(0,0,0,0.06); z-index: 2; pointer-events: none; } .share-status.verified-password { background: rgba(237, 255, 237, 0.96); border: 1px solid #b7eb8f; } .share-status .verified-password-text { color: #389e0d; font-weight: 600; } .network-status { margin-bottom: 12px; } .network-warning { color: red; margin-top: 5px; } .progress-bar-dynamic { width: var(--progress-width, 0%); } .status-info-grid { display: flex; flex-wrap: wrap; gap: 10px; } .status-info-column { flex: 1; min-width: 45%; } .batch-complete-message { color: #fbbc05; margin-top: 10px; border-top: 1px solid rgba(0,0,0,0.08); padding-top: 10px; } .modal-content-wide { width: 700px; max-height: 90vh; display: flex; flex-direction: column; } .modal-content-extra-wide { width: 800px; } .modal-scrollable { overflow-y: auto; flex: 1; padding: 15px; } .modal-form-row { display: flex; gap: 10px; } .modal-form-column { flex: 1; } .progress-container-margin { margin-top: 15px; margin-bottom: 4px; display: none; } .progress-header { display: flex; justify-content: space-between; margin-bottom: 8px; align-items: center; } .progress-info { font-size: 13px; color: #3b82f6; font-weight: 500; } .progress-bar-container { display: flex; justify-content: space-between; margin-bottom: 8px; align-items: center; } .progress-footer { display: flex; justify-content: space-between; margin-top: 5px; } .results-container-margin { margin-top: 15px; display: none; } .summary-container-margin { margin-top: 20px; display: none; } .summary-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .summary-spacer { flex: 1; } .export-results-btn { background-color: #2196F3; color: white; } .summary-content { padding: 10px; background-color: #f5f5f5; border-radius: 4px; } .batch-result-btn-success { background-color: #4caf50; color: white; } .batch-result-btn-error { background-color: #f44336; color: white; } .batch-result-btn-warning { background-color: #ff9800; color: white; } .batch-result-btn-network { background-color: #2196F3; color: white; } .batch-result-btn-skipped { background-color: #ff9800; color: white; } .batch-result-btn-verified { background-color: #4caf50; color: white; } .batch-result-btn-unverified { background-color: #ff9800; color: white; } .no-recognition-message { padding: 10px; text-align: center; color: #666; } .import-content { padding: 20px; } .import-info { padding: 15px; margin-bottom: 15px; background: #f5f5f5; border-radius: 4px; } .import-info-header { margin-bottom: 10px; } .import-info-list { margin: 0; padding-left: 20px; } .import-warning { margin-top: 10px; color: #ff5722; } .import-progress-container { margin-top: 10px; margin-bottom: 4px; background: #f5f7fa; border-radius: 6px; padding: 8px; border: 1px solid #e1e8ed; } .import-remaining-time { margin-top: 5px; font-size: 12px; color: #666; } .import-failed-items { display: none; margin-top: 10px; } .import-complete-btn { display: none; } .batch-result-btn-exists { background-color: #ff9800; color: white; } .batch-result-btn-no-password { background-color: #f44336; color: white; } .batch-result-btn-imported { background-color: #4caf50; color: white; } .element-block-item-header-relative { position: relative; } .status-text { color: var(--status-color, #4285f4); } .batch-recognize-input-container { margin-bottom: 12px; position: relative; } .batch-recognize-textarea, #batch-receive-textarea { height: 350px; width: 100%; } #batch-receive-input-container #batch-receive-textarea { padding-right: 40px; } #batch-recognize-input-container #batch-recognize-textarea { padding-right: 40px; } .batch-recognize-controls { display: flex; gap: 16px; align-items: center; margin-bottom: 12px; } .batch-recognize-controls-main { flex: 1; } .batch-recognize-controls-row { display: flex; align-items: center; gap: 16px; } .batch-recognize-setting-item, .batch-receive-setting-item, .batch-share-switch-group { display: flex; flex-direction: column; align-items: center; gap: 8px; } .batch-recognize-setting-item .label, .batch-receive-setting-item .label, .batch-share-switch-group .label { font-size: 12px; color: #666; text-align: center; margin: 0; display: block; } .batch-size-select, .verify-method-select { width: 140px; } .batch-recognize-start-btn, .batch-receive-start-btn { width: 100px; min-width: 100px; margin-top: 22px; margin-left: auto; } .batch-recognize-progress { margin-bottom: 12px; background: #f5f7fa; border-radius: 6px; padding: 8px; border: 1px solid #e1e8ed; } .batch-recognize-ready-message { text-align: center; color: #666; padding: 20px; font-size: 14px; } .batch-recognize-file-size { font-size: 12px; color: #666; margin-right: 8px; flex-shrink: 0; } .batch-recognize-file-name, .batch-receive-file-name { font-weight: 500; color: #333; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0; } .batch-size-input { width: 80px; text-align: center; } .verify-method-select { text-align: center; } .batch-recognize-back-btn { display: none; } .batch-recognize-progress-header { display: flex; justify-content: space-between; align-items: center; } .batch-recognize-progress-btn { display: none; margin: 0; width: 100px; min-width: 100px; } .batch-recognize-progress-bar-container { display: flex; justify-content: space-between; align-items: center; } .batch-recognize-export-btn { display: none; } .batch-result-item-title { display: flex; align-items: center; justify-content: space-between; width: 100%; } .batch-result-item-title > div { display: flex; align-items: center; min-width: 0; } .batch-result-item-actions { display: flex; gap: 4px; flex-shrink: 0; } .batch-result-item-actions .storage-item-btn { width: auto; min-width: fit-content; } .batch-result-item-details { display: flex; align-items: center; justify-content: space-between; } .batch-result-link { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #2196f3; cursor: pointer; transition: color 0.2s ease; } .batch-result-link:hover { color: #4caf50; } .batch-result-status { font-size: 12px; flex-shrink: 0; margin-left: 8px; padding: 2px 6px; border-radius: 3px; } .batch-result-status.success { background: #e8f5e8; color: #2e7d32; } .batch-result-status.warning { background: #fff3e0; color: #ef6c00; } .batch-result-status.error { background: #ffebee; color: #c62828; } .batch-recognize-file-name, .batch-receive-file-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .batch-recognize-progress-status { display: inline-flex; align-items: center; font-size: 12px; margin-right: 16px; background: #f8f9fa; border-radius: 6px; padding: 4px 10px; border: 1px solid #e9ecef; box-shadow: 0 1px 3px rgba(0,0,0,0.1); } .batch-recognize-progress-status .status-label { color: #6c757d; font-weight: 500; } .batch-recognize-progress-status .status-separator { color: #dee2e6; margin: 0 6px; font-weight: bold; } .batch-recognize-progress-status .status-progress { color: #007bff; font-weight: 500; } .batch-recognize-progress-status .status-success { color: #28a745; font-weight: 500; } .batch-recognize-progress-status .status-failed { color: #dc3545; font-weight: 500; } .batch-recognize-progress-status .status-skipped { color: #ffc107; font-weight: 500; } .batch-recognize-file-size, .batch-receive-file-size { background: #e3f2fd; color: #1976d2; padding: 2px 6px; border-radius: 3px; font-size: 11px; margin-right: 8px; } .batch-recognize-ready { text-align: center; color: #666; margin-top: 60px; } .batch-recognize-status-display { display: inline-flex; align-items: center; font-size: 12px; background: #f8f9fa; border-radius: 6px; padding: 4px 10px; border: 1px solid #e9ecef; box-shadow: 0 1px 3px rgba(0,0,0,0.1); } .batch-recognize-status-display .status-label { color: #6c757d; font-weight: 500; } .batch-recognize-status-display .status-separator { color: #dee2e6; margin: 0 6px; font-weight: bold; } .batch-recognize-status-display .status-success { color: #28a745; font-weight: 500; } .batch-recognize-status-display .status-warning { color: #ffc107; font-weight: 500; } .batch-recognize-status-display .status-error { color: #dc3545; font-weight: 500; } .batch-mode-switch { display: flex; gap: 2px; margin-bottom: 16px; background: #f5f5f5; border-radius: 6px; padding: 2px; } .mode-switch-btn { flex: 1; padding: 8px 16px; border: none; background: transparent; color: #666; border-radius: 4px; cursor: pointer; font-size: 14px; font-weight: 500; transition: all 0.2s ease; } .mode-switch-btn.active { background: #fff; color: #333; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); } .mode-switch-btn:hover:not(.active) { background: rgba(255, 255, 255, 0.5); color: #333; } .batch-mode-content { display: none; } .batch-mode-content.active { display: block; } .batch-recognize-status { margin-top: 12px; } .batch-recognize-status-header { display: flex; justify-content: space-between; align-items: center; width: 100%; } .batch-recognize-export-btn { display: none; width: 80px; text-align: center; flex: none; } .batch-result-link { color: #4285f4; cursor: pointer; margin-left: 8px; } .batch-result-link:hover { color: #4caf50; } .batch-result-link.copied { color: #4caf50; } .batch-receive-file-name { margin-right: 8px; } .batch-receive-ready-message { text-align: center; color: #666; margin-top: 60px; } .batch-share-flex-row { display: flex; flex-direction: row; gap: 4px; align-items: center; justify-content: center; margin-bottom: 4px; flex-wrap: nowrap; width: 100%; } .batch-share-flex-column { display: flex; flex-direction: column; align-items: center; min-width: 70px; flex: 1; } .batch-share-label { margin-bottom: 1px; cursor: pointer; text-align: center; } .batch-share-input { width: 100%; min-width: 60px; text-align: center; } .batch-share-checkbox { width: 100%; height: 100%; opacity: 0.01; position: absolute; left: 0; top: 0; z-index: 2; pointer-events: auto; } .batch-share-btn { width: auto; white-space: nowrap; } .batch-share-cancel-btn { display: none; } .batch-share-file-list { margin: 8px 0; display: none; } .batch-share-file-count { color: #666; font-size: 12px; } .batch-share-file-list-container { max-height: 290px; overflow-y: auto; transition: max-height 0.3s ease; } #batch-receive-input-container { margin-bottom: 12px; position: relative; } .batch-receive-controls { display: flex; gap: 16px; align-items: center; margin-bottom: 12px; } .batch-receive-controls-main { flex: 1; } .batch-receive-controls-row { display: flex; align-items: center; gap: 16px; } .batch-receive-cid-controls { display: flex; gap: 8px; align-items: center; } #batch-receive-cid { width: 120px; text-align: center; } #batch-receive-cid-select { width: auto; } #batch-receive-progress { display: none; margin-bottom: 8px; } #batch-receive-progress-bar { width: 0%; } #batch-receive-status { display: none; } .batch-receive-status-header { display: flex; align-items: center; } #batch-receive-export-btn { display: none; margin-left: auto; } #batch-receive-back-btn { display: none; } .batch-result-item-btn { flex-shrink: 0; white-space: nowrap; } .batch-share-file-item { display: flex; align-items: center; padding: 8px; border-bottom: 1px solid #eee; background: #fff; } .batch-share-file-item:last-child { border-bottom: none; } .batch-share-file-icon { width: 24px; height: 24px; margin-right: 8px; flex-shrink: 0; white-space: nowrap; object-fit: contain; object-position: center; } .batch-share-file-info { flex: 1; min-width: 0; } .batch-share-file-name { font-weight: bold; color: #4285f4; word-break: break-word; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-right: 10px; cursor: pointer; display: flex; align-items: center; } .batch-share-actions-container { display: flex; gap: 4px; margin-left: auto; } .batch-share-action-btn { width: auto; min-width: fit-content; } .batch-share-status-success { margin-left: auto; font-size: 12px; } .batch-share-status-text { --status-color: #4285f4; color: var(--status-color); } .batch-share-details-container { display: flex; align-items: center; } .batch-share-export-btn { margin-left: auto; } .batch-share-copy-all-btn { background: #4caf50; color: white; border: none; border-radius: 4px; cursor: pointer; transition: background-color 0.2s; } .batch-share-copy-all-btn:hover { background: #45a049; } .batch-share-copy-all-btn.copied { background: #2196f3; } .batch-share-progress-actions { z-index: 10; } .batch-share-btn-disabled { opacity: 0.5 !important; cursor: not-allowed !important; } .batch-share-btn-enabled { opacity: 1 !important; cursor: text !important; } .batch-share-progress-hidden { display: none !important; } .batch-share-progress-visible { display: block !important; } .batch-share-btn-hidden { display: none !important; } .batch-share-btn-visible { display: inline-block !important; } .batch-share-flex-row-maximized { width: 100% !important; } .batch-share-file-list-maximized { max-height: calc(100vh - 400px) !important; height: calc(100vh - 400px) !important; } .batch-share-file-list-normal { max-height: 290px !important; height: auto !important; } .batch-share-file-status { margin-left: 8px; padding: 2px 6px; border-radius: 3px; font-size: 11px; font-weight: 500; } .batch-share-file-status.pending { background: #f5f5f5; color: #666; } .batch-share-file-status.processing { background: #e3f2fd; color: #1976d2; } .batch-share-file-status.success { background: #e8f5e8; color: #2e7d32; } .batch-share-file-status.error { background: #ffebee; color: #c62828; } .batch-share-file-status.skipped { background: #fff3e0; color: #ef6c00; } .batch-share-result-item { display: flex; align-items: center; padding: 8px; border-bottom: 1px solid #eee; background: #fff; } .batch-share-result-item:last-child { border-bottom: none; } .batch-share-result-icon { width: 24px; height: 24px; margin-right: 8px; flex-shrink: 0; } .batch-share-result-info { flex: 1; min-width: 0; } .batch-share-result-name { font-weight: 500; color: #333; margin-bottom: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .batch-share-result-details { font-size: 12px; color: #666; margin-bottom: 2px; } .batch-share-result-link { font-size: 12px; color: #4285f4; word-break: break-all; cursor: pointer; } .batch-share-result-link:hover { color: #4caf50; } .batch-share-result-actions { margin-left: 8px; display: flex; gap: 4px; } .batch-share-result-btn { padding: 2px 6px; background: rgba(0,0,0,0.05); border: none; border-radius: 3px; cursor: pointer; font-size: 11px; white-space: nowrap; } .batch-share-result-btn:hover { background: rgba(0,0,0,0.1); } .batch-share-result-btn.copy-btn { background-color: rgba(66,133,244,0.1); color: #4285f4; } .batch-share-result-btn.copy-btn:hover { background-color: rgba(66,133,244,0.2); } .batch-share-result-btn.open-btn { background-color: rgba(76,175,80,0.1); color: #4caf50; } .batch-share-result-btn.open-btn:hover { background-color: rgba(76,175,80,0.2); } .batch-share-switches-container { display: flex; gap: 16px; align-items: center; } .batch-share-buttons-container { display: flex; gap: 4px; align-items: center; margin-top: 12px; } .batch-share-file-list-header { display: flex; justify-content: flex-start; align-items: center; margin-bottom: 4px; gap: 8px; } .storage-item-title, .batch-share-file-list-title { font-weight: bold; color: #4285f4; } .batch-share-status-header { display: flex; justify-content: space-between; align-items: center; height: 10px; line-height: 10px; } .network-disconnect-warning { color: #F44336; margin-top: 5px; } .virtual-scroll-item { position: absolute; width: 100%; height: 99px; box-sizing: border-box; } .batch-share-error-icon { color: #f44336; width: 16px; height: 16px; display: inline-block; } .batch-share-error-msg { color: #f44336; font-size: 11px; } .batch-share-file-type { display: inline-block; padding: 2px 6px; background: #333333; color: white; border-radius: 4px; font-size: 12px; margin-right: 8px; font-family: normal; white-space: nowrap; } .batch-share-processing-icon { color: #ff9800; width: 16px; height: 16px; display: inline-block; } .element-block-switch-clickable { cursor: pointer; } .element-block-switch input { opacity: 0; width: 0; height: 0; position: absolute; z-index: 1; } .element-block-switch .element-block-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: .4s; border-radius: 24px; z-index: 0; } .network-reconnect-message { color: #4CAF50; margin-top: 5px; } .batch-input-textarea { height: 200px; } .batch-share-layout-container { display: flex; justify-content: space-between; align-items: center; margin-bottom: 4px; } .batch-share-status-preparing { color: #ffa726; font-size: 12px; background-image: url("data:image/svg+xml,%3Csvg width='12' height='12' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z' fill='%23ffa726'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: left center; background-size: 12px; padding-left: 16px; display: inline-block; font-weight: bold; text-align: center; } `; document.head.appendChild(style); (function() { 'use strict'; window.addEventListener('online', () => { if (statusDiv) { statusDiv.innerHTML += '
网络连接已恢复
'; } }); document.addEventListener('keydown', (e) => { const dedupeTabContent = document.querySelector('.storage-tab-content[data-tab-content="dedupe"]'); if (!dedupeTabContent || !dedupeTabContent.classList.contains('active')) return; if (e.ctrlKey && e.key === 'a') { e.preventDefault(); dedupeSelectedItems.clear(); for (const key of dedupeCurrentPageItems) { dedupeSelectedItems.add(key); } dedupeLastListRef = null; dedupeLastIndex = -1; updateDedupeItemSelection(); } else if (e.key === 'Escape') { dedupeSelectedItems.clear(); dedupeLastListRef = null; dedupeLastIndex = -1; updateDedupeItemSelection(); } }); window.addEventListener('offline', () => { if (statusDiv) { statusDiv.innerHTML += '
网络连接已断开,验证可能失败
'; } if (isRunning && !isPaused) { togglePauseResume(); } }); function shouldInjectButton() { const html115 = document.querySelector('html.layout-frame.bd-core.layout-allscreen'); if (html115 && html115.querySelector('head meta[charset="UTF-8"]')) { return true; } const html115cdn = document.querySelector('html.layout-frame'); if (html115cdn && html115cdn.querySelector('head meta[charset="UTF-8"]')) { return true; } const html115cdnAlt = document.querySelector('html'); if (html115cdnAlt && html115cdnAlt.querySelector('head meta[charset="UTF-8"]') && html115cdnAlt.querySelector('head meta[name="viewport"][content*="viewport-fit=cover"]')) { return true; } return false; } if (!shouldInjectButton()) { return; } const DEFAULT_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; let allChars = DEFAULT_CHARS; let shareInfo = { shareCode: '', userId: '', face: '', isAccessible: false, shareTitle: '', expireTime: -1, fileSize: 0, autoRenewal: '0' }; let selectedItems = new Set(); let lastSelectedIndex = -1; let isMultiSelectMode = false; let dedupeSelectedItems = new Set(); let dedupeLastListRef = null; let dedupeLastIndex = -1; let dedupeCurrentPageItems = []; const dedupeKeyMap = new Map(); const elementBlockItems = [ { selector: '.ceiling-feature#js_common_act-enter', name: '顶部活动广告', enabled: true, category: '通用' }, { selector: '.ceiling-link-temp', name: '顶部净网2025', enabled: true, category: '通用' }, { selector: '.feature-float#js_common_mini-dialog', name: '右下角浮动广告', enabled: true, category: '通用' }, { selector: '.sharing-banner#js_common_sharing_banner2', name: '分享页横幅广告', enabled: true, category: '分享页' }, { selector: '.sharing-banner#js_common_sharing_banner', name: '横幅广告', enabled: true, category: '分享页' }, { selector: '.promptbar-caution', name: '底部警告提示栏', enabled: true, category: '分享页' }, { selector: 'li:has(.ibc-notice)', name: '我聊', enabled: false, category: '导航' }, { selector: 'li:has(.ibc-service)', name: '帮助', enabled: true, category: '导航' }, { selector: 'li:has(.ibc-app)', name: '客户端下载', enabled: true, category: '导航' }, { selector: '.ceiling-vip-door', name: '购买VIP', enabled: true, category: '导航' } ]; function initElementBlockSettings() { const savedSettings = GM_getValue('elementBlockSettings'); if (savedSettings) { try { const parsedSettings = JSON.parse(savedSettings); parsedSettings.forEach(savedItem => { const item = elementBlockItems.find(i => i.selector === savedItem.selector); if (item) item.enabled = savedItem.enabled; }); } catch (e) { console.error('解析元素屏蔽设置失败:', e); } } } function saveElementBlockSettings() { GM_setValue('elementBlockSettings', JSON.stringify(elementBlockItems)); } function executeElementBlock() { elementBlockItems.forEach(item => { if (item.enabled) { document.querySelectorAll(item.selector).forEach(el => el.remove()); } }); } function formatFileSize(bytes) { if (bytes === 0 || bytes === undefined) return '0B'; const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']; const digitGroups = Math.floor(Math.log10(bytes) / Math.log10(1024)); const size = bytes / Math.pow(1024, digitGroups); if (digitGroups >= 4) { return size.toFixed(2) + units[digitGroups]; } else if (digitGroups >= 2) { return size.toFixed(2) + units[digitGroups]; } else { return Math.round(size) + units[digitGroups]; } } const floatingBtn = document.createElement('div'); floatingBtn.className = 'btn'; floatingBtn.innerHTML = `
`; document.body.appendChild(floatingBtn); const badge = document.createElement('span'); badge.className = 'floating-badge'; badge.style.cssText = 'position:absolute;top:-6px;right:-6px;min-width:18px;height:18px;background:#4285f4;color:#fff;border-radius:9px;font-size:12px;line-height:18px;text-align:center;display:none;z-index:10001;padding:0 4px;pointer-events:none;box-shadow:0 1px 4px rgba(0,0,0,0.15);font-weight:bold;'; floatingBtn.style.position = 'fixed'; floatingBtn.appendChild(badge); function updateFloatingBadgeAndGear() { let count = 0; try { const iframe = document.querySelector('iframe'); const iframeWindow = iframe?.contentWindow || unsafeWindow; const selectDOM = iframeWindow?.document?.querySelectorAll('div.list-contents > ul li.selected'); count = selectDOM ? selectDOM.length : 0; } catch(e) { count = 0; } if (count > 0) { badge.textContent = count; badge.style.display = 'block'; floatingBtn.querySelector('.gear-icon').classList.add('active'); } else { badge.style.display = 'none'; floatingBtn.querySelector('.gear-icon').classList.remove('active'); } } setInterval(updateFloatingBadgeAndGear, 500); floatingBtn.addEventListener('click', (e) => { if (e.defaultPrevented || e.target !== floatingBtn) return; let count = 0; try { const iframe = document.querySelector('iframe'); const iframeWindow = iframe?.contentWindow || unsafeWindow; const selectDOM = iframeWindow?.document?.querySelectorAll('div.list-contents > ul li.selected'); count = selectDOM ? selectDOM.length : 0; } catch(e) { count = 0; } if (count > 0) { openWindowAndActivate('batchshare'); } else { openWindowAndActivate('storage'); } }); const windowElement = document.createElement('div'); windowElement.className = 'window'; windowElement.style.position = 'fixed'; windowElement.style.left = '0px'; windowElement.style.top = '0px'; windowElement.style.transform = 'none'; windowElement.innerHTML = `

访问码验证助手GreasyFork:wangzijian0@vip.qq.com

存储管理
内容查重
批量接收
批量识别
批量分享
验证访问码
元素屏蔽
附加功能
已选 0 项
多选与快捷键
  • Ctrl+左键:添加/取消单项选择
  • Shift+左键:选择范围(与上次选中形成区间)
  • Ctrl+A:全选
  • 点击空白处或取消按钮清空选择
暂无存储数据
正在获取分享信息...
`; document.body.appendChild(windowElement); function openWindowAndActivate(tabName) { try { windowElement.style.display = 'block'; } catch (e) {} document.querySelectorAll('.storage-tab').forEach(tab => tab.classList.remove('active')); document.querySelectorAll('.storage-tab-content').forEach(tab => tab.classList.remove('active')); const tabEl = document.querySelector(`.storage-tab[data-tab="${tabName}"]`); const contentEl = document.querySelector(`.storage-tab-content[data-tab-content="${tabName}"]`); if (tabEl && contentEl) { tabEl.classList.add('active'); contentEl.classList.add('active'); if (tabName === 'batchshare' && typeof renderBatchSharePage === 'function') { renderBatchSharePage(); } } } const charsInput = windowElement.querySelector('.chars-input'); const charsError = windowElement.querySelector('.chars-error'); const strategySelect = windowElement.querySelector('.strategy-select'); const concurrentInput = windowElement.querySelector('.concurrent-input'); const pauseResumeBtn = windowElement.querySelector('.pause-resume-btn'); const stopBtn = windowElement.querySelector('.stop-btn'); const statusDiv = windowElement.querySelector('.status-div'); const statsInfo = windowElement.querySelector('.stats-info'); const shareDetails = windowElement.querySelector('.share-details'); const storageContainer = windowElement.querySelector('#storage-container'); const storageScrollContent = windowElement.querySelector('#storage-scroll-content'); const storageEmpty = windowElement.querySelector('#storage-empty'); const exportBtn = windowElement.querySelector('#export-btn'); const importBtn = windowElement.querySelector('#import-btn'); const extractBtn = windowElement.querySelector('#extract-btn'); const clearBtn = windowElement.querySelector('#clear-btn'); const tabContents = windowElement.querySelectorAll('.storage-tab-content'); const tabs = windowElement.querySelectorAll('.storage-tab'); const statusTagContainer = windowElement.querySelector('.status-tag-container'); const elementBlockContainer = windowElement.querySelector('#element-block-container'); const searchInput = windowElement.querySelector('#search-input'); const searchType = windowElement.querySelector('#search-type'); const apiRefreshBtn = windowElement.querySelector('#api-refresh-btn'); const apiRefreshBadge = windowElement.querySelector('.api-refresh-badge'); const refreshBtn = windowElement.querySelector('.refresh-btn'); const filterButtons = windowElement.querySelectorAll('.filter-buttons button[data-filter]'); let apiRefreshRunning = false; let apiRefreshCancelled = false; const deleteExpiredBtn = windowElement.querySelector('#delete-expired-btn'); const deleteInvalidBtn = windowElement.querySelector('#delete-invalid-btn'); const sortButtons = windowElement.querySelectorAll('.sort-buttons .storage-item-btn'); const settingsBlockContainer = windowElement.querySelector('#settings-block-container'); const batchReceiveContainer = windowElement.querySelector('#batch-receive-container'); const batchShareContainer = windowElement.querySelector('#batch-share-container'); const batchRecognizeContainer = windowElement.querySelector('#batch-recognize-container'); const dedupeContainer = windowElement.querySelector('#dedupe-container'); let currentSearchTerm = ''; let currentSearchType = 'all'; let currentFilterType = 'all'; let currentSortType = 'time-desc'; let filteredItems = []; let allItems = []; let itemHeight = 99; let visibleItemCount = 10; let dedupeMode = (function(){ try { return GM_getValue('dedupeMode', 'size+title'); } catch(_) { return 'size+title'; } })(); let dedupeGroups = []; let dedupePage = 1; const DEDUPE_PAGE_SIZE = 1; function getDedupeKey(item) { const size = Number(item.fileSize || 0); if (!size || size <= 0) return null; if (dedupeMode === 'size') return `size:${size}`; const title = (item.shareTitle || '').trim().toLowerCase(); if (!title) return null; return `size:${size}|title:${title}`; } function rebuildDedupeGroups() { try { const items = getAllStorageItems(); const map = new Map(); for (const item of items) { const key = getDedupeKey(item); if (!key) continue; if (!map.has(key)) { map.set(key, { key, size: Number(item.fileSize || 0), title: item.shareTitle || '', items: [] }); } map.get(key).items.push(item); } dedupeGroups = Array.from(map.values()).filter(g => g.items.length >= 2); dedupeGroups.sort((a, b) => { const byCount = b.items.length - a.items.length; if (byCount !== 0) return byCount; const bySize = (b.size || 0) - (a.size || 0); if (bySize !== 0) return bySize; return (a.title || '').localeCompare(b.title || ''); }); } catch (e) { console.error('重建查重分组失败:', e); dedupeGroups = []; } } function bindDedupeItemActions(itemElement, item) { const copyBtn = itemElement.querySelector('.copy-btn'); const deleteBtn = itemElement.querySelector('.delete-btn'); const openBtn = itemElement.querySelector('.open-btn'); if (copyBtn) { copyBtn.addEventListener('click', () => { const enableMagnetTitleCopy = GM_getValue('enableMagnetTitleCopy', false); if (item.magnet) { let magnetToCopy; if (enableMagnetTitleCopy && (item.shareTitle || item.note)) { const title = item.shareTitle || item.note; magnetToCopy = `${title}\n${item.magnet}`; } else { magnetToCopy = item.magnet; if (!item.magnet.includes('?name=') && (item.shareTitle || item.note)) { const title = item.shareTitle || item.note; magnetToCopy = `${item.magnet}?name=${title}`; } } navigator.clipboard.writeText(magnetToCopy).then(() => handleCopyButtonStatus(copyBtn)).catch(() => {}); } else if (item.ed2k) { const text = `${item.shareTitle || '无标题'}\n${item.ed2k}`; navigator.clipboard.writeText(text).then(() => handleCopyButtonStatus(copyBtn)).catch(() => {}); } else { const title = item.shareTitle || '无标题'; const link = `https://115cdn.com/s/${item.shareCode}${item.password ? `?password=${item.password}` : ''}`; const enableShareTitleCopy = GM_getValue('enableShareTitleCopy', false); let text; if (enableShareTitleCopy && title) { text = `${title}\n${link}`; } else { text = `${link}#\n${title}`; } navigator.clipboard.writeText(text).then(() => handleCopyButtonStatus(copyBtn)).catch(() => {}); } }); } if (openBtn) { openBtn.addEventListener('click', () => { if (item.magnet) { navigator.clipboard.writeText(item.magnet).then(() => handleCopyButtonStatus(openBtn)).catch(() => {}); } else if (item.ed2k) { navigator.clipboard.writeText(item.ed2k).then(() => handleCopyButtonStatus(openBtn)).catch(() => {}); } else { window.open(`https://115cdn.com/s/${item.shareCode}${item.password ? `?password=${item.password}` : ''}`, '_blank'); } }); } if (deleteBtn) { deleteBtn.addEventListener('click', () => { const enableDeleteConfirm = GM_getValue('enableDeleteConfirm', true); if (!enableDeleteConfirm || confirm('确定要删除该条目吗?')) { GM_deleteValue(generateStorageKey(item.shareCode, item.ed2k, item.magnet)); rebuildDedupeGroups(); renderDedupePage(); } }); } } function renderDedupePage() { if (!dedupeContainer) return; if (!Array.isArray(dedupeGroups) || dedupeGroups.length === 0) { rebuildDedupeGroups(); } dedupeContainer.innerHTML = ''; const sizeDisplayMode = (function(){ try { return GM_getValue('dedupeSizeDisplay', 'auto'); } catch(_) { return 'auto'; } })(); const sizeToText = (bytes) => { const v = Number(bytes || 0); if (sizeDisplayMode === 'bytes') return `${v.toLocaleString()} B`; return formatFileSize(v); }; const sortOrder = (function(){ try { return GM_getValue('dedupeSortOrder', 'desc'); } catch(_) { return 'desc'; } })(); const controls = document.createElement('div'); controls.className = 'dedupe-controls'; controls.style.display = 'flex'; controls.style.alignItems = 'center'; controls.style.gap = '8px'; controls.style.margin = '8px 0'; controls.innerHTML = `
已选 0 项
多选与快捷键
  • Ctrl+左键:添加/取消单项选择
  • Shift+左键:选择范围(与上次选中形成区间)
  • Ctrl+A:全选
  • 点击空白处或取消按钮清空选择
`; dedupeContainer.appendChild(controls); const modeSelect = controls.querySelector('#dedupe-mode-select'); if (dedupeMode !== 'size' && dedupeMode !== 'size+title') dedupeMode = 'size'; modeSelect.value = dedupeMode; modeSelect.addEventListener('change', () => { dedupeMode = modeSelect.value; try { GM_setValue('dedupeMode', dedupeMode); } catch (_) {} dedupePage = 1; rebuildDedupeGroups(); renderDedupePage(); }); const sizeSelect = controls.querySelector('#dedupe-size-display'); if (sizeSelect) { sizeSelect.value = sizeDisplayMode; sizeSelect.addEventListener('change', () => { try { GM_setValue('dedupeSizeDisplay', sizeSelect.value); } catch(_) {} renderDedupePage(); }); } const sortSelect = controls.querySelector('#dedupe-sort-order'); if (sortSelect) { sortSelect.value = sortOrder; sortSelect.addEventListener('change', () => { try { GM_setValue('dedupeSortOrder', sortSelect.value); } catch(_) {} dedupePage = 1; renderDedupePage(); }); } const scanBtn = controls.querySelector('#dedupe-scan-btn'); if (scanBtn && !scanBtn._bound) { scanBtn.addEventListener('click', () => { scanBtn.disabled = true; scanBtn.style.pointerEvents = 'none'; scanBtn.setAttribute('aria-busy', 'true'); scanBtn.classList.add('scanning'); setTimeout(() => { rebuildDedupeGroups(); dedupePage = 1; renderDedupePage(); }, 800); }); scanBtn._bound = true; } const statsText = (() => { let totalDupItems = 0; for (const g of dedupeGroups) totalDupItems += g.items.length; return `查重结果:${dedupeGroups.length} 组,共 ${totalDupItems} 项(每组≥2)`; })(); const dedupeBatchContainer = controls.querySelector('.batch-actions-container'); if (dedupeBatchContainer && !dedupeBatchContainer._bound) { const deleteBtn = dedupeBatchContainer.querySelector('.delete-btn'); if (deleteBtn) deleteBtn.addEventListener('click', (e) => { e.stopPropagation(); batchDeleteSelectedDedupe(); }); dedupeBatchContainer._bound = true; } try { updateBatchActions(); } catch (_) {} const sortedGroups = (() => { const arr = dedupeGroups.slice(); arr.sort((a, b) => { let cmp = 0; if (a.size !== b.size) cmp = a.size - b.size; else if (dedupeMode === 'size+title') cmp = (a.title || '').localeCompare(b.title || ''); return sortOrder === 'asc' ? cmp : -cmp; }); return arr; })(); const totalPages = Math.max(1, Math.ceil(sortedGroups.length / DEDUPE_PAGE_SIZE)); if (dedupePage < 1) dedupePage = 1; if (dedupePage > totalPages) dedupePage = totalPages; const pagerTop = document.createElement('div'); pagerTop.className = 'dedupe-pagination'; pagerTop.style.display = 'flex'; pagerTop.style.alignItems = 'center'; pagerTop.style.gap = '8px'; pagerTop.style.margin = '10px 0'; pagerTop.style.justifyContent = 'space-between'; pagerTop.style.width = '100%'; pagerTop.innerHTML = `
/ ${totalPages} 页
`; const prevBtnTop = pagerTop.querySelector('.dedupe-prev'); const nextBtnTop = pagerTop.querySelector('.dedupe-next'); const statsEl = pagerTop.querySelector('.dedupe-stats'); if (statsEl) statsEl.textContent = statsText; const pageInput = pagerTop.querySelector('#dedupe-page-input'); if (pageInput) { const applyPage = () => { const raw = parseInt(pageInput.value, 10); if (!Number.isFinite(raw)) { pageInput.value = String(dedupePage); return; } const clamped = Math.min(Math.max(raw, 1), totalPages); if (clamped !== dedupePage) { dedupePage = clamped; renderDedupePage(); } else { pageInput.value = String(dedupePage); } }; let pageInputTimer = null; pageInput.addEventListener('input', () => { if (pageInputTimer) clearTimeout(pageInputTimer); pageInputTimer = setTimeout(() => { pageInputTimer = null; const raw = parseInt(pageInput.value, 10); if (!Number.isFinite(raw)) return; const clamped = Math.min(Math.max(raw, 1), totalPages); if (clamped !== dedupePage) { dedupePage = clamped; renderDedupePage(); } }, 450); }); pageInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') applyPage(); }); pageInput.addEventListener('blur', applyPage); } prevBtnTop.addEventListener('click', () => { if (dedupePage > 1) { dedupePage--; renderDedupePage(); } }); nextBtnTop.addEventListener('click', () => { if (dedupePage < totalPages) { dedupePage++; renderDedupePage(); } }); dedupeContainer.appendChild(pagerTop); const groupsWrap = document.createElement('div'); groupsWrap.className = 'dedupe-groups'; dedupeContainer.appendChild(groupsWrap); const start = (dedupePage - 1) * DEDUPE_PAGE_SIZE; const end = Math.min(sortedGroups.length, start + DEDUPE_PAGE_SIZE); const currentGroups = sortedGroups.slice(start, end); dedupeCurrentPageItems = []; const getDedupeListMaxHeight = (el) => { const vh = window.innerHeight || document.documentElement.clientHeight || 800; if (el && el.getBoundingClientRect) { const rect = el.getBoundingClientRect(); let h = Math.floor(vh - rect.top - 40); if (!Number.isFinite(h)) h = 396; return Math.max(280, h); } return Math.max(396, Math.floor(vh * 0.8)); }; if (dedupeContainer._dedupeResizeHandler) { window.removeEventListener('resize', dedupeContainer._dedupeResizeHandler); } if (dedupeContainer._resizeObserver) { try { dedupeContainer._resizeObserver.disconnect(); } catch(_) {} dedupeContainer._resizeObserver = null; } dedupeContainer._dedupeResizeHandler = () => { document.querySelectorAll('.dedupe-item-list').forEach(el => { const h = `${getDedupeListMaxHeight(el)}px`; el.style.maxHeight = h; if (typeof el._onResize === 'function') { try { el._onResize(); } catch(_) {} } }); }; window.addEventListener('resize', dedupeContainer._dedupeResizeHandler); if (window.ResizeObserver && windowElement) { dedupeContainer._resizeObserver = new ResizeObserver(() => { dedupeContainer._dedupeResizeHandler(); }); try { dedupeContainer._resizeObserver.observe(windowElement); } catch(_) {} } try { dedupeContainer._dedupeResizeHandler(); } catch (_) {} if (currentGroups.length === 0) { const empty = document.createElement('div'); empty.style.padding = '12px'; empty.style.color = '#888'; empty.textContent = '未找到查重分组,请点击“查重”。'; groupsWrap.appendChild(empty); } else { for (const group of currentGroups) { try { for (const it of group.items) { const key = it.shareCode + (it.ed2k || '') + (it.magnet || ''); dedupeCurrentPageItems.push(key); dedupeKeyMap.set(key, { shareCode: it.shareCode, ed2k: it.ed2k, magnet: it.magnet }); } } catch (_) {} const groupEl = document.createElement('div'); groupEl.className = 'dedupe-group'; groupEl.style.border = '1px solid #eee'; groupEl.style.borderRadius = '6px'; groupEl.style.margin = '8px 0'; groupEl.style.padding = '8px'; const sizeChipText = sizeToText(group.size); const titleChipText = (group.title || '无标题'); const countChipText = `查重 ${group.items.length} 项`; const header = document.createElement('div'); header.className = 'dedupe-group-header'; header.style.display = 'flex'; header.style.justifyContent = 'space-between'; header.style.alignItems = 'center'; header.style.marginBottom = '6px'; header.innerHTML = `
${countChipText} ${sizeChipText} ${dedupeMode === 'size+title' ? `${titleChipText}` : ''}
`; groupEl.appendChild(header); const list = document.createElement('div'); list.className = 'dedupe-item-list'; list.style.position = 'relative'; list.style.overflowY = 'auto'; list.style.maxHeight = `${getDedupeListMaxHeight(list)}px`; const scrollContent = document.createElement('div'); scrollContent.style.position = 'relative'; scrollContent.style.width = '100%'; scrollContent.style.height = `${group.items.length * itemHeight}px`; list.appendChild(scrollContent); let gRenderStartIndex = 0; let gRenderEndIndex = 0; let gVisibleItemCount = Math.ceil((list.clientHeight || 396) / itemHeight) + 2; let gItemPool = []; const gCachedElements = new Map(); let gLastScrollTop = -1; let gScrollThrottle = null; list._onResize = () => { const newVisible = Math.ceil((list.clientHeight || 396) / itemHeight) + 2; if (newVisible !== gVisibleItemCount) { gVisibleItemCount = newVisible; try { gRenderVisibleItems(); } catch(_) {} } }; function gRenderVisibleItems() { const needCount = gRenderEndIndex - gRenderStartIndex; while (gItemPool.length < needCount) { const div = document.createElement('div'); div.className = 'virtual-scroll-item'; div.style.height = `${itemHeight}px`; div.style.position = 'absolute'; gItemPool.push(div); } while (gItemPool.length > needCount + 5) { const removed = gItemPool.pop(); if (removed && removed._itemKey) { gCachedElements.delete(removed._itemKey); } } const fragment = document.createDocumentFragment(); for (let i = 0; i < needCount; i++) { const idx = gRenderStartIndex + i; const item = group.items[idx]; const div = gItemPool[i]; if (!item) { div.style.display = 'none'; continue; } div.style.display = ''; div.style.top = `${idx * itemHeight}px`; const itemKey = item.shareCode + (item.ed2k || '') + (item.magnet || ''); if (!div._itemKey || div._itemKey !== itemKey) { let el; if (gCachedElements.has(itemKey)) { el = gCachedElements.get(itemKey).cloneNode(true); const cloned = el; const copyBtn = cloned.querySelector('.copy-btn'); const openBtn = cloned.querySelector('.open-btn'); const deleteBtn = cloned.querySelector('.delete-btn'); if (copyBtn) { copyBtn.addEventListener('click', () => { const enableMagnetTitleCopy = GM_getValue('enableMagnetTitleCopy', false); if (item.magnet) { let magnetToCopy; if (enableMagnetTitleCopy && (item.shareTitle || item.note)) { const title = item.shareTitle || item.note; magnetToCopy = `${title}\n${item.magnet}`; } else { magnetToCopy = item.magnet; if (!item.magnet.includes('?name=') && (item.shareTitle || item.note)) { const title = item.shareTitle || item.note; magnetToCopy = `${item.magnet}?name=${title}`; } } navigator.clipboard.writeText(magnetToCopy).then(() => handleCopyButtonStatus(copyBtn)).catch(() => {}); } else if (item.ed2k) { const text = `${item.shareTitle || '无标题'}\n${item.ed2k}`; navigator.clipboard.writeText(text).then(() => handleCopyButtonStatus(copyBtn)).catch(() => {}); } else { const title = item.shareTitle || '无标题'; const link = `https://115cdn.com/s/${item.shareCode}${item.password ? `?password=${item.password}` : ''}`; const enableShareTitleCopy = GM_getValue('enableShareTitleCopy', false); let text; if (enableShareTitleCopy && title) { text = `${title}\n${link}`; } else { text = `${link}#\n${title}`; } navigator.clipboard.writeText(text).then(() => handleCopyButtonStatus(copyBtn)).catch(() => {}); } }); } if (openBtn) { openBtn.addEventListener('click', () => { if (item.magnet) { navigator.clipboard.writeText(item.magnet).then(() => handleCopyButtonStatus(openBtn)).catch(() => {}); } else if (item.ed2k) { navigator.clipboard.writeText(item.ed2k).then(() => handleCopyButtonStatus(openBtn)).catch(() => {}); } else { window.open(`https://115cdn.com/s/${item.shareCode}${item.password ? `?password=${item.password}` : ''}`, '_blank'); } }); } if (deleteBtn) { deleteBtn.addEventListener('click', () => { const enableDeleteConfirm = GM_getValue('enableDeleteConfirm', true); if (!enableDeleteConfirm || confirm('确定要删除该条目吗?')) { GM_deleteValue(generateStorageKey(item.shareCode, item.ed2k, item.magnet)); rebuildDedupeGroups(); renderDedupePage(); } }); } } else { el = createStorageItemElement(item, { bindActions: true, renderContext: 'dedupe' }); const template = el.cloneNode(true); gCachedElements.set(itemKey, template); } try { const sizeSpan = el.querySelector('.file-size'); if (sizeSpan && (item.fileSize || item.fileSize === 0)) { sizeSpan.textContent = sizeToText(item.fileSize || 0); } } catch (_) {} try { el.dataset.key = itemKey; } catch(_) {} if (dedupeSelectedItems.has(itemKey)) { el.classList.add('selected'); } else { el.classList.remove('selected'); } el.addEventListener('click', (e) => { if (e.target.closest('.storage-item-btn')) return; const listRef = list; if (e.shiftKey && dedupeLastListRef === listRef && dedupeLastIndex >= 0) { const start = Math.min(dedupeLastIndex, idx); const end = Math.max(dedupeLastIndex, idx); for (let k = start; k <= end; k++) { const it = group.items[k]; if (!it) continue; const key = it.shareCode + (it.ed2k || '') + (it.magnet || ''); dedupeSelectedItems.add(key); } } else if (e.ctrlKey || e.metaKey) { if (dedupeSelectedItems.has(itemKey)) dedupeSelectedItems.delete(itemKey); else dedupeSelectedItems.add(itemKey); dedupeLastListRef = listRef; dedupeLastIndex = idx; } else { dedupeSelectedItems.clear(); dedupeSelectedItems.add(itemKey); dedupeLastListRef = listRef; dedupeLastIndex = idx; } updateDedupeItemSelection(); }); div.innerHTML = ''; div.appendChild(el); div._itemKey = itemKey; } fragment.appendChild(div); } scrollContent.innerHTML = ''; scrollContent.appendChild(fragment); } function gUpdateOnResize() { gVisibleItemCount = Math.ceil((list.clientHeight || 396) / itemHeight) + 2; const bufferSize = Math.max(10, Math.ceil(gVisibleItemCount * 0.5)); const currentTop = list.scrollTop; gRenderStartIndex = Math.max(0, Math.floor(currentTop / itemHeight) - bufferSize); gRenderEndIndex = Math.min(group.items.length, gRenderStartIndex + gVisibleItemCount + bufferSize * 2); scrollContent.style.height = `${group.items.length * itemHeight}px`; gRenderVisibleItems(); } function gHandleScroll() { const currentTop = list.scrollTop; if (Math.abs(currentTop - gLastScrollTop) < 10) return; gLastScrollTop = currentTop; const bufferSize = Math.max(10, Math.ceil(gVisibleItemCount * 0.5)); const newStart = Math.max(0, Math.floor(currentTop / itemHeight) - bufferSize); const newEnd = Math.min(group.items.length, newStart + gVisibleItemCount + bufferSize * 2); if (newStart !== gRenderStartIndex || newEnd !== gRenderEndIndex) { gRenderStartIndex = newStart; gRenderEndIndex = newEnd; gRenderVisibleItems(); } } gUpdateOnResize(); list.addEventListener('scroll', () => { if (gScrollThrottle) return; gScrollThrottle = requestAnimationFrame(() => { gHandleScroll(); gScrollThrottle = null; }); }); const resizeObserver = new ResizeObserver(() => gUpdateOnResize()); resizeObserver.observe(list); groupEl.appendChild(list); groupsWrap.appendChild(groupEl); } } } function getLocalQuota() { if (typeof window.get115QuotaLocal === 'function') { return window.get115QuotaLocal(); } try { const c = GM_getValue('vip_quota_cache_v1', null); return c && c.data ? c.data : null; } catch (_) { return null; } } function setLocalQuota(data) { if (typeof window.set115QuotaLocal === 'function') { window.set115QuotaLocal(data); return; } try { GM_setValue('vip_quota_cache_v1', { t: Date.now(), data }); } catch (_) {} } function decrementQuotaLocal() { const q = getLocalQuota(); if (!q) return; const next = { surplus: Math.max(0, Number(q.surplus || 0) - 1), count: Number(q.count || 0), }; next.used = Math.max(0, next.count - next.surplus); setLocalQuota(next); updateQuotaWidget(); } const storageTabContentEl = windowElement.querySelector('.storage-tab-content[data-tab-content="storage"]'); let quotaWidgetEl = null; let quotaTextEl = null; let quotaRefreshBtn = null; function ensureQuotaWidget() { if (!storageTabContentEl) return; if (!quotaWidgetEl) { storageTabContentEl.style.position = storageTabContentEl.style.position || 'relative'; quotaWidgetEl = document.createElement('div'); quotaWidgetEl.id = 'offline-quota-widget'; quotaWidgetEl.style.position = 'absolute'; quotaWidgetEl.style.right = '12px'; quotaWidgetEl.style.bottom = '12px'; quotaWidgetEl.style.zIndex = '5'; quotaWidgetEl.style.display = 'inline-flex'; quotaWidgetEl.style.alignItems = 'center'; quotaWidgetEl.style.gap = '8px'; quotaWidgetEl.style.padding = '6px 10px'; quotaWidgetEl.style.background = 'rgba(255,255,255,0.9)'; quotaWidgetEl.style.backdropFilter = 'blur(2px)'; quotaWidgetEl.style.border = '1px solid #e6e6e6'; quotaWidgetEl.style.borderRadius = '8px'; quotaWidgetEl.style.boxShadow = '0 2px 8px rgba(0,0,0,0.08)'; quotaWidgetEl.style.fontSize = '12px'; quotaTextEl = document.createElement('span'); quotaTextEl.className = 'quota-text'; quotaTextEl.textContent = '离线额度:--/--'; quotaRefreshBtn = document.createElement('button'); quotaRefreshBtn.type = 'button'; quotaRefreshBtn.className = 'storage-item-btn quota-refresh-btn'; quotaRefreshBtn.textContent = '刷新'; quotaRefreshBtn.style.minWidth = '48px'; quotaRefreshBtn.addEventListener('click', async () => { const btn = quotaRefreshBtn; const oldText = btn.textContent; btn.disabled = true; btn.textContent = '刷新中...'; try { let data = null; if (typeof window.refresh115Quota === 'function') { data = await window.refresh115Quota(); } else { data = await new Promise((resolve, reject) => { GM_xmlhttpRequest({ url: 'https://115.com/web/lixian/?ct=lixian&ac=get_quota_package_info', method: 'GET', headers: { 'Accept': 'application/json, text/plain, */*', 'Referer': 'https://115.com/web/lixian/' }, onload: (resp) => { try { const json = JSON.parse(resp.responseText || 'null'); resolve({ surplus: Number(json?.surplus ?? json?.package?.["1"]?.surplus ?? 0), count: Number(json?.count ?? json?.package?.["1"]?.count ?? 0), used: Number(json?.used ?? json?.package?.["1"]?.used ?? 0), }); } catch (e) { reject(e); } }, onerror: (e) => reject(e) }); }); } if (data) setLocalQuota(data); } catch (e) { console.error('刷新离线额度失败', e); } finally { btn.disabled = false; btn.textContent = oldText; updateQuotaWidget(); } }); quotaWidgetEl.appendChild(quotaTextEl); quotaWidgetEl.appendChild(quotaRefreshBtn); storageTabContentEl.appendChild(quotaWidgetEl); } updateQuotaWidget(); } function updateQuotaWidget() { if (!quotaTextEl) return; const q = getLocalQuota(); if (q && typeof q.surplus !== 'undefined' && typeof q.count !== 'undefined') { quotaTextEl.textContent = `离线额度:${q.surplus}/${q.count}`; } else { quotaTextEl.textContent = '离线额度:--/--'; } } function updateQuotaWidgetVisibility() { const enabled = GM_getValue('enableOfflineQuotaWidget', true); if (!quotaWidgetEl) { if (enabled) ensureQuotaWidget(); return; } quotaWidgetEl.style.display = enabled ? 'inline-flex' : 'none'; } ensureQuotaWidget(); updateQuotaWidgetVisibility(); let scrollTop = 0; let renderStartIndex = 0; let renderEndIndex = 0; let lastRenderTime = 0; let requestAnimationFrameId = null; let debounceTimer = null; let itemPool = []; let cachedElements = new Map(); let lastScrollTop = 0; let scrollThrottleTimer = null; let isScrolling = false; let scrollSpeed = 0; let lastScrollTime = 0; let renderCount = 0; let performanceLastRenderTime = 0; let totalRenderTime = 0; function processShareTitle(data) { const enableHarmonizeTitle = GM_getValue('enableHarmonizeTitle', true); if (!enableHarmonizeTitle) { return data.data?.shareinfo?.share_title || ''; } const shareTitle = data.data?.shareinfo?.share_title || ''; if (shareTitle.includes('***')) { if (data.data?.list && data.data.list.length > 0) { return data.data.list[0].n || shareTitle; } } return shareTitle; } function setupVirtualScroll() { const containerHeight = storageContainer.clientHeight; visibleItemCount = Math.ceil(containerHeight / itemHeight) + 2; updateScrollContentHeight(); storageContainer.addEventListener('scroll', () => { if (scrollThrottleTimer) return; scrollThrottleTimer = requestAnimationFrame(() => { handleScroll(); scrollThrottleTimer = null; }); }); handleScroll(); scheduleCacheCleanup(); } function updateScrollContentHeight() { const totalHeight = filteredItems.length * itemHeight; storageScrollContent.style.height = `${totalHeight}px`; } function handleScroll() { const currentScrollTop = storageContainer.scrollTop; const currentTime = performance.now(); if (lastScrollTime > 0) { const timeDiff = currentTime - lastScrollTime; const scrollDiff = Math.abs(currentScrollTop - lastScrollTop); scrollSpeed = scrollDiff / timeDiff; } lastScrollTime = currentTime; if (Math.abs(currentScrollTop - lastScrollTop) < 10) return; lastScrollTop = currentScrollTop; scrollTop = currentScrollTop; let bufferSize; if (scrollSpeed > 2) { bufferSize = Math.max(20, Math.ceil(visibleItemCount * 0.8)); } else if (scrollSpeed > 0.5) { bufferSize = Math.max(15, Math.ceil(visibleItemCount * 0.6)); } else { bufferSize = Math.max(10, Math.ceil(visibleItemCount * 0.4)); } const newRenderStartIndex = Math.max(0, Math.floor(scrollTop / itemHeight) - bufferSize); const newRenderEndIndex = Math.min(filteredItems.length, newRenderStartIndex + visibleItemCount + bufferSize * 2); if (newRenderStartIndex !== renderStartIndex || newRenderEndIndex !== renderEndIndex) { renderStartIndex = newRenderStartIndex; renderEndIndex = newRenderEndIndex; renderVisibleItems(); } if (selectedItems.size > 0 && !isScrolling) { isScrolling = true; requestAnimationFrame(() => { updateStorageItemSelection(); isScrolling = false; }); } } function handleCopyButtonStatus(button, text) { if (button._copyTimer) clearTimeout(button._copyTimer); const originalText = button.textContent; button.textContent = '已复制'; button.classList.add('copied'); button._copyTimer = setTimeout(() => { button.textContent = originalText; button.classList.remove('copied'); button._copyTimer = null; }, 2000); } function renderVisibleItems() { const startTime = performance.now(); const needCount = renderEndIndex - renderStartIndex; while (itemPool.length < needCount) { const div = document.createElement('div'); div.className = 'virtual-scroll-item'; div.style.height = `${itemHeight}px`; div.style.position = 'absolute'; itemPool.push(div); } while (itemPool.length > needCount + 5) { const removedDiv = itemPool.pop(); if (removedDiv._item) { cachedElements.delete(removedDiv._item.shareCode + (removedDiv._item.ed2k || '')); } } const fragment = document.createDocumentFragment(); for (let i = 0; i < needCount; i++) { const idx = renderStartIndex + i; const item = filteredItems[idx]; const div = itemPool[i]; if (!item) { div.style.display = 'none'; continue; } div.style.display = ''; div.style.top = `${idx * itemHeight}px`; const itemKey = item.shareCode + (item.ed2k || ''); if (!div._item || div._item !== item) { let el; if (cachedElements.has(itemKey)) { el = cachedElements.get(itemKey).cloneNode(true); rebindEventListeners(el, item, idx); } else { el = createStorageItemElement({...item, index: idx}); const template = el.cloneNode(true); cachedElements.set(itemKey, template); } div.innerHTML = ''; div.appendChild(el); div._item = item; } const storageItem = div.querySelector('.storage-item'); if (storageItem) { storageItem.classList.toggle('selected', selectedItems.has(idx)); } fragment.appendChild(div); } storageScrollContent.innerHTML = ''; storageScrollContent.appendChild(fragment); const endTime = performance.now(); const renderTime = endTime - startTime; renderCount++; totalRenderTime += renderTime; performanceLastRenderTime = renderTime; if (renderCount % 100 === 0) { const bufferSize = Math.max(10, Math.ceil(visibleItemCount * 0.4)); console.log(`虚拟滚动性能统计: 平均渲染时间 ${(totalRenderTime / renderCount).toFixed(2)}ms, 最近渲染时间 ${renderTime.toFixed(2)}ms, 缓存命中率 ${((cachedElements.size / Math.max(1, renderCount)) * 100).toFixed(1)}%, 缓冲区域 ${bufferSize}项, 滚动速度 ${scrollSpeed.toFixed(2)}px/ms`); } } function rebindEventListeners(element, item, index) { element.dataset.index = index; const copyBtn = element.querySelector('.copy-btn'); const deleteBtn = element.querySelector('.delete-btn'); const offlineBtn = element.querySelector('.offline-btn'); const fetchBtn = element.querySelector('.fetch-btn'); const receiveBtn = element.querySelector('.receive-btn'); const openBtn = element.querySelector('.open-btn'); const noteLabel = element.querySelector('.note-label'); if (copyBtn) { copyBtn.addEventListener('click', () => { if (item.ed2k) { const text = `${item.shareTitle || '无标题'}\n${item.ed2k}`; navigator.clipboard.writeText(text).then(() => { handleCopyButtonStatus(copyBtn); }).catch(err => { console.error('复制失败:', err); }); } else { const title = item.shareTitle || '无标题'; const link = `https://115cdn.com/s/${item.shareCode}${item.password ? `?password=${item.password}` : ''}`; const text = `${link}#\n${title}`; navigator.clipboard.writeText(text).then(() => { handleCopyButtonStatus(copyBtn); }); } }); } if (deleteBtn) { deleteBtn.addEventListener('click', () => { const enableDeleteConfirm = GM_getValue('enableDeleteConfirm', true); if (enableDeleteConfirm) { if (!confirm('确定要删除该条目吗?')) return; } GM_deleteValue(generateStorageKey(item.shareCode, item.ed2k, item.magnet)); renderStorage(false); }); } if (offlineBtn) { offlineBtn.addEventListener('click', () => { const url = item.magnet || item.ed2k; const encodedUrl = encodeURIComponent(url); const apiUrl = `https://115.com/web/lixian/?ct=lixian&ac=add_task_url&url=${encodedUrl}`; setupButtonWithStatus(offlineBtn, () => { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url: apiUrl, onload: function(response) { try { const data = JSON.parse(response.responseText); if (data.state === true) { decrementQuotaLocal(); if (renderContext === 'dedupe') { rebuildDedupeGroups(); renderDedupePage(); } resolve(); } else { const errorMsg = data.error_msg || data.error || data.errtype || '离线失败'; reject(new Error(errorMsg)); } } catch (e) { reject(new Error('解析响应失败')); } }, onerror: function(error) { reject(new Error(`请求失败: ${error.statusText || '网络错误'}`)); } }); }); }, '离线成功', '离线失败'); }); } if (receiveBtn) { receiveBtn.addEventListener('click', () => { setupButtonWithStatus(receiveBtn, async () => { const { user_id } = unsafeWindow || {}; const formData = new URLSearchParams(); formData.append("user_id", user_id); formData.append("share_code", item.shareCode); formData.append("receive_code", item.password); formData.append("cid", "100115"); return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "POST", url: 'https://webapi.115.com/share/receive', headers: {'Content-Type': 'application/x-www-form-urlencoded'}, data: formData.toString(), onload: r => { try { const data = JSON.parse(r.responseText); if (data.state === true) { if (renderContext === 'dedupe') { rebuildDedupeGroups(); renderDedupePage(); } resolve(); } else { reject(new Error(data.error_msg || data.error || '接收失败')); } } catch(e) { reject(e); } }, onerror: e => reject(e) }); }); }, '接收成功', '接收失败'); }); } if (openBtn) { openBtn.addEventListener('click', () => { if (item.ed2k) { const text = item.ed2k; navigator.clipboard.writeText(text).then(() => { handleCopyButtonStatus(openBtn); }); } else { window.open(`https://115cdn.com/s/${item.shareCode}${item.password ? `?password=${item.password}` : ''}`, '_blank'); } }); } if (fetchBtn) { fetchBtn.addEventListener('click', () => { setupButtonWithStatus(fetchBtn, () => { return new Promise((resolve, reject) => { if (item.ed2k) { reject(new Error('ED2K链接无需更新')); return; } checkPasswordCorrect(item.shareCode, item.password, (isCorrect, responseData) => { if (isCorrect) { delete item.error; if (responseData?.shareTitle) item.shareTitle = responseData.shareTitle; if (responseData?.expireTime !== undefined) item.expireTime = responseData.expireTime; if (responseData?.fileSize !== undefined) item.fileSize = responseData.fileSize; if (responseData?.autoRenewal !== undefined) item.autoRenewal = String(responseData.autoRenewal); updateItemData(item.note, item.shareTitle, item.password); resolve(); } else { const rawMsg = responseData?.error || '验证失败'; const errno = responseData?.errno; const shareInfo = responseData?.rawResponse?.data?.shareinfo || {}; const shareState = shareInfo?.share_state; const isCancelledErrno = errno === 4100010; const isCancelledMsg = typeof rawMsg === 'string' && rawMsg.includes('取消'); if (errno === 4100008) { item.error = '访问码错误'; updateItemData(item.note, item.shareTitle, item.password, item.error); reject(new Error('访问码错误')); return; } if (shareState === -1 || isCancelledErrno || isCancelledMsg) { item.shareTitle = ''; item.expireTime = -1; item.fileSize = 0; item.autoRenewal = '0'; delete item.error; updateItemData(item.note, '', item.password); reject(new Error('分享已取消')); return; } if (rawMsg === '分享已过期' || rawMsg.includes('过期')) { const expireTime = shareInfo?.expire_time || -1; const fileSize = parseInt(shareInfo?.file_size || '0'); const autoRenewal = String(shareInfo?.auto_renewal || '0'); const newTitle = processShareTitle(responseData?.rawResponse || {}); item.expireTime = expireTime; item.fileSize = fileSize; item.autoRenewal = autoRenewal; if (newTitle) item.shareTitle = newTitle; item.error = shareInfo?.forbid_reason || '分享已过期'; updateItemData(item.note, item.shareTitle, item.password, item.error); reject(new Error('分享已过期')); return; } item.error = '访问码错误'; updateItemData(item.note, item.shareTitle, item.password, item.error); reject(new Error('访问码错误')); } }); }); }, '更新成功', '更新失败'); }); } element.addEventListener('click', (e) => { if (e.target.tagName === 'BUTTON' || e.target.tagName === 'INPUT' || e.target.closest('button') || e.target.closest('input')) { return; } const currentIndex = parseInt(element.dataset.index); if (e.ctrlKey) { if (selectedItems.has(currentIndex)) { selectedItems.delete(currentIndex); } else { selectedItems.add(currentIndex); } lastSelectedIndex = currentIndex; } else if (e.shiftKey && lastSelectedIndex !== -1) { const start = Math.min(lastSelectedIndex, currentIndex); const end = Math.max(lastSelectedIndex, currentIndex); for (let i = start; i <= end; i++) { selectedItems.add(i); } } else { selectedItems.clear(); selectedItems.add(currentIndex); lastSelectedIndex = currentIndex; } updateStorageItemSelection(); updateBatchActions(); }); } function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } function clearVirtualScrollCache() { cachedElements.clear(); itemPool.forEach(div => { if (div._item) { div._item = null; } }); itemPool.length = 0; if (window.gc) { window.gc(); } } function getMemoryUsage() { if (performance.memory) { const memory = performance.memory; return { used: Math.round(memory.usedJSHeapSize / 1024 / 1024), total: Math.round(memory.totalJSHeapSize / 1024 / 1024), limit: Math.round(memory.jsHeapSizeLimit / 1024 / 1024) }; } return null; } function scheduleCacheCleanup() { setInterval(() => { const memory = getMemoryUsage(); if (memory && memory.used > memory.limit * 0.8) { console.log('内存使用率过高,清理虚拟滚动缓存'); clearVirtualScrollCache(); } if (cachedElements.size > 1000) { const keys = Array.from(cachedElements.keys()); const toDelete = keys.slice(0, 500); toDelete.forEach(key => cachedElements.delete(key)); console.log(`清理了 ${toDelete.length} 个缓存元素`); } const currentTime = performance.now(); if (currentTime - lastScrollTime > 1000) { scrollSpeed = 0; } }, 30000); } function testVirtualScrollPerformance() { console.log('=== 虚拟滚动性能测试 ==='); console.log(`当前渲染范围: ${renderStartIndex} - ${renderEndIndex} (共${renderEndIndex - renderStartIndex}项)`); console.log(`可见项数量: ${visibleItemCount}`); console.log(`缓冲区域大小: ${Math.max(10, Math.ceil(visibleItemCount * 0.4))}项`); console.log(`缓存元素数量: ${cachedElements.size}`); console.log(`元素池大小: ${itemPool.length}`); console.log(`滚动速度: ${scrollSpeed.toFixed(2)}px/ms`); const memory = getMemoryUsage(); if (memory) { console.log(`内存使用: ${memory.used}MB / ${memory.total}MB (${(memory.used / memory.total * 100).toFixed(1)}%)`); } console.log(`渲染统计: 总渲染次数 ${renderCount}, 平均渲染时间 ${(totalRenderTime / Math.max(1, renderCount)).toFixed(2)}ms`); console.log('========================'); } const debouncedSearch = debounce((searchTerm) => { currentSearchTerm = searchTerm; clearVirtualScrollCache(); renderStorage(false); }, 300); function setupEditableField(displayElement, inputElement, onSave) { displayElement.addEventListener('dblclick', () => { displayElement.classList.add('storage-item-input-hidden'); inputElement.classList.remove('storage-item-input-hidden'); inputElement.classList.add('storage-item-input-visible'); inputElement.focus(); inputElement.select(); }); const handleClickOutside = (e) => { if (!inputElement.contains(e.target) && !displayElement.contains(e.target)) { const newValue = inputElement.value.trim(); if (onSave) { onSave(newValue); } displayElement.classList.remove('storage-item-input-hidden'); inputElement.classList.add('storage-item-input-hidden'); inputElement.classList.remove('storage-item-input-visible'); document.removeEventListener('click', handleClickOutside); } }; inputElement.addEventListener('focus', () => { setTimeout(() => { document.addEventListener('click', handleClickOutside); }, 0); }); inputElement.addEventListener('blur', () => { const newValue = inputElement.value.trim(); if (onSave) { onSave(newValue); } displayElement.classList.remove('storage-item-input-hidden'); inputElement.classList.add('storage-item-input-hidden'); inputElement.classList.remove('storage-item-input-visible'); document.removeEventListener('click', handleClickOutside); }); inputElement.addEventListener('keypress', (e) => { if (e.key === 'Enter') inputElement.blur(); }); } function setupButtonWithStatus(button, action, successText = '成功', errorText = '失败') { const originalText = button.textContent; button.textContent = '处理中...'; button.disabled = true; return action().then(() => { button.textContent = successText; button.style.backgroundColor = 'rgba(76,175,80,0.2)'; button.style.color = '#4caf50'; }).catch((error) => { const errorMessage = error.message || errorText; button.textContent = errorMessage.length > 8 ? errorMessage.substring(0, 8) + '...' : errorMessage; button.style.backgroundColor = 'rgba(244,67,54,0.2)'; button.style.color = '#f44336'; console.error('操作失败:', error); if (errorMessage.length > 8) { button.title = errorMessage; } }).finally(() => { setTimeout(() => { button.textContent = originalText; button.style.backgroundColor = ''; button.style.color = ''; button.disabled = false; button.title = ''; }, 2000); }); } function createStorageItemElement(item, options = {}) { const bindActions = !(options && options.bindActions === false); const renderContext = (options && options.renderContext) ? options.renderContext : 'storage'; const now = Math.floor(Date.now() / 1000); const isExpired = item.expireTime !== -1 && item.expireTime <= now; const isLongTerm = item.expireTime === -1; const isTimeLimited = item.expireTime !== -1 && !isExpired; const isCancelled = item.expireTime === -1 && item.fileSize === 0 && item.shareTitle === ''; const isEd2k = item.ed2k && item.ed2k !== ''; const isMagnet = item.magnet && item.magnet !== ''; const hasError = item.error; let expireDisplay = ''; if (hasError) { const isExpiredError = item.error === "分享已过期" || item.error === "链接已过期"; const isCancelledError = item.error === "分享已取消"; if (isExpiredError) { expireDisplay = '已过期'; } else if (isCancelledError) { expireDisplay = '已取消分享'; } else { if (isLongTerm) { expireDisplay = '长期访问码错误'; } else if (item.autoRenewal === '1') { expireDisplay = '自动续期访问码错误'; } else if (isExpired) { expireDisplay = '已过期访问码错误'; } else if (isTimeLimited) { expireDisplay = '限时访问码错误'; } else { expireDisplay = '访问码错误'; } } } else if (isCancelled) { expireDisplay = '已取消分享'; } else if (isLongTerm) { expireDisplay = '长期' + (item.autoRenewal === '1' ? '自动续期' : ''); } else if (item.autoRenewal === '1') { expireDisplay = '自动续期'; } else if (isExpired) { expireDisplay = '已过期'; } else if (isTimeLimited) { const remainingSeconds = item.expireTime - now; expireDisplay = `${formatTime(remainingSeconds)}`; } const fileSizeDisplay = item.fileSize ? `${formatFileSize(item.fileSize)}` : ''; const ed2kTag = isEd2k ? 'ED2K' : ''; const magnetTag = isMagnet ? '磁力链' : ''; const itemElement = document.createElement('div'); itemElement.className = 'storage-item'; itemElement.dataset.index = item.index || 0; if (item.ed2k) { const ed2kMatch = item.ed2k.match(/ed2k:\/\/\|file\|([^|]+)\|(\d+)\|([0-9A-F]{32})(?:\|h=([^|]+))?(\||\/)?/i); const ed2kTitle = ed2kMatch ? decodeURIComponent(ed2kMatch[1]) : 'ED2K文件'; const ed2kHash = ed2kMatch ? ed2kMatch[3] : ''; itemElement.innerHTML = `
${fileSizeDisplay}${ed2kTag}${ed2kTitle}
${item.ed2k || ''}
备注: ${item.note || '无备注'}
`; const ed2kDisplay = itemElement.querySelector('.ed2k-display'); const ed2kInput = itemElement.querySelector('.storage-item-ed2k-input'); setupEditableField(ed2kDisplay, ed2kInput, (newEd2k) => { const newEd2kMatch = newEd2k.match(/ed2k:\/\/\|file\|([^|]+)\|(\d+)\|([0-9A-F]{32})(?:\|h=([^|]+))?(\||\/)?/i); if (newEd2kMatch) { const newHash = newEd2kMatch[3]; const oldHash = item.shareCode; if (newHash !== oldHash) { GM_deleteValue(generateStorageKey(oldHash, item.ed2k)); if (renderContext === 'dedupe') { saveToStorage(newHash, item.password, item.note, item.shareTitle, item.expireTime, item.fileSize, item.autoRenewal, newEd2k, '', '', false, true); rebuildDedupeGroups(); renderDedupePage(); } else { saveToStorage(newHash, item.password, item.note, item.shareTitle, item.expireTime, item.fileSize, item.autoRenewal, newEd2k); } } else { if (renderContext === 'dedupe') { saveToStorage(item.shareCode, item.password, item.note, item.shareTitle, item.expireTime, item.fileSize, item.autoRenewal, newEd2k, '', '', false, true); rebuildDedupeGroups(); renderDedupePage(); } else { saveToStorage(item.shareCode, item.password, item.note, item.shareTitle, item.expireTime, item.fileSize, item.autoRenewal, newEd2k); } } ed2kDisplay.textContent = newEd2k; } else { ed2kInput.value = item.ed2k; alert('ED2K链接格式不正确,请检查后重试'); } }); const titleDisplay = itemElement.querySelector('.title-value'); const titleInput = itemElement.querySelector('.storage-item-title-input'); setupEditableField(titleDisplay, titleInput, (newTitle) => { titleDisplay.textContent = newTitle || '无标题'; titleDisplay.title = newTitle || '无标题'; updateItemData(item.note, newTitle); }); } else if (item.magnet) { const magnetMatch = item.magnet.match(/magnet:\?xt=urn:btih:([a-fA-F0-9]{40})/i); const magnetHash = magnetMatch ? magnetMatch[1] : ''; let magnetName = '磁力链文件'; const nameMatch = item.magnet.match(/[?&]name=([^&]+)/i); if (nameMatch) { try { magnetName = decodeURIComponent(nameMatch[1]); } catch (e) { magnetName = nameMatch[1]; } } else { const dnMatch = item.magnet.match(/[?&]dn=([^&]+)/i); if (dnMatch) { try { magnetName = decodeURIComponent(dnMatch[1]); } catch (e) { magnetName = dnMatch[1]; } } } const displayName = item.shareTitle || item.note || magnetName; const linkType = 'magnet'; const linkDisplay = 'magnet-display'; const linkInput = 'storage-item-magnet-input'; const linkValue = item.magnet || ''; itemElement.innerHTML = `
${magnetTag}${displayName}
${linkValue}
备注: ${item.note || '无备注'}
`; const magnetDisplay = itemElement.querySelector('.magnet-display'); const magnetInput = itemElement.querySelector('.storage-item-magnet-input'); setupEditableField(magnetDisplay, magnetInput, (newMagnet) => { const newMagnetMatch = newMagnet.match(/magnet:\?xt=urn:btih:([a-fA-F0-9]{40})/i); if (newMagnetMatch) { const newHash = newMagnetMatch[1]; const oldHash = item.shareCode; let newName = ''; const nameMatch = newMagnet.match(/[?&]name=([^&]+)/i); if (nameMatch) { try { newName = decodeURIComponent(nameMatch[1]); } catch (e) { newName = nameMatch[1]; } } else { const dnMatch = newMagnet.match(/[?&]dn=([^&]+)/i); if (dnMatch) { try { newName = decodeURIComponent(dnMatch[1]); } catch (e) { newName = dnMatch[1]; } } } if (newHash !== oldHash) { GM_deleteValue(generateStorageKey(oldHash, item.ed2k, item.magnet)); if (renderContext === 'dedupe') { saveToStorage(newHash, item.password, item.note, item.shareTitle, item.expireTime, item.fileSize, item.autoRenewal, item.ed2k, newMagnet, '', false, true); rebuildDedupeGroups(); renderDedupePage(); } else { saveToStorage(newHash, item.password, item.note, item.shareTitle, item.expireTime, item.fileSize, item.autoRenewal, item.ed2k, newMagnet); } } else { if (renderContext === 'dedupe') { saveToStorage(item.shareCode, item.password, item.note, item.shareTitle, item.expireTime, item.fileSize, item.autoRenewal, item.ed2k, newMagnet, '', false, true); rebuildDedupeGroups(); renderDedupePage(); } else { saveToStorage(item.shareCode, item.password, item.note, item.shareTitle, item.expireTime, item.fileSize, item.autoRenewal, item.ed2k, newMagnet); } } magnetDisplay.textContent = newMagnet; } else { magnetInput.value = item.magnet; alert('磁力链格式不正确,请检查后重试'); } }); const titleDisplay = itemElement.querySelector('.title-value'); const titleInput = itemElement.querySelector('.storage-item-title-input'); setupEditableField(titleDisplay, titleInput, (newTitle) => { titleDisplay.textContent = newTitle || '无标题'; titleDisplay.title = newTitle || '无标题'; updateItemData(item.note, newTitle); }); const noteDisplay = itemElement.querySelector('.note-display'); const noteInput = itemElement.querySelector('.storage-item-note-input'); setupEditableField(noteDisplay, noteInput, (newNote) => { noteDisplay.textContent = newNote || '无备注'; updateItemData(newNote, item.shareTitle); }); } else { itemElement.innerHTML = `
${fileSizeDisplay}${item.shareTitle || '无标题'}
分享码: ${item.shareCode} 访问码: ${item.password} ${expireDisplay}
${(!isEd2k && !isMagnet) ? '' : ''}
备注: ${item.note || '无备注'}
`; } const copyBtn = itemElement.querySelector('.copy-btn'); const offlineBtn = itemElement.querySelector('.offline-btn'); const fetchBtn = itemElement.querySelector('.fetch-btn'); const receiveBtn = itemElement.querySelector('.receive-btn'); const openBtn = itemElement.querySelector('.open-btn'); const deleteBtn = itemElement.querySelector('.delete-btn'); const noteLabel = itemElement.querySelector('.note-label'); const noteDisplay = itemElement.querySelector('.note-display'); const noteInput = itemElement.querySelector('.storage-item-note-input'); const passwordDisplay = itemElement.querySelector('.password-value'); const passwordInput = itemElement.querySelector('.storage-item-password-input'); const copyStatus = itemElement.querySelector('.note-copy-status'); const titleDisplay = itemElement.querySelector('.title-value'); const titleInput = itemElement.querySelector('.storage-item-title-input'); if (offlineBtn) { offlineBtn.addEventListener('click', () => { const url = item.magnet || item.ed2k; const encodedUrl = encodeURIComponent(url); const apiUrl = `https://115.com/web/lixian/?ct=lixian&ac=add_task_url&url=${encodedUrl}`; setupButtonWithStatus(offlineBtn, () => { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url: apiUrl, onload: function(response) { try { const data = JSON.parse(response.responseText); if (data.state === true) { decrementQuotaLocal(); resolve(); } else { const errorMsg = data.error_msg || data.error || data.errtype || '离线失败'; reject(new Error(errorMsg)); } } catch (e) { reject(new Error('解析响应失败')); } }, onerror: function(error) { reject(new Error(`请求失败: ${error.statusText || '网络错误'}`)); } }); }); }, '离线成功', '离线失败'); }); } if (receiveBtn) { receiveBtn.addEventListener('click', () => { setupButtonWithStatus(receiveBtn, async () => { const { user_id } = unsafeWindow || {}; const formData = new URLSearchParams(); formData.append("user_id", user_id); formData.append("share_code", item.shareCode); formData.append("receive_code", item.password); formData.append("cid", "100115"); return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "POST", url: 'https://webapi.115.com/share/receive', headers: {'Content-Type': 'application/x-www-form-urlencoded'}, data: formData.toString(), onload: r => { try { const data = JSON.parse(r.responseText); if (data.state === true) { resolve(); } else { reject(new Error(data.error_msg || data.error || '接收失败')); } } catch(e) { reject(e); } }, onerror: e => reject(e) }); }); }, '接收成功', '接收失败'); }); } if (bindActions) { copyBtn.addEventListener('click', () => { const enableMagnetTitleCopy = GM_getValue('enableMagnetTitleCopy', false); if (item.magnet) { let magnetToCopy; if (enableMagnetTitleCopy && (item.shareTitle || item.note)) { const title = item.shareTitle || item.note; magnetToCopy = `${title}\n${item.magnet}`; } else { magnetToCopy = item.magnet; if (!item.magnet.includes('?name=') && (item.shareTitle || item.note)) { const title = item.shareTitle || item.note; magnetToCopy = `${item.magnet}?name=${title}`; } } navigator.clipboard.writeText(magnetToCopy).then(() => { handleCopyButtonStatus(copyBtn); }); } else if (item.ed2k) { const text = `${item.shareTitle || '无标题'}\n${item.ed2k}`; navigator.clipboard.writeText(text).then(() => { handleCopyButtonStatus(copyBtn); }); } else { const title = item.shareTitle || '无标题'; const link = `https://115cdn.com/s/${item.shareCode}${item.password ? `?password=${item.password}` : ''}`; const enableShareTitleCopy = GM_getValue('enableShareTitleCopy', false); let text; if (enableShareTitleCopy && title) { text = `${title}\n${link}`; } else { text = `${link}#\n${title}`; } navigator.clipboard.writeText(text).then(() => { handleCopyButtonStatus(copyBtn); }); } }); } if (bindActions && fetchBtn) { fetchBtn.addEventListener('click', () => { setupButtonWithStatus(fetchBtn, () => { return new Promise((resolve, reject) => { checkPasswordCorrect(item.shareCode, item.password, (isCorrect, responseData) => { if (isCorrect) { delete item.error; if (responseData?.shareTitle) item.shareTitle = responseData.shareTitle; if (responseData?.expireTime !== undefined) item.expireTime = responseData.expireTime; if (responseData?.fileSize !== undefined) item.fileSize = responseData.fileSize; if (responseData?.autoRenewal !== undefined) item.autoRenewal = String(responseData.autoRenewal); updateItemData(item.note, item.shareTitle, item.password); resolve(); } else { const rawMsg = responseData?.error || '验证失败'; const errno = responseData?.errno; const shareInfo = responseData?.rawResponse?.data?.shareinfo || {}; const shareState = shareInfo?.share_state; const isCancelledErrno = errno === 4100010; const isCancelledMsg = typeof rawMsg === 'string' && rawMsg.includes('取消'); if (errno === 4100008) { item.error = '访问码错误'; updateItemData(item.note, item.shareTitle, item.password, item.error); reject(new Error('访问码错误')); return; } if (shareState === -1 || isCancelledErrno || isCancelledMsg) { delete item.error; item.shareTitle = ''; item.expireTime = -1; item.fileSize = 0; item.autoRenewal = '0'; updateItemData(item.note, '', item.password); reject(new Error('分享已取消')); return; } if (rawMsg === '分享已过期' || rawMsg.includes('过期')) { const expireTime = shareInfo?.expire_time || -1; const fileSize = parseInt(shareInfo?.file_size || '0'); const autoRenewal = String(shareInfo?.auto_renewal || '0'); const newTitle = processShareTitle(responseData?.rawResponse || {}); item.expireTime = expireTime; item.fileSize = fileSize; item.autoRenewal = autoRenewal; if (newTitle) item.shareTitle = newTitle; item.error = shareInfo?.forbid_reason || '分享已过期'; updateItemData(item.note, item.shareTitle, item.password, item.error); reject(new Error('分享已过期')); return; } item.error = '访问码错误'; updateItemData(item.note, item.shareTitle, item.password, item.error); reject(new Error('访问码错误')); } }); }); }, '获取成功', '获取失败'); }); } if (bindActions && openBtn) { openBtn.addEventListener('click', () => { if (item.magnet) { navigator.clipboard.writeText(item.magnet).then(() => { handleCopyButtonStatus(openBtn); }); } else if (item.ed2k) { navigator.clipboard.writeText(item.ed2k).then(() => { handleCopyButtonStatus(openBtn); }); } else { window.open(`https://115cdn.com/s/${item.shareCode}?password=${item.password}`, '_blank'); } }); } noteLabel.addEventListener('dblclick', () => { if (!item.ed2k && !isCancelled) { copyStatus.textContent = '处理中...'; copyStatus.style.display = 'inline'; checkPasswordCorrect(item.shareCode, item.password, (isCorrect, responseData) => { if (isCorrect && responseData) { const newNote = `${responseData.shareTitle || '无标题'}`; noteDisplay.textContent = newNote; noteInput.value = newNote; updateItemData(newNote); copyStatus.textContent = '已完成'; setTimeout(() => { copyStatus.style.display = 'none'; }, 2000); } else { copyStatus.style.display = 'none'; } }); } }); function updateItemData(newNote = item.note, newTitle = item.shareTitle, newPassword = item.password, newError = item.error) { const params = [ item.shareCode, newPassword, newNote || '', newTitle || '', item.expireTime, item.fileSize, item.autoRenewal, item.ed2k, item.magnet, newError ]; if (renderContext === 'dedupe') { saveToStorage(...params, true, true); rebuildDedupeGroups(); renderDedupePage(); } else { updateStorageItem(...params); } } setupEditableField(noteDisplay, noteInput, (newNote) => { noteDisplay.textContent = newNote || '无备注'; updateItemData(newNote); }); if (passwordDisplay && passwordInput) { setupEditableField(passwordDisplay, passwordInput, (newPassword) => { if (newPassword.length === 4 && /^[0-9a-zA-Z]+$/.test(newPassword)) { passwordDisplay.textContent = newPassword; updateItemData(item.note, item.shareTitle, newPassword); } else { passwordDisplay.textContent = item.password; passwordInput.value = item.password; } }); passwordInput.addEventListener('input', (e) => { passwordInput.value = passwordInput.value.replace(/[^0-9a-zA-Z]/g, ''); if (passwordInput.value.length > 4) passwordInput.value = passwordInput.value.slice(0, 4); }); } if (titleDisplay && titleInput) { setupEditableField(titleDisplay, titleInput, (newTitle) => { titleDisplay.textContent = newTitle || '无标题'; titleDisplay.title = newTitle || '无标题'; updateItemData(item.note, newTitle); }); } if (bindActions) { deleteBtn.addEventListener('click', () => { const enableDeleteConfirm = GM_getValue('enableDeleteConfirm', true); if (enableDeleteConfirm) { if (!confirm('确定要删除该条目吗?')) return; } GM_deleteValue(generateStorageKey(item.shareCode, item.ed2k, item.magnet)); if (renderContext === 'dedupe') { rebuildDedupeGroups(); renderDedupePage(); } else { renderStorage(false); } }); } if (bindActions) { itemElement.addEventListener('click', (e) => { if (e.target.tagName === 'BUTTON' || e.target.tagName === 'INPUT' || e.target.closest('button') || e.target.closest('input')) { return; } const currentIndex = parseInt(itemElement.dataset.index); if (e.ctrlKey) { if (selectedItems.has(currentIndex)) { selectedItems.delete(currentIndex); } else { selectedItems.add(currentIndex); } lastSelectedIndex = currentIndex; } else if (e.shiftKey && lastSelectedIndex !== -1) { const start = Math.min(lastSelectedIndex, currentIndex); const end = Math.max(lastSelectedIndex, currentIndex); for (let i = start; i <= end; i++) { selectedItems.add(i); } } else { selectedItems.clear(); selectedItems.add(currentIndex); lastSelectedIndex = currentIndex; } updateStorageItemSelection(); updateBatchActions(); }); } const allInputs = itemElement.querySelectorAll('input[type="text"], input[type="password"], input[type="number"]'); allInputs.forEach(input => { input.addEventListener('blur', (e) => { setTimeout(() => { if (input.style.display !== 'none' && input.style.display !== '') { const displayElement = input.previousElementSibling; if (displayElement && displayElement.classList.contains('storage-item-title')) { displayElement.style.display = 'inline'; input.style.display = 'none'; } } }, 10); }); }); return itemElement; } function updateStorageItemSelection() { const virtualScrollItems = document.querySelectorAll('.virtual-scroll-item'); virtualScrollItems.forEach((virtualItem) => { const storageItem = virtualItem.querySelector('.storage-item'); if (storageItem) { const index = parseInt(storageItem.dataset.index); if (selectedItems.has(index)) { storageItem.classList.add('selected'); } else { storageItem.classList.remove('selected'); } } }); } function updateDedupeItemSelection() { const dedupeContent = document.querySelector('.storage-tab-content[data-tab-content="dedupe"]'); if (!dedupeContent) return; const items = dedupeContent.querySelectorAll('.virtual-scroll-item .storage-item'); items.forEach((el) => { const key = el?.dataset?.key; if (!key) return; if (dedupeSelectedItems.has(key)) el.classList.add('selected'); else el.classList.remove('selected'); }); try { updateBatchActions(); } catch (_) {} } function updateBatchActions() { const activeContent = document.querySelector('.storage-tab-content.active'); if (!activeContent) return; const container = activeContent.querySelector('.batch-actions-container'); const countSpan = container?.querySelector('.selected-count'); const batchCopyBtn = container?.querySelector('.copy-btn'); const batchDeleteBtn = container?.querySelector('.delete-btn'); const batchCancelBtn = container?.querySelector('.cancel-btn'); const helpBtn = container?.querySelector('.selected-help-btn'); const hintBox = container?.querySelector('.multi-select-hint'); const isDedupe = activeContent.getAttribute('data-tab-content') === 'dedupe'; const count = isDedupe ? dedupeSelectedItems.size : selectedItems.size; if (count > 0) { if (container) container.classList.add('has-selection'); if (countSpan) { countSpan.textContent = `已选 ${count} 项`; countSpan.style.display = 'inline-block'; } if (helpBtn) helpBtn.style.display = 'none'; if (hintBox) hintBox.style.display = 'none'; if (batchCopyBtn) batchCopyBtn.style.display = 'inline-block'; if (batchDeleteBtn) batchDeleteBtn.style.display = 'inline-block'; if (batchCancelBtn) batchCancelBtn.style.display = 'inline-block'; } else { if (container) container.classList.remove('has-selection'); if (countSpan) { countSpan.textContent = '已选 0 项'; countSpan.style.display = 'none'; } if (helpBtn) helpBtn.style.display = 'inline-flex'; if (batchCopyBtn) batchCopyBtn.style.display = 'none'; if (batchDeleteBtn) batchDeleteBtn.style.display = 'none'; if (batchCancelBtn) batchCancelBtn.style.display = 'none'; if (hintBox && helpBtn && container) { if (!helpBtn._bound) { helpBtn.addEventListener('click', (e) => { e.stopPropagation(); hintBox.style.display = hintBox.style.display === 'none' || hintBox.style.display === '' ? 'block' : 'none'; }); hintBox.addEventListener('click', (e) => { e.stopPropagation(); }); document.addEventListener('click', (e) => { if (!hintBox.contains(e.target) && e.target !== helpBtn && !helpBtn.contains(e.target)) { hintBox.style.display = 'none'; } }); document.addEventListener('keydown', (e) => { if (e.key === 'Escape') { hintBox.style.display = 'none'; } }); helpBtn._bound = true; } } } } function extractFileNameFromEd2k(ed2k) { if (!ed2k) return ''; const match = ed2k.match(/ed2k:\/\/\|file\|([^|]+)\|/); return match ? decodeURIComponent(match[1]) : ''; } function batchCopySelected() { const items = filteredItems; const selectedItemsList = Array.from(selectedItems).map(index => items[index]).filter(Boolean); if (selectedItemsList.length === 0) return; const enableMagnetTitleCopy = GM_getValue('enableMagnetTitleCopy', false); const copyText = selectedItemsList.map(item => { if (item.magnet) { if (enableMagnetTitleCopy && (item.shareTitle || item.note)) { const title = item.shareTitle || item.note; return `${title}\n${item.magnet}`; } else { let magnetToCopy = item.magnet; if (!item.magnet.includes('?name=') && (item.shareTitle || item.note)) { const title = item.shareTitle || item.note; magnetToCopy = `${item.magnet}?name=${title}`; } return magnetToCopy; } } else if (item.ed2k) { return item.ed2k; } else { const shareUrl = `https://115cdn.com/s/${item.shareCode}`; const password = item.password || ''; const title = item.shareTitle || item.note || ''; const fullUrl = `${shareUrl}${password ? `?password=${password}` : ''}`; const enableShareTitleCopy = GM_getValue('enableShareTitleCopy', false); if (enableShareTitleCopy && title) { return `${title}\n${fullUrl}`; } else { return title ? `${fullUrl}#\n${title}` : fullUrl; } } }).join('\n\n'); navigator.clipboard.writeText(copyText).then(() => { const batchCopyBtn = document.querySelector('.batch-actions-container .copy-btn'); if (batchCopyBtn) { const originalText = batchCopyBtn.textContent; const originalBackground = batchCopyBtn.style.backgroundColor; batchCopyBtn.textContent = '已复制'; batchCopyBtn.style.backgroundColor = '#4caf50'; batchCopyBtn.style.color = 'white'; setTimeout(() => { batchCopyBtn.textContent = originalText; batchCopyBtn.style.backgroundColor = originalBackground; batchCopyBtn.style.color = 'white'; }, 2000); } }).catch(err => { console.error('复制失败:', err); const batchCopyBtn = document.querySelector('.batch-actions-container .copy-btn'); if (batchCopyBtn) { const originalText = batchCopyBtn.textContent; const originalBackground = batchCopyBtn.style.backgroundColor; batchCopyBtn.textContent = '复制失败'; batchCopyBtn.style.backgroundColor = '#f44336'; batchCopyBtn.style.color = 'white'; setTimeout(() => { batchCopyBtn.textContent = originalText; batchCopyBtn.style.backgroundColor = originalBackground; batchCopyBtn.style.color = 'white'; }, 2000); } }); } function batchCancelSelected() { selectedItems.clear(); lastSelectedIndex = -1; updateStorageItemSelection(); updateBatchActions(); } function batchDeleteSelected() { const items = filteredItems; const selectedItemsList = Array.from(selectedItems).map(index => items[index]).filter(Boolean); if (selectedItemsList.length === 0) return; const enableDeleteConfirm = GM_getValue('enableDeleteConfirm', true); if (enableDeleteConfirm) { if (!confirm(`确定要删除选中的 ${selectedItemsList.length} 个项目吗?`)) return; } selectedItemsList.forEach(item => { GM_deleteValue(generateStorageKey(item.shareCode, item.ed2k, item.magnet)); }); selectedItems.clear(); lastSelectedIndex = -1; renderStorage(false); } function batchCancelSelectedDedupe() { dedupeSelectedItems.clear(); dedupeLastListRef = null; dedupeLastIndex = -1; updateDedupeItemSelection(); updateBatchActions(); } function batchDeleteSelectedDedupe() { const list = Array.from(dedupeSelectedItems); if (list.length === 0) return; const enableDeleteConfirm = GM_getValue('enableDeleteConfirm', true); if (enableDeleteConfirm) { if (!confirm(`确定要删除选中的 ${list.length} 个项目吗?`)) return; } for (const key of list) { const info = dedupeKeyMap.get(key); if (!info) continue; try { GM_deleteValue(generateStorageKey(info.shareCode, info.ed2k, info.magnet)); } catch (_) {} } dedupeSelectedItems.clear(); dedupeLastListRef = null; dedupeLastIndex = -1; rebuildDedupeGroups(); renderDedupePage(); } function batchCopySelectedDedupe() { const list = Array.from(dedupeSelectedItems).map(k => dedupeKeyMap.get(k)).filter(Boolean); if (list.length === 0) return; const enableMagnetTitleCopy = GM_getValue('enableMagnetTitleCopy', false); const enableShareTitleCopy = GM_getValue('enableShareTitleCopy', false); const text = list.map(info => { if (info.magnet) { return info.magnet; } else if (info.ed2k) { return info.ed2k; } else { const shareUrl = `https://115cdn.com/s/${info.shareCode}`; return shareUrl; } }).join('\n\n'); navigator.clipboard.writeText(text).then(() => { const activeContent = document.querySelector('.storage-tab-content.active'); const btn = activeContent?.querySelector('.batch-actions-container .copy-btn'); if (!btn) return; const originalText = btn.textContent; const originalBg = btn.style.backgroundColor; btn.textContent = '已复制'; btn.style.backgroundColor = '#4caf50'; btn.style.color = 'white'; setTimeout(() => { btn.textContent = originalText; btn.style.backgroundColor = originalBg; btn.style.color = 'white'; }, 2000); }).catch(() => {}); } function getShareCode() { const url = window.location.href; const match = url.match(/115cdn\.com\/s\/([a-z0-9]+)/); return match ? match[1] : ''; } function getPasswordFromUrl() { const url = window.location.href; const passwordMatch = url.match(/[?&]password=([^&#]*)/); return passwordMatch ? decodeURIComponent(passwordMatch[1]) : ''; } function checkCurrentUrlPassword() { const shareCode = getShareCode(); const password = getPasswordFromUrl(); if (shareCode && password) { try { autoFillPassword(password); } catch (e) {} checkPasswordCorrect(shareCode, password, (isCorrect, data) => { if (isCorrect) { saveToStorage(shareCode, password, '', data?.shareTitle, data?.expireTime, data?.fileSize, data?.autoRenewal, ''); try { applySuccessUI(password); } catch (e) {} try { __verifiedOK = true; __verificationCompleted = true; ensureErrorObserver(); suppressAccessCodeErrors(document); } catch (e) {} try { setTimeout(() => { try { fetchShareInfo(); } catch (e) {} }, 600); } catch (e) {} } }); } } async function getUserNameByUserId(userId) { if (!userId || userId === '未知') { return '未知'; } try { console.log(`正在获取用户ID ${userId} 的名称...`); const response = await new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url: `https://pmsg.115.com/api/1.0/web/1.0/friend/find?find_str=${userId}`, onload: r => { try { console.log(`API响应状态: ${r.status}, 响应内容:`, r.responseText); const data = JSON.parse(r.responseText); resolve(data); } catch(e) { console.error('解析API响应失败:', e); reject(e); } }, onerror: e => { console.error('API请求失败:', e); reject(e); } }); }); console.log('API响应数据:', response); if (response.state && response.data && response.data.length > 0) { const userName = response.data[0].friend_name || '未知'; console.log(`获取到用户名称: ${userName}`); return userName; } else { console.log('API返回数据为空或格式不正确'); return '未知'; } } catch (error) { console.error('获取用户名称失败:', error); return '未知'; } } async function fetchShareInfo() { shareInfo.shareCode = getShareCode(); if (__lastShareCode !== shareInfo.shareCode) { __lastShareCode = shareInfo.shareCode; __verificationCompleted = false; __verifiedOK = false; __autoConfirm = { key: null, inProgress: false, done: false }; __verifiedPassword = null; } if (!shareInfo.shareCode) { shareDetails.innerHTML = '当前URL不是有效的115分享链接'; return; } const apiUrl = `https://115cdn.com/webapi/share/snap?share_code=${shareInfo.shareCode}`; GM_xmlhttpRequest({ method: 'GET', url: apiUrl, onload: async function(response) { try { const data = JSON.parse(response.responseText); const showOwner = GM_getValue('enableShareOwnerInfo', false); const shareState = data?.data?.shareinfo?.state; if (data.state === false) { const errorMsg = data.error || '未知错误'; const userId = showOwner ? (data.data?.userinfo?.user_id || '未知') : ''; const face = showOwner ? (data.data?.userinfo?.face || '') : ''; const userName = showOwner ? await getUserNameByUserId(userId) : ''; shareDetails.innerHTML = `