diff --git a/sa-token-doc/doc.html b/sa-token-doc/doc.html
index 07cfb0eb..b45ed643 100644
--- a/sa-token-doc/doc.html
+++ b/sa-token-doc/doc.html
@@ -152,6 +152,7 @@
+
diff --git a/sa-token-doc/static/is-star-plugin.js b/sa-token-doc/static/is-star-plugin.js
new file mode 100644
index 00000000..15c2f1f9
--- /dev/null
+++ b/sa-token-doc/static/is-star-plugin.js
@@ -0,0 +1,218 @@
+//
+
+// 声明 docsify 插件
+var isStarPlugin = function(hook, vm) {
+
+ // 切换文档的次数,每隔固定次数检测一下
+ let changePage = -1;
+
+ // 钩子函数:解析之前执行
+ hook.beforeEach(function(content) {
+ return content;
+ });
+
+ // 钩子函数:每次路由切换时,解析内容之后执行
+ hook.afterEach(function(html) {
+ changePage++;
+ if(changePage % 15 === 0) {
+ isStarRepo();
+ }
+ return html;
+ });
+
+ // 每钩子函数:次路由切换时数据全部加载完成后调用,没有参数。
+ hook.doneEach(function() {
+
+ });
+
+ // 钩子函数:初始化并第一次加载完成数据后调用,没有参数。
+ hook.ready(function() {
+
+ });
+
+}
+
+// 应用参数
+const client_id = '0cc618beb08db99bff50e500e38c2144d95ada9abb51c00c44592726ecd583f4';
+const client_secret = '2574c2aac8ce2142e34752dc5957dddcb30bc68df5c61de64251a3a6b11a51e5';
+// const redirect_uri = 'http://local.dev33.cn:8848/sa-token-doc/doc.html';
+const redirect_uri = 'https://sa-token.cc/doc.html';
+// const docDomain = 'local.dev33.cn:8848';
+const docDomain = 'sa-token.cc';
+
+// 检查成功后,多少天不再检查
+const allowDisparity = 1000 * 60 * 60 * 24 * 30;
+// const allowDisparity = 1000 * 10;
+
+
+// 判断当前是否已 star
+function isStarRepo() {
+ // 非PC端不检查
+ if(document.body.offsetWidth < 800) {
+ console.log('small screen ...');
+ return;
+ }
+
+ // 判断是否在主域名下
+ if(location.host !== docDomain) {
+ console.log('非主域名,不检测...');
+ return;
+ }
+
+ // 判断是否近期已经判断过了
+ try{
+ const isStarRepo = localStorage.isStarRepo;
+ if(isStarRepo) {
+ // 记录 star 的时间,和当前时间的差距
+ const disparity = new Date().getTime() - parseInt(isStarRepo);
+
+ // 差距小于一月,不再检测,大于一月,再检测一下
+ if(disparity < allowDisparity) {
+ console.log('checked ...');
+ return;
+ }
+ }
+ }catch(e){
+ console.error(e);
+ }
+
+ // 开始获取 code
+ getCode();
+}
+
+// 去请求授权
+function getCode() {
+
+ // 检查url中是否有code
+ const code = getParam('code');
+ if(code) {
+ // 有 code,进一步去请求 access_token
+ getAccessToken(code);
+ } else {
+ // 不存在code,弹窗提示询问
+ confirmStar();
+ }
+}
+
+// 弹窗提示点 star
+function confirmStar() {
+
+ // 弹窗提示文字
+ let tipStr = "
嗨,同学,来支持一下 Sa-Token 吧,为项目点个 star !
";
+ tipStr += "仅需两步即可完成:
" +
+ '
1、打开 Sa-Token
开源仓库主页,在右上角点个 star 。
' +
+ '
2、点击下方 [ 同意授权检测 ] 按钮,同意 Sa-Token 获取 API 权限进行检测。
?' +
+ "
";
+ tipStr += "不点也没关系 ❤️ ❤️ ❤️,Sa-Token 将努力变得更加完善!😇
";
+ tipStr = '' + tipStr + '
'
+ layer.confirm(tipStr, {title: '提示', btn: ['同意授权检测', '暂时不要,我先看看文档'], area: '450px', offset: '20%'}, function(index) {
+ //
+ layer.close(index);
+ // 用户点了确认,去 gitee 官方请求授权获取
+ goAuth();
+ });
+}
+
+
+// 跳转到 gitee 授权界面
+function goAuth() {
+ const authUrl = "https://gitee.com/oauth/authorize" +
+ "?client_id=" + client_id +
+ "&redirect_uri=" + redirect_uri +
+ "&response_type=code" +
+ "&scope=projects";
+ location.href = authUrl;
+}
+
+
+// 获取 access_token
+function getAccessToken(code) {
+ // 根据 code 获取 access_token
+ $.ajax({
+ url: 'https://gitee.com/oauth/token',
+ method: 'post',
+ data: {
+ grant_type: 'authorization_code',
+ code: code,
+ client_id: client_id,
+ redirect_uri: redirect_uri,
+ client_secret: client_secret,
+ },
+ success: function(res) {
+ // 拿到 access_token
+ const access_token = res.access_token;
+
+ // 根据 access_token 判断是否 star 了仓库
+ $.ajax({
+ url: 'https://gitee.com/api/v5/user/starred/dromara/sa-token',
+ method: 'get',
+ data: {
+ access_token: access_token
+ },
+ success: function(res) {
+ // success 回调即代表已经 star,gitee API 请求体不返回任何数据
+ console.log('-> stared ...');
+ // 记录本次检查时间
+ localStorage.isStarRepo = new Date().getTime();
+ //
+ layer.alert('感谢你的支持 ❤️ ❤️ ❤️ ,Sa-Token 将努力变得更加完善!', function(index) {
+ layer.close(index);
+ // 刷新url,去掉 code 参数
+ location.href = location.href.replace("?code=" + code, '');
+ })
+ },
+ error: function(e) {
+ // console.log('ff请求错误 ', e);
+ // 如下返回,代表没有 star
+ if(e.statusText = 'Not Found'){
+ console.log('not star ...');
+ layer.alert('未检测到 star 数据...', function() {
+ // 刷新url,去掉 code 参数
+ location.href = location.href.replace("?code=" + code, '');
+ });
+ }
+ }
+ });
+
+ },
+ error: function(e) {
+ console.log('请求错误 ', e);
+ // 无效授权,可能是 code 无效
+ if(e.responseJSON.error == 'invalid_grant') {
+ console.log('无效code', code);
+ }
+ layer.alert('check error...' + e.responseJSON.error, function(index) {
+ layer.close(index);
+ // 刷新url,去掉 code 参数
+ let url = location.href.replace("?code=" + code, '');
+ url = url.replace("&code=" + code, '');
+ location.href = url;
+ });
+ // 一天内不再检查,否则容易引起无限重定向
+ // const ygTime = allowDisparity - (1000 * 60 * 60 * 24);
+ // localStorage.isStarRepo = new Date().getTime() - ygTime;
+ // // 刷新url,去掉 code 参数
+ // location.href = location.href.replace("?code=" + code, '');
+ }
+ })
+}
+
+
+// 疑问
+function authDetails() {
+ const str = "用于检测的凭证信息将仅保存你的浏览器本地,不发往任何第三方服务器,Sa-Token 文档已完整开源,源码可查";
+ alert(str);
+}
+
+
+// 获取 url 携带的参数
+function getParam(name, defaultValue){
+ var query = window.location.search.substring(1);
+ var vars = query.split("&");
+ for (var i=0;i