Index.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. <?php
  2. namespace app\controller\admin;
  3. use app\BaseController;
  4. use app\model\CardModel;
  5. use app\model\LinkStoreModel;
  6. use app\model\SettingModel;
  7. use app\model\UserModel;
  8. use DateInterval;
  9. use DatePeriod;
  10. use DateTime;
  11. use think\facade\Cache;
  12. use think\facade\Db;
  13. //use Upgrade;
  14. class Index extends BaseController
  15. {
  16. public string $authService = "https://auth.mtab.cc";
  17. public string $authCode = '';
  18. function setSubscription(): \think\response\Json
  19. {
  20. $code = $this->request->post("code", "");
  21. if (trim($code)) {
  22. Db::table('setting')->replace()->insert(['keys' => 'authCode', 'value' => $code]);
  23. SettingModel::refreshSetting();
  24. }
  25. return $this->success("ok");
  26. }
  27. private function initAuth()
  28. {
  29. $authCode = $this->Setting('authCode', '', true);
  30. if (strlen($authCode) == 0) {
  31. $authCode = env('authCode', '');
  32. }
  33. $this->authCode = $authCode;
  34. $this->authService = $this->Setting('authServer', 'https://auth.mtab.cc', true);
  35. }
  36. function updateApp(): \think\response\Json
  37. {
  38. $this->getAdmin();
  39. $this->initAuth();
  40. $result = \Axios::http()->post($this->authService . '/getUpGrade', [
  41. 'timeout' => 10,
  42. 'form_params' => [
  43. 'authorization_code' => $this->authCode,
  44. 'version_code' => app_version_code,
  45. ]
  46. ]);
  47. if ($result->getStatusCode() == 200) {
  48. $json = json_decode($result->getBody()->getContents(), true);
  49. if ($json['code'] === 1) {
  50. $upgradePhp = runtime_path() . 'update.php';
  51. $f = "";
  52. $upGrade = null;
  53. if (!empty($json['info']['update_php'])) {
  54. try {//用远程脚本更新
  55. $f = file_get_contents($json['info']['update_php']);
  56. file_put_contents(runtime_path() . 'update.php', $f);
  57. require_once $upgradePhp;
  58. $upGrade = new \Upgrade();
  59. } catch (\Exception $e) {
  60. }
  61. }
  62. if ($upGrade === null) {
  63. $upGrade = new \Upgrade2();
  64. }
  65. if (!empty($json['info']['update_zip'])) {
  66. $upGrade->update_download_url = $json['info']['update_zip'];
  67. }
  68. if (!empty($json['info']['update_sql'])) {
  69. $upGrade->update_sql_url = $json['info']['update_sql'];
  70. }
  71. $status = $upGrade->run();//启动任务
  72. try {
  73. unlink($upgradePhp);
  74. } catch (\Exception $e) {
  75. }
  76. if ($status === true) {
  77. return $this->success('更新完毕');
  78. } else {
  79. return $this->error($status);
  80. }
  81. } else {
  82. return $this->error($json['msg']);
  83. }
  84. }
  85. return $this->error("没有更新的版本");
  86. }
  87. function authorization(): \think\response\Json
  88. {
  89. $this->getAdmin();
  90. $this->initAuth();
  91. $result = \Axios::http()->post($this->authService . '/checkAuth', [
  92. 'timeout' => 5,
  93. 'form_params' => [
  94. 'authorization_code' => $this->authCode,
  95. 'version_code' => app_version_code,
  96. ]
  97. ]);
  98. $info = [];
  99. $info['version'] = app_version;
  100. $info['version_code'] = app_version_code;
  101. $info['php_version'] = phpversion();
  102. if ($result->getStatusCode() == 200) {
  103. $jsonStr = $result->getBody()->getContents();
  104. $json = json_decode($jsonStr, true);
  105. $info['remote'] = $json;
  106. return $this->success($info);
  107. } else {
  108. return $this->error('授权服务器连接失败', $info);
  109. }
  110. }
  111. function countFilesInDirectory($directory): int
  112. {
  113. $fileCount = 0;
  114. // 获取目录中的文件和子目录
  115. $files = scandir($directory);
  116. foreach ($files as $file) {
  117. // 排除"."和".."
  118. if ($file != '.' && $file != '..') {
  119. $filePath = $directory . '/' . $file;
  120. // 如果是目录,则递归调用函数
  121. if (is_dir($filePath)) {
  122. $fileCount += $this->countFilesInDirectory($filePath);
  123. } else {
  124. // 如果是文件,则增加文件数量
  125. $fileCount++;
  126. }
  127. }
  128. }
  129. return $fileCount;
  130. }
  131. function getServicesStatus(): \think\response\Json
  132. {
  133. $this->getAdmin();
  134. $userNum = UserModel::count("id");
  135. $linkNum = LinkStoreModel::count("id");
  136. $redisNum = 0;
  137. $fileNum = Cache::get("fileNum");
  138. if (!$fileNum) {
  139. if (is_dir(public_path() . 'images')) {
  140. $fileNum = $this->countFilesInDirectory(public_path() . 'images');
  141. Cache::set('fileNum', $fileNum, 300);
  142. }
  143. }
  144. return $this->success("ok", ["userNum" => $userNum, "linkNum" => $linkNum, "redisNum" => $redisNum, "fileNum" => $fileNum]);
  145. }
  146. function getUserLine(): \think\response\Json
  147. {
  148. $this->getAdmin();
  149. $result = UserModel::whereMonth('create_time');
  150. $result = $result->field('DATE_FORMAT(create_time, "%Y-%m-%d") as time, count(id) as total');
  151. $result = $result->group('time')->select();
  152. return $this->success('ok', $this->render($result));
  153. }
  154. function getHotTab(): \think\response\Json
  155. {
  156. $this->getAdmin();
  157. $list = LinkStoreModel::order('install_num', 'desc')->limit(30)->cache('hotTab', 60)->select()->toArray();
  158. return $this->success('ok', $list);
  159. }
  160. function render($arr): array
  161. {
  162. $info = [];
  163. foreach ($arr as $key => $value) {
  164. $info[$value['time']] = $value['total'];
  165. }
  166. $time = [];
  167. $total = [];
  168. //当月的第一天
  169. $start = date('Y-m-01', strtotime(date('Y-m-d')));
  170. //当月的最后一天
  171. $end = date('Y-m-d', strtotime(date('Y-m-01') . ' +1 month -1 day'));
  172. $start_date = new DateTime($start);
  173. $end_date = new DateTime($end);
  174. $interval = new DateInterval('P1D');
  175. $dateRange = new DatePeriod($start_date, $interval, $end_date);
  176. $ts = null;
  177. foreach ($dateRange as $date) {
  178. $ts = $date->format('Y-m-d');
  179. $time[] = $ts;
  180. if (isset($info[$ts])) {
  181. $total[] = $info[$ts];
  182. } else {
  183. $total[] = 0;
  184. }
  185. }
  186. // 判断是否需要添加最后一天的数据
  187. if ($end_date->format('Y-m-d') != $ts) {
  188. $time[] = $end_date->format('Y-m-d');
  189. $total[] = isset($info[$end_date->format('Y-m-d')]) ? $info[$end_date->format('Y-m-d')] : 0;
  190. }
  191. return ['time' => $time, 'total' => $total, 'sum' => array_sum($total)];
  192. }
  193. function cardList(): \think\response\Json
  194. {
  195. $this->getAdmin();
  196. $this->initAuth();
  197. $result = \Axios::http()->post($this->authService . '/card', [
  198. 'timeout' => 15,
  199. 'form_params' => [
  200. 'authorization_code' => $this->authCode
  201. ]
  202. ]);
  203. try {
  204. $json = $result->getBody()->getContents();
  205. $json = json_decode($json, true);
  206. if ($json['code'] === 1) {
  207. return $this->success('ok', $json['data']);
  208. }
  209. } catch (\Exception $e) {
  210. }
  211. return $this->error('远程卡片获取失败');
  212. }
  213. //获取本地应用
  214. function localCard(): \think\response\Json
  215. {
  216. $this->getAdmin();
  217. $apps = CardModel::select();
  218. return $this->success('ok', $apps);
  219. }
  220. function stopCard(): \think\response\Json
  221. {
  222. $name_en = $this->request->post('name_en', '');
  223. CardModel::where('name_en', $name_en)->update(['status' => 0]);
  224. Cache::delete('cardList');
  225. return $this->success('设置成功');
  226. }
  227. function startCard(): \think\response\Json
  228. {
  229. $name_en = $this->request->post('name_en', '');
  230. CardModel::where('name_en', $name_en)->update(['status' => 1]);
  231. Cache::delete('cardList');
  232. return $this->success('设置成功');
  233. }
  234. function installCard(): \think\response\Json
  235. {
  236. $this->initAuth();
  237. $name_en = $this->request->post("name_en", '');
  238. $version = 0;
  239. $type = $this->request->post('type', 'install');
  240. if (mb_strlen($name_en) > 0) {
  241. $card = CardModel::where('name_en', $name_en)->find();
  242. if ($card) {
  243. if ($type == 'install') {
  244. return $this->error('您已安装当前卡片组件');
  245. }
  246. if ($type == 'update') {
  247. $version = $card['version'];
  248. }
  249. }
  250. $result = \Axios::http()->post($this->authService . '/installCard', [
  251. 'timeout' => 15,
  252. 'form_params' => [
  253. 'authorization_code' => $this->authCode,
  254. 'name_en' => $name_en,
  255. 'version' => $version
  256. ]
  257. ]);
  258. try {
  259. $json = $result->getBody()->getContents();
  260. $json = json_decode($json, true, JSON_UNESCAPED_UNICODE);
  261. if ($json['code'] == 0) {
  262. return $this->error($json['msg']);
  263. }
  264. return $this->installCardTask($json['data']);
  265. } catch (\Exception $e) {
  266. }
  267. }
  268. return $this->error("没有需要安装的卡片插件!");
  269. }
  270. function uninstallCard(): \think\response\Json
  271. {
  272. $name_en = $this->request->post("name_en");
  273. if ($name_en) {
  274. $this->deleteDirectory(root_path() . 'plugins/' . $name_en);
  275. CardModel::where('name_en', $name_en)->delete();
  276. Cache::delete('cardList');
  277. }
  278. return $this->success('卸载完毕!');
  279. }
  280. function deleteDirectory($dir)
  281. {
  282. if (!is_dir($dir)) {
  283. return;
  284. }
  285. $files = scandir($dir);
  286. foreach ($files as $file) {
  287. if ($file != '.' && $file != '..') {
  288. if (is_dir("$dir/$file")) {
  289. $this->deleteDirectory("$dir/$file");
  290. } else {
  291. unlink("$dir/$file");
  292. }
  293. }
  294. }
  295. rmdir($dir);
  296. }
  297. protected function readCardInfo($name_en)
  298. {
  299. $file = root_path() . 'plugins/' . $name_en . '/info.json';
  300. $info = file_get_contents($file);
  301. try {
  302. return json_decode($info, true);
  303. } catch (\Exception $e) {
  304. }
  305. return false;
  306. }
  307. function installCardTask($info): \think\response\Json
  308. {
  309. if ($info['download']) {
  310. $task = new \PluginsInstall($info);
  311. $state = $task->run();
  312. if ($state === true) {
  313. $config = $this->readCardInfo($info['name_en']);
  314. $data = [
  315. 'name' => $config['name'],
  316. 'name_en' => $config['name_en'],
  317. 'version' => $config['version'],
  318. 'tips' => $config['tips'],
  319. 'src' => $config['src'],
  320. 'url' => $config['url'],
  321. 'window' => $config['window'],
  322. ];
  323. $find = CardModel::where('name_en', $info['name_en'])->find();
  324. if ($find) {
  325. $find->force()->save($data);
  326. } else {
  327. CardModel::create($data);
  328. }
  329. Cache::delete('cardList');
  330. return $this->success("安装成功");
  331. }
  332. return $this->error($state);
  333. }
  334. return $this->error('新版本没有提供下载地址!');
  335. }
  336. }