Compare commits

...
Author SHA1 Message Date
蘭 193b0f3cd4 fix: Update swagger docs (#8002)
Refs #8001
2025-02-26 10:55:40 +08:00
zhengkunwang 67c1bf2924 feat: Add certificate validation when creating AI Proxy (#7994) 2025-02-25 15:21:16 +08:00
ssongliu b1373ff77e feat: Support gpu of schema v11 (#7988) 2025-02-25 14:16:34 +08:00
dependabot[bot] 55d0e27212 chore(deps): bump github.com/go-jose/go-jose/v4 from 4.0.4 to 4.0.5
Bumps [github.com/go-jose/go-jose/v4](https://github.com/go-jose/go-jose) from 4.0.4 to 4.0.5.
- [Release notes](https://github.com/go-jose/go-jose/releases)
- [Changelog](https://github.com/go-jose/go-jose/blob/main/CHANGELOG.md)
- [Commits](https://github.com/go-jose/go-jose/compare/v4.0.4...v4.0.5)

---
updated-dependencies:
- dependency-name: github.com/go-jose/go-jose/v4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-25 09:34:14 +08:00
zhengkunwang 1c052b7c13 fix: Fix the issue with AI proxy certificate res error (#7983) 2025-02-24 22:24:51 +08:00
蘭 6c8d48c2dc feat: API interface IP whitelist supports IPv6 (#7981)
Refs #7836
2025-02-24 10:05:13 +00:00
ssongliu b61dae638b fix(forward): Fix the problem of duplicate creation of port forwardin… (#7975)
Refs #7969
2025-02-24 09:21:14 +00:00
zhengkunwang 872a93aa07 fix: Fix the issue with the homepage route refresh (#7974) 2025-02-24 15:00:20 +08:00
igophper b1f337020c fix(container/log): enable close-on-click-modal and wrap log update in nextTick (#7960)
Refs #7547
2025-02-24 13:34:51 +08:00
maninhill 56858dd74c chore: Update README.md 2025-02-24 10:54:05 +08:00
Johannes Plunien 358415f737 feat: Support freemyip.com DNS provider (#7958) 2025-02-24 10:21:37 +08:00
david082321 5e73260103 feat: Update zh-Hant translation (#7966) 2025-02-22 23:16:38 +08:00
zhengkunwang e169f46784 fix: Fixed the issue of no echo after binding the SSL to the AI. (#7953) 2025-02-21 09:29:51 +00:00
ssongliu 39416abd47 fix: Fix the issue of inconsistent deletion status for the ollama model (#7950)
Refs #7948
2025-02-21 08:51:51 +00:00
wanghe-fit2cloud 640a0ca815 chore: Optimize some command outputs 2025-02-21 16:45:56 +08:00
ssongliu 8e54cd5162 style: Adjust the width display of the model list (#7946) 2025-02-21 07:54:29 +00:00
ssongliu 0f0099accb fix: Fix the issue of loading errors for editing container port data (#7945)
Refs #7938
2025-02-21 04:01:49 +00:00
ssongliu 718ebeb203 fix: Modify help information about Ollama pull (#7935) 2025-02-20 15:21:50 +08:00
ssongliu 4101bf691d style: Fix the issue of inconsistent menu spacing. (#7932) 2025-02-20 13:45:48 +08:00
蘭 a97deb3dca feat: API timestamp verification (#7927)
* feat: API timestamp verification

* feat: API timestamp verification
2025-02-20 13:29:26 +08:00
zhengkunwang 10203d5c0c fix: Resolve the issue of local application label loss (#7926) 2025-02-20 13:29:04 +08:00
maninhill a357d6697d chore: Update README.md 2025-02-19 22:58:06 +08:00
ssongliu 555b0aa999 fix: Optimize status display. (#7920) 2025-02-19 22:54:34 +08:00
蘭 6dd0dbe2c3 feat: Improve international language (#7918) 2025-02-19 13:35:39 +00:00
zhengkunwang c31bbae768 feat: Optimized the display when no certificate is present. (#7917) 2025-02-19 11:03:39 +00:00
ssongliu 2bb0f15973 fix: Fix the loading method of slow logs in MySQL and MariaDB (#7915)
Refs #6353
2025-02-19 09:48:36 +00:00
zhengkunwang be229551e3 feat: AI tool Added quick jump functionality (#7913) 2025-02-19 08:26:31 +00:00
蘭 6283eb4c69 feat: Add language translation and icons (#7912) 2025-02-19 08:14:32 +00:00
ssongliu c329fb6599 feat: Support for terminal operation with the Ollama model (#7907) 2025-02-19 14:07:05 +08:00
zhengkunwang223 c3685f6b74 feat: Adjusted the position of the quick jump button. 2025-02-18 20:25:31 +08:00
maninhill f4f5a36475 chore: Update README.md 2025-02-18 20:25:04 +08:00
zhengkunwang ea1261b48e feat: Added partial prompt messages (#7900) 2025-02-18 10:08:52 +00:00
wanghe-fit2cloud 0c68f16a66 feat: Modify some translations 2025-02-18 17:09:13 +08:00
ssongliu 33e5c9230f fix: Optimized ollama model status display (#7899) 2025-02-18 17:06:20 +08:00
zhengkunwang 96eefab36f feat: Added underscore support for website default documents (#7898) 2025-02-18 17:06:10 +08:00
zhengkunwang b0b6bf458f feat: Added display of ollama proxy address (#7897) 2025-02-18 15:00:33 +08:00
zhengkunwang f3d85d1309 fix: Fixed the issue where local application descriptions were not di… (#7896)
Refs https://github.com/1Panel-dev/1Panel/issues/7886
2025-02-18 06:17:11 +00:00
ssongliu 39385ea0a0 fix: Adjust the synchronization method for the Ollama model (#7895) 2025-02-18 06:09:10 +00:00
zhengkunwang e492c6573c feat: Modified the logic for AI Tool (#7894) 2025-02-18 05:59:10 +00:00
wanghe-fit2cloud 10a7fb3be2 feat: Update the official website URL for the international version 2025-02-18 10:31:38 +08:00
王贺 8bc7cfade3 Update README.md (#7891) 2025-02-17 22:26:29 +08:00
ssongliu ea044d6c32 fix: change the AI routing interface (#7887) 2025-02-17 15:33:57 +08:00
zhengkunwang f6ee3dc75b feat: Added streaming transmission configuration (#7875) 2025-02-15 12:59:38 +00:00
ssongliu 367a74503f fix: Fix the problem of duplicate content display in the model list (#7872) 2025-02-14 09:10:05 +00:00
蘭 53b1a7af4c feat: Copy and move files with the same name file processing (#7871) 2025-02-14 06:28:06 +00:00
zhengkunwang 078d7fbe1e feat: Add AI-enhanced configuration (#7870) 2025-02-14 06:26:05 +00:00
ssongliu c709e48ceb feat: support load ollama model details (#7867) 2025-02-13 14:56:24 +00:00
endymx 0741f60896 fix(iptables): 复杂环境下转发删除端口错误 (#7868) 2025-02-13 22:56:09 +08:00
ssongliu af8eef4a91 feat: Support Ollama model management (#7866) 2025-02-13 15:28:29 +08:00
zhengkunwang f233ef7069 feat: Adding GPU acceleration configuration to some applications (#7865) 2025-02-13 07:02:08 +00:00
蘭 1c199bd3d7 style: Optimize app store style and layout (#7858)
Refs #7846
2025-02-12 21:56:52 +08:00
ssongliu 036c973fec fix: Fix the security entry verification error issue. (#7854)
Refs #7853
2025-02-11 10:13:49 +00:00
蘭 8bb225d272 feat: Check for duplicate files before uploading (#7849)
Refs #5893
2025-02-11 10:11:48 +00:00
zhengkunwang ab932ae154 fix: Fixed the issue where application labels were not displayed after updating. (#7834) 2025-02-10 11:17:24 +08:00
david082321 89f969ec6e feat: Update zh-Hant translation (#7830) 2025-02-09 22:01:02 +08:00
ssongliu afa8cf22b1 feat: Add function backups by default for MySQL and MariaDB databases. (#7823) 2025-02-08 22:56:46 +08:00
ssongliu 67aa8471dc fix: Remove some comments. (#7822) 2025-02-08 08:41:27 +00:00
zhengkunwang 0617b81b3b feat: The appstore has added support for the Korean language (#7818) 2025-02-07 13:07:20 +00:00
ssongliu 98c535a12c fix: improve the backend verification for security entry settings (#7810)
Refs #7657
2025-02-06 10:15:06 +00:00
ssongliu ec46518936 feat: Improve the name of the professional version (#7807) 2025-02-06 10:13:03 +00:00
ssongliu a7b034387f fix: fix some internationalization formats (#7803) 2025-02-05 14:41:59 +00:00
endymx 7905dd00a6 fix(firewall): 删除复杂转发规则时报错 (#7791) 2025-02-05 18:37:42 +08:00
zhengkunwang 74583aa1aa feat: fix anti-leech is not work on proxy website (#7801)
Refs https://github.com/1Panel-dev/1Panel/issues/7752
2025-02-05 10:07:16 +00:00
dependabot[bot] 4be9d71edf chore(deps): bump github.com/golang/glog from 1.2.2 to 1.2.4 (#7787) 2025-01-31 13:08:01 +08:00
zhengkunwang 57bfc38eb8 feat: Application details have been enhanced with tags. (#7777)
Refs https://github.com/1Panel-dev/1Panel/issues/7774
2025-01-27 11:04:26 +00:00
zhengkunwang aaaa5980b5 feat: Added password encryption for login functionality (#7764) 2025-01-23 18:09:12 +08:00
蘭 4f57dfc76e feat: Unify the response body of the API interface (#7761) 2025-01-23 08:28:04 +00:00
wanghe-fit2cloud 2c31ffc66b feat: Enhance app redirection messages 2025-01-23 15:32:11 +08:00
王贺 b104a13b71 Update README.md (#7747) 2025-01-20 22:48:29 +08:00
maninhill 28633d2fef chore: Update README.md 2025-01-20 22:33:20 +08:00
蘭 9052386c83 feat: Korean language support (#7727)
Refs #7363
2025-01-15 10:26:30 +00:00
maninhill 7bc45f2d77 chore: Update README.md 2025-01-15 15:24:20 +08:00
wanghe-fit2cloud 2ef6ecb951 chore: Update the README.md 2025-01-15 10:40:22 +08:00
zhengkunwang ca0dc71338 feat: Enable Multi-Language Support for Application Installation Forms (#7717) 2025-01-14 19:03:22 +08:00
zhengkunwang 04a1ec9a9a feat: Add Multi-Language Support for Application Labels (#7714) 2025-01-14 16:00:09 +08:00
蘭 999e5a779a feat: Update swagger docs (#7710) 2025-01-13 15:10:04 +00:00
zhengkunwang 99f62b7230 fix(website):Fix Reverse Proxy Deletion Failure in Certain Scenarios (#7709)
Refs https://github.com/1Panel-dev/1Panel/issues/7701
2025-01-13 15:08:04 +00:00
zhengkunwang 4dee4e1cc2 feat: Update Application Name Restrictions (#7706) 2025-01-13 07:56:03 +00:00
maninhill 539addc656 chore: Update README.md 2025-01-10 23:07:15 +08:00
BugKing 1a35b307fa docs: add introduction of 1Panel Pro in README (#7699) 2025-01-10 22:32:02 +08:00
蘭 a04f4a8b96 feat: Improve international language and style (#7697)
Refs #7696
2025-01-10 10:57:45 +00:00
ssongliu 6b88e1adf2 fix: Remove redundant code (#7694) 2025-01-10 15:06:18 +08:00
蘭 99bc8177d4 feat: Save custom theme color scheme (#7690) 2025-01-10 04:13:44 +00:00
ssongliu cf2a1372f2 style: Optimize some internationalization styles (#7689) 2025-01-10 04:11:44 +00:00
蘭 42c30f324a feat: Improve international language (#7687) 2025-01-10 02:21:44 +00:00
蘭 dab83fee20 feat: Modify international version functions (#7686) 2025-01-10 02:19:44 +00:00
蘭 6f3c5586fc feat: Update international address (#7685) 2025-01-10 02:17:43 +00:00
ssongliu aab8df6abc fix: Fix the issue of database cover exception display. (#7682) 2025-01-09 13:59:41 +00:00
蘭 b9be79b05a feat: Menu enables vue-router mode (#7681) 2025-01-09 12:15:42 +00:00
zhengkunwang ec3024f2c3 feat: Change AppDto to AppItem (#7680) 2025-01-09 12:13:41 +00:00
ssongliu 070f61e229 fix: Fix the issue of pagination errors in the backup list (#7673) 2025-01-09 03:07:40 +00:00
蘭 a82a4ebfc5 style: Optimize style and layout (#7671) 2025-01-08 10:19:37 +00:00
蘭 87009ddb27 feat: Modify the copyright (#7670) 2025-01-08 07:39:37 +00:00
蘭 3650ff27b3 feat: Dealing with Sass version compatibility issues and removing debugger from build (#7669) 2025-01-08 07:21:38 +00:00
ssongliu 6c08a3114a fix: Fix the issue of interface returning internationalization failure (#7668) 2025-01-08 07:19:37 +00:00
蘭 381cb61185 feat: Internationalization language order (#7666) 2025-01-08 03:33:37 +00:00
蘭 8d69da7702 feat: Break long menu items into multiple lines (#7665) 2025-01-08 03:31:36 +00:00
ssongliu 8922395fdc fix: Fix the issue of frontend packaging errors (#7661) 2025-01-07 06:47:35 +00:00
ssongliu 83db40e261 feat: Support for asynchronously obtaining the backup file size (#7660) 2025-01-07 06:35:33 +00:00
zhengkunwang 95ec6c62ef feat(system): Fix Issue Allowing Access via Old Secure Entry After Mo… (#7659)
Refs https://github.com/1Panel-dev/1Panel/issues/7658
2025-01-07 06:09:32 +00:00
蘭 56fc9ea428 feat: Improve international language proficiency (#7656) 2025-01-07 04:19:33 +00:00
蘭 88c6fc050b feat: Upgrade package version (#7655) 2025-01-07 04:03:33 +00:00
蘭 2392f91567 feat: Panel aliases support common special characters (#7654)
Refs #6909
2025-01-07 04:01:33 +00:00
蘭 5f0c740eb0 feat: Improve and format language files (#7645) 2025-01-06 05:48:21 +00:00
Lucas Pedro 120d0dd7c6 Traducao pt br (#7624) 2025-01-06 10:57:34 +08:00
liuchang_cloud 2844f6db7f feat: Support Japanese by Google Translate (#7437) 2025-01-06 10:39:49 +08:00
王贺 570074f92d Update README.md 2025-01-04 10:56:43 +08:00
Anye a13047c855 Update Default PHP Extensions (#7637) 2025-01-04 10:44:41 +08:00
蘭 ca0d24bf56 feat: Improve and format language files (#7634) 2025-01-03 08:52:09 +00:00
Pisyek K. 2b18251360 chore: add bahasa melayu translation (#7623)
* chore: add bahasa melayu translation
2025-01-03 11:42:13 +08:00
蘭 f7c875acda feat: Save the theme color scheme to the client (#7626)
Refs #7074
2025-01-03 02:30:07 +00:00
ssongliu a291a50c9f feat: Support for license import in the international version (#7625) 2025-01-02 15:00:05 +00:00
蘭 5bc7bc6aac fix: Fix missing response types in Swagger API endpoints (#7611)
Refs #7607
2024-12-31 09:57:55 +00:00
zhengkunwang 9c376300ff feat(ssl): Add Support for Rain Yun in DNS Account (#7613)
Refs https://github.com/1Panel-dev/1Panel/issues/7115
2024-12-31 09:55:54 +00:00
Ryan Wang 5187b20252 fix: correct Swagger API definitions (#7606)
Signed-off-by: Ryan Wang <i@ryanc.cc>
2024-12-31 10:32:47 +08:00
ssongliu fc401ffd8f fix: Optimize image deletion error return (#7602)
Refs #7068
2024-12-30 09:17:49 +00:00
zhengkunwang 667ee5256e fix: Fix Application Startup Failure Caused by Case-Sensitive Applica… (#7601)
Refs https://github.com/1Panel-dev/1Panel/issues/7600
2024-12-30 09:15:49 +00:00
wanghe-fit2cloud f8356de93c Modify the copyright 2024-12-30 16:38:54 +08:00
endymx 55bb997d51 feat(iptables): Support forwarding for complex networks (#7598)
* feat(iptables): 支持对复杂网络的转发

* refactor(iptables): 提供更完善的接口和报错
2024-12-30 13:55:53 +08:00
ssongliu 7c46f54e15 fix: Fix the issue of failure to retrieve firewall status (#7597)
Refs #7527
2024-12-30 05:37:49 +00:00
ssongliu 6dbb6d2247 fix: Fix the issue of backup failure due to complex passwords in the pg (#7596) 2024-12-30 13:36:51 +08:00
ssongliu 9d0ae45edc feat: Optimize the display of scheduled task execution cycles (#7595) 2024-12-30 05:35:49 +00:00
蘭 b467dfa3b2 feat: Add expiration time setting for API key (#7584) 2024-12-30 05:33:49 +00:00
蘭 c13387bc70 style: Optimize the display of status cards on the overview page (#7562)
* style: Optimize the display of status cards on the overview page
2024-12-27 14:01:02 +08:00
BugKing 41b2523750 docs: replace Discord link in readme (#7573) 2024-12-26 18:32:50 +08:00
zhengkunwang afe82bd4be feat: Remove Default Configuration for Reverse Proxy Cache (#7566) 2024-12-26 10:16:07 +08:00
JB-SelfCompany 0f296fb70b Update README for Russian language (#7560) 2024-12-25 16:37:06 +08:00
JB-SelfCompanyandBubblegum d96ccd06a3 Russian language support. (#7554)
* Add Russian language

* Use prettier

---------

Co-authored-by: Bubblegum <jack_benq@selfhosted.lan>
2024-12-25 09:34:50 +08:00
BugKing 14095affa9 docs: add discord badge in readme (#7544) 2024-12-24 14:03:05 +08:00
Anye ed60565bc9 Update cache.conf (#7516)
Remove `proxy_cache ` from the global config to prevent it from being enabled for sites that don't need caching.
2024-12-23 11:21:23 +08:00
david082321 8313912c4f fix: Update zh-Hant translation (#7515) 2024-12-21 20:34:24 +08:00
wolf 6274015d06 fix: Optimize some translations (#7495) 2024-12-20 18:45:45 +08:00
蘭 d195ce9155 feat: Login to access Swagger documentation (#7496) 2024-12-20 18:37:59 +08:00
Flyum cd0cd8a152 fix: Modify some English translations (#7494) 2024-12-20 18:06:44 +08:00
liuboF2candliubo 1f45ed6b06 fix: Correct English internationalization translations (#7493)
Co-authored-by: liubo <liubo@fit2cloud.com>
2024-12-20 18:05:58 +08:00
zhengkunwang 7f6ad89edf feat: Optimize some translations (#7492) 2024-12-20 17:48:52 +08:00
liuboF2candliubo 5cdea288e2 fix: 修正英文国际化翻译 (#7491)
Co-authored-by: liubo <liubo@fit2cloud.com>
2024-12-20 17:29:43 +08:00
wanghe-fit2cloud e56feaf826 docs: Optimize README 2024-12-20 16:35:23 +08:00
zhengkunwang 1288a09647 fix: Optimize some translations (#7490) 2024-12-20 16:33:35 +08:00
wanghe-fit2cloud 0cdaafa1c0 docs: Optimize README 2024-12-20 16:21:23 +08:00
Frist soulful 0b3334253c Update zh-Hant.yaml (#7489) 2024-12-20 16:20:31 +08:00
Yuki Guo 10f72f12d2 docs: Update tw.ts (#7487) 2024-12-20 16:08:07 +08:00
feng626 01643b2816 perf: Optimize FTP sync function for better performance and readability (#7479) 2024-12-20 15:45:05 +08:00
zrfit 56e0da4fe3 docs: Update README.tr.md (#7486) 2024-12-20 15:41:27 +08:00
song-cc-rock 144c397bf4 fix: update zh-hant spell 2024-12-20 15:34:57 +08:00
ZhaoJiSen e06541984f Add ImportMeta type definition (#7481) 2024-12-20 15:32:58 +08:00
zhengkunwang ea7e92db84 feat: Remove Redundant Code (#7484) 2024-12-20 07:32:25 +00:00
wxg 8d48640c1d fix: Update zh-Hant.yaml (#7483) 2024-12-20 15:31:25 +08:00
zrfit cfe5cb4b6b Add File README.tr.md (#7480) 2024-12-20 15:25:53 +08:00
9527 05c4d7dd38 docs: Add German README (#7482) 2024-12-20 15:20:45 +08:00
wangyicheng 13c6e0df99 docs: Update README.es.md (#7477) 2024-12-20 15:11:10 +08:00
MignonZhang dafd6ba71e fix: fix typos (#7478) 2024-12-20 15:09:26 +08:00
莫鹍 2751c37716 refactor(i18n): fix spelling error (#7476) 2024-12-20 15:08:22 +08:00
蘭 50c01762e7 feat: Open international professional features (#7472) 2024-12-20 07:04:26 +00:00
w940853815 a77ebd3eb6 fix: Typo in hostname save function and button click (#7475) 2024-12-20 15:02:30 +08:00
gerry-f2c d84f0b5597 style: Optimize the backup account style code (#7474) 2024-12-20 15:00:14 +08:00
Slooop a3cdf87ea2 style: Optimize the backup account style code (#7473) 2024-12-20 14:59:57 +08:00
Chenyang Shen 8ab3c16b3d Update zh-Hant.yaml 2024-12-20 14:54:24 +08:00
Shenguobin0102 18e943fd06 fix: Modified the RTL format to right-align the first sentence of the body (#7470) 2024-12-20 14:52:53 +08:00
zyyfit 3b7a067dda Create README.fr.md (#7469) 2024-12-20 14:24:09 +08:00
ZhaoQian1222 4636ba815b fix: Corrected some internationalization translations (#7468) 2024-12-20 14:22:30 +08:00
Shenguobin0102 317fad2a28 docs: Update README.ar.md (#7467) 2024-12-20 14:18:31 +08:00
MatataYou 0ae28a1dd9 Update README.es.md (#7466) 2024-12-20 14:05:28 +08:00
Anye bbfe5f1d96 style: Modify some styles to improve the appearance of the version button (#7464) 2024-12-20 13:59:02 +08:00
zhengkunwang b713f20b66 style: Optimize OpenResty Warnings Displayed During Zooming (#7465)
Refs https://github.com/1Panel-dev/1Panel/issues/7452
2024-12-20 05:50:25 +00:00
Shenguobin0102 3eb7a5adc5 docs: Add Arabic README (#7463) 2024-12-20 13:49:23 +08:00
MatataYou 956af78749 docs: Add Spanish Language README (#7461) 2024-12-20 13:43:55 +08:00
zhengkunwang 69ad01687e feat: Optimize Location Information Display in System Login Logs (#7459) 2024-12-20 04:16:25 +00:00
Anye e83d07e88e style: Modify some styles to improve the appearance of the version button (#7462) 2024-12-20 12:03:49 +08:00
zhengkunwang 6683696032 fix(system): Fix Cloudflare Proxy Access Issue with 1Panel When Secure Entry Is Enabled (#7458) 2024-12-20 11:03:49 +08:00
zhengkunwang 3396a5ffea go: upgraded golang.org/x/crypto v0.28.0 => v0.31.0 (#7456) 2024-12-20 02:26:24 +00:00
zhengkunwang 18a14d3b75 go: upgraded golang.org/x/net v0.30.0 => v0.33.0 (#7455) 2024-12-20 02:14:23 +00:00
王贺 2b13352004 chore: Add Indonesian language (#7445) 2024-12-19 23:20:48 +08:00
maninhill 94e5d7e642 chore: Update README.md 2024-12-19 22:42:35 +08:00
maninhill 001b4dbada docs: Create README.id.md 2024-12-19 22:41:22 +08:00
BugKing 1192dec689 docs: Add Product Hunt badge (#7434) 2024-12-19 11:55:18 +08:00
蘭 956d47f9da refactor: Demo server, prohibit operation (#7433) 2024-12-19 02:06:19 +00:00
John Niang 063a071228 Fix invalid postion of before content in home page in Firefox Linux (#7429) 2024-12-18 18:33:59 +08:00
Ryan Wang c54a7de827 docs: add Korean README documentation (#7427)
Signed-off-by: Ryan Wang <i@ryanc.cc>
2024-12-18 17:15:10 +08:00
老广 0410e48aad docs: Add README.pt-br.md (#7425) 2024-12-18 16:29:44 +08:00
liuchang_cloud a4d95737d3 docs: Update README.md (#7424) 2024-12-18 16:16:14 +08:00
jianneng-fit2cloud bc64d83ab2 style: Container style (#7422) 2024-12-18 15:32:30 +08:00
蘭 87616e388b style: Optimize style (#7414)
Refs #7419
2024-12-18 06:44:14 +00:00
taojinlongandtaojinlong 3f35f90fc2 fix: fix typos (#7413)
Co-authored-by: taojinlong <jinlong@fit2cloud.com>
2024-12-18 14:06:00 +08:00
王嘉豪 c3ba69814c Update fa.yaml (#7411) 2024-12-18 14:05:46 +08:00
wisonic-s 66a517e58d fix: fix typos (#7407) 2024-12-18 14:05:24 +08:00
Bryan 3108c927af fix: typos (#7405) 2024-12-18 14:04:51 +08:00
Junjun 5738cceac9 fix typos (#7404) 2024-12-18 14:04:17 +08:00
dataeaseShu db2f648bce fix: fix typos (#7403) 2024-12-18 14:04:06 +08:00
fit2cloud-chenyw 6012a6cf9f fix: datas should be dataList (#7402) 2024-12-18 14:03:56 +08:00
ulleo a4dcbc90e6 fix: fix typos (#7401) 2024-12-18 14:03:40 +08:00
BugKing 955ecce952 docs: Update README.md (#7416) 2024-12-18 13:34:56 +08:00
maninhill 91fba21ed3 chore: Update README.md 2024-12-18 11:55:20 +08:00
wanghe-fit2cloud 490e2934b8 chore: Optimize the README file 2024-12-18 11:54:06 +08:00
wanghe-fit2cloud cb6d3d4fc3 chore: Optimize the README file 2024-12-18 11:52:05 +08:00
295 changed files with 30887 additions and 4934 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ PR are always welcome, even if they only contain small fixes like typos or a few
Please submit a PR broken down into small changes bit by bit. A PR consisting of a lot of features and code changes may be hard to review. It is recommended to submit PRs in an incremental fashion.
This [development guideline](https://1panel.cn/docs/dev_manual/dev_manual/) contains information about repository structure, how to set up development environment, how to run it, and more.
This [development guideline](https://docs.1panel.pro/dev_manual/dev_manual/) contains information about repository structure, how to set up development environment, how to run it, and more.
Note: If you split your pull request to small changes, please make sure any of the changes goes to master will not break anything. Otherwise, it can not be merged until this feature complete.
+46 -40
View File
@@ -1,68 +1,74 @@
<p align="center"><a href="https://1panel.cn"><img src="http://1panel.oss-cn-hangzhou.aliyuncs.com/img/1panel-logo.png" alt="1Panel" width="300" /></a></p>
<p align="center"><b>Top-Rated Web-based Linux Server Management Tool</b></p>
<p align="center"><b>现代化、开源的 Linux 服务器运维管理面板</b></p>
<p align="center"><a href="https://1panel.pro"><img src="https://resource.1panel.pro/img/1panel-logo.png" alt="1Panel" width="300" /></a></p>
<p align="center"><b>Top-Rated Web-based Linux Server Management Tool</b><br>Best VPS control panel<br>新一代的 Linux 服务器运维管理面板</p>
<p align="center">
<a href="https://trendshift.io/repositories/2462" target="_blank"><img src="https://trendshift.io/api/badge/repositories/2462" alt="1Panel-dev%2F1Panel | Trendshift" style="width: 180px; height: auto;" /></a>
<a href="https://hellogithub.com/repository/71791baf930149ac9b84e1acf186573f" target="_blank"><img src="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=71791baf930149ac9b84e1acf186573f&claim_uid=p8vB3kP5CMrthiL&theme=dark&theme=neutral" alt="Featured|HelloGitHub" style="width: 180px; height: auto;" /></a>
<a href="https://market.aliyun.com/products/53690006/cmjj00062740.html?userCode=kmemb8jp" target="_blank"><img src="https://img.alicdn.com/imgextra/i2/O1CN01H5JIwY1rZ0OobDjnJ_!!6000000005644-2-tps-1000-216.png" alt="1Panel-dev%2F1Panel | Aliyun" style="width: 180px; height: auto;" /></a>
<a href="https://trendshift.io/repositories/2462" target="_blank"><img src="https://trendshift.io/api/badge/repositories/2462" alt="1Panel-dev%2F1Panel | Trendshift" style="width: 240px; height: auto;" /></a>
</p>
<p align="center">
<a href="https://www.gnu.org/licenses/gpl-3.0.html"><img src="https://shields.io/github/license/1Panel-dev/1Panel?color=%231890FF" alt="License: GPL v3"></a>
<a href="https://app.codacy.com/gh/1Panel-dev/1Panel?utm_source=github.com&utm_medium=referral&utm_content=1Panel-dev/1Panel&utm_campaign=Badge_Grade_Dashboard"><img src="https://app.codacy.com/project/badge/Grade/da67574fd82b473992781d1386b937ef" alt="Codacy"></a>
<a href="https://discord.gg/bUpUqWqdRr" target="_blank">
<img src="https://img.shields.io/discord/1318846410149335080?logo=discord&labelColor=%20%235462eb&logoColor=%20%23f5f5f5&color=%20%235462eb"
alt="chat on Discord"></a>
<a href="https://github.com/1Panel-dev/1Panel/releases"><img src="https://img.shields.io/github/v/release/1Panel-dev/1Panel" alt="GitHub release"></a>
<a href="https://github.com/1Panel-dev/1Panel"><img src="https://img.shields.io/github/stars/1Panel-dev/1Panel?color=%231890FF&style=flat-square" alt="GitHub Stars"></a>
<a href="https://gitee.com/fit2cloud-feizhiyun/1Panel"><img src="https://gitee.com/fit2cloud-feizhiyun/1Panel/badge/star.svg?theme=gvp" alt="Gitee Stars"></a><br>
[<a href="docs/README_EN.md">English</a>] | [<a href="docs/README_TW.md">中文(繁體)</a>] | [<a href="docs/README_JP.md">日本語</a>]
<a href="https://github.com/1Panel-dev/1Panel"><img src="https://img.shields.io/github/stars/1Panel-dev/1Panel?color=%231890FF&style=flat-square" alt="Stars"></a><br>
</p>
<p align="center">
<a href="/README.md"><img alt="English" src="https://img.shields.io/badge/English-d9d9d9"></a>
<a href="/docs/README.zh-Hans.md"><img alt="中文(简体)" src="https://img.shields.io/badge/中文(简体)-d9d9d9"></a>
<a href="/docs/README.ja.md"><img alt="日本語" src="https://img.shields.io/badge/日本語-d9d9d9"></a>
<a href="/docs/README.pt-br.md"><img alt="Português (Brasil)" src="https://img.shields.io/badge/Português (Brasil)-d9d9d9"></a>
<a href="/docs/README.ar.md"><img alt="العربية" src="https://img.shields.io/badge/العربية-d9d9d9"></a>
<a href="/docs/README.de.md"><img alt="Deutsch" src="https://img.shields.io/badge/Deutsch-d9d9d9"></a>
<a href="/docs/README.es.md"><img alt="Español" src="https://img.shields.io/badge/Español-d9d9d9"></a><br>
<a href="/docs/README.fr.md"><img alt="français" src="https://img.shields.io/badge/français-d9d9d9"></a>
<a href="/docs/README.ko.md"><img alt="한국어" src="https://img.shields.io/badge/한국어-d9d9d9"></a>
<a href="/docs/README.id.md"><img alt="Bahasa Indonesia" src="https://img.shields.io/badge/Bahasa Indonesia-d9d9d9"></a>
<a href="/docs/README.zh-Hant.md"><img alt="中文(繁體)" src="https://img.shields.io/badge/中文(繁體)-d9d9d9"></a>
<a href="/docs/README.tr.md"><img alt="Türkçe" src="https://img.shields.io/badge/Türkçe-d9d9d9"></a>
<a href="/docs/README.ru.md"><img alt="Русский" src="https://img.shields.io/badge/%D0%A0%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9-d9d9d9"></a>
<a href="/docs/README.ms.md"><img alt="Bahasa Melayu" src="https://img.shields.io/badge/Bahasa Melayu-d9d9d9"></a>
</p>
[![Watch the video](https://resource.fit2cloud.com/1panel/img/overview_video.png)](https://www.bilibili.com/video/BV1Mt421n7LZ/)
------------------------------
## 什么是 1Panel?
1Panel 是新一代的 Linux 服务器运维管理面板。
1Panel is an open-source, modern web-based control panel for Linux server management.
- **高效管理**:用户可以通过 Web 界面轻松管理 Linux 服务器,如主机监控、文件管理、数据库管理、容器管理等;
- **快速建站**:深度集成开源建站软件 WordPress 和 [Halo](https://github.com/halo-dev/halo/),域名绑定、SSL 证书配置等操作一键搞定;
- **应用商店**:精选上架各类高质量的开源工具和应用软件,协助用户轻松安装并升级;
- **安全可靠**:基于容器管理并部署应用,实现最小的漏洞暴露面,同时提供病毒防护、防火墙和日志审计等功能;
- **一键备份**:支持一键备份和恢复,用户可以将数据备份到各类云端存储介质,永不丢失。
- **Efficient Management**: Through a user-friendly web graphical interface, 1Panel enables users to effortlessly manage their Linux servers. Key features include host monitoring, file management, database administration, container management, LLMs management.
- **Rapid Website Deployment**: With deep integration of the popular open-source website building software WordPress, 1Panel streamlines the process of domain binding and SSL certificate configuration, all achievable with just one click.
- **Application Store**: 1Panel curates a wide range of high-quality open-source tools and applications, facilitating easy installation and updates for its users.
- **Security and Reliability**: By leveraging containerization and secure application deployment practices, 1Panel minimizes vulnerability exposure. It further enhances security through integrated firewall management and log auditing capabilities.
- **One-Click Backup & Restore**: Data protection is made simple with 1Panel's one-click backup and restore functionality, supporting various cloud storage solutions to ensure data integrity and availability.
## 快速开始
## Quick Start
**一键安装**
Execute the script below and follow the prompts to install 1Panel:
执行如下命令一键安装 1Panel:
```sh
curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh && sudo bash quick_start.sh
```bash
curl -sSL https://resource.1panel.pro/quick_start.sh -o quick_start.sh && bash quick_start.sh
```
如果是用于离线环境,推荐使用 [安装包方式](https://1panel.cn/docs/installation/package_installation/) 进行安装部署。
Please refer to our [documentation](https://docs.1panel.pro/quick_start/) for more details.
**学习资料**
中国用户请使用这个 [安装脚本](https://1panel.cn/docs/installation/online_installation/),其应用数量比国际版本更丰富。
- [在线文档](https://1panel.cn/docs/)
- [社区论坛](https://bbs.fit2cloud.com/c/1p/7)
- [如何加入微信交流群?](https://bbs.fit2cloud.com/t/topic/2147)
## Screenshot
## 专业版
![UI Display](https://resource.1panel.pro/img/1panel.png)
相比于社区版,1Panel 专业版为用户提供了大量增强功能及技术支持服务,增强功能包括 WAF 增强、网站防篡改、网站监控、GPU 监控、黑金主题及自定义界面等。 [点击查看专业版详细介绍](https://www.lxware.cn/1panel)。
## Star History
## 飞致云的其他明星项目
[![Star History Chart](https://api.star-history.com/svg?repos=1Panel-dev/1Panel&type=Date)](https://star-history.com/#1Panel-dev/1Panel&Date)
- [MaxKB](https://github.com/1Panel-dev/MaxKB/) - 基于 LLM 大语言模型的开源知识库问答系统
- [JumpServer](https://github.com/jumpserver/jumpserver/) - 广受欢迎的开源堡垒机
- [Halo](https://github.com/halo-dev/halo/) - 强大易用的开源建站工具
- [DataEase](https://github.com/dataease/dataease/) - 人人可用的开源数据可视化分析工具
- [MeterSphere](https://github.com/metersphere/metersphere/) - 开源持续测试工具
- [KubePi](https://github.com/1Panel-dev/KubePi/) - 现代化、开源的 K8s 面板
## Pro Edition
Compared to the OSS Edition, 1Panel Pro Edition provides users with a wealth of enhanced features and technical support services. Enhanced features include WAF enhancement, website tamper protection, website monitoring, GPU monitoring, custom logo and theme color, etc. [Click to view the detailed introduction of the Pro Edition](https://1panel.pro/pricing).
## Security Information
If you discover any security issues, please refer to [SECURITY.md](/SECURITY.md).
## License
Copyright (c) 2014-2024 [FIT2CLOUD 飞致云](https://fit2cloud.com/), All rights reserved.
Licensed under The GNU General Public License version 3 (GPLv3) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
<https://www.gnu.org/licenses/gpl-3.0.html>
+257
View File
@@ -0,0 +1,257 @@
package v1
import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/utils/ai_tools/gpu"
"github.com/1Panel-dev/1Panel/backend/utils/ai_tools/gpu/common"
"github.com/1Panel-dev/1Panel/backend/utils/ai_tools/xpu"
"github.com/gin-gonic/gin"
)
// @Tags AI
// @Summary Create Ollama model
// @Accept json
// @Param request body dto.OllamaModelName true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/ollama/model [post]
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加 Ollama 模型 [name]","formatEN":"add Ollama model [name]"}
func (b *BaseApi) CreateOllamaModel(c *gin.Context) {
var req dto.OllamaModelName
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := AIToolService.Create(req.Name); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
// @Tags AI
// @Summary Rereate Ollama model
// @Accept json
// @Param request body dto.OllamaModelName true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/ollama/model/recreate [post]
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加 Ollama 模型重试 [name]","formatEN":"re-add Ollama model [name]"}
func (b *BaseApi) RecreateOllamaModel(c *gin.Context) {
var req dto.OllamaModelName
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := AIToolService.Recreate(req.Name); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
// @Tags AI
// @Summary Close Ollama model conn
// @Accept json
// @Param request body dto.OllamaModelName true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/ollama/model/close [post]
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"关闭 Ollama 模型连接 [name]","formatEN":"close conn for Ollama model [name]"}
func (b *BaseApi) CloseOllamaModel(c *gin.Context) {
var req dto.OllamaModelName
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := AIToolService.Close(req.Name); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
// @Tags AI
// @Summary Sync Ollama model list
// @Success 200 {array} dto.OllamaModelDropList
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/ollama/model/sync [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"同步 Ollama 模型列表","formatEN":"sync Ollama model list"}
func (b *BaseApi) SyncOllamaModel(c *gin.Context) {
list, err := AIToolService.Sync()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, list)
}
// @Tags AI
// @Summary Page Ollama models
// @Accept json
// @Param request body dto.SearchWithPage true "request"
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/ollama/model/search [post]
func (b *BaseApi) SearchOllamaModel(c *gin.Context) {
var req dto.SearchWithPage
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, list, err := AIToolService.Search(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, dto.PageResult{
Items: list,
Total: total,
})
}
// @Tags AI
// @Summary Page Ollama models
// @Accept json
// @Param request body dto.OllamaModelName true "request"
// @Success 200 {string} details
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/ollama/model/load [post]
func (b *BaseApi) LoadOllamaModelDetail(c *gin.Context) {
var req dto.OllamaModelName
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
detail, err := AIToolService.LoadDetail(req.Name)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, detail)
}
// @Tags AI
// @Summary Delete Ollama model
// @Accept json
// @Param request body dto.ForceDelete true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/ollama/model/del [post]
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"ollama_models","output_column":"name","output_value":"names"}],"formatZH":"删除 Ollama 模型 [names]","formatEN":"remove Ollama model [names]"}
func (b *BaseApi) DeleteOllamaModel(c *gin.Context) {
var req dto.ForceDelete
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := AIToolService.Delete(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithOutData(c)
}
// @Tags AI
// @Summary Load gpu / xpu info
// @Accept json
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/gpu/load [get]
func (b *BaseApi) LoadGpuInfo(c *gin.Context) {
ok, client := gpu.New()
if ok {
info, err := client.LoadGpuInfo()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, info)
return
}
xpuOK, xpuClient := xpu.New()
if xpuOK {
info, err := xpuClient.LoadGpuInfo()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, info)
return
}
helper.SuccessWithData(c, &common.GpuInfo{})
}
// @Tags AI
// @Summary Bind domain
// @Accept json
// @Param request body dto.OllamaBindDomain true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/domain/bind [post]
func (b *BaseApi) BindDomain(c *gin.Context) {
var req dto.OllamaBindDomain
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := AIToolService.BindDomain(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithOutData(c)
}
// @Tags AI
// @Summary Get bind domain
// @Accept json
// @Param request body dto.OllamaBindDomainReq true "request"
// @Success 200 {object} dto.OllamaBindDomainRes
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /ai/domain/get [post]
func (b *BaseApi) GetBindDomain(c *gin.Context) {
var req dto.OllamaBindDomainReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
res, err := AIToolService.GetBindDomain(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, res)
}
// Tags AI
// Summary Update bind domain
// Accept json
// Param request body dto.OllamaBindDomain true "request"
// Success 200
// Security ApiKeyAuth
// Security Timestamp
// Router /ai/domain/update [post]
func (b *BaseApi) UpdateBindDomain(c *gin.Context) {
var req dto.OllamaBindDomain
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := AIToolService.UpdateBindDomain(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithOutData(c)
}
+10 -10
View File
@@ -13,7 +13,7 @@ import (
// @Summary List apps
// @Accept json
// @Param request body request.AppSearch true "request"
// @Success 200
// @Success 200 {object} response.AppRes
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/search [post]
@@ -22,7 +22,7 @@ func (b *BaseApi) SearchApp(c *gin.Context) {
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
list, err := appService.PageApp(req)
list, err := appService.PageApp(c, req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -68,14 +68,14 @@ func (b *BaseApi) SyncApp(c *gin.Context) {
// @Success 200 {object} response.AppDTO
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/:key [get]
// @Router /apps/{key} [get]
func (b *BaseApi) GetApp(c *gin.Context) {
appKey, err := helper.GetStrParamByKey(c, "key")
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
appDTO, err := appService.GetApp(appKey)
appDTO, err := appService.GetApp(c, appKey)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -88,11 +88,11 @@ func (b *BaseApi) GetApp(c *gin.Context) {
// @Accept json
// @Param appId path integer true "app id"
// @Param version path string true "app version"
// @Param version path string true "app type"
// @Param type path string true "app type"
// @Success 200 {object} response.AppDetailDTO
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/detail/:appId/:version/:type [get]
// @Router /apps/detail/{appId}/{version}/{type} [get]
func (b *BaseApi) GetAppDetail(c *gin.Context) {
appID, err := helper.GetIntParamByKey(c, "appId")
if err != nil {
@@ -112,11 +112,11 @@ func (b *BaseApi) GetAppDetail(c *gin.Context) {
// @Tags App
// @Summary Get app detail by id
// @Accept json
// @Param appId path integer true "id"
// @Param id path integer true "id"
// @Success 200 {object} response.AppDetailDTO
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/details/:id [get]
// @Router /apps/details/{id} [get]
func (b *BaseApi) GetAppDetailByID(c *gin.Context) {
appDetailID, err := helper.GetIntParamByKey(c, "id")
if err != nil {
@@ -173,7 +173,7 @@ func (b *BaseApi) InstallApp(c *gin.Context) {
}
func (b *BaseApi) GetAppTags(c *gin.Context) {
tags, err := appService.GetAppTags()
tags, err := appService.GetAppTags(c)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -183,7 +183,7 @@ func (b *BaseApi) GetAppTags(c *gin.Context) {
// @Tags App
// @Summary Get app list update
// @Success 200
// @Success 200 {object} response.AppUpdateRes
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/checkupdate [get]
+13 -10
View File
@@ -13,7 +13,7 @@ import (
// @Summary Page app installed
// @Accept json
// @Param request body request.AppInstalledSearch true "request"
// @Success 200
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/installed/search [post]
@@ -28,7 +28,10 @@ func (b *BaseApi) SearchAppInstalled(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, list)
helper.SuccessWithData(c, dto.PageResult{
Items: list,
Total: int64(len(list)),
})
} else {
total, list, err := appInstallService.Page(req)
if err != nil {
@@ -45,7 +48,7 @@ func (b *BaseApi) SearchAppInstalled(c *gin.Context) {
// @Tags App
// @Summary List app installed
// @Accept json
// @Success 200 array dto.AppInstallInfo
// @Success 200 {array} dto.AppInstallInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/installed/list [get]
@@ -104,10 +107,11 @@ func (b *BaseApi) LoadPort(c *gin.Context) {
// @Summary Search app password by key
// @Accept json
// @Param request body dto.OperationWithNameAndType true "request"
// @Success 200 {string} response.DatabaseConn
// @Param key path string true "key"
// @Success 200 {object} response.DatabaseConn
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/installed/conninfo/:key [get]
// @Router /apps/installed/conninfo/{key} [get]
func (b *BaseApi) LoadConnInfo(c *gin.Context) {
var req dto.OperationWithNameAndType
if err := helper.CheckBindAndValidate(&req, c); err != nil {
@@ -128,7 +132,7 @@ func (b *BaseApi) LoadConnInfo(c *gin.Context) {
// @Success 200 {array} dto.AppResource
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/installed/delete/check/:appInstallId [get]
// @Router /apps/installed/delete/check/{appInstallId} [get]
func (b *BaseApi) DeleteCheck(c *gin.Context) {
appInstallId, err := helper.GetIntParamByKey(c, "appInstallId")
if err != nil {
@@ -187,7 +191,7 @@ func (b *BaseApi) OperateInstalled(c *gin.Context) {
// @Success 200 {array} response.AppService
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/services/:key [get]
// @Router /apps/services/{key} [get]
func (b *BaseApi) GetServices(c *gin.Context) {
key := c.Param("key")
services, err := appInstallService.GetServices(key)
@@ -201,7 +205,6 @@ func (b *BaseApi) GetServices(c *gin.Context) {
// @Tags App
// @Summary Search app update version by install id
// @Accept json
// @Param appInstallId path integer true "request"
// @Success 200 {array} dto.AppVersion
// @Security ApiKeyAuth
// @Security Timestamp
@@ -266,10 +269,10 @@ func (b *BaseApi) GetDefaultConfig(c *gin.Context) {
// @Summary Search params by appInstallId
// @Accept json
// @Param appInstallId path string true "request"
// @Success 200 {object} response.AppParam
// @Success 200 {object} response.AppConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /apps/installed/params/:appInstallId [get]
// @Router /apps/installed/params/{appInstallId} [get]
func (b *BaseApi) GetParams(c *gin.Context) {
appInstallId, err := helper.GetIntParamByKey(c, "appInstallId")
if err != nil {
+3 -10
View File
@@ -8,8 +8,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/captcha"
"github.com/1Panel-dev/1Panel/backend/utils/common"
"github.com/1Panel-dev/1Panel/backend/utils/geo"
"github.com/gin-gonic/gin"
)
@@ -121,7 +119,7 @@ func (b *BaseApi) GetResponsePage(c *gin.Context) {
// @Tags Auth
// @Summary Check System isDemo
// @Success 200
// @Success 200 {boolean} isDemo
// @Router /auth/demo [get]
func (b *BaseApi) CheckIsDemo(c *gin.Context) {
helper.SuccessWithData(c, global.CONF.System.IsDemo)
@@ -129,7 +127,7 @@ func (b *BaseApi) CheckIsDemo(c *gin.Context) {
// @Tags Auth
// @Summary Check System isIntl
// @Success 200
// @Success 200 {boolean} isIntl
// @Router /auth/intl [get]
func (b *BaseApi) CheckIsIntl(c *gin.Context) {
helper.SuccessWithData(c, global.CONF.System.IsIntl)
@@ -137,7 +135,7 @@ func (b *BaseApi) CheckIsIntl(c *gin.Context) {
// @Tags Auth
// @Summary Load System Language
// @Success 200
// @Success 200 {string} language
// @Router /auth/language [get]
func (b *BaseApi) GetLanguage(c *gin.Context) {
settingInfo, err := settingService.GetSettingInfo()
@@ -157,11 +155,6 @@ func saveLoginLogs(c *gin.Context, err error) {
logs.Status = constant.StatusSuccess
}
logs.IP = c.ClientIP()
address, err := geo.GetIPLocation(logs.IP, common.GetLang(c))
if err != nil {
global.LOG.Errorf("get ip location failed: %s", err)
}
logs.Agent = c.GetHeader("User-Agent")
logs.Address = address
_ = logService.CreateLoginLog(logs)
}
+50 -4
View File
@@ -64,7 +64,7 @@ func (b *BaseApi) RefreshOneDriveToken(c *gin.Context) {
// @Summary List buckets
// @Accept json
// @Param request body dto.ForBuckets true "request"
// @Success 200 {array} string
// @Success 200 {array} object
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/backup/search [post]
@@ -140,7 +140,7 @@ func (b *BaseApi) DeleteBackup(c *gin.Context) {
// @Summary Page backup records
// @Accept json
// @Param request body dto.RecordSearch true "request"
// @Success 200
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/backup/record/search [post]
@@ -162,11 +162,34 @@ func (b *BaseApi) SearchBackupRecords(c *gin.Context) {
})
}
// @Tags Backup Account
// @Summary Load backup records size
// @Accept json
// @Param request body dto.RecordSearch true "request"
// @Success 200 {array} dto.BackupFile
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/backup/record/size [post]
func (b *BaseApi) LoadBackupSize(c *gin.Context) {
var req dto.RecordSearch
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
list, err := backupService.LoadSize(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, list)
}
// @Tags Backup Account
// @Summary Page backup records by cronjob
// @Accept json
// @Param request body dto.RecordSearchByCronjob true "request"
// @Success 200
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/backup/record/search/bycronjob [post]
@@ -188,11 +211,34 @@ func (b *BaseApi) SearchBackupRecordsByCronjob(c *gin.Context) {
})
}
// @Tags Backup Account
// @Summary Load backup records size for cronjob
// @Accept json
// @Param request body dto.RecordSearchByCronjob true "request"
// @Success 200 {array} dto.BackupFile
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/backup/record/size/bycronjob [post]
func (b *BaseApi) LoadBackupSizeByCronjob(c *gin.Context) {
var req dto.RecordSearchByCronjob
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
list, err := backupService.LoadSizeByCronjob(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, list)
}
// @Tags Backup Account
// @Summary Download backup record
// @Accept json
// @Param request body dto.DownloadRecord true "request"
// @Success 200
// @Success 200 {string} filePath
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/backup/record/download [post]
+4 -2
View File
@@ -120,6 +120,7 @@ func (b *BaseApi) LoadClamBaseInfo(c *gin.Context) {
// @Summary Operate Clam
// @Accept json
// @Param request body dto.Operate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/clam/operate [post]
@@ -142,6 +143,7 @@ func (b *BaseApi) OperateClam(c *gin.Context) {
// @Summary Clean clam record
// @Accept json
// @Param request body dto.OperateByID true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/clam/record/clean [post]
@@ -189,7 +191,7 @@ func (b *BaseApi) SearchClamRecord(c *gin.Context) {
// @Summary Load clam record detail
// @Accept json
// @Param request body dto.ClamLogReq true "request"
// @Success 200
// @Success 200 {string} content
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/clam/record/log [post]
@@ -212,7 +214,7 @@ func (b *BaseApi) LoadClamRecordLog(c *gin.Context) {
// @Summary Load clam file
// @Accept json
// @Param request body dto.ClamFileReq true "request"
// @Success 200 {object} dto.PageResult
// @Success 200 {string} content
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/clam/file/search [post]
+2 -2
View File
@@ -106,7 +106,7 @@ func (b *BaseApi) SearchRedisCommand(c *gin.Context) {
// @Tags Command
// @Summary Tree commands
// @Accept json
// @Success 200 {Array} dto.CommandTree
// @Success 200 {array} dto.CommandTree
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/command/tree [get]
@@ -122,7 +122,7 @@ func (b *BaseApi) SearchCommandTree(c *gin.Context) {
// @Tags Redis Command
// @Summary List redis commands
// @Success 200 {Array} dto.RedisCommand
// @Success 200 {array} dto.RedisCommand
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/command/redis [get]
+11 -7
View File
@@ -1,13 +1,14 @@
package v1
import (
"strconv"
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
"strconv"
)
// @Tags Container
@@ -40,7 +41,7 @@ func (b *BaseApi) SearchContainer(c *gin.Context) {
// @Summary List containers
// @Accept json
// @Produce json
// @Success 200
// @Success 200 {array} string
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/list [post]
@@ -82,7 +83,7 @@ func (b *BaseApi) SearchCompose(c *gin.Context) {
// @Summary Test compose
// @Accept json
// @Param request body dto.ComposeCreate true "request"
// @Success 200
// @Success 200 {boolean} isOK
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/compose/test [post]
@@ -105,7 +106,7 @@ func (b *BaseApi) TestCompose(c *gin.Context) {
// @Summary Create compose
// @Accept json
// @Param request body dto.ComposeCreate true "request"
// @Success 200
// @Success 200 {string} log
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/compose [post]
@@ -311,7 +312,7 @@ func (b *BaseApi) CleanContainerLog(c *gin.Context) {
// @Summary Load container log
// @Accept json
// @Param request body dto.OperationWithNameAndType true "request"
// @Success 200
// @Success 200 {string} content
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/load/log [post]
@@ -390,11 +391,11 @@ func (b *BaseApi) ContainerOperation(c *gin.Context) {
// @Tags Container
// @Summary Container stats
// @Param id path integer true "container id"
// @Param id path string true "container id"
// @Success 200 {object} dto.ContainerStats
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/stats/:id [get]
// @Router /containers/stats/{id} [get]
func (b *BaseApi) ContainerStats(c *gin.Context) {
containerID, ok := c.Params.Get("id")
if !ok {
@@ -438,6 +439,7 @@ func (b *BaseApi) Inspect(c *gin.Context) {
// @Param since query string false "since"
// @Param follow query string false "follow"
// @Param tail query string false "tail"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/search/log [post]
@@ -464,6 +466,7 @@ func (b *BaseApi) ContainerLogs(c *gin.Context) {
// @Summary Download Container logs
// @Accept json
// @Param request body dto.ContainerLog true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/download/log [post]
@@ -680,6 +683,7 @@ func (b *BaseApi) ComposeUpdate(c *gin.Context) {
// @Param since query string false "date"
// @Param follow query string false "follow"
// @Param tail query string false "tail"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/compose/search/log [get]
+1 -1
View File
@@ -92,7 +92,7 @@ func (b *BaseApi) SearchJobRecords(c *gin.Context) {
// @Summary Load Cronjob record log
// @Accept json
// @Param request body dto.OperateByID true "request"
// @Success 200
// @Success 200 {string} content
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /cronjobs/records/log [post]
+2 -2
View File
@@ -34,7 +34,7 @@ func (b *BaseApi) LoadDashboardOsInfo(c *gin.Context) {
// @Success 200 {object} dto.DashboardBase
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/base/:ioOption/:netOption [get]
// @Router /dashboard/base/{ioOption}/{netOption} [get]
func (b *BaseApi) LoadDashboardBaseInfo(c *gin.Context) {
ioOption, ok := c.Params.Get("ioOption")
if !ok {
@@ -78,7 +78,7 @@ func (b *BaseApi) LoadDashboardCurrentInfo(c *gin.Context) {
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /dashboard/system/restart/:operation [post]
// @Router /dashboard/system/restart/{operation} [post]
func (b *BaseApi) SystemRestart(c *gin.Context) {
operation, ok := c.Params.Get("operation")
if !ok {
+7 -4
View File
@@ -43,7 +43,7 @@ func (b *BaseApi) CreateDatabase(c *gin.Context) {
// @Summary Check database
// @Accept json
// @Param request body dto.DatabaseCreate true "request"
// @Success 200
// @Success 200 {boolean} isOk
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /databases/db/check [post]
@@ -93,10 +93,11 @@ func (b *BaseApi) SearchDatabase(c *gin.Context) {
// @Tags Database
// @Summary List databases
// @Param type path string true "type"
// @Success 200 {array} dto.DatabaseOption
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /databases/db/list/:type [get]
// @Router /databases/db/list/{type} [get]
func (b *BaseApi) ListDatabase(c *gin.Context) {
dbType, err := helper.GetStrParamByKey(c, "type")
if err != nil {
@@ -114,10 +115,11 @@ func (b *BaseApi) ListDatabase(c *gin.Context) {
// @Tags Database
// @Summary Retrieve database list based on type
// @Param type path string true "type"
// @Success 200 {array} dto.DatabaseItem
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /databases/db/item/:type [get]
// @Router /databases/db/item/{type} [get]
func (b *BaseApi) LoadDatabaseItems(c *gin.Context) {
dbType, err := helper.GetStrParamByKey(c, "type")
if err != nil {
@@ -135,10 +137,11 @@ func (b *BaseApi) LoadDatabaseItems(c *gin.Context) {
// @Tags Database
// @Summary Get databases
// @Param name path string true "name"
// @Success 200 {object} dto.DatabaseInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /databases/db/:name [get]
// @Router /databases/db/{name} [get]
func (b *BaseApi) GetDatabase(c *gin.Context) {
name, err := helper.GetStrParamByKey(c, "name")
if err != nil {
+1 -1
View File
@@ -34,7 +34,7 @@ func (b *BaseApi) LoadDBBaseInfo(c *gin.Context) {
// @Summary Load Database conf
// @Accept json
// @Param request body dto.OperationWithNameAndType true "request"
// @Success 200
// @Success 200 {string} content
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /databases/common/load/file [post]
+1
View File
@@ -217,6 +217,7 @@ func (b *BaseApi) ListDBName(c *gin.Context) {
// @Summary Load mysql database from remote
// @Accept json
// @Param request body dto.MysqlLoadDB true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /databases/load [post]
+3 -1
View File
@@ -168,9 +168,11 @@ func (b *BaseApi) SearchPostgresql(c *gin.Context) {
// @Summary Load postgresql database from remote
// @Accept json
// @Param request body dto.PostgresqlLoadDB true "request"
// @Param database path string true "database"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /databases/pg/:database/load [post]
// @Router /databases/pg/{database}/load [post]
func (b *BaseApi) LoadPostgresqlDBFromRemote(c *gin.Context) {
database, err := helper.GetStrParamByKey(c, "database")
if err != nil {
+4 -4
View File
@@ -28,7 +28,7 @@ func (b *BaseApi) LoadDeviceBaseInfo(c *gin.Context) {
// @Tags Device
// @Summary list time zone options
// @Accept json
// @Success 200 {Array} string
// @Success 200 {array} string
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/device/zone/options [get]
@@ -46,7 +46,7 @@ func (b *BaseApi) LoadTimeOption(c *gin.Context) {
// @Summary load conf
// @Accept json
// @Param request body dto.OperationWithName true "request"
// @Success 200
// @Success 200 {array} string
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/device/conf [post]
@@ -185,7 +185,7 @@ func (b *BaseApi) UpdateDeviceSwap(c *gin.Context) {
// @Summary Check device DNS conf
// @Accept json
// @Param request body dto.SettingUpdate true "request"
// @Success 200
// @Success 200 {boolean} data
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/device/check/dns [post]
@@ -206,7 +206,7 @@ func (b *BaseApi) CheckDNS(c *gin.Context) {
// @Tags Device
// @Summary Scan system
// @Success 200
// @Success 200 {object} dto.CleanData
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/scan [post]
+2
View File
@@ -15,6 +15,8 @@ var (
appService = service.NewIAppService()
appInstallService = service.NewIAppInstalledService()
AIToolService = service.NewIAIToolService()
containerService = service.NewIContainerService()
composeTemplateService = service.NewIComposeTemplateService()
imageRepoService = service.NewIImageRepoService()
+4 -2
View File
@@ -29,7 +29,7 @@ func (b *BaseApi) LoadFail2BanBaseInfo(c *gin.Context) {
// @Summary Page fail2ban ip list
// @Accept json
// @Param request body dto.Fail2BanSearch true "request"
// @Success 200 {Array} string
// @Success 200 {array} string
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/fail2ban/search [post]
@@ -52,6 +52,7 @@ func (b *BaseApi) SearchFail2Ban(c *gin.Context) {
// @Summary Operate fail2ban
// @Accept json
// @Param request body dto.Operate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/fail2ban/operate [post]
@@ -74,6 +75,7 @@ func (b *BaseApi) OperateFail2Ban(c *gin.Context) {
// @Summary Operate sshd of fail2ban
// @Accept json
// @Param request body dto.Operate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/fail2ban/operate/sshd [post]
@@ -116,7 +118,7 @@ func (b *BaseApi) UpdateFail2BanConf(c *gin.Context) {
// @Tags Fail2ban
// @Summary Load fail2ban conf
// @Accept json
// @Success 200
// @Success 200 {string} file
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/fail2ban/load/conf [get]
+2 -2
View File
@@ -12,7 +12,7 @@ import (
// @Summary List favorites
// @Accept json
// @Param request body dto.PageInfo true "request"
// @Success 200
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /files/favorite/search [post]
@@ -36,7 +36,7 @@ func (b *BaseApi) SearchFavorite(c *gin.Context) {
// @Summary Create favorite
// @Accept json
// @Param request body request.FavoriteCreate true "request"
// @Success 200
// @Success 200 {object} model.Favorite
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /files/favorite [post]
+26 -7
View File
@@ -39,19 +39,19 @@ func (b *BaseApi) ListFiles(c *gin.Context) {
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
files, err := fileService.GetFileList(req)
fileList, err := fileService.GetFileList(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, files)
helper.SuccessWithData(c, fileList)
}
// @Tags File
// @Summary Page file
// @Accept json
// @Param request body request.SearchUploadWithPage true "request"
// @Success 200 {array} response.FileInfo
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /files/upload/search [post]
@@ -290,6 +290,7 @@ func (b *BaseApi) SaveContent(c *gin.Context) {
// @Tags File
// @Summary Upload file
// @Accept multipart/form-data
// @Param file formData file true "request"
// @Success 200
// @Security ApiKeyAuth
@@ -400,7 +401,7 @@ func (b *BaseApi) UploadFiles(c *gin.Context) {
// @Summary Check file exist
// @Accept json
// @Param request body request.FilePathCheck true "request"
// @Success 200
// @Success 200 {boolean} isOk
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /files/check [post]
@@ -416,6 +417,23 @@ func (b *BaseApi) CheckFile(c *gin.Context) {
helper.SuccessWithData(c, true)
}
// @Tags File
// @Summary Batch check file exist
// @Accept json
// @Param request body request.FilePathsCheck true "request"
// @Success 200 {array} response.ExistFileInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /files/batch/check [post]
func (b *BaseApi) BatchCheckFiles(c *gin.Context) {
var req request.FilePathsCheck
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
fileList := fileService.BatchCheckFiles(req)
helper.SuccessWithData(c, fileList)
}
// @Tags File
// @Summary Change file name
// @Accept json
@@ -441,7 +459,7 @@ func (b *BaseApi) ChangeFileName(c *gin.Context) {
// @Summary Wget file
// @Accept json
// @Param request body request.FileWget true "request"
// @Success 200
// @Success 200 {object} response.FileWgetRes
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /files/wget [post]
@@ -583,7 +601,7 @@ func (b *BaseApi) DownloadChunkFiles(c *gin.Context) {
// @Summary Load file size
// @Accept json
// @Param request body request.DirSizeReq true "request"
// @Success 200
// @Success 200 {object} response.DirSizeRes
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /files/size [post]
@@ -662,6 +680,7 @@ func mergeChunks(fileName string, fileDir string, dstDir string, chunkCount int,
// @Tags File
// @Summary Chunk upload file
// @Accept multipart/form-data
// @Param file formData file true "request"
// @Success 200
// @Security ApiKeyAuth
@@ -784,7 +803,7 @@ func (b *BaseApi) Keys(c *gin.Context) {
// @Tags File
// @Summary Read file by Line
// @Param request body request.FileReadByLineReq true "request"
// @Success 200
// @Success 200 {object} response.FileLineContent
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /files/read [post]
+2 -2
View File
@@ -53,7 +53,7 @@ func (b *BaseApi) SearchFirewallRule(c *gin.Context) {
// @Summary Page firewall status
// @Accept json
// @Param request body dto.FirewallOperation true "request"
// @Success 200 {object} dto.PageResult
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/firewall/operate [post]
@@ -203,7 +203,7 @@ func (b *BaseApi) UpdatePortRule(c *gin.Context) {
}
// @Tags Firewall
// @Summary Uodate address group
// @Summary Update address group
// @Accept json
// @Param request body dto.AddrRuleUpdate true "request"
// @Success 200
+1
View File
@@ -55,6 +55,7 @@ func (b *BaseApi) LoadFtpLogInfo(c *gin.Context) {
// @Summary Operate FTP
// @Accept json
// @Param request body dto.Operate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /toolbox/ftp/operate [post]
+4 -4
View File
@@ -12,7 +12,7 @@ import (
// @Summary Create host
// @Accept json
// @Param request body dto.HostOperate true "request"
// @Success 200
// @Success 200 {object} dto.HostInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts [post]
@@ -35,7 +35,7 @@ func (b *BaseApi) CreateHost(c *gin.Context) {
// @Summary Test host conn by info
// @Accept json
// @Param request body dto.HostConnTest true "request"
// @Success 200
// @Success 200 {boolean} connStatus
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/test/byinfo [post]
@@ -56,7 +56,7 @@ func (b *BaseApi) TestByInfo(c *gin.Context) {
// @Success 200 {boolean} connStatus
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/test/byid/:id [post]
// @Router /hosts/test/byid/{id} [post]
func (b *BaseApi) TestByID(c *gin.Context) {
id, err := helper.GetParamID(c)
if err != nil {
@@ -95,7 +95,7 @@ func (b *BaseApi) HostTree(c *gin.Context) {
// @Summary Page host
// @Accept json
// @Param request body dto.SearchHostWithPage true "request"
// @Success 200 {array} dto.HostTree
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/search [post]
+5 -5
View File
@@ -11,7 +11,7 @@ import (
// @Summary Get tool status
// @Accept json
// @Param request body request.HostToolReq true "request"
// @Success 200
// @Success 200 {object} response.HostToolRes
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /host/tool [post]
@@ -77,7 +77,7 @@ func (b *BaseApi) OperateTool(c *gin.Context) {
// @Summary Get tool config
// @Accept json
// @Param request body request.HostToolConfig true "request"
// @Success 200
// @Success 200 {object} response.HostToolConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /host/tool/config [post]
@@ -100,7 +100,7 @@ func (b *BaseApi) OperateToolConfig(c *gin.Context) {
// @Summary Get tool logs
// @Accept json
// @Param request body request.HostToolLogReq true "request"
// @Success 200
// @Success 200 {string} logContent
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /host/tool/log [post]
@@ -144,7 +144,7 @@ func (b *BaseApi) OperateProcess(c *gin.Context) {
// @Tags Host tool
// @Summary Get Supervisor process config
// @Accept json
// @Success 200
// @Success 200 {object} response.SupervisorProcessConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /host/tool/supervisor/process [get]
@@ -161,7 +161,7 @@ func (b *BaseApi) GetProcess(c *gin.Context) {
// @Summary Get Supervisor process config
// @Accept json
// @Param request body request.SupervisorProcessFileReq true "request"
// @Success 200
// @Success 200 {string} content
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /host/tool/supervisor/process/file [post]
+2 -2
View File
@@ -94,7 +94,7 @@ func (b *BaseApi) ImageBuild(c *gin.Context) {
// @Summary Pull image
// @Accept json
// @Param request body dto.ImagePull true "request"
// @Success 200 {string} log
// @Success 200 {string} logPath
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/image/pull [post]
@@ -118,7 +118,7 @@ func (b *BaseApi) ImagePull(c *gin.Context) {
// @Summary Push image
// @Accept json
// @Param request body dto.ImagePush true "request"
// @Success 200 {string} log
// @Success 200 {string} logPath
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /containers/image/push [post]
+4 -4
View File
@@ -21,7 +21,7 @@ func (b *BaseApi) GetLoginLogs(c *gin.Context) {
return
}
total, list, err := logService.PageLoginLog(req)
total, list, err := logService.PageLoginLog(c, req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
@@ -63,7 +63,7 @@ func (b *BaseApi) GetOperationLogs(c *gin.Context) {
// @Summary Clean operation logs
// @Accept json
// @Param request body dto.CleanLog true "request"
// @Success 200 {object} dto.PageResult
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /logs/clean [post]
@@ -84,7 +84,7 @@ func (b *BaseApi) CleanLogs(c *gin.Context) {
// @Tags Logs
// @Summary Load system log files
// @Success 200
// @Success 200 {array} string
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /logs/system/files [get]
@@ -100,7 +100,7 @@ func (b *BaseApi) GetSystemFiles(c *gin.Context) {
// @Tags Logs
// @Summary Load system logs
// @Success 200
// @Success 200 {string} data
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /logs/system [post]
+1 -1
View File
@@ -18,7 +18,7 @@ import (
// @Tags Monitor
// @Summary Load monitor datas
// @Param request body dto.MonitorSearch true "request"
// @Success 200
// @Success 200 {array} dto.MonitorData
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/monitor/search [post]
+1 -1
View File
@@ -9,7 +9,7 @@ import (
// @Tags OpenResty
// @Summary Load OpenResty conf
// @Success 200 {object} response.FileInfo
// @Success 200 {object} response.NginxFile
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /openresty [get]
+5 -2
View File
@@ -12,7 +12,7 @@ import (
// @Summary Page Extensions
// @Accept json
// @Param request body request.PHPExtensionsSearch true "request"
// @Success 200 {array} response.PHPExtensionsDTO
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/php/extensions/search [post]
@@ -27,7 +27,10 @@ func (b *BaseApi) PagePHPExtensions(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, list)
helper.SuccessWithData(c, dto.PageResult{
Total: int64(len(list)),
Items: list,
})
} else {
total, list, err := phpExtensionsService.Page(req)
if err != nil {
+2 -2
View File
@@ -12,7 +12,7 @@ import (
// @Summary List Recycle Bin files
// @Accept json
// @Param request body dto.PageInfo true "request"
// @Success 200
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /files/recycle/search [post]
@@ -72,7 +72,7 @@ func (b *BaseApi) ClearRecycleBinFile(c *gin.Context) {
// @Tags File
// @Summary Get Recycle Bin status
// @Accept json
// @Success 200
// @Success 200 {string} content
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /files/recycle/status [get]
+6 -6
View File
@@ -12,7 +12,7 @@ import (
// @Summary List runtimes
// @Accept json
// @Param request body request.RuntimeSearch true "request"
// @Success 200
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/search [post]
@@ -36,7 +36,7 @@ func (b *BaseApi) SearchRuntimes(c *gin.Context) {
// @Summary Create runtime
// @Accept json
// @Param request body request.RuntimeCreate true "request"
// @Success 200
// @Success 200 {object} model.Runtime
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes [post]
@@ -115,10 +115,10 @@ func (b *BaseApi) UpdateRuntime(c *gin.Context) {
// @Summary Get runtime
// @Accept json
// @Param id path string true "request"
// @Success 200
// @Success 200 {object} response.RuntimeDTO
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/:id [get]
// @Router /runtimes/{id} [get]
func (b *BaseApi) GetRuntime(c *gin.Context) {
id, err := helper.GetIntParamByKey(c, "id")
if err != nil {
@@ -137,7 +137,7 @@ func (b *BaseApi) GetRuntime(c *gin.Context) {
// @Summary Get Node package scripts
// @Accept json
// @Param request body request.NodePackageReq true "request"
// @Success 200
// @Success 200 {array} response.PackageScripts
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/node/package [post]
@@ -180,7 +180,7 @@ func (b *BaseApi) OperateRuntime(c *gin.Context) {
// @Summary Get Node modules
// @Accept json
// @Param request body request.NodeModuleReq true "request"
// @Success 200
// @Success 200 {array} response.NodeModule
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/node/modules [post]
+23 -3
View File
@@ -3,8 +3,10 @@ package v1
import (
"encoding/base64"
"errors"
"fmt"
"os"
"path"
"regexp"
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
@@ -53,11 +55,21 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) {
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if req.Key == "SecurityEntrance" {
if !checkEntrancePattern(req.Value) {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, fmt.Errorf("the format of the security entrance %s is incorrect.", req.Value))
return
}
}
if err := settingService.Update(req.Key, req.Value); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
if req.Key == "SecurityEntrance" {
entranceValue := base64.StdEncoding.EncodeToString([]byte(req.Value))
c.SetCookie("SecurityEntrance", entranceValue, 0, "", "", false, true)
}
helper.SuccessWithData(c, nil)
}
@@ -160,7 +172,7 @@ func (b *BaseApi) UpdateSSL(c *gin.Context) {
// @Tags System Setting
// @Summary Load system cert info
// @Success 200 {object} dto.SettingInfo
// @Success 200 {object} dto.SSLInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/ssl/info [get]
@@ -192,7 +204,7 @@ func (b *BaseApi) DownloadSSL(c *gin.Context) {
// @Tags System Setting
// @Summary Load system address
// @Accept json
// @Success 200
// @Success 200 {array} string
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/interface [get]
@@ -346,7 +358,7 @@ func (b *BaseApi) MFABind(c *gin.Context) {
// @Tags System Setting
// @Summary Generate api key
// @Accept json
// @Success 200
// @Success 200 {string} apiKey
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/api/config/generate/key [post]
@@ -391,3 +403,11 @@ func (b *BaseApi) UpdateApiConfig(c *gin.Context) {
}
helper.SuccessWithData(c, nil)
}
func checkEntrancePattern(val string) bool {
if len(val) == 0 {
return true
}
result, _ := regexp.MatchString("^[a-zA-Z0-9]{5,116}$", val)
return result
}
+2 -2
View File
@@ -55,7 +55,7 @@ func (b *BaseApi) ImportSnapshot(c *gin.Context) {
// @Summary Load Snapshot status
// @Accept json
// @Param request body dto.OperateByID true "request"
// @Success 200
// @Success 200 {object} dto.SnapshotStatus
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/snapshot/status [post]
@@ -124,7 +124,7 @@ func (b *BaseApi) SearchSnapshot(c *gin.Context) {
// @Summary Load system snapshot size
// @Accept json
// @Param request body dto.PageSnapshot true "request"
// @Success 200
// @Success 200 {array} dto.SnapshotFile
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/snapshot/size [post]
+3 -2
View File
@@ -26,6 +26,7 @@ func (b *BaseApi) GetSSHInfo(c *gin.Context) {
// @Summary Operate SSH
// @Accept json
// @Param request body dto.Operate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /host/ssh/operate [post]
@@ -113,7 +114,7 @@ func (b *BaseApi) GenerateSSH(c *gin.Context) {
// @Summary Load host SSH secret
// @Accept json
// @Param request body dto.GenerateLoad true "request"
// @Success 200
// @Success 200 {string} data
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /host/ssh/secret [post]
@@ -155,7 +156,7 @@ func (b *BaseApi) LoadSSHLogs(c *gin.Context) {
// @Tags SSH
// @Summary Load host SSH conf
// @Success 200
// @Success 200 {string} data
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /host/ssh/conf [get]
+65
View File
@@ -10,6 +10,7 @@ import (
"time"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/app/service"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/copier"
@@ -146,6 +147,70 @@ func (b *BaseApi) RedisWsSsh(c *gin.Context) {
}
}
func (b *BaseApi) OllamaWsSsh(c *gin.Context) {
wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
global.LOG.Errorf("gin context http handler failed, err: %v", err)
return
}
defer wsConn.Close()
if global.CONF.System.IsDemo {
if wshandleError(wsConn, errors.New(" demo server, prohibit this operation!")) {
return
}
}
cols, err := strconv.Atoi(c.DefaultQuery("cols", "80"))
if wshandleError(wsConn, errors.WithMessage(err, "invalid param cols in request")) {
return
}
rows, err := strconv.Atoi(c.DefaultQuery("rows", "40"))
if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) {
return
}
name := c.Query("name")
if cmd.CheckIllegal(name) {
if wshandleError(wsConn, errors.New(" The command contains illegal characters.")) {
return
}
}
container, err := service.LoadContainerName()
if wshandleError(wsConn, errors.WithMessage(err, " load container name for ollama failed")) {
return
}
commands := []string{"ollama", "run", name}
pidMap := loadMapFromDockerTop(container)
fmt.Println("pidMap")
for k, v := range pidMap {
fmt.Println(k, v)
}
itemCmds := append([]string{"exec", "-it", container}, commands...)
slave, err := terminal.NewCommand(itemCmds)
if wshandleError(wsConn, err) {
return
}
defer killBash(container, strings.Join(commands, " "), pidMap)
defer slave.Close()
tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false)
if wshandleError(wsConn, err) {
return
}
quitChan := make(chan bool, 3)
tty.Start(quitChan)
go slave.Wait(quitChan)
<-quitChan
global.LOG.Info("websocket finished")
if wshandleError(wsConn, err) {
return
}
}
func (b *BaseApi) ContainerWsSsh(c *gin.Context) {
wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
+1 -1
View File
@@ -26,7 +26,7 @@ func (b *BaseApi) GetUpgradeInfo(c *gin.Context) {
// @Summary Load release notes by version
// @Accept json
// @Param request body dto.Upgrade true "request"
// @Success 200
// @Success 200 {string} notes
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /settings/upgrade [get]
+39 -14
View File
@@ -51,7 +51,7 @@ func (b *BaseApi) GetWebsites(c *gin.Context) {
// @Tags Website
// @Summary List website names
// @Success 200 {array} string
// @Success 200 {array} response.WebsiteOption
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/options [get]
@@ -166,7 +166,7 @@ func (b *BaseApi) UpdateWebsite(c *gin.Context) {
// @Success 200 {object} response.WebsiteDTO
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/:id [get]
// @Router /websites/{id} [get]
func (b *BaseApi) GetWebsite(c *gin.Context) {
id, err := helper.GetParamID(c)
if err != nil {
@@ -185,10 +185,11 @@ func (b *BaseApi) GetWebsite(c *gin.Context) {
// @Summary Search website nginx by id
// @Accept json
// @Param id path integer true "request"
// @Param type path string true "type"
// @Success 200 {object} response.FileInfo
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/:id/config/:type [get]
// @Router /websites/{id}/config/{type} [get]
func (b *BaseApi) GetWebsiteNginx(c *gin.Context) {
id, err := helper.GetParamID(c)
if err != nil {
@@ -254,7 +255,7 @@ func (b *BaseApi) UpdateNginxConfig(c *gin.Context) {
// @Success 200 {object} response.WebsiteHTTPS
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/:id/https [get]
// @Router /websites/{id}/https [get]
func (b *BaseApi) GetHTTPSConfig(c *gin.Context) {
id, err := helper.GetParamID(c)
if err != nil {
@@ -272,11 +273,12 @@ func (b *BaseApi) GetHTTPSConfig(c *gin.Context) {
// @Tags Website HTTPS
// @Summary Update https conf
// @Accept json
// @Param id path integer true "request"
// @Param request body request.WebsiteHTTPSOp true "request"
// @Success 200 {object} response.WebsiteHTTPS
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/:id/https [post]
// @Router /websites/{id}/https [post]
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] https 配置","formatEN":"Update website https [domain] conf"}
func (b *BaseApi) UpdateHTTPSConfig(c *gin.Context) {
var req request.WebsiteHTTPSOp
@@ -386,7 +388,7 @@ func (b *BaseApi) ChangeDefaultServer(c *gin.Context) {
// @Success 200 {object} response.PHPConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/php/config/:id [get]
// @Router /websites/php/config/{id} [get]
func (b *BaseApi) GetWebsitePHPConfig(c *gin.Context) {
id, err := helper.GetParamID(c)
if err != nil {
@@ -468,7 +470,7 @@ func (b *BaseApi) ChangePHPVersion(c *gin.Context) {
// @Summary Get rewrite conf
// @Accept json
// @Param request body request.NginxRewriteReq true "request"
// @Success 200
// @Success 200 {object} response.NginxRewriteRes
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/rewrite [post]
@@ -552,7 +554,7 @@ func (b *BaseApi) UpdateSiteDirPermission(c *gin.Context) {
// @Summary Get proxy conf
// @Accept json
// @Param request body request.WebsiteProxyReq true "request"
// @Success 200
// @Success 200 {array} request.WebsiteProxyConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/proxies [post]
@@ -569,6 +571,28 @@ func (b *BaseApi) GetProxyConfig(c *gin.Context) {
helper.SuccessWithData(c, res)
}
// @Tags Website
// @Summary Delete proxy conf
// @Accept json
// @Param request body request.WebsiteProxyDel true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/proxies/del [post]
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"删除网站 [domain] 反向代理配置","formatEN":"Delete domain [domain] proxy config"}
func (b *BaseApi) DeleteProxyConfig(c *gin.Context) {
var req request.WebsiteProxyDel
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := websiteService.DeleteProxy(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithOutData(c)
}
// @Tags Website
// @Summary Update proxy conf
// @Accept json
@@ -616,7 +640,7 @@ func (b *BaseApi) UpdateProxyConfigFile(c *gin.Context) {
// @Summary Get AuthBasic conf
// @Accept json
// @Param request body request.NginxAuthReq true "request"
// @Success 200
// @Success 200 {object} response.NginxAuthRes
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/auths [post]
@@ -657,7 +681,7 @@ func (b *BaseApi) UpdateAuthConfig(c *gin.Context) {
// @Summary Get AntiLeech conf
// @Accept json
// @Param request body request.NginxCommonReq true "request"
// @Success 200
// @Success 200 {object} response.NginxAntiLeechRes
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/leech [post]
@@ -720,7 +744,7 @@ func (b *BaseApi) UpdateRedirectConfig(c *gin.Context) {
// @Summary Get redirect conf
// @Accept json
// @Param request body request.WebsiteProxyReq true "request"
// @Success 200
// @Success 200 {array} response.NginxRedirectConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/redirect [post]
@@ -762,7 +786,7 @@ func (b *BaseApi) UpdateRedirectConfigFile(c *gin.Context) {
// @Summary Get website dir
// @Accept json
// @Param request body request.WebsiteCommonReq true "request"
// @Success 200
// @Success 200 {object} response.WebsiteDirConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/dir [post]
@@ -782,10 +806,11 @@ func (b *BaseApi) GetDirConfig(c *gin.Context) {
// @Tags Website
// @Summary Get default html
// @Accept json
// @Success 200 {object} response.FileInfo
// @Param type path string true "type"
// @Success 200 {object} response.WebsiteHtmlRes
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/default/html/:type [get]
// @Router /websites/default/html/{type} [get]
func (b *BaseApi) GetDefaultHtml(c *gin.Context) {
resourceType, err := helper.GetStrParamByKey(c, "type")
if err != nil {
+2 -2
View File
@@ -32,7 +32,7 @@ func (b *BaseApi) DeleteWebDomain(c *gin.Context) {
// @Summary Create website domain
// @Accept json
// @Param request body request.WebsiteDomainCreate true "request"
// @Success 200 {object} model.WebsiteDomain
// @Success 200 {array} model.WebsiteDomain
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/domains [post]
@@ -57,7 +57,7 @@ func (b *BaseApi) CreateWebDomain(c *gin.Context) {
// @Success 200 {array} model.WebsiteDomain
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/domains/:websiteId [get]
// @Router /websites/domains/{websiteId} [get]
func (b *BaseApi) GetWebDomains(c *gin.Context) {
websiteId, err := helper.GetIntParamByKey(c, "websiteId")
if err != nil {
+5 -5
View File
@@ -17,7 +17,7 @@ import (
// @Summary Page website ssl
// @Accept json
// @Param request body request.WebsiteSSLSearch true "request"
// @Success 200
// @Success 200 {array} response.WebsiteSSLDTO
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/ssl/search [post]
@@ -135,10 +135,10 @@ func (b *BaseApi) DeleteWebsiteSSL(c *gin.Context) {
// @Summary Search website ssl by website id
// @Accept json
// @Param websiteId path integer true "request"
// @Success 200
// @Success 200 {object} response.WebsiteSSLDTO
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/ssl/website/:websiteId [get]
// @Router /websites/ssl/website/{websiteId} [get]
func (b *BaseApi) GetWebsiteSSLByWebsiteId(c *gin.Context) {
websiteId, err := helper.GetIntParamByKey(c, "websiteId")
if err != nil {
@@ -157,10 +157,10 @@ func (b *BaseApi) GetWebsiteSSLByWebsiteId(c *gin.Context) {
// @Summary Search website ssl by id
// @Accept json
// @Param id path integer true "request"
// @Success 200
// @Success 200 {object} response.WebsiteSSLDTO
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/ssl/:id [get]
// @Router /websites/ssl/{id} [get]
func (b *BaseApi) GetWebsiteSSLById(c *gin.Context) {
id, err := helper.GetParamID(c)
if err != nil {
+45
View File
@@ -0,0 +1,45 @@
package dto
import "time"
type OllamaModelInfo struct {
ID uint `json:"id"`
Name string `json:"name"`
Size string `json:"size"`
From string `json:"from"`
LogFileExist bool `json:"logFileExist"`
Status string `json:"status"`
Message string `json:"message"`
CreatedAt time.Time `json:"createdAt"`
}
type OllamaModelDropList struct {
ID uint `json:"id"`
Name string `json:"name"`
}
type OllamaModelName struct {
Name string `json:"name"`
}
type OllamaBindDomain struct {
Domain string `json:"domain" validate:"required"`
AppInstallID uint `json:"appInstallID" validate:"required"`
SSLID uint `json:"sslID"`
WebsiteID uint `json:"websiteID"`
IPList string `json:"ipList"`
}
type OllamaBindDomainReq struct {
AppInstallID uint `json:"appInstallID" validate:"required"`
}
type OllamaBindDomainRes struct {
Domain string `json:"domain"`
SSLID uint `json:"sslID"`
AcmeAccountID uint `json:"acmeAccountID"`
AllowIPs []string `json:"allowIPs"`
WebsiteID uint `json:"websiteID"`
ConnUrl string `json:"connUrl"`
}
+21 -10
View File
@@ -1,9 +1,5 @@
package dto
import (
"github.com/1Panel-dev/1Panel/backend/app/model"
)
type AppDatabase struct {
ServiceName string `json:"PANEL_DB_HOST"`
DbName string `json:"PANEL_DB_NAME"`
@@ -62,7 +58,7 @@ type AppDefine struct {
}
type LocalAppAppDefine struct {
AppProperty model.App `json:"additionalProperties" yaml:"additionalProperties"`
AppProperty AppProperty `json:"additionalProperties" yaml:"additionalProperties"`
}
type LocalAppParam struct {
@@ -82,8 +78,9 @@ type AppProperty struct {
Name string `json:"name"`
Type string `json:"type"`
Tags []string `json:"tags"`
ShortDescZh string `json:"shortDescZh"`
ShortDescEn string `json:"shortDescEn"`
ShortDescZh string `json:"shortDescZh" yaml:"shortDescZh"`
ShortDescEn string `json:"shortDescEn" yaml:"shortDescEn"`
Description Locale `json:"description"`
Key string `json:"key"`
Required []string `json:"Required"`
CrossVersionUpdate bool `json:"crossVersionUpdate"`
@@ -93,6 +90,7 @@ type AppProperty struct {
Github string `json:"github"`
Document string `json:"document"`
Version float64 `json:"version"`
GpuSupport bool `json:"gpuSupport"`
}
type AppConfigVersion struct {
@@ -104,9 +102,21 @@ type AppConfigVersion struct {
}
type Tag struct {
Key string `json:"key"`
Name string `json:"name"`
Sort int `json:"sort"`
Key string `json:"key"`
Name string `json:"name"`
Sort int `json:"sort"`
Locales Locale `json:"locales"`
}
type Locale struct {
En string `json:"en"`
Ja string `json:"ja"`
Ms string `json:"ms"`
PtBr string `json:"pt-br" yaml:"pt-br"`
Ru string `json:"ru"`
ZhHant string `json:"zh-hant" yaml:"zh-hant"`
Zh string `json:"zh"`
Ko string `json:"ko"`
}
type AppForm struct {
@@ -118,6 +128,7 @@ type AppFormFields struct {
Type string `json:"type"`
LabelZh string `json:"labelZh"`
LabelEn string `json:"labelEn"`
Label Locale `json:"label"`
Required bool `json:"required"`
Default interface{} `json:"default"`
EnvKey string `json:"envKey"`
+1 -1
View File
@@ -29,7 +29,7 @@ type Login struct {
Captcha string `json:"captcha"`
CaptchaID string `json:"captchaID"`
AuthMethod string `json:"authMethod" validate:"required,oneof=jwt session"`
Language string `json:"language" validate:"required,oneof=zh en tw"`
Language string `json:"language" validate:"required,oneof=zh en tw ja ko ru ms 'pt-BR'"`
}
type MFALogin struct {
+6 -1
View File
@@ -21,6 +21,12 @@ type BackupInfo struct {
Vars string `json:"vars"`
}
type BackupFile struct {
ID uint `json:"id"`
Name string `json:"name"`
Size int64 `json:"size"`
}
type OneDriveInfo struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
@@ -66,7 +72,6 @@ type BackupRecords struct {
BackupType string `json:"backupType"`
FileDir string `json:"fileDir"`
FileName string `json:"fileName"`
Size int64 `json:"size"`
}
type DownloadRecord struct {
+5
View File
@@ -52,3 +52,8 @@ type OperationWithNameAndType struct {
Name string `json:"name"`
Type string `json:"type" validate:"required"`
}
type ForceDelete struct {
IDs []uint `json:"ids"`
ForceDelete bool `json:"forceDelete"`
}
+1 -1
View File
@@ -19,7 +19,7 @@ type Fail2BanSearch struct {
}
type Fail2BanUpdate struct {
Key string `json:"key" validate:"required,oneof=port bantime findtime maxretry banaction logpath port"`
Key string `json:"key" validate:"required,oneof=port bantime findtime maxretry banaction logpath"`
Value string `json:"value"`
}
+2 -1
View File
@@ -30,7 +30,8 @@ type PortRuleOperate struct {
}
type ForwardRuleOperate struct {
Rules []struct {
ForceDelete bool `json:"forceDelete"`
Rules []struct {
Operation string `json:"operation" validate:"required,oneof=add remove"`
Num string `json:"num"`
Protocol string `json:"protocol" validate:"required,oneof=tcp udp tcp/udp"`
+1
View File
@@ -33,6 +33,7 @@ type AppContainerConfig struct {
DockerCompose string `json:"dockerCompose"`
HostMode bool `json:"hostMode"`
PullImage bool `json:"pullImage"`
GpuConfig bool `json:"gpuConfig"`
}
type AppInstalledSearch struct {
+4
View File
@@ -79,6 +79,10 @@ type FilePathCheck struct {
Path string `json:"path" validate:"required"`
}
type FilePathsCheck struct {
Paths []string `json:"paths" validate:"required"`
}
type FileWget struct {
Url string `json:"url" validate:"required"`
Path string `json:"path" validate:"required"`
+5
View File
@@ -193,6 +193,11 @@ type WebsiteProxyConfig struct {
ProxySSLName string `json:"proxySSLName"`
}
type WebsiteProxyDel struct {
ID uint `json:"id" validate:"required"`
Name string `json:"name" validate:"required"`
}
type WebsiteProxyReq struct {
ID uint `json:"id" validate:"required"`
}
+31 -27
View File
@@ -10,8 +10,8 @@ import (
)
type AppRes struct {
Items []*AppDto `json:"items"`
Total int64 `json:"total"`
Items []*AppItem `json:"items"`
Total int64 `json:"total"`
}
type AppUpdateRes struct {
@@ -23,29 +23,31 @@ type AppUpdateRes struct {
type AppDTO struct {
model.App
Installed bool `json:"installed"`
Versions []string `json:"versions"`
Tags []model.Tag `json:"tags"`
Installed bool `json:"installed"`
Versions []string `json:"versions"`
Tags []TagDTO `json:"tags"`
}
type AppDto struct {
Name string `json:"name"`
Key string `json:"key"`
ID uint `json:"id"`
ShortDescZh string `json:"shortDescZh"`
ShortDescEn string `json:"shortDescEn"`
Icon string `json:"icon"`
Type string `json:"type"`
Status string `json:"status"`
Resource string `json:"resource"`
Installed bool `json:"installed"`
Versions []string `json:"versions"`
Limit int `json:"limit"`
Tags []model.Tag `json:"tags"`
type AppItem struct {
Name string `json:"name"`
Key string `json:"key"`
ID uint `json:"id"`
Description string `json:"description"`
Icon string `json:"icon"`
Type string `json:"type"`
Status string `json:"status"`
Resource string `json:"resource"`
Installed bool `json:"installed"`
Versions []string `json:"versions"`
Limit int `json:"limit"`
Tags []TagDTO `json:"tags"`
GpuSupport bool `json:"gpuSupport"`
}
type TagDTO struct {
model.Tag
ID uint `json:"id"`
Key string `json:"key"`
Name string `json:"name"`
}
type AppInstalledCheck struct {
@@ -65,10 +67,11 @@ type AppInstalledCheck struct {
type AppDetailDTO struct {
model.AppDetail
Enable bool `json:"enable"`
Params interface{} `json:"params"`
Image string `json:"image"`
HostMode bool `json:"hostMode"`
Enable bool `json:"enable"`
Params interface{} `json:"params"`
Image string `json:"image"`
HostMode bool `json:"hostMode"`
GpuSupport bool `json:"gpuSupport"`
}
type IgnoredApp struct {
@@ -89,9 +92,10 @@ type AppInstalledDTO struct {
}
type AppDetail struct {
Website string `json:"website"`
Document string `json:"document"`
Github string `json:"github"`
Website string `json:"website"`
Document string `json:"document"`
Github string `json:"github"`
GpuSupport bool `json:"gpuSupport"`
}
type AppInstallDTO struct {
+8
View File
@@ -2,6 +2,7 @@ package response
import (
"github.com/1Panel-dev/1Panel/backend/utils/files"
"time"
)
type FileInfo struct {
@@ -46,3 +47,10 @@ type FileLineContent struct {
type FileExist struct {
Exist bool `json:"exist"`
}
type ExistFileInfo struct {
Name string `json:"name"`
Path string `json:"path"`
Size float64 `json:"size"`
ModTime time.Time `json:"modTime"`
}
+2
View File
@@ -70,6 +70,7 @@ type SettingInfo struct {
ApiInterfaceStatus string `json:"apiInterfaceStatus"`
ApiKey string `json:"apiKey"`
IpWhiteList string `json:"ipWhiteList"`
ApiKeyValidityTime string `json:"apiKeyValidityTime"`
}
type SettingUpdate struct {
@@ -240,4 +241,5 @@ type ApiInterfaceConfig struct {
ApiInterfaceStatus string `json:"apiInterfaceStatus"`
ApiKey string `json:"apiKey"`
IpWhiteList string `json:"ipWhiteList"`
ApiKeyValidityTime string `json:"apiKeyValidityTime"`
}
+11
View File
@@ -0,0 +1,11 @@
package model
type OllamaModel struct {
BaseModel
Name string `json:"name"`
Size string `json:"size"`
From string `json:"from"`
Status string `json:"status"`
Message string `json:"message"`
}
+18 -1
View File
@@ -1,7 +1,10 @@
package model
import (
"encoding/json"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/utils/common"
"github.com/gin-gonic/gin"
"path/filepath"
"strings"
)
@@ -12,10 +15,12 @@ type App struct {
Key string `json:"key" gorm:"type:varchar(64);not null;"`
ShortDescZh string `json:"shortDescZh" yaml:"shortDescZh" gorm:"type:longtext;"`
ShortDescEn string `json:"shortDescEn" yaml:"shortDescEn" gorm:"type:longtext;"`
Description string `json:"description"`
Icon string `json:"icon" gorm:"type:longtext;"`
Type string `json:"type" gorm:"type:varchar(64);not null"`
Status string `json:"status" gorm:"type:varchar(64);not null"`
Required string `json:"required" gorm:"type:varchar(64);"`
GpuSupport bool `json:"gpuSupport"`
CrossVersionUpdate bool `json:"crossVersionUpdate" yaml:"crossVersionUpdate"`
Limit int `json:"limit" gorm:"type:Integer;not null"`
Website string `json:"website" gorm:"type:varchar(64);not null"`
@@ -36,8 +41,20 @@ func (i *App) IsLocalApp() bool {
}
func (i *App) GetAppResourcePath() string {
if i.IsLocalApp() {
//这里要去掉本地应用的local前缀
return filepath.Join(constant.LocalAppResourceDir, strings.TrimPrefix(i.Key, "local"))
}
return filepath.Join(constant.RemoteAppResourceDir, i.Key)
}
func (i *App) GetDescription(ctx *gin.Context) string {
var translations = make(map[string]string)
_ = json.Unmarshal([]byte(i.Description), &translations)
lang := strings.ToLower(common.GetLang(ctx))
if desc, ok := translations[lang]; ok && desc != "" {
return desc
}
if lang == "zh" {
return i.ShortDescZh
}
return i.ShortDescEn
}
+4 -3
View File
@@ -2,7 +2,8 @@ package model
type Tag struct {
BaseModel
Key string `json:"key" gorm:"type:varchar(64);not null"`
Name string `json:"name" gorm:"type:varchar(64);not null"`
Sort int `json:"sort" gorm:"type:int;not null;default:1"`
Key string `json:"key" gorm:"type:varchar(64);not null"`
Name string `json:"name" gorm:"type:varchar(64);not null"`
Translations string `json:"translations"`
Sort int `json:"sort" gorm:"type:int;not null;default:1"`
}
+69
View File
@@ -0,0 +1,69 @@
package repo
import (
"github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/global"
)
type AiRepo struct{}
type IAiRepo interface {
Get(opts ...DBOption) (model.OllamaModel, error)
List(opts ...DBOption) ([]model.OllamaModel, error)
Page(limit, offset int, opts ...DBOption) (int64, []model.OllamaModel, error)
Create(cronjob *model.OllamaModel) error
Update(id uint, vars map[string]interface{}) error
Delete(opts ...DBOption) error
}
func NewIAiRepo() IAiRepo {
return &AiRepo{}
}
func (u *AiRepo) Get(opts ...DBOption) (model.OllamaModel, error) {
var item model.OllamaModel
db := global.DB
for _, opt := range opts {
db = opt(db)
}
err := db.First(&item).Error
return item, err
}
func (u *AiRepo) List(opts ...DBOption) ([]model.OllamaModel, error) {
var list []model.OllamaModel
db := global.DB.Model(&model.OllamaModel{})
for _, opt := range opts {
db = opt(db)
}
err := db.Find(&list).Error
return list, err
}
func (u *AiRepo) Page(page, size int, opts ...DBOption) (int64, []model.OllamaModel, error) {
var list []model.OllamaModel
db := global.DB.Model(&model.OllamaModel{})
for _, opt := range opts {
db = opt(db)
}
count := int64(0)
db = db.Count(&count)
err := db.Limit(size).Offset(size * (page - 1)).Find(&list).Error
return count, list, err
}
func (u *AiRepo) Create(item *model.OllamaModel) error {
return global.DB.Create(item).Error
}
func (u *AiRepo) Update(id uint, vars map[string]interface{}) error {
return global.DB.Model(&model.OllamaModel{}).Where("id = ?", id).Updates(vars).Error
}
func (u *AiRepo) Delete(opts ...DBOption) error {
db := global.DB
for _, opt := range opts {
db = opt(db)
}
return db.Delete(&model.OllamaModel{}).Error
}
+7
View File
@@ -15,6 +15,7 @@ type DBOption func(*gorm.DB) *gorm.DB
type ICommonRepo interface {
WithByID(id uint) DBOption
WithByName(name string) DBOption
WithByLowerName(name string) DBOption
WithByType(tp string) DBOption
WithOrderBy(orderStr string) DBOption
WithOrderRuleBy(orderBy, order string) DBOption
@@ -45,6 +46,12 @@ func (c *CommonRepo) WithByName(name string) DBOption {
}
}
func (c *CommonRepo) WithByLowerName(name string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("LOWER(name) = LOWER(?)", name)
}
}
func (c *CommonRepo) WithByDate(startTime, endTime time.Time) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("start_time > ? AND start_time < ?", startTime, endTime)
+5
View File
@@ -16,6 +16,7 @@ type ISettingRepo interface {
Create(key, value string) error
Update(key, value string) error
WithByKey(key string) DBOption
UpdateOrCreate(key, value string) error
CreateMonitorBase(model model.MonitorBase) error
BatchCreateMonitorIO(ioList []model.MonitorIO) error
@@ -85,3 +86,7 @@ func (u *SettingRepo) DelMonitorIO(timeForDelete time.Time) error {
func (u *SettingRepo) DelMonitorNet(timeForDelete time.Time) error {
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorNetwork{}).Error
}
func (u *SettingRepo) UpdateOrCreate(key, value string) error {
return global.DB.Model(&model.Setting{}).Where("key = ?", key).Assign(model.Setting{Key: key, Value: value}).FirstOrCreate(&model.Setting{}).Error
}
+415
View File
@@ -0,0 +1,415 @@
package service
import (
"context"
"fmt"
"io"
"os"
"os/exec"
"path"
"strings"
"github.com/1Panel-dev/1Panel/backend/utils/common"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
"github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/app/repo"
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
)
type AIToolService struct{}
type IAIToolService interface {
Search(search dto.SearchWithPage) (int64, []dto.OllamaModelInfo, error)
Create(name string) error
Close(name string) error
Recreate(name string) error
Delete(req dto.ForceDelete) error
Sync() ([]dto.OllamaModelDropList, error)
LoadDetail(name string) (string, error)
BindDomain(req dto.OllamaBindDomain) error
GetBindDomain(req dto.OllamaBindDomainReq) (*dto.OllamaBindDomainRes, error)
UpdateBindDomain(req dto.OllamaBindDomain) error
}
func NewIAIToolService() IAIToolService {
return &AIToolService{}
}
func (u *AIToolService) Search(req dto.SearchWithPage) (int64, []dto.OllamaModelInfo, error) {
var options []repo.DBOption
if len(req.Info) != 0 {
options = append(options, commonRepo.WithLikeName(req.Info))
}
total, list, err := aiRepo.Page(req.Page, req.PageSize, options...)
if err != nil {
return 0, nil, err
}
var dtoLists []dto.OllamaModelInfo
for _, itemModel := range list {
var item dto.OllamaModelInfo
if err := copier.Copy(&item, &itemModel); err != nil {
return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
}
logPath := path.Join(global.CONF.System.DataDir, "log", "AITools", itemModel.Name)
if _, err := os.Stat(logPath); err == nil {
item.LogFileExist = true
}
dtoLists = append(dtoLists, item)
}
return int64(total), dtoLists, err
}
func (u *AIToolService) LoadDetail(name string) (string, error) {
if cmd.CheckIllegal(name) {
return "", buserr.New(constant.ErrCmdIllegal)
}
containerName, err := LoadContainerName()
if err != nil {
return "", err
}
stdout, err := cmd.Execf("docker exec %s ollama show %s", containerName, name)
if err != nil {
return "", err
}
return stdout, err
}
func (u *AIToolService) Create(name string) error {
if cmd.CheckIllegal(name) {
return buserr.New(constant.ErrCmdIllegal)
}
modelInfo, _ := aiRepo.Get(commonRepo.WithByName(name))
if modelInfo.ID != 0 {
return constant.ErrRecordExist
}
containerName, err := LoadContainerName()
if err != nil {
return err
}
logItem := path.Join(global.CONF.System.DataDir, "log", "AITools", name)
if _, err := os.Stat(path.Dir(logItem)); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(path.Dir(logItem), os.ModePerm); err != nil {
return err
}
}
info := model.OllamaModel{
Name: name,
From: "local",
Status: constant.StatusWaiting,
}
if err := aiRepo.Create(&info); err != nil {
return err
}
file, err := os.OpenFile(logItem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
return err
}
go pullOllamaModel(file, containerName, info)
return nil
}
func (u *AIToolService) Close(name string) error {
if cmd.CheckIllegal(name) {
return buserr.New(constant.ErrCmdIllegal)
}
containerName, err := LoadContainerName()
if err != nil {
return err
}
stdout, err := cmd.Execf("docker exec %s ollama stop %s", containerName, name)
if err != nil {
return fmt.Errorf("handle ollama stop %s failed, stdout: %s, err: %v", name, stdout, err)
}
return nil
}
func (u *AIToolService) Recreate(name string) error {
if cmd.CheckIllegal(name) {
return buserr.New(constant.ErrCmdIllegal)
}
modelInfo, _ := aiRepo.Get(commonRepo.WithByName(name))
if modelInfo.ID == 0 {
return constant.ErrRecordNotFound
}
containerName, err := LoadContainerName()
if err != nil {
return err
}
if err := aiRepo.Update(modelInfo.ID, map[string]interface{}{"status": constant.StatusWaiting, "from": "local"}); err != nil {
return err
}
logItem := path.Join(global.CONF.System.DataDir, "log", "AITools", name)
if _, err := os.Stat(path.Dir(logItem)); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(path.Dir(logItem), os.ModePerm); err != nil {
return err
}
}
file, err := os.OpenFile(logItem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
return err
}
go pullOllamaModel(file, containerName, modelInfo)
return nil
}
func (u *AIToolService) Delete(req dto.ForceDelete) error {
ollamaList, _ := aiRepo.List(commonRepo.WithIdsIn(req.IDs))
if len(ollamaList) == 0 {
return constant.ErrRecordNotFound
}
containerName, err := LoadContainerName()
if err != nil && !req.ForceDelete {
return err
}
for _, item := range ollamaList {
if item.Status != constant.StatusDeleted {
stdout, err := cmd.Execf("docker exec %s ollama rm %s", containerName, item.Name)
if err != nil && !req.ForceDelete {
return fmt.Errorf("handle ollama rm %s failed, stdout: %s, err: %v", item.Name, stdout, err)
}
}
_ = aiRepo.Delete(commonRepo.WithByID(item.ID))
logItem := path.Join(global.CONF.System.DataDir, "log", "AITools", item.Name)
_ = os.Remove(logItem)
}
return nil
}
func (u *AIToolService) Sync() ([]dto.OllamaModelDropList, error) {
containerName, err := LoadContainerName()
if err != nil {
return nil, err
}
stdout, err := cmd.Execf("docker exec %s ollama list", containerName)
if err != nil {
return nil, err
}
var list []model.OllamaModel
lines := strings.Split(stdout, "\n")
for _, line := range lines {
parts := strings.Fields(line)
if len(parts) < 5 {
continue
}
if parts[0] == "NAME" {
continue
}
list = append(list, model.OllamaModel{Name: parts[0], Size: parts[2] + " " + parts[3]})
}
listInDB, _ := aiRepo.List()
var dropList []dto.OllamaModelDropList
for _, itemModel := range listInDB {
isExit := false
for i := 0; i < len(list); i++ {
if list[i].Name == itemModel.Name {
_ = aiRepo.Update(itemModel.ID, map[string]interface{}{"status": constant.StatusSuccess, "message": "", "size": list[i].Size})
list = append(list[:i], list[(i+1):]...)
isExit = true
break
}
}
if !isExit && itemModel.Status != constant.StatusWaiting {
_ = aiRepo.Update(itemModel.ID, map[string]interface{}{"status": constant.StatusDeleted, "message": "not exist", "size": ""})
dropList = append(dropList, dto.OllamaModelDropList{ID: itemModel.ID, Name: itemModel.Name})
continue
}
}
for _, item := range list {
item.Status = constant.StatusSuccess
item.From = "remote"
_ = aiRepo.Create(&item)
}
return dropList, nil
}
func (u *AIToolService) BindDomain(req dto.OllamaBindDomain) error {
nginxInstall, _ := getAppInstallByKey(constant.AppOpenresty)
if nginxInstall.ID == 0 {
return buserr.New("ErrOpenrestyInstall")
}
var (
ipList []string
err error
)
if len(req.IPList) > 0 {
ipList, err = common.HandleIPList(req.IPList)
if err != nil {
return err
}
}
if req.SSLID > 0 {
ssl, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(req.SSLID))
if err != nil {
return err
}
if ssl.Pem == "" {
return buserr.New("ErrSSL")
}
}
createWebsiteReq := request.WebsiteCreate{
PrimaryDomain: req.Domain,
Alias: strings.ToLower(req.Domain),
Type: constant.Deployment,
AppType: constant.InstalledApp,
AppInstallID: req.AppInstallID,
}
websiteService := NewIWebsiteService()
if err := websiteService.CreateWebsite(createWebsiteReq); err != nil {
return err
}
website, err := websiteRepo.GetFirst(websiteRepo.WithAlias(strings.ToLower(req.Domain)))
if err != nil {
return err
}
if len(ipList) > 0 {
if err = ConfigAllowIPs(ipList, website); err != nil {
return err
}
}
if req.SSLID > 0 {
sslReq := request.WebsiteHTTPSOp{
WebsiteID: website.ID,
Enable: true,
Type: "existed",
WebsiteSSLID: req.SSLID,
HttpConfig: "HTTPSOnly",
}
if _, err = websiteService.OpWebsiteHTTPS(context.Background(), sslReq); err != nil {
return err
}
}
if err = ConfigAIProxy(website); err != nil {
return err
}
return nil
}
func (u *AIToolService) GetBindDomain(req dto.OllamaBindDomainReq) (*dto.OllamaBindDomainRes, error) {
install, err := appInstallRepo.GetFirst(commonRepo.WithByID(req.AppInstallID))
if err != nil {
return nil, err
}
res := &dto.OllamaBindDomainRes{}
website, _ := websiteRepo.GetFirst(websiteRepo.WithAppInstallId(install.ID))
if website.ID == 0 {
return res, nil
}
res.WebsiteID = website.ID
res.Domain = website.PrimaryDomain
if website.WebsiteSSLID > 0 {
res.SSLID = website.WebsiteSSLID
ssl, _ := websiteSSLRepo.GetFirst(commonRepo.WithByID(website.WebsiteSSLID))
res.AcmeAccountID = ssl.AcmeAccountID
}
res.ConnUrl = fmt.Sprintf("%s://%s", strings.ToLower(website.Protocol), website.PrimaryDomain)
res.AllowIPs = GetAllowIps(website)
return res, nil
}
func (u *AIToolService) UpdateBindDomain(req dto.OllamaBindDomain) error {
nginxInstall, _ := getAppInstallByKey(constant.AppOpenresty)
if nginxInstall.ID == 0 {
return buserr.New("ErrOpenrestyInstall")
}
var (
ipList []string
err error
)
if len(req.IPList) > 0 {
ipList, err = common.HandleIPList(req.IPList)
if err != nil {
return err
}
}
if req.SSLID > 0 {
ssl, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(req.SSLID))
if err != nil {
return err
}
if ssl.Pem == "" {
return buserr.New("ErrSSL")
}
}
websiteService := NewIWebsiteService()
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
if err != nil {
return err
}
if err = ConfigAllowIPs(ipList, website); err != nil {
return err
}
if req.SSLID > 0 {
sslReq := request.WebsiteHTTPSOp{
WebsiteID: website.ID,
Enable: true,
Type: "existed",
WebsiteSSLID: req.SSLID,
HttpConfig: "HTTPSOnly",
}
if _, err = websiteService.OpWebsiteHTTPS(context.Background(), sslReq); err != nil {
return err
}
return nil
}
if website.WebsiteSSLID > 0 && req.SSLID == 0 {
sslReq := request.WebsiteHTTPSOp{
WebsiteID: website.ID,
Enable: false,
}
if _, err = websiteService.OpWebsiteHTTPS(context.Background(), sslReq); err != nil {
return err
}
}
return nil
}
func LoadContainerName() (string, error) {
ollamaBaseInfo, err := appInstallRepo.LoadBaseInfo("ollama", "")
if err != nil {
return "", fmt.Errorf("ollama service is not found, err: %v", err)
}
if ollamaBaseInfo.Status != constant.Running {
return "", fmt.Errorf("container %s of ollama is not running, please check and retry!", ollamaBaseInfo.ContainerName)
}
return ollamaBaseInfo.ContainerName, nil
}
func pullOllamaModel(file *os.File, containerName string, info model.OllamaModel) {
defer file.Close()
cmd := exec.Command("docker", "exec", containerName, "ollama", "pull", info.Name)
multiWriter := io.MultiWriter(os.Stdout, file)
cmd.Stdout = multiWriter
cmd.Stderr = multiWriter
_ = cmd.Run()
itemSize, err := loadModelSize(info.Name, containerName)
if len(itemSize) != 0 {
_ = aiRepo.Update(info.ID, map[string]interface{}{"status": constant.StatusSuccess, "size": itemSize})
} else {
_ = aiRepo.Update(info.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
}
_, _ = file.WriteString("ollama pull completed!")
}
func loadModelSize(name string, containerName string) (string, error) {
stdout, err := cmd.Execf("docker exec %s ollama list | grep %s", containerName, name)
if err != nil {
return "", err
}
lines := strings.Split(string(stdout), "\n")
for _, line := range lines {
parts := strings.Fields(line)
if len(parts) < 5 {
continue
}
return parts[2] + " " + parts[3], nil
}
return "", fmt.Errorf("no such model %s in ollama list, std: %s", name, string(stdout))
}
+53 -35
View File
@@ -5,6 +5,7 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"os"
"path/filepath"
@@ -34,9 +35,9 @@ type AppService struct {
}
type IAppService interface {
PageApp(req request.AppSearch) (interface{}, error)
GetAppTags() ([]response.TagDTO, error)
GetApp(key string) (*response.AppDTO, error)
PageApp(ctx *gin.Context, req request.AppSearch) (interface{}, error)
GetAppTags(ctx *gin.Context) ([]response.TagDTO, error)
GetApp(ctx *gin.Context, key string) (*response.AppDTO, error)
GetAppDetail(appId uint, version, appType string) (response.AppDetailDTO, error)
Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error)
SyncAppListFromRemote() error
@@ -50,7 +51,7 @@ func NewIAppService() IAppService {
return &AppService{}
}
func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{}, error) {
var opts []repo.DBOption
opts = append(opts, appRepo.OrderByRecommend())
if req.Name != "" {
@@ -89,31 +90,24 @@ func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
if err != nil {
return nil, err
}
var appDTOs []*response.AppDto
var appDTOs []*response.AppItem
lang := strings.ToLower(common.GetLang(ctx))
for _, ap := range apps {
appDTO := &response.AppDto{
ID: ap.ID,
Name: ap.Name,
Key: ap.Key,
Type: ap.Type,
Icon: ap.Icon,
ShortDescZh: ap.ShortDescZh,
ShortDescEn: ap.ShortDescEn,
Resource: ap.Resource,
Limit: ap.Limit,
appDTO := &response.AppItem{
ID: ap.ID,
Name: ap.Name,
Key: ap.Key,
Type: ap.Type,
Icon: ap.Icon,
Resource: ap.Resource,
Limit: ap.Limit,
GpuSupport: ap.GpuSupport,
}
appDTO.Description = ap.GetDescription(ctx)
appDTOs = append(appDTOs, appDTO)
appTags, err := appTagRepo.GetByAppId(ap.ID)
tags, err := getAppTags(ap.ID, lang)
if err != nil {
continue
}
var tagIds []uint
for _, at := range appTags {
tagIds = append(tagIds, at.TagId)
}
tags, err := tagRepo.GetByIds(tagIds)
if err != nil {
continue
return nil, err
}
appDTO.Tags = tags
installs, _ := appInstallRepo.ListBy(appInstallRepo.WithAppId(ap.ID))
@@ -125,18 +119,32 @@ func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
return res, nil
}
func (a AppService) GetAppTags() ([]response.TagDTO, error) {
func (a AppService) GetAppTags(ctx *gin.Context) ([]response.TagDTO, error) {
tags, _ := tagRepo.All()
res := make([]response.TagDTO, 0)
lang := strings.ToLower(common.GetLang(ctx))
for _, tag := range tags {
res = append(res, response.TagDTO{
Tag: tag,
})
tagDTO := response.TagDTO{
ID: tag.ID,
Key: tag.Key,
}
var translations = make(map[string]string)
_ = json.Unmarshal([]byte(tag.Translations), &translations)
if name, ok := translations[lang]; ok && name != "" {
tagDTO.Name = name
} else {
if lang == "zh" || lang == "zh-Hant" {
tagDTO.Name = tag.Name
} else {
tagDTO.Name = tag.Key
}
}
res = append(res, tagDTO)
}
return res, nil
}
func (a AppService) GetApp(key string) (*response.AppDTO, error) {
func (a AppService) GetApp(ctx *gin.Context, key string) (*response.AppDTO, error) {
var appDTO response.AppDTO
if key == "postgres" {
key = "postgresql"
@@ -146,6 +154,7 @@ func (a AppService) GetApp(key string) (*response.AppDTO, error) {
return nil, err
}
appDTO.App = app
appDTO.App.Description = app.GetDescription(ctx)
details, err := appDetailRepo.GetBy(appDetailRepo.WithAppId(app.ID))
if err != nil {
return nil, err
@@ -155,7 +164,12 @@ func (a AppService) GetApp(key string) (*response.AppDTO, error) {
versionsRaw = append(versionsRaw, detail.Version)
}
appDTO.Versions = common.GetSortedVersions(versionsRaw)
tags, err := getAppTags(app.ID, strings.ToLower(common.GetLang(ctx)))
if err != nil {
return nil, err
}
appDTO.GpuSupport = app.GpuSupport
appDTO.Tags = tags
return &appDTO, nil
}
@@ -252,6 +266,7 @@ func (a AppService) GetAppDetail(appID uint, version, appType string) (response.
if err := checkLimit(app); err != nil {
appDetailDTO.Enable = false
}
appDetailDTO.GpuSupport = app.GpuSupport
return appDetailDTO, nil
}
func (a AppService) GetAppDetailByID(id uint) (*response.AppDetailDTO, error) {
@@ -296,7 +311,8 @@ func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (
err = buserr.WithDetail(constant.Err1PanelNetworkFailed, err.Error(), nil)
return
}
if list, _ := appInstallRepo.ListBy(commonRepo.WithByName(req.Name)); len(list) > 0 {
if list, _ := appInstallRepo.ListBy(commonRepo.WithByLowerName(req.Name)); len(list) > 0 {
err = buserr.New(constant.ErrAppNameExist)
return
}
@@ -827,10 +843,11 @@ func (a AppService) SyncAppListFromRemote() (err error) {
oldAppIds []uint
)
for _, t := range list.Extra.Tags {
translations, _ := json.Marshal(t.Locales)
tags = append(tags, &model.Tag{
Key: t.Key,
Name: t.Name,
Sort: t.Sort,
Key: t.Key,
Translations: string(translations),
Sort: t.Sort,
})
}
oldApps, err := appRepo.GetBy(appRepo.WithResource(constant.AppResourceRemote))
@@ -848,6 +865,7 @@ func (a AppService) SyncAppListFromRemote() (err error) {
global.LOG.Infof("Starting synchronization of application details...")
for _, l := range list.Apps {
app := appsMap[l.AppProperty.Key]
app.GpuSupport = l.AppProperty.GpuSupport
if l.AppProperty.Version > 0 && common.CompareVersion(strconv.FormatFloat(l.AppProperty.Version, 'f', -1, 64), setting.SystemVersion) {
delete(appsMap, l.AppProperty.Key)
+1
View File
@@ -750,6 +750,7 @@ func (a *AppInstallService) GetParams(id uint) (*response.AppConfig, error) {
}
res.AppContainerConfig = config
res.HostMode = isHostModel(install.DockerCompose)
res.GpuConfig = isGpuConfig(install.DockerCompose)
return &res, nil
}
+107 -8
View File
@@ -1051,6 +1051,8 @@ func getApps(oldApps []model.App, items []dto.AppDefine) map[string]model.App {
app.Key = key
app.ShortDescZh = config.ShortDescZh
app.ShortDescEn = config.ShortDescEn
description, _ := json.Marshal(config.Description)
app.Description = string(description)
app.Website = config.Website
app.Document = config.Document
app.Github = config.Github
@@ -1150,14 +1152,31 @@ func handleLocalApp(appDir string) (app *model.App, err error) {
err = buserr.WithMap(constant.ErrFileParseApp, map[string]interface{}{"name": "data.yml", "err": err.Error()}, err)
return
}
app = &localAppDefine.AppProperty
appDefine := localAppDefine.AppProperty
app = &model.App{}
app.Name = appDefine.Name
app.TagsKey = append(appDefine.Tags, "Local")
app.Type = appDefine.Type
app.CrossVersionUpdate = appDefine.CrossVersionUpdate
app.Limit = appDefine.Limit
app.Recommend = appDefine.Recommend
app.Website = appDefine.Website
app.Github = appDefine.Github
app.Document = appDefine.Document
if appDefine.ShortDescZh != "" {
app.ShortDescZh = appDefine.ShortDescZh
}
if appDefine.ShortDescEn != "" {
app.ShortDescEn = appDefine.ShortDescEn
}
desc, _ := json.Marshal(appDefine.Description)
app.Description = string(desc)
app.Key = "local" + appDefine.Key
app.Resource = constant.AppResourceLocal
app.Status = constant.AppNormal
app.Recommend = 9999
app.TagsKey = append(app.TagsKey, "Local")
app.Key = "local" + app.Key
readMePath := path.Join(appDir, "README.md")
readMeByte, err := fileOp.GetContent(readMePath)
readMeByte, err := fileOp.GetContent(path.Join(appDir, "README.md"))
if err == nil {
app.ReadMe = string(readMeByte)
}
@@ -1319,9 +1338,10 @@ func handleInstalled(appInstallList []model.AppInstall, updated bool, sync bool)
Path: installed.GetPath(),
CreatedAt: installed.CreatedAt,
App: response.AppDetail{
Github: installed.App.Github,
Website: installed.App.Website,
Document: installed.App.Document,
Github: installed.App.Github,
Website: installed.App.Website,
Document: installed.App.Document,
GpuSupport: installed.App.GpuSupport,
},
}
if updated {
@@ -1480,6 +1500,20 @@ func addDockerComposeCommonParam(composeMap map[string]interface{}, serviceName
deploy["resources"] = resource
serviceValue["deploy"] = deploy
if req.GpuConfig {
resource["reservations"] = map[string]interface{}{
"devices": []map[string]interface{}{
{
"driver": "nvidia",
"count": "all",
"capabilities": []string{"gpu"},
},
},
}
} else {
delete(resource, "reservations")
}
ports, ok := serviceValue["ports"].([]interface{})
if ok {
for i, port := range ports {
@@ -1581,9 +1615,74 @@ func isHostModel(dockerCompose string) bool {
return false
}
func isGpuConfig(dockerCompose string) bool {
composeMap := make(map[string]interface{})
_ = yaml.Unmarshal([]byte(dockerCompose), &composeMap)
services, serviceValid := composeMap["services"].(map[string]interface{})
if !serviceValid {
return false
}
for _, service := range services {
serviceValue := service.(map[string]interface{})
deploy := map[string]interface{}{}
if de, ok := serviceValue["deploy"]; ok {
deploy = de.(map[string]interface{})
}
resource := map[string]interface{}{}
if res, ok := deploy["resources"]; ok {
resource = res.(map[string]interface{})
}
if reservations, ok := resource["reservations"]; ok {
reservationsMap := reservations.(map[string]interface{})
if _, dOk := reservationsMap["devices"]; dOk {
return true
}
}
}
return false
}
func RequestDownloadCallBack(downloadCallBackUrl string) {
if downloadCallBackUrl == "" {
return
}
_, _, _ = httpUtil.HandleGet(downloadCallBackUrl, http.MethodGet, constant.TimeOut5s)
}
func getAppTags(appID uint, lang string) ([]response.TagDTO, error) {
appTags, err := appTagRepo.GetByAppId(appID)
if err != nil {
return nil, err
}
var tagIds []uint
for _, at := range appTags {
tagIds = append(tagIds, at.TagId)
}
tags, err := tagRepo.GetByIds(tagIds)
if err != nil {
return nil, err
}
var res []response.TagDTO
for _, t := range tags {
if t.Name != "" {
tagDTO := response.TagDTO{
ID: t.ID,
Key: t.Key,
Name: t.Name,
}
res = append(res, tagDTO)
} else {
var translations = make(map[string]string)
_ = json.Unmarshal([]byte(t.Translations), &translations)
if name, ok := translations[lang]; ok {
tagDTO := response.TagDTO{
ID: t.ID,
Key: t.Key,
Name: name,
}
res = append(res, tagDTO)
}
}
}
return res, nil
}
+31 -19
View File
@@ -38,16 +38,11 @@ func (u *AuthService) Login(c *gin.Context, info dto.Login, entrance string) (*d
if err != nil {
return nil, errors.WithMessage(constant.ErrRecordNotFound, err.Error())
}
passwordSetting, err := settingRepo.Get(settingRepo.WithByKey("Password"))
if err != nil {
return nil, errors.WithMessage(constant.ErrRecordNotFound, err.Error())
}
pass, err := encrypt.StringDecrypt(passwordSetting.Value)
if err != nil {
if nameSetting.Value != info.Name {
return nil, constant.ErrAuth
}
if !hmac.Equal([]byte(info.Password), []byte(pass)) || nameSetting.Value != info.Name {
return nil, constant.ErrAuth
if err = checkPassword(info.Password); err != nil {
return nil, err
}
entranceSetting, err := settingRepo.Get(settingRepo.WithByKey("SecurityEntrance"))
if err != nil {
@@ -83,17 +78,12 @@ func (u *AuthService) MFALogin(c *gin.Context, info dto.MFALogin, entrance strin
if err != nil {
return nil, errors.WithMessage(constant.ErrRecordNotFound, err.Error())
}
passwordSetting, err := settingRepo.Get(settingRepo.WithByKey("Password"))
if err != nil {
return nil, errors.WithMessage(constant.ErrRecordNotFound, err.Error())
}
pass, err := encrypt.StringDecrypt(passwordSetting.Value)
if err != nil {
return nil, err
}
if !hmac.Equal([]byte(info.Password), []byte(pass)) || nameSetting.Value != info.Name {
if nameSetting.Value != info.Name {
return nil, constant.ErrAuth
}
if err = checkPassword(info.Password); err != nil {
return nil, err
}
entranceSetting, err := settingRepo.Get(settingRepo.WithByKey("SecurityEntrance"))
if err != nil {
return nil, err
@@ -214,8 +204,30 @@ func (u *AuthService) GetSecurityEntrance() string {
func (u *AuthService) IsLogin(c *gin.Context) bool {
sID, _ := c.Cookie(constant.SessionName)
_, err := global.SESSION.Get(sID)
return err == nil
}
func checkPassword(password string) error {
priKey, _ := settingRepo.Get(settingRepo.WithByKey("PASSWORD_PRIVATE_KEY"))
privateKey, err := encrypt.ParseRSAPrivateKey(priKey.Value)
if err != nil {
return false
return err
}
return true
loginPassword, err := encrypt.DecryptPassword(password, privateKey)
if err != nil {
return err
}
passwordSetting, err := settingRepo.Get(settingRepo.WithByKey("Password"))
if err != nil {
return errors.WithMessage(constant.ErrRecordNotFound, err.Error())
}
existPassword, err := encrypt.StringDecrypt(passwordSetting.Value)
if err != nil {
return err
}
if !hmac.Equal([]byte(loginPassword), []byte(existPassword)) {
return constant.ErrAuth
}
return nil
}
+51 -17
View File
@@ -8,7 +8,6 @@ import (
"fmt"
"os"
"path"
"sort"
"strings"
"sync"
"time"
@@ -30,7 +29,9 @@ type BackupService struct{}
type IBackupService interface {
List() ([]dto.BackupInfo, error)
SearchRecordsWithPage(search dto.RecordSearch) (int64, []dto.BackupRecords, error)
LoadSize(req dto.RecordSearch) ([]dto.BackupFile, error)
SearchRecordsByCronjobWithPage(search dto.RecordSearchByCronjob) (int64, []dto.BackupRecords, error)
LoadSizeByCronjob(req dto.RecordSearchByCronjob) ([]dto.BackupFile, error)
LoadOneDriveInfo() (dto.OneDriveInfo, error)
DownloadRecord(info dto.DownloadRecord) (string, error)
Create(backupDto dto.BackupOperate) error
@@ -94,11 +95,29 @@ func (u *BackupService) SearchRecordsWithPage(search dto.RecordSearch) (int64, [
return 0, nil, err
}
datas, err := u.loadRecordSize(records)
sort.Slice(datas, func(i, j int) bool {
return datas[i].CreatedAt.After(datas[j].CreatedAt)
})
return total, datas, err
var list []dto.BackupRecords
for _, item := range records {
var itemRecord dto.BackupRecords
if err := copier.Copy(&itemRecord, &item); err != nil {
continue
}
list = append(list, itemRecord)
}
return total, list, err
}
func (u *BackupService) LoadSize(req dto.RecordSearch) ([]dto.BackupFile, error) {
_, records, err := backupRepo.PageRecord(
req.Page, req.PageSize,
commonRepo.WithOrderBy("created_at desc"),
commonRepo.WithByName(req.Name),
commonRepo.WithByType(req.Type),
backupRepo.WithByDetailName(req.DetailName),
)
if err != nil {
return nil, err
}
return u.loadRecordSize(records)
}
func (u *BackupService) ListAppRecords(name, detailName, fileName string) ([]model.BackupRecord, error) {
@@ -125,11 +144,27 @@ func (u *BackupService) SearchRecordsByCronjobWithPage(search dto.RecordSearchBy
return 0, nil, err
}
datas, err := u.loadRecordSize(records)
sort.Slice(datas, func(i, j int) bool {
return datas[i].CreatedAt.After(datas[j].CreatedAt)
})
return total, datas, err
var list []dto.BackupRecords
for _, item := range records {
var itemRecord dto.BackupRecords
if err := copier.Copy(&itemRecord, &item); err != nil {
continue
}
list = append(list, itemRecord)
}
return total, list, err
}
func (u *BackupService) LoadSizeByCronjob(req dto.RecordSearchByCronjob) ([]dto.BackupFile, error) {
_, records, err := backupRepo.PageRecord(
req.Page, req.PageSize,
commonRepo.WithOrderBy("created_at desc"),
backupRepo.WithByCronID(req.CronjobID),
)
if err != nil {
return nil, err
}
return u.loadRecordSize(records)
}
type loadSizeHelper struct {
@@ -482,15 +517,14 @@ func (u *BackupService) loadAccessToken(backup *model.BackupAccount) error {
return nil
}
func (u *BackupService) loadRecordSize(records []model.BackupRecord) ([]dto.BackupRecords, error) {
var datas []dto.BackupRecords
func (u *BackupService) loadRecordSize(records []model.BackupRecord) ([]dto.BackupFile, error) {
var datas []dto.BackupFile
clientMap := make(map[string]loadSizeHelper)
var wg sync.WaitGroup
for i := 0; i < len(records); i++ {
var item dto.BackupRecords
if err := copier.Copy(&item, &records[i]); err != nil {
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
}
var item dto.BackupFile
item.ID = records[i].ID
item.Name = records[i].FileName
itemPath := path.Join(records[i].FileDir, records[i].FileName)
if _, ok := clientMap[records[i].Source]; !ok {
backup, err := backupRepo.Get(commonRepo.WithByType(records[i].Source))
+5 -2
View File
@@ -2,13 +2,14 @@ package service
import (
"fmt"
"github.com/1Panel-dev/1Panel/backend/constant"
"os"
"path"
"path/filepath"
"strings"
"time"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/app/dto"
@@ -169,8 +170,9 @@ func handleMysqlRecover(req dto.CommonRecover, isRollback bool) error {
Timeout: 300,
}); err != nil {
global.LOG.Errorf("rollback mysql db %s from %s failed, err: %v", req.DetailName, rollbackFile, err)
} else {
global.LOG.Infof("rollback mysql db %s from %s successful", req.DetailName, rollbackFile)
}
global.LOG.Infof("rollback mysql db %s from %s successful", req.DetailName, rollbackFile)
_ = os.RemoveAll(rollbackFile)
} else {
_ = os.RemoveAll(rollbackFile)
@@ -186,6 +188,7 @@ func handleMysqlRecover(req dto.CommonRecover, isRollback bool) error {
Timeout: 300,
}); err != nil {
global.LOG.Errorf("recover mysql db %s from %s failed, err: %v", req.DetailName, req.File, err)
return err
}
isOk = true
+5 -2
View File
@@ -2,13 +2,14 @@ package service
import (
"fmt"
"github.com/1Panel-dev/1Panel/backend/constant"
"os"
"path"
"path/filepath"
"strings"
"time"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/utils/common"
pgclient "github.com/1Panel-dev/1Panel/backend/utils/postgresql/client"
@@ -157,8 +158,9 @@ func handlePostgresqlRecover(req dto.CommonRecover, isRollback bool) error {
Timeout: 300,
}); err != nil {
global.LOG.Errorf("rollback postgresql db %s from %s failed, err: %v", req.DetailName, rollbackFile, err)
} else {
global.LOG.Infof("rollback postgresql db %s from %s successful", req.DetailName, rollbackFile)
}
global.LOG.Infof("rollback postgresql db %s from %s successful", req.DetailName, rollbackFile)
_ = os.RemoveAll(rollbackFile)
} else {
_ = os.RemoveAll(rollbackFile)
@@ -171,6 +173,7 @@ func handlePostgresqlRecover(req dto.CommonRecover, isRollback bool) error {
Username: dbInfo.Username,
Timeout: 300,
}); err != nil {
global.LOG.Errorf("recover postgresql db %s from %s failed, err: %v", req.DetailName, req.File, err)
return err
}
isOk = true
+1 -1
View File
@@ -1262,12 +1262,12 @@ func loadContainerPortForInfo(itemPorts []types.Port) []dto.PortHelper {
var exposedPorts []dto.PortHelper
samePortMap := make(map[string]dto.PortHelper)
ports := transPortToStr(itemPorts)
var itemPort dto.PortHelper
for _, item := range ports {
itemStr := strings.Split(item, "->")
if len(itemStr) < 2 {
continue
}
var itemPort dto.PortHelper
lastIndex := strings.LastIndex(itemStr[0], ":")
if lastIndex == -1 {
itemPort.HostPort = itemStr[0]
+28 -8
View File
@@ -10,19 +10,19 @@ import (
"sync"
"time"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/shirou/gopsutil/v3/load"
"github.com/shirou/gopsutil/v3/mem"
"github.com/shirou/gopsutil/v3/net"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/ai_tools/gpu"
"github.com/1Panel-dev/1Panel/backend/utils/ai_tools/xpu"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/copier"
"github.com/1Panel-dev/1Panel/backend/utils/xpack"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/host"
"github.com/shirou/gopsutil/v3/load"
"github.com/shirou/gopsutil/v3/mem"
"github.com/shirou/gopsutil/v3/net"
)
type DashboardService struct{}
@@ -341,7 +341,17 @@ func loadDiskInfo() []dto.DiskInfo {
}
func loadGPUInfo() []dto.GPUInfo {
list := xpack.LoadGpuInfo()
ok, client := gpu.New()
var list []interface{}
if ok {
info, err := client.LoadGpuInfo()
if err != nil || len(info.GPUs) == 0 {
return nil
}
for _, item := range info.GPUs {
list = append(list, item)
}
}
if len(list) == 0 {
return nil
}
@@ -359,7 +369,17 @@ func loadGPUInfo() []dto.GPUInfo {
}
func loadXpuInfo() []dto.XPUInfo {
list := xpack.LoadXpuInfo()
var list []interface{}
ok, xpuClient := xpu.New()
if ok {
xpus, err := xpuClient.LoadDashData()
if err != nil || len(xpus) == 0 {
return nil
}
for _, item := range xpus {
list = append(list, item)
}
}
if len(list) == 0 {
return nil
}
-4
View File
@@ -50,10 +50,6 @@ func (u *DBCommonService) LoadDatabaseFile(req dto.OperationWithNameAndType) (st
filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/postgresql/%s/data/postgresql.conf", req.Name))
case "redis-conf":
filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/redis/%s/conf/redis.conf", req.Name))
case "mysql-slow-logs":
filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mysql/%s/data/1Panel-slow.log", req.Name))
case "mariadb-slow-logs":
filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mariadb/%s/db/data/1Panel-slow.log", req.Name))
}
if _, err := os.Stat(filePath); err != nil {
return "", buserr.New("ErrHttpReqNotFound")
+2
View File
@@ -12,6 +12,8 @@ var (
appInstallRepo = repo.NewIAppInstallRepo()
appInstallResourceRepo = repo.NewIAppInstallResourceRpo()
aiRepo = repo.NewIAiRepo()
mysqlRepo = repo.NewIMysqlRepo()
postgresqlRepo = repo.NewIPostgresqlRepo()
databaseRepo = repo.NewIDatabaseRepo()
+22
View File
@@ -50,6 +50,7 @@ type IFileService interface {
ChangeMode(op request.FileCreate) error
BatchChangeModeAndOwner(op request.FileRoleReq) error
ReadLogByLine(req request.FileReadByLineReq) (*response.FileLineContent, error)
BatchCheckFiles(req request.FilePathsCheck) []response.ExistFileInfo
}
var filteredPaths = []string{
@@ -478,6 +479,12 @@ func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.Fi
}
case "image-pull", "image-push", "image-build", "compose-create":
logFilePath = path.Join(global.CONF.System.TmpDir, fmt.Sprintf("docker_logs/%s", req.Name))
case "ollama-model":
logFilePath = path.Join(global.CONF.System.DataDir, "log", "AITools", req.Name)
case "mysql-slow-logs":
logFilePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mysql/%s/data/1Panel-slow.log", req.Name))
case "mariadb-slow-logs":
logFilePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mariadb/%s/db/data/1Panel-slow.log", req.Name))
}
lines, isEndOfFile, total, err := files.ReadFileByLine(logFilePath, req.Page, req.PageSize, req.Latest)
@@ -501,3 +508,18 @@ func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.Fi
}
return res, nil
}
func (f *FileService) BatchCheckFiles(req request.FilePathsCheck) []response.ExistFileInfo {
fileList := make([]response.ExistFileInfo, 0, len(req.Paths))
for _, filePath := range req.Paths {
if info, err := os.Stat(filePath); err == nil {
fileList = append(fileList, response.ExistFileInfo{
Size: float64(info.Size()),
Name: info.Name(),
Path: filePath,
ModTime: info.ModTime(),
})
}
}
return fileList
}
+4
View File
@@ -381,6 +381,10 @@ func (u *FirewallService) OperateForwardRule(req dto.ForwardRuleOperate) error {
TargetIP: r.TargetIP,
TargetPort: r.TargetPort,
}, r.Operation); err != nil {
if req.ForceDelete {
global.LOG.Error(err)
continue
}
return err
}
}
+16 -11
View File
@@ -103,23 +103,28 @@ func (f *FtpService) Sync() error {
if err != nil {
return err
}
currentData := make(map[string]model.Ftp)
for _, item := range listsInDB {
currentData[item.User] = item
}
sameData := make(map[string]struct{})
for _, item := range lists {
for _, itemInDB := range listsInDB {
if item.User == itemInDB.User {
sameData[item.User] = struct{}{}
if item.Path != itemInDB.Path || item.Status != itemInDB.Status {
_ = ftpRepo.Update(itemInDB.ID, map[string]interface{}{"path": item.Path, "status": item.Status})
if itemInDB, ok := currentData[item.User]; ok {
sameData[item.User] = struct{}{}
if item.Path != itemInDB.Path || item.Status != itemInDB.Status {
if err := ftpRepo.Update(itemInDB.ID, map[string]interface{}{"path": item.Path, "status": item.Status}); err != nil {
return err
}
break
}
} else {
if err := ftpRepo.Create(&model.Ftp{User: item.User, Path: item.Path, Status: item.Status}); err != nil {
return err
}
}
}
for _, item := range lists {
if _, ok := sameData[item.User]; !ok {
_ = ftpRepo.Create(&model.Ftp{User: item.User, Path: item.Path, Status: item.Status})
}
}
for _, item := range listsInDB {
if _, ok := sameData[item.User]; !ok {
_ = ftpRepo.Update(item.ID, map[string]interface{}{"status": "deleted"})
+3
View File
@@ -439,6 +439,9 @@ func (u *ImageService) ImageRemove(req dto.BatchDelete) error {
}
return buserr.WithDetail(constant.ErrInUsed, id, nil)
}
if strings.Contains(err.Error(), "image has dependent") {
return buserr.New(constant.ErrObjectBeDependent)
}
return err
}
}
+6 -2
View File
@@ -2,6 +2,9 @@ package service
import (
"fmt"
"github.com/1Panel-dev/1Panel/backend/utils/common"
"github.com/1Panel-dev/1Panel/backend/utils/geo"
"github.com/gin-gonic/gin"
"os"
"path"
"path/filepath"
@@ -26,7 +29,7 @@ const logs = "https://resource.fit2cloud.com/installation-log.sh"
type ILogService interface {
ListSystemLogFile() ([]string, error)
CreateLoginLog(operation model.LoginLog) error
PageLoginLog(search dto.SearchLgLogWithPage) (int64, interface{}, error)
PageLoginLog(c *gin.Context, search dto.SearchLgLogWithPage) (int64, interface{}, error)
CreateOperationLog(operation model.OperationLog) error
PageOperationLog(search dto.SearchOpLogWithPage) (int64, interface{}, error)
@@ -77,7 +80,7 @@ func (u *LogService) ListSystemLogFile() ([]string, error) {
return files, nil
}
func (u *LogService) PageLoginLog(req dto.SearchLgLogWithPage) (int64, interface{}, error) {
func (u *LogService) PageLoginLog(c *gin.Context, req dto.SearchLgLogWithPage) (int64, interface{}, error) {
total, ops, err := logRepo.PageLoginLog(
req.Page,
req.PageSize,
@@ -91,6 +94,7 @@ func (u *LogService) PageLoginLog(req dto.SearchLgLogWithPage) (int64, interface
if err := copier.Copy(&item, &op); err != nil {
return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
}
item.Address, _ = geo.GetIPLocation(item.IP, common.GetLang(c))
dtoOps = append(dtoOps, item)
}
return total, dtoOps, err
+51
View File
@@ -1,6 +1,8 @@
package service
import (
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"encoding/json"
@@ -42,6 +44,7 @@ type ISettingService interface {
HandlePasswordExpired(c *gin.Context, old, new string) error
GenerateApiKey() (string, error)
UpdateApiConfig(req dto.ApiInterfaceConfig) error
GenerateRSAKey() error
}
func NewISettingService() ISettingService {
@@ -510,5 +513,53 @@ func (u *SettingService) UpdateApiConfig(req dto.ApiInterfaceConfig) error {
return err
}
global.CONF.System.IpWhiteList = req.IpWhiteList
if err := settingRepo.Update("ApiKeyValidityTime", req.ApiKeyValidityTime); err != nil {
return err
}
global.CONF.System.ApiKeyValidityTime = req.ApiKeyValidityTime
return nil
}
func exportPrivateKeyToPEM(privateKey *rsa.PrivateKey) string {
privateKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
privateKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: privateKeyBytes,
})
return string(privateKeyPEM)
}
func exportPublicKeyToPEM(publicKey *rsa.PublicKey) (string, error) {
publicKeyBytes, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return "", err
}
publicKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: publicKeyBytes,
})
return string(publicKeyPEM), nil
}
func (u *SettingService) GenerateRSAKey() error {
priKey, _ := settingRepo.Get(settingRepo.WithByKey("PASSWORD_PRIVATE_KEY"))
pubKey, _ := settingRepo.Get(settingRepo.WithByKey("PASSWORD_PUBLIC_KEY"))
if priKey.Value != "" && pubKey.Value != "" {
return nil
}
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return err
}
privateKeyPEM := exportPrivateKeyToPEM(privateKey)
publicKeyPEM, err := exportPublicKeyToPEM(&privateKey.PublicKey)
err = settingRepo.UpdateOrCreate("PASSWORD_PRIVATE_KEY", privateKeyPEM)
if err != nil {
return err
}
err = settingRepo.UpdateOrCreate("PASSWORD_PUBLIC_KEY", publicKeyPEM)
if err != nil {
return err
}
return nil
}
+41 -1
View File
@@ -87,13 +87,18 @@ type IWebsiteService interface {
LoadWebsiteDirConfig(req request.WebsiteCommonReq) (*response.WebsiteDirConfig, error)
UpdateSiteDir(req request.WebsiteUpdateDir) error
UpdateSitePermission(req request.WebsiteUpdateDirPermission) error
OperateProxy(req request.WebsiteProxyConfig) (err error)
GetProxies(id uint) (res []request.WebsiteProxyConfig, err error)
UpdateProxyFile(req request.NginxProxyUpdate) (err error)
DeleteProxy(req request.WebsiteProxyDel) (err error)
GetAuthBasics(req request.NginxAuthReq) (res response.NginxAuthRes, err error)
UpdateAuthBasic(req request.NginxAuthUpdate) (err error)
GetAntiLeech(id uint) (*response.NginxAntiLeechRes, error)
UpdateAntiLeech(req request.NginxAntiLeechUpdate) (err error)
OperateRedirect(req request.NginxRedirectReq) (err error)
GetRedirect(id uint) (res []response.NginxRedirectConfig, err error)
UpdateRedirectFile(req request.NginxRedirectUpdate) (err error)
@@ -1553,6 +1558,29 @@ func (w WebsiteService) UpdateSitePermission(req request.WebsiteUpdateDirPermiss
return websiteRepo.Save(context.Background(), &website)
}
func (w WebsiteService) DeleteProxy(req request.WebsiteProxyDel) (err error) {
fileOp := files.NewFileOp()
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.ID))
if err != nil {
return
}
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return
}
includeDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "proxy")
if !fileOp.Stat(includeDir) {
_ = fileOp.CreateDir(includeDir, 0755)
}
fileName := fmt.Sprintf("%s.conf", req.Name)
includePath := path.Join(includeDir, fileName)
backName := fmt.Sprintf("%s.bak", req.Name)
backPath := path.Join(includeDir, backName)
_ = fileOp.DeleteFile(includePath)
_ = fileOp.DeleteFile(backPath)
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
}
func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error) {
var (
website model.Website
@@ -2043,7 +2071,19 @@ func (w WebsiteService) UpdateAntiLeech(req request.NginxAntiLeechUpdate) (err e
}
newBlock.Directives = append(newBlock.Directives, ifDir)
newDirective.Block = newBlock
block.Directives = append(block.Directives, &newDirective)
index := -1
for i, directive := range block.Directives {
if directive.GetName() == "include" {
index = i
break
}
}
if index != -1 {
block.Directives = append(block.Directives[:index], append([]components.IDirective{&newDirective}, block.Directives[index:]...)...)
} else {
block.Directives = append(block.Directives, &newDirective)
}
}
if err = nginx.WriteConfig(nginxFull.SiteConfig.Config, nginx.IndentedStyle); err != nil {
+58
View File
@@ -642,9 +642,15 @@ func applySSL(website model.Website, websiteSSL model.WebsiteSSL, req request.We
}
if param.Name == "ssl_protocols" {
nginxParams[i].Params = req.SSLProtocol
if len(req.SSLProtocol) == 0 {
nginxParams[i].Params = []string{"TLSv1.3", "TLSv1.2", "TLSv1.1", "TLSv1"}
}
}
if param.Name == "ssl_ciphers" {
nginxParams[i].Params = []string{req.Algorithm}
if len(req.Algorithm) == 0 {
nginxParams[i].Params = []string{"ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK:!KRB5:!SRP:!CAMELLIA:!SEED"}
}
}
}
if req.Hsts {
@@ -1106,3 +1112,55 @@ func getResourceContent(fileOp files.FileOp, resourcePath string) (string, error
}
return "", nil
}
func ConfigAllowIPs(ips []string, website model.Website) error {
nginxFull, err := getNginxFull(&website)
if err != nil {
return err
}
nginxConfig := nginxFull.SiteConfig
config := nginxFull.SiteConfig.Config
server := config.FindServers()[0]
server.RemoveDirective("allow", nil)
server.RemoveDirective("deny", nil)
if len(ips) > 0 {
server.UpdateAllowIPs(ips)
}
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
return err
}
return nginxCheckAndReload(nginxConfig.OldContent, config.FilePath, nginxFull.Install.ContainerName)
}
func GetAllowIps(website model.Website) []string {
nginxFull, err := getNginxFull(&website)
if err != nil {
return nil
}
config := nginxFull.SiteConfig.Config
server := config.FindServers()[0]
dirs := server.GetDirectives()
var ips []string
for _, dir := range dirs {
if dir.GetName() == "allow" {
ips = append(ips, dir.GetParameters()...)
}
}
return ips
}
func ConfigAIProxy(website model.Website) error {
nginxFull, err := getNginxFull(&website)
if err != nil {
return nil
}
config := nginxFull.SiteConfig.Config
server := config.FindServers()[0]
dirs := server.GetDirectives()
for _, dir := range dirs {
if dir.GetName() == "location" && dir.GetParameters()[0] == "/" {
server.UpdateRootProxyForAi([]string{fmt.Sprintf("http://%s", website.Proxy)})
}
}
return nil
}
+1
View File
@@ -30,4 +30,5 @@ type System struct {
ApiInterfaceStatus string `mapstructure:"api_interface_status"`
ApiKey string `mapstructure:"api_key"`
IpWhiteList string `mapstructure:"ip_white_list"`
ApiKeyValidityTime string `mapstructure:"api_key_validity_time"`
}
+5 -1
View File
@@ -32,6 +32,10 @@ var WebUrlMap = map[string]struct{}{
"/apps/installed": {},
"/apps/upgrade": {},
"/ai": {},
"/ai/model": {},
"/ai/gpu": {},
"/containers": {},
"/containers/container": {},
"/containers/image": {},
@@ -113,11 +117,11 @@ var WebUrlMap = map[string]struct{}{
"/xpack/monitor/rank": {},
"/xpack/monitor/log": {},
"/xpack/tamper": {},
"/xpack/gpu": {},
"/xpack/alert/dashboard": {},
"/xpack/alert/log": {},
"/xpack/alert/setting": {},
"/xpack/setting": {},
"/xpack/app": {},
}
var DynamicRoutes = []string{
+30 -20
View File
@@ -37,22 +37,23 @@ var (
// api
var (
ErrTypeInternalServer = "ErrInternalServer"
ErrTypeInvalidParams = "ErrInvalidParams"
ErrTypeNotLogin = "ErrNotLogin"
ErrTypePasswordExpired = "ErrPasswordExpired"
ErrNameIsExist = "ErrNameIsExist"
ErrDemoEnvironment = "ErrDemoEnvironment"
ErrCmdIllegal = "ErrCmdIllegal"
ErrXpackNotFound = "ErrXpackNotFound"
ErrXpackNotActive = "ErrXpackNotActive"
ErrXpackLost = "ErrXpackLost"
ErrXpackTimeout = "ErrXpackTimeout"
ErrXpackOutOfDate = "ErrXpackOutOfDate"
ErrApiConfigStatusInvalid = "ErrApiConfigStatusInvalid"
ErrApiConfigKeyInvalid = "ErrApiConfigKeyInvalid"
ErrApiConfigIPInvalid = "ErrApiConfigIPInvalid"
ErrApiConfigDisable = "ErrApiConfigDisable"
ErrTypeInternalServer = "ErrInternalServer"
ErrTypeInvalidParams = "ErrInvalidParams"
ErrTypeNotLogin = "ErrNotLogin"
ErrTypePasswordExpired = "ErrPasswordExpired"
ErrNameIsExist = "ErrNameIsExist"
ErrDemoEnvironment = "ErrDemoEnvironment"
ErrCmdIllegal = "ErrCmdIllegal"
ErrXpackNotFound = "ErrXpackNotFound"
ErrXpackNotActive = "ErrXpackNotActive"
ErrXpackLost = "ErrXpackLost"
ErrXpackTimeout = "ErrXpackTimeout"
ErrXpackOutOfDate = "ErrXpackOutOfDate"
ErrApiConfigStatusInvalid = "ErrApiConfigStatusInvalid"
ErrApiConfigKeyInvalid = "ErrApiConfigKeyInvalid"
ErrApiConfigIPInvalid = "ErrApiConfigIPInvalid"
ErrApiConfigDisable = "ErrApiConfigDisable"
ErrApiConfigKeyTimeInvalid = "ErrApiConfigKeyTimeInvalid"
)
// app
@@ -125,10 +126,11 @@ var (
// container
var (
ErrInUsed = "ErrInUsed"
ErrObjectInUsed = "ErrObjectInUsed"
ErrPortRules = "ErrPortRules"
ErrPgImagePull = "ErrPgImagePull"
ErrInUsed = "ErrInUsed"
ErrObjectInUsed = "ErrObjectInUsed"
ErrObjectBeDependent = "ErrObjectBeDependent"
ErrPortRules = "ErrPortRules"
ErrPgImagePull = "ErrPgImagePull"
)
// runtime
@@ -167,6 +169,7 @@ var (
var (
ErrLicense = "ErrLicense"
ErrLicenseCheck = "ErrLicenseCheck"
ErrXpackVersion = "ErrXpackVersion"
ErrLicenseSave = "ErrLicenseSave"
ErrLicenseSync = "ErrLicenseSync"
)
@@ -179,3 +182,10 @@ var (
ErrAlertSync = "ErrAlertSync"
ErrAlertRemote = "ErrAlertRemote"
)
// mobile app
var (
ErrVerifyToken = "ErrVerifyToken"
ErrInvalidToken = "ErrInvalidToken"
ErrExpiredToken = "ErrExpiredToken"
)
+2
View File
@@ -6,6 +6,8 @@ const (
StatusWaiting = "Waiting"
StatusSuccess = "Success"
StatusFailed = "Failed"
StatusDeleted = "Deleted"
StatusCanceled = "Canceled"
StatusUploading = "Uploading"
StatusEnable = "Enable"
StatusDisable = "Disable"
+3 -1
View File
@@ -13,8 +13,10 @@ func NewAppStoreJob() *app {
func (a *app) Run() {
global.LOG.Info("AppStore scheduled task in progress ...")
if err := service.NewIAppService().SyncAppListFromRemote(); err != nil {
appService := service.NewIAppService()
if err := appService.SyncAppListFromRemote(); err != nil {
global.LOG.Errorf("AppStore sync failed %s", err.Error())
}
appService.SyncAppListFromLocal()
global.LOG.Info("AppStore scheduled task has completed")
}
+6 -3
View File
@@ -100,15 +100,18 @@ func Init() {
_, _ = bundle.LoadMessageFileFS(fs, "lang/zh-Hant.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/fa.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/pt.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/pt-BR.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/ja.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/ru.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/ms.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/ko.yaml")
}
func UseI18nForCmd(lang string) {
if lang == "" {
lang = "en"
}
if lang == "pt-BR" {
lang = "pt"
}
if bundle == nil {
Init()
}
+19 -7
View File
@@ -12,9 +12,10 @@ ErrApiConfigStatusInvalid: "API Interface access prohibited: {{ .detail }}"
ErrApiConfigKeyInvalid: "API Interface key error: {{ .detail }}"
ErrApiConfigIPInvalid: "API Interface IP is not on the whitelist: {{ .detail }}"
ErrApiConfigDisable: "This interface prohibits the use of API Interface calls: {{ .detail }}"
ErrApiConfigKeyTimeInvalid: "API Interface timestamp error: {{ .detail }}"
#common
ErrNameIsExist: "Name is already exist"
ErrNameIsExist: "Name already exists"
ErrDemoEnvironment: "Demo server, prohibit this operation!"
ErrCmdTimeout: "Command execution timed out!"
ErrCmdIllegal: "The command contains illegal characters. Please modify and try again!"
@@ -31,7 +32,7 @@ SystemRestart: "System restart causes task interruption"
#app
ErrPortInUsed: "{{ .detail }} port already in use"
ErrAppLimit: "App exceeds install limit"
ErrAppRequired: "{{ .detail }} app is required"
ErrAppRequired: "The {{ .detail }} app is required"
ErrNotInstall: "App not installed"
ErrPortInOtherApp: "{{ .port }} port already in use by app {{ .apps }}"
ErrDbUserNotValid: "Stock database, username and password do not match!"
@@ -59,7 +60,7 @@ ErrContainerNotFound: '{{ .name }} container does not exist'
ErrContainerMsg: '{{ .name }} container is abnormal, please check the log on the container page for details'
ErrAppBackup: '{{ .name }} application backup failed err {{.err}}'
ErrImagePull: '{{ .name }} image pull failed err {{.err}}'
ErrVersionTooLow: 'The current 1Panel version is too low to update the app store, please upgrade the version'
ErrVersionTooLow: 'The current 1Panel version is too low for updating the app store, please upgrade the version'
ErrAppNameExist: 'App name is already exist'
AppStoreIsSyncing: 'The App Store is syncing, please try again later'
ErrGetCompose: "Failed to obtain docker-compose.yml file! {{ .detail }}"
@@ -88,8 +89,8 @@ ErrInvalidChar: "Illegal characters are prohibited"
ErrPathNotDelete: "The selected directory cannot be deleted"
#website
ErrDomainIsExist: "Domain is already exist"
ErrAliasIsExist: "Alias is already exist"
ErrDomainIsExist: "The domain name already exists"
ErrAliasIsExist: "The alias already exists"
ErrAppDelete: 'Other Website use this App'
ErrGroupIsUsed: "The group is in use and can't be deleted"
ErrBackupMatch: "the backup file doesn't match the current partial data of the website: {{ .detail}}"
@@ -145,12 +146,13 @@ ErrTypeOfRedis: "The recovery file type does not match the current persistence m
#container
ErrInUsed: "{{ .detail }} is in use and can't be deleted"
ErrObjectInUsed: "This object is in use and can't be deleted"
ErrObjectBeDependent: "This image is dependent on other images and can't be deleted"
ErrPortRules: "The number of ports does not match, please re-enter!"
ErrPgImagePull: "Image pull timeout. Please configure image acceleration or manually pull the postgres:16.0-alpine image and try again"
#runtime
ErrDirNotFound: "The build folder does not exist! Please check file integrity!"
ErrFileNotExist: "{{ .detail }} file does not exist! Please check source file integrity!"
ErrDirNotFound: "The build folder does not exist! Please check the integrity of the file!"
ErrFileNotExist: "{{ .detail }} file does not exist! Please check the integrity of the source file!"
ErrImageBuildErr: "Image build failed"
ErrImageExist: "Image is already exist!"
ErrDelWithWebsite: "The operating environment has been associated with a website and cannot be deleted"
@@ -203,6 +205,7 @@ ErrIPExist: "IP is exit"
#license
ErrLicense: "License format error, please check and try again!"
ErrLicenseCheck: "License verification failed, please check and try again!"
ErrXpackVersion: "License verification failed, this license is version-restricted and cannot be successfully imported. Please check and try again!"
ErrLicenseSave: "Failed to save license information, error {{ .err }}, please try again!"
ErrLicenseSync: "Failed to sync license information, no license information detected in the database!"
ErrXpackNotFound: "This section is a professional edition feature, please import the license first in Panel Settings-License interface"
@@ -281,3 +284,12 @@ UserInfoPassHelp: "Tip: To change the password, you can execute the command: "
DBConnErr: "Error: Failed to initialize database connection, {{ .err }}"
SystemVersion: "version: "
SystemMode: "mode: "
#ai-tool
ErrOpenrestyInstall: 'Please install Openresty first'
ErrSSL: "Certificate content is empty, please check the certificate!"
#mobile app
ErrVerifyToken: 'Token verification error, please reset and scan again.'
ErrInvalidToken: 'Invalid token, please reset and scan again.'
ErrExpiredToken: 'Token has expired, please reset and scan again.'
-63
View File
@@ -1,63 +0,0 @@
#cmd
AppVersion: "Lotfan noskhe-ye barname ra vared konid"
AppCommands: "Dasturat-e marbut be barname"
AppInit: "Barname ra shoru' konid"
AppKeyVal: "Kelid-e barname (faghat az zabane englisi poshtibani mikonad)"
AppCreateFileErr: "Khalgh-e file {{ .name }} namovaffagh bud {{ .err }}"
AppCreateDirErr: "Khalgh-e folder {{ .name }} namovaffagh bud {{ .err }}"
AppMissKey: "Kelid-e barname mojood nist, az -k estefade konid"
AppMissVersion: "Noskhe-ye barname mojood nist, az -v estefade konid"
AppVersionExist: "Noskhe ghablan mojood ast!"
AppCreateSuccessful: "Khalgh ba movaffaghiat anjam shod!"
AppWriteErr: "Neveshtan file {{ .name }} namovaffagh bud {{ .err }}"
SudoHelper: "Lotfan in eskript ra be onvane karbare root ya ba mojavez sudo ejra konid"
ListenIPCommands: "IP goosh dadan ra taghir dahid"
ListenIPv4: "Goosh dadan bar IPv4"
ListenIPv6: "Goosh dadan bar IPv6"
ListenChangeSuccessful: "Taghir movaffagh! Hala bar {{ .value }} goosh midahad"
ResetCommands: "E'ade setadad etela'at-e system"
ResetMFA: "Fa'al-sazi do marhale'i 1Panel ra laghv konid"
ResetHttps: "Voroud HTTPS baraye 1Panel ra laghv konid"
ResetEntrance: "Voroud amin 1Panel ra laghv konid"
ResetIPs: "Mahdudiyat IP-haye mojaz 1Panel ra laghv konid"
ResetDomain: "Sazgari domain 1Panel ra laghv konid"
RestoreCommands: "Bargasht be khadamate 1Panel va data"
RestoreNoSuchFile: "Hich file mojood baraye bargasht nist"
RestoreStep1: "(1/5) Shoru' bargasht be khadamate 1Panel va data az directory {{ .name }} ..."
RestoreStep2: "(2/5) Bargasht be binary 1Panel ba movaffaghiat anjam shod"
RestoreStep3: "(3/5) Bargasht be script 1Panel ba movaffaghiat anjam shod"
RestoreStep4: "(4/5) Bargasht be khadamat 1Panel ba movaffaghiat anjam shod"
RestoreStep5: "(5/5) Bargasht be data 1Panel ba movaffaghiat anjam shod"
RestoreSuccessful: "Bargasht ba movaffaghiat anjam shod! Khadamat dar hale restart ast, lotfan montazer bashid..."
UpdateCommands: "Be'rooz resani etela'at-e panel"
UpdateUser: "Be'rooz resani karbare panel"
UpdatePassword: "Be'rooz resani ramz-e panel"
UpdatePort: "Be'rooz resani port-e panel"
UpdateUserNull: "Khatta: karbare panel khalist!"
UpdateUserBlank: "Khatta: karbare panel shamel faseleh ast!"
UpdateUserFormat: "Khatta: format-e karbare panel na dorost ast! Faghat az englisi, chine'i, adad va _, ba tool-e 3-30 poshtibani mikonad"
UpdateUserErr: "Khatta: be'rooz resani karbare panel namovaffagh bud, {{ .err }}"
UpdateSuccessful: "Be'rooz resani ba movaffaghiat anjam shod!"
UpdateUserResult: "Karbare panel: {{ .name }}"
UpdatePasswordRead: "Khatta: khatayi dar khandan etela'at-e ramz-e panel, {{ .err }}"
UpdatePasswordNull: "Khatta: ramz-e panel khalist!"
UpdateUPasswordBlank: "Khatta: ramz-e panel shamel faseleh ast!"
UpdatePasswordFormat: "Khatta: ramz-e panel faghat az harf, adad, karakter-haye vizhe !@#$%*_,.? ba tool-e 8-30 poshtibani mikonad!"
UpdatePasswordLen: "Khatta: lotfan ramzi bishtar az 6 karakter vared konid!"
UpdatePasswordRe: "Teyid-e ramz:"
UpdatePasswordErr: "Khatta: be'rooz resani ramz-e panel namovaffagh bud, {{ .err }}"
UpdatePasswordSame: "Khatta: do ramz ba ham yeksan nistand, lotfan barrasi konid va dobare talash konid!"
UpdatePasswordResult: "Ramz-e panel: {{ .name }}"
UpdatePortFormat: "Khatta: shomareye port bayad bein 1 ta 65535 bashad!"
UpdatePortUsed: "Khatta: shomareye port ghablan estefade shode ast, lotfan barrasi konid va dobare talash konid!"
UpdatePortErr: "Khatta: be'rooz resani port-e panel namovaffagh bud, {{ .err }}"
UpdatePortResult: "Port-e panel: {{ .name }}"
UpdatePortFirewallAdd: "Ezafe kardane ghanoun-e port firewall namovaffagh bud, {{ .err }}, lotfan port {{ .name }} ra be dast az qavaneen firewall ezafe konid."
UpdatePortFirewallDel: "Khatta: hazf-e port firewall namovaffagh bud, {{ .err }}"
UpdatePortFirewallReload: "Reload firewall namovaffagh bud, {{ .err }}, lotfan firewall ra be dast reload konid."
UserInfo: "Daryaft etela'at-e panel"
UserInfoAddr: "Adres-e panel: "
UserInfoPassHelp: "Nokte: baraye taghiri ramz, mitavanid dastur zir ra anjam dahid: "
DBConnErr: "Khatta: etesal be database namovaffagh bud, {{ .err }}"
SystemVersion: "noskhe: "
SystemMode: "halat: "
+293
View File
@@ -0,0 +1,293 @@
ErrInvalidParams: "リクエストパラメーターエラー: {{.Detail}}"
ErrTokenParse: "トークン生成エラー: {{.Detail}}"
ErrInitialPassword: "初期パスワードエラー"
ErrInternalServer: "サービス内部エラー: {{.Detail}}"
ErrRecordExist: "レコードはすでに存在します"
ErrRecordNotFound: "記録が見つかりません"
ErrStructTransform: "タイプ変換障害: {{.Detail}}"
ErrNotLogin: "ユーザーはログインしません: {{.Detail}}"
ErrPasswordExpired: "現在のパスワードが期限切れになっています: {{.Detail}}"
ErrNotSupportType: "システムは現在のタイプをサポートしていません: {{.Detail}}"
ErrApiConfigStatusInvalid: "APIインターフェイスアクセス禁止: {{.Detail}}"
ErrApiConfigKeyInvalid: "APIインターフェイスキーエラー: {{.Detail}}"
ErrApiConfigIPInvalid: "APIインターフェイスIPはホワイトリストにありません: {{.Detail}}"
ErrApiConfigDisable: "このインターフェイスは、APIインターフェイスコールの使用を禁止しています: {{.Detail}}"
#common
ErrNameIsExist: "名前はすでに存在しています"
ErrDemoEnvironment: "デモサーバー、この操作を禁止します!"
ErrCmdTimeout: "コマンド実行がタイムアウトしました!"
ErrCmdIllegal: "コマンドには違法な文字が含まれています。変更してもう一度やり直してください!"
ErrPortExist: '{{.port}}ポートはすでに{{.type}} [{{.name}}]によって占有されています。'
TYPE_APP: "応用"
TYPE_RUNTIME: "ランタイム環境"
TYPE_DOMAIN: "ドメイン名"
ErrTypePort: 'port {{.name}}フォーマットエラー'
ErrTypePortRange: 'ポートレンジは1-65535の間である必要があります'
Success: "成功"
Failed: "失敗した"
SystemRestart: "システムの再起動により、タスクが中断されます"
#app
ErrPortInUsed: "{{.Detail}}ポートはすでに使用されています"
ErrAppLimit: "アプリはインストール制限を超えています"
ErrAppRequired: "{{.Detail}}アプリが必要です"
ErrNotInstall: "アプリがインストールされていません"
ErrPortInOtherApp: "{{.port}}ポートは既にapp {{.apps}}で使用されています"
ErrDbUserNotValid: "ストックデータベース、ユーザー名、パスワードが一致しません!"
ErrDockerComposeNotValid: "Docker-Composeファイル形式のエラー!"
ErrUpdateBuWebsite: 'アプリケーションは正常に更新されましたが、Webサイト構成ファイルの変更に失敗しました。構成を確認してください!'
Err1PanelNetworkFailed: 'デフォルトのコンテナネットワークの作成に失敗しました!{{ 。詳細 }}'
ErrFileParse: 'アプリケーションDocker-Composeファイルの解析は失敗しました!'
ErrInstallDirNotFound: 'インストールディレクトリは存在しません'
AppStoreIsUpToDate: '最新の'
LocalAppVersionNull: '{{.name}}アプリはバージョンに同期されません!アプリケーションリストに追加できませんでした'
LocalAppVersionErr: '{{.name}}}バージョン{{.version}}の同期に失敗しました!{{.err}}'
ErrFileNotFound: '{{.name}}ファイルは存在しません'
ErrFileParseApp: '{{.name}} file {{.err}}を解析できなかった'
ErrAppDirNull: 'バージョンフォルダーは存在しません'
LocalAppErr: "app {{.name}}同期が失敗しました!{{.err}}"
ErrContainerName: "cantablernameはすでに存在しています"
ErrAppSystemRestart: "1パネルの再起動により、タスクが終了します"
ErrCreateHttpClient: "http request {{.err}}の作成に失敗しました"
ErrHttpReqTimeOut: "リクエスト{{.err}}"
ErrHttpReqFailed: "リクエストが失敗しました{{.err}}"
ErrHttpReqNotFound: "ファイルは存在しません"
ErrNoSuchHost: "ネットワーク接続に失敗しました"
ErrImagePullTimeOut: '画像プルタイムアウト'
ErrContainerNotFound: '{{.name}}コンテナは存在しません'
ErrContainerMsg: '{{.name}}コンテナは異常です。詳細については、コンテナページのログを確認してください'
ErrAppBackup: '{{.name}}アプリケーションバックアップが失敗したerr {{.err}}'
ErrImagePull: '{{.name}}画像プルFailed err {{.err}}'
ErrVersionTooLow: '現在の1パネルバージョンが低すぎてApp Storeを更新できないので、バージョンをアップグレードしてください'
ErrAppNameExist: 'アプリ名はすでに存在しています'
AppStoreIsSyncing: 'App Storeが同期しています。後でもう一度やり直してください'
ErrGetCompose: "docker-compose.ymlファイルを取得できませんでした!{{ 。詳細 }}"
ErrAppWarn: "異常なステータス、ログを確認してください"
ErrAppParamKey: "parameter {{.name}}フィールド例外"
ErrAppUpgrade: "アプリケーションのアップグレードに失敗しました{{.name}} {{.err}}"
AppRecover: "app {{.name}}ロールバック"
PullImageStart: "画像の引っ張りを開始{{.name}}"
PullImageSuccess: "画像が正常に引っ張られました"
UpgradeAppStart: "アプリケーションのアップグレードを起動{{.name}}"
UpgradeAppSuccess: "App {{.Name}}アップグレードされました"
#file
ErrFileCanNotRead: "ファイルは読み取れません"
ErrFileToLarge: "ファイルが大きすぎます"
ErrPathNotFound: "パスは見つかりません"
ErrMovePathFailed: "ターゲットパスには元のパスが含まれていません!"
ErrLinkPathNotFound: "ターゲットパスは存在しません!"
ErrFileIsExist: "ファイルまたはディレクトリはすでに存在します!"
ErrFileUpload: "file {{.name}} {{.detail}}}のアップロードに失敗しました"
ErrFileDownloadDir: "サポートされていないフォルダーをダウンロードします"
ErrCmdNotFound: "{{.name}}コマンドは存在しません。最初にホストにこのコマンドをインストールしてください"
ErrSourcePathNotFound: "ソースディレクトリは存在しません"
ErrFavoriteExist: "このパスが収集されました"
ErrInvalidChar: "違法なキャラクターは禁止されています"
ErrPathNotDelete: "選択したディレクトリを削除することはできません"
#website
ErrDomainIsExist: "ドメインはすでに存在しています"
ErrAliasIsExist: "エイリアスはすでに存在しています"
ErrAppDelete: '他のウェブサイトはこのアプリを使用します'
ErrGroupIsUsed: "グループは使用されており、削除することはできません"
ErrBackupMatch: "バックアップファイルは、ウェブサイトの現在の部分的なデータと一致しません: {{.Detail}}"
ErrBackupExist: 'バックアップファイルは、存在しない元のデータの一部に対応しています。{{.Detail}}'
ErrPHPResource: 'ローカルランタイムはスイッチングをサポートしません!'
ErrPathPermission: 'インデックスディレクトリで1000: 1000以外のアクセス許可を持つフォルダーが検出されたため、Webサイトにアクセスするとアクセスが拒否された場合があります。上の[保存]ボタンをクリックしてください'
ErrDomainIsUsed: "ドメインはすでにWebサイトで使用されています{{.Name}}"
ErrDomainFormat: "{{.name}}ドメイン形式エラー"
ErrDefaultAlias: "デフォルトは予約済みのコード名です。別のコード名を使用してください"
ErrImageNotExist: "実行中の環境{{.name}}画像は存在しません。実行中の環境を再編集してください"
#ssl
ErrSSLCannotDelete: "証明書{{.Name}}はWebサイトで使用されており、削除できません"
ErrAccountCannotDelete: "アカウントに関連付けられた証明書を削除することはできません"
ErrSSLApply: "証明書は引き続き正常に署名されていますが、OpenRestyリロードが失敗します。構成を確認してください!"
ErrEmailIsExist: 'メールはすでに存在しています'
ErrSSLKeyNotFound: '秘密キーファイルは存在しません'
ErrSSLCertificateNotFound: '証明書ファイルは存在しません'
ErrSSLKeyFormat: '秘密キーファイル検証エラー'
ErrSSLCertificateFormat: '証明書ファイル形式エラー、PEM形式を使用してください'
ErrEabKidOrEabHmacKeyCannotBlank: 'eabkidまたはeabhmackeyは空にすることはできません'
ErrOpenrestyNotFound: 'HTTPモードでは、最初にOpenRestyをインストールする必要があります'
ApplySSLStart: '証明書、ドメイン名[{{.domain}}]アプリケーションメソッド[{{.type}}]の申請を開始します'
dnsAccount: "DNSオートマチック"
dnsManual: "DNSマニュアル"
http: "http"
ApplySSLFailed: '[{{.domain}}]証明書のアプリケーションが失敗しました、{{.detail}}'
ApplySSLSuccess: '[{{{.domain}}]証明書のアプリケーションが成功しました!!'
DNSAccountName: 'dnsアカウント[{{.name}}]メーカー[{{.type}}]'
PushDirLog: 'ディレクトリにプッシュされた証明書[{{.Path}}] {{.Status}}'
ErrDeleteCAWithSSL: "現在の組織の下に発行された証明書があり、削除できません"
ErrDeleteWithPanelSSL: "パネルSSL構成はこの証明書を使用しており、削除できません"
ErrDefaultCA: "デフォルトの証明書当局は削除できません"
ApplyWebSiteSSLLog: "{{.name}} Webサイト証明書の更新を開始します"
ErrUpdateWebsiteSSL: "{{.name}}ウェブサイトは証明書の更新に失敗しました: {{.err}}"
ApplyWebSiteSSLSuccess: "ウェブサイトの証明書を正常に更新します"
ErrExecShell: "スクリプトの実行に失敗した{{.err}}"
ExecShellStart: "スクリプトの実行を開始します"
ExecShellSuccess: "スクリプトは正常に実行されました"
StartUpdateSystemSSL: "システム証明書の更新を開始します"
UpdateSystemSSLSuccess: "システム証明書を正常に更新します"
#mysql
ErrUserIsExist: "現在のユーザーはすでに存在しています。新しいユーザーを入力してください"
ErrDatabaseIsExist: "現在のデータベースはすでに存在しています。新しいデータベースを入力してください"
ErrExecTimeOut: "SQL実行のタイミングを出して、データベースを確認してください"
ErrRemoteExist: "リモートデータベースはすでにその名前に存在しています。それを変更して、再試行してください"
ErrLocalExist: "ローカルデータベースはすでにその名前に存在しています。それを変更して、もう一度試してください"
#redis
ErrTypeOfRedis: "回復ファイルのタイプは、現在の永続性モードと一致しません。ファイルタイプを変更して、再試行してください"
#container
ErrInUsed: "{{.Detail}}が使用されており、削除できません"
ErrObjectInUsed: "このオブジェクトは使用されており、削除することはできません"
ErrPortRules: "ポートの数が一致しません。再入力してください!"
ErrPgImagePull: "画像プルタイムアウト。画像の加速を構成するか、Postgres: 16.0-Alpine画像を手動で引いて、再試行してください"
#runtime
ErrDirNotFound: "ビルドフォルダーは存在しません!ファイルの整合性を確認してください!"
ErrFileNotExist: "{{.Detail}}ファイルは存在しません!ソースファイルの完全性を確認してください!"
ErrImageBuildErr: "画像ビルドが失敗しました"
ErrImageExist: "画像はすでに存在しています!"
ErrDelWithWebsite: "運用環境はウェブサイトに関連付けられており、削除することはできません"
ErrRuntimeStart: "開始に失敗しました"
ErrPackageJsonNotFound: "package.jsonファイルは存在しません"
ErrScriptsNotFound: "Package.jsonにスクリプト構成アイテムは見つかりませんでした"
ErrContainerNameNotFound: "コンテナ名を取得できない場合は、.envファイルを確認してください"
ErrNodeModulesNotFound: "node_modulesフォルダーは存在しません!実行中の環境を編集するか、実行中の環境が正常に開始するのを待ちます"
#setting
ErrBackupInUsed: "バックアップアカウントは既にCronjobで使用されており、削除することはできません。"
ErrBackupCheck: "バックアップアカウントテスト接続に失敗した{{.err}}"
ErrOSSConn: "最新バージョンを取得できない場合は、サーバーが外部ネットワークに接続できるかどうかを確認してください。"
ErrEntrance: "セキュリティ入り口情報エラー。チェックしてもう一度やり直してください!"
#tool
ErrConfigNotFound: "構成ファイルは存在しません"
ErrConfigParse: "構成ファイル形式エラー"
ErrConfigIsNull: "構成ファイルは空にすることは許可されていません"
ErrConfigDirNotFound: "実行中のディレクトリは存在しません"
ErrConfigAlreadyExist: "同じ名前の構成ファイルが既に存在しています"
ErrUserFindErr: "ユーザー{{.name}} {{.err}}を見つけられなかった"
#ssh
ErrFirewallNone: "システムでFirewalldまたはUFWサービスは検出されませんでした。チェックしてもう一度やり直してください!"
ErrFirewallBoth: "FirewalldサービスとUFWサービスの両方がシステムで検出されます。競合を避けるために、1つをアンインストールして再試行してください!"
#cronjob
ErrBashExecute: "スクリプト実行エラー、タスク出力テキスト領域の特定の情報を確認してください。"
ErrCutWebsiteLog: "{{.Name}} Webサイトログの切断が失敗した、エラー{{.err}}"
CutWebsiteLogSuccess: "{{.Name}} Webサイトログカットに正常にカット、バックアップパス{{.Path}}"
#toolbox
ErrNotExistUser: "現在のユーザーは存在しません。変更して再試行してください!"
ErrBanAction: "失敗した設定では、現在の{{.name}}サービスが利用できません。チェックして再試行してください!"
ErrClamdscanNotFound: "Clamdscanコマンドは検出されませんでした。インストールするためにドキュメントを参照してください!"
#waf
ErrScope: "この構成の変更はサポートされていません"
ErrStateChange: "状態の変更に失敗しました"
ErrRuleExist: "ルールが存在します"
ErrRuleNotExist: "ルールは存在しません"
ErrParseIP: "IP形式エラー"
ErrDefaultIP: "デフォルトは予約済みの名前です。別の名前に変更してください"
ErrGroupInUse: "IPグループはブラック/ホワイトリストで使用され、削除できません"
ErrGroupExist: "IPグループ名はすでに存在しています"
ErrIPRange: "間違ったIP範囲"
ErrIPExist: "IPは終了します"
#license
ErrLicense: "ライセンス形式のエラー、チェックして再試行してください!"
ErrLicenseCheck: "ライセンスの確認が失敗しました。チェックしてもう一度やり直してください!"
ErrLicenseSave: "ライセンス情報の保存に失敗しました、{{.err}}、もう一度やり直してください!"
ErrLicenseSync: "ライセンス情報の同期に失敗し、データベースでライセンス情報は検出されませんでした!"
ErrXpackNotFound: "このセクションはプロフェッショナルエディション機能です。最初にパネルsettings-licenseインターフェイスにライセンスをインポートしてください"
ErrXpackNotActive: "このセクションはプロフェッショナルエディション機能です。最初にパネル設定リセンスインターフェイスでライセンスステータスを同期してください"
ErrXpackOutOfDate: "現在のライセンスの有効期限が切れています。パネル設定リセンスインターフェイスにライセンスを再輸入してください"
ErrXpackLost: "ライセンスは、再試行の最大数に達しました。[設定] [ライセンス]ページに移動し、[同期]ボタンを手動でクリックして、プロフェッショナルバージョンの機能が適切に機能していることを確認してください。"
ErrXpackTimeout: "リクエストタイムアウト、ネットワーク接続が不安定な場合があります。後でもう一度やり直してください!"
#license
ErrAlert: "情報形式のエラーをアラートしてください。チェックして再試行してください!"
ErrAlertPush: "アラートプッシュエラー、チェックして再試行してください!"
ErrAlertSave: "エラーを保存してください、チェックして再試行してください!"
ErrAlertSync: "アラート同期エラー、チェックして再試行してください!"
ErrAlertRemote: "リモートアラートエラー、チェックして再試行してください!"
#cmd
AppVersion: "アプリバージョン"
AppCommands: "アプリ関連のコマンド"
AppInit: "アプリを初期化します"
AppKeyVal: "アプリキー(英語のみをサポートする)"
AppCreateFileErr: "file {{.name}}作成に失敗した{{.err}}"
AppCreateDirErr: "Folder {{.name}}作成に失敗した{{.err}}"
AppMissKey: "アプリキーがありません、-kを使用して指定します"
AppMissVersion: "アプリバージョンがありません、-vを使用して指定します"
AppVersionExist: "バージョンはすでに存在します!"
AppCreateSuccessful: "創造は成功しました!"
AppWriteErr: "file {{.name}} write failed {{.err}}"
SudoHelper: "{{.cmd}}を使用するか、ルートユーザーに切り替えてください"
ListenIPCommands: "リスニングIPを切り替えます"
ListenIPv4: "IPv4で聞いてください"
ListenIPv6: "IPv6で聞く"
ListenChangeSuccessful: "切り替え成功!{{.Value}}で聞いています"
ResetCommands: "システム情報をリセットします"
ResetMFA: "1パネルの2要素認証をキャンセルします"
ResetHttps: "1Panel HTTPSログインをキャンセルします"
ResetEntrance: "1パネルの安全な入り口をキャンセルします"
ResetIPs: "1パネル認定IP制限をキャンセルします"
ResetDomain: "1パネルドメインバインディングをキャンセルします"
RestoreCommands: "ロールバック1パネルサービスとデータ"
RestoreNoSuchFile: "ロールバックに使用できるファイルはありません"
RestoreStep1: "(1/5){{.name}}ディレクトリからの1パネルサービスとデータの開始ロールバック..."
RestoreStep2: "(2/5)1パネルバイナリロールバックが成功しました"
RestoreStep3: "(3/5)1パネルスクリプトロールバック成功"
RestoreStep4: "(4/5)1パネルサービスロールバックが成功しました"
RestoreStep5: "(5/5)1パネルデータロールバックが成功しました"
RestoreSuccessful: "ロールバックが成功しました!サービスを再起動します、待ってください..."
UpdateCommands: "パネル情報を更新します"
UpdateUser: "パネルユーザーを更新します"
UpdatePassword: "パスワードを更新します"
UpdatePort: "パネルポートを更新します"
UpdateUserNull: "エラー: パネルユーザーは空です!"
UpdateUserBlank: "エラー: パネルユーザーにはスペースが含まれています!"
UpdateUserFormat: "エラー: 無効なパネルユーザー形式!英語、中国語、数字、_、長さ3〜30のみをサポートしています"
UpdateUserErr: "エラー: パネルユーザーの更新に失敗しました{{.err}}"
UpdateSuccessful: "更新成功!"
UpdateUserResult: "パネルユーザー: {{.name}}"
UpdatePasswordRead: "エラー: パネルパスワード情報の読み取りに失敗しました、{{.err}}"
UpdatePasswordNull: "エラー: パネルパスワードは空です!"
UpdateUPasswordBlank: "エラー: パスワードにはスペースが含まれています!"
UpdatePasswordFormat: "エラー: パネルパスワードは、文字、数字、特殊文字のみをサポートします!@#$%*_、。、、長さ8-30!"
UpdatePasswordLen: "エラー: 6文字より長くパスワードを入力してください!"
UpdatePasswordRe: "パスワードを認証する: "
UpdatePasswordErr: "エラー: {{.err}}のパスワードの更新に失敗しました"
UpdatePasswordSame: "エラー: 2つのパスワードが一致しません。チェックして再試行してください!"
UpdatePasswordResult: "パネルパスワード: {{.name}}"
UpdatePortFormat: "エラー: 入力ポート番号は1〜65535でなければなりません!"
UpdatePortUsed: "エラー: ポート番号はすでに使用されています。チェックして再試行してください!"
UpdatePortErr: "エラー: パネルポートの更新に失敗しました{{.err}}"
UpdatePortResult: "パネルポート: {{.name}}"
UpdatePortFirewallAdd: "ファイアウォールポートルールの追加に失敗した{{.err}}、ファイアウォールルールに{{.name}}ポートを手動で追加してください。"
UpdatePortFirewallDel: "エラー: ファイアウォールポートの削除に失敗しました、{{.err}}"
UpdatePortFirewallReload: "ファイアウォールのリロードに失敗しました{{.err}}、ファイアウォールを手動でリロードしてください。"
UserInfo: "パネル情報を取得します"
UserInfoAddr: "パネルアドレス: "
UserInfoPassHelp: "ヒント: パスワードを変更するには、コマンドを実行できます。"
DBConnErr: "エラー: データベース接続の初期化に失敗しました、{{.err}}"
SystemVersion: "バージョン: "
SystemMode: "モード: "
#ai-tool
ErrOpenrestyInstall: 'まず Openresty をインストールしてください'
ErrSSL: "証明書の内容が空です。証明書を確認してください!"
#mobile app
ErrVerifyToken: 'トークンの検証エラーです。リセット後、再度QRコードをスキャンしてください。'
ErrInvalidToken: '無効なトークンです。リセット後、再度QRコードをスキャンしてください。'
ErrExpiredToken: 'トークンの有効期限が切れました。リセット後、再度QRコードをスキャンしてください。'
+296
View File
@@ -0,0 +1,296 @@
ErrInvalidParams: "요청 매개변수 오류: {{ .detail }}"
ErrTokenParse: "토큰 생성 오류: {{ .detail }}"
ErrInitialPassword: "초기 비밀번호 오류"
ErrInternalServer: "서버 내부 오류: {{ .detail }}"
ErrRecordExist: "기록이 이미 존재합니다"
ErrRecordNotFound: "기록을 찾을 수 없습니다"
ErrStructTransform: "형식 변환 실패: {{ .detail }}"
ErrNotLogin: "사용자가 로그인되지 않았습니다: {{ .detail }}"
ErrPasswordExpired: "현재 비밀번호가 만료되었습니다: {{ .detail }}"
ErrNotSupportType: "시스템에서 현재 유형을 지원하지 않습니다: {{ .detail }}"
ErrApiConfigStatusInvalid: "API 인터페이스 액세스 금지: {{ .detail }}"
ErrApiConfigKeyInvalid: "API 인터페이스 키 오류: {{ .detail }}"
ErrApiConfigIPInvalid: "API 인터페이스 IP가 화이트리스트에 없습니다: {{ .detail }}"
ErrApiConfigDisable: "이 인터페이스는 API 호출을 금지합니다: {{ .detail }}"
ErrApiConfigKeyTimeInvalid: "API 인터페이스 타임스탬프 오류: {{ .detail }}"
# 공통
ErrNameIsExist: "이름이 이미 존재합니다"
ErrDemoEnvironment: "데모 서버에서는 이 작업이 금지되어 있습니다!"
ErrCmdTimeout: "명령어 실행 시간이 초과되었습니다!"
ErrCmdIllegal: "명령어에 잘못된 문자가 포함되어 있습니다. 수정 후 다시 시도하세요!"
ErrPortExist: '{{ .port }} 포트가 {{ .type }} [{{ .name }}]에 의해 이미 사용 중입니다'
TYPE_APP: "애플리케이션"
TYPE_RUNTIME: "실행 환경"
TYPE_DOMAIN: "도메인 이름"
ErrTypePort: '포트 {{ .name }} 형식 오류'
ErrTypePortRange: '포트 범위는 1-65535 사이여야 합니다'
Success: "성공"
Failed: "실패"
SystemRestart: "시스템 재시작으로 인해 작업이 중단되었습니다"
# 애플리케이션
ErrPortInUsed: "{{ .detail }} 포트가 이미 사용 중입니다"
ErrAppLimit: "앱 설치 제한을 초과했습니다"
ErrAppRequired: "{{ .detail }} 앱이 필요합니다"
ErrNotInstall: "앱이 설치되지 않았습니다"
ErrPortInOtherApp: "{{ .port }} 포트가 {{ .apps }} 앱에 의해 이미 사용 중입니다"
ErrDbUserNotValid: "데이터베이스 사용자 이름과 비밀번호가 일치하지 않습니다!"
ErrDockerComposeNotValid: "docker-compose 파일 형식 오류!"
ErrUpdateBuWebsite: "애플리케이션이 성공적으로 업데이트되었지만, 웹사이트 구성 파일 수정에 실패했습니다. 구성을 확인하세요!"
Err1PanelNetworkFailed: "기본 컨테이너 네트워크 생성 실패! {{ .detail }}"
ErrFileParse: "애플리케이션 docker-compose 파일 분석 실패!"
ErrInstallDirNotFound: "설치 디렉터리가 존재하지 않습니다"
AppStoreIsUpToDate: "최신 상태입니다"
LocalAppVersionNull: "{{.name}} 앱 버전이 동기화되지 않았습니다! 애플리케이션 목록에 추가할 수 없습니다"
LocalAppVersionErr: "{{.name}} 버전 {{.version}} 동기화 실패! {{.err}}"
ErrFileNotFound: "{{.name}} 파일이 존재하지 않습니다"
ErrFileParseApp: "{{.name}} 파일 분석 실패 {{.err}}"
ErrAppDirNull: "버전 폴더가 존재하지 않습니다"
LocalAppErr: "앱 {{.name}} 동기화 실패! {{.err}}"
ErrContainerName: "컨테이너 이름이 이미 존재합니다"
ErrAppSystemRestart: "1Panel 재시작으로 인해 작업이 중단되었습니다"
ErrCreateHttpClient: "HTTP 요청 생성 실패 {{.err}}"
ErrHttpReqTimeOut: "요청 시간이 초과되었습니다 {{.err}}"
ErrHttpReqFailed: "요청 실패 {{.err}}"
ErrHttpReqNotFound: "파일이 존재하지 않습니다"
ErrNoSuchHost: "네트워크 연결 실패"
ErrImagePullTimeOut: "이미지 가져오기 시간 초과"
ErrContainerNotFound: "{{ .name }} 컨테이너가 존재하지 않습니다"
ErrContainerMsg: "{{ .name }} 컨테이너가 비정상적입니다. 자세한 내용은 컨테이너 페이지의 로그를 확인하세요"
ErrAppBackup: "{{ .name }} 애플리케이션 백업 실패 오류 {{.err}}"
ErrImagePull: "{{ .name }} 이미지 가져오기 실패 오류 {{.err}}"
ErrVersionTooLow: "현재 1Panel 버전이 낮아 앱 스토어를 업데이트할 수 없습니다. 버전을 업그레이드하세요"
ErrAppNameExist: "앱 이름이 이미 존재합니다"
AppStoreIsSyncing: "앱 스토어가 동기화 중입니다. 나중에 다시 시도하세요"
ErrGetCompose: "docker-compose.yml 파일 가져오기 실패! {{ .detail }}"
ErrAppWarn: "비정상 상태, 로그를 확인하세요"
ErrAppParamKey: "매개변수 {{ .name }} 필드 예외"
ErrAppUpgrade: "애플리케이션 {{ .name }} 업그레이드 실패 {{ .err }}"
AppRecover: "앱 {{ .name }} 롤백 완료"
PullImageStart: "이미지 {{ .name }} 가져오기 시작"
PullImageSuccess: "이미지 가져오기 성공"
UpgradeAppStart: "애플리케이션 {{ .name }} 업그레이드 시작"
UpgradeAppSuccess: "앱 {{ .name }} 업그레이드 성공"
# 파일
ErrFileCanNotRead: "파일을 읽을 수 없습니다"
ErrFileToLarge: "파일이 너무 큽니다"
ErrPathNotFound: "경로를 찾을 수 없습니다"
ErrMovePathFailed: "대상 경로가 원래 경로를 포함할 수 없습니다!"
ErrLinkPathNotFound: "대상 경로가 존재하지 않습니다!"
ErrFileIsExist: "파일 또는 디렉터리가 이미 존재합니다!"
ErrFileUpload: "파일 업로드 실패 {{.name}} {{.detail}}"
ErrFileDownloadDir: "다운로드 폴더는 지원되지 않습니다"
ErrCmdNotFound: "{{ .name }} 명령이 존재하지 않습니다. 호스트에 이 명령을 먼저 설치하세요"
ErrSourcePathNotFound: "소스 디렉터리가 존재하지 않습니다"
ErrFavoriteExist: "이 경로는 이미 즐겨찾기에 추가되었습니다"
ErrInvalidChar: "잘못된 문자는 금지됩니다"
ErrPathNotDelete: "선택한 디렉터리는 삭제할 수 없습니다"
# 웹사이트
ErrDomainIsExist: "도메인 이름이 이미 존재합니다"
ErrAliasIsExist: "별칭이 이미 존재합니다"
ErrAppDelete: "다른 웹사이트에서 이 애플리케이션을 사용 중입니다"
ErrGroupIsUsed: "그룹이 사용 중이므로 삭제할 수 없습니다"
ErrBackupMatch: "백업 파일이 현재 웹사이트 데이터와 일치하지 않습니다: {{ .detail }}"
ErrBackupExist: "백업 파일이 원본 데이터의 일부와 일치하지 않습니다: {{ .detail }}"
ErrPHPResource: "로컬 런타임에서 전환을 지원하지 않습니다!"
ErrPathPermission: "인덱스 디렉터리에 1000:1000 권한이 아닌 폴더가 감지되었습니다. 웹사이트 액세스 시 '접근 거부' 오류가 발생할 수 있습니다. 상단의 저장 버튼을 클릭하세요"
ErrDomainIsUsed: "도메인이 웹사이트 {{ .name }}에서 이미 사용 중입니다"
ErrDomainFormat: "{{ .name }} 도메인 형식 오류"
ErrDefaultAlias: "기본은 예약된 코드 이름입니다. 다른 이름을 사용하세요"
ErrImageNotExist: "실행 환경 {{.name}} 이미지가 존재하지 않습니다. 실행 환경을 다시 편집하세요"
# SSL 관련
ErrSSLCannotDelete: "인증서 {{ .name }}은(는) 웹사이트에서 사용 중이므로 삭제할 수 없습니다."
ErrAccountCannotDelete: "계정과 연결된 인증서는 삭제할 수 없습니다."
ErrSSLApply: "인증서가 성공적으로 서명되었지만 Openresty 다시 로드에 실패했습니다. 구성을 확인하세요!"
ErrEmailIsExist: "이메일이 이미 존재합니다."
ErrSSLKeyNotFound: "개인 키 파일이 존재하지 않습니다."
ErrSSLCertificateNotFound: "인증서 파일이 존재하지 않습니다."
ErrSSLKeyFormat: "개인 키 파일 검증 오류"
ErrSSLCertificateFormat: "인증서 파일 형식 오류입니다. pem 형식을 사용하세요."
ErrEabKidOrEabHmacKeyCannotBlank: "EabKid 또는 EabHmacKey 는 비워둘 수 없습니다."
ErrOpenrestyNotFound: "HTTP 모드는 먼저 Openresty 를 설치해야 합니다."
ApplySSLStart: "인증서를 신청하기 시작합니다. 도메인 이름 [{{ .domain }}], 신청 방법 [{{ .type }}]"
dnsAccount: "DNS 자동"
dnsManual: "DNS 수동"
http: "HTTP"
ApplySSLFailed: "도메인 [{{ .domain }}] 인증서 신청 실패, {{ .detail }}"
ApplySSLSuccess: "도메인 [{{ .domain }}] 인증서 신청 성공!"
DNSAccountName: "DNS 계정 [{{ .name }}] 제조사 [{{ .type }}]"
PushDirLog: "인증서를 디렉토리 [{{ .path }}]에 푸시했습니다. {{ .status }}"
ErrDeleteCAWithSSL: "현재 조직에 발급된 인증서가 있으므로 삭제할 수 없습니다."
ErrDeleteWithPanelSSL: "패널 SSL 구성이 이 인증서를 사용 중이므로 삭제할 수 없습니다."
ErrDefaultCA: "기본 인증 기관은 삭제할 수 없습니다."
ApplyWebSiteSSLLog: "{{ .name }} 웹사이트 인증서를 업데이트하기 시작합니다."
ErrUpdateWebsiteSSL: "{{ .name }} 웹사이트 인증서 업데이트 실패: {{ .err }}"
ApplyWebSiteSSLSuccess: "웹사이트 인증서 업데이트 성공"
ErrExecShell: "스크립트 실행 실패 {{ .err }}"
ExecShellStart: "스크립트 실행 시작"
ExecShellSuccess: "스크립트 실행 성공"
StartUpdateSystemSSL: "시스템 인증서 업데이트 시작"
UpdateSystemSSLSuccess: "시스템 인증서 업데이트 성공"
# MySQL
ErrUserIsExist: "현재 사용자가 이미 존재합니다. 새로운 사용자를 입력하세요."
ErrDatabaseIsExist: "현재 데이터베이스가 이미 존재합니다. 새로운 데이터베이스를 입력하세요."
ErrExecTimeOut: "SQL 실행이 시간 초과되었습니다. 데이터베이스를 확인하세요."
ErrRemoteExist: "원격 데이터베이스에 동일한 이름이 이미 존재합니다. 이름을 수정한 후 다시 시도하세요."
ErrLocalExist: "로컬 데이터베이스에 동일한 이름이 이미 존재합니다. 이름을 수정한 후 다시 시도하세요."
# Redis
ErrTypeOfRedis: "복구 파일 형식이 현재 지속성 모드와 일치하지 않습니다. 파일 형식을 수정한 후 다시 시도하세요."
# Container
ErrInUsed: "{{ .detail }}이(가) 사용 중이므로 삭제할 수 없습니다."
ErrObjectInUsed: "이 객체는 사용 중이므로 삭제할 수 없습니다."
ErrObjectBeDependent: "이 이미지는 다른 이미지에 의해 의존되고 있어 삭제할 수 없습니다."
ErrPortRules: "포트 수가 일치하지 않습니다. 다시 입력하세요!"
ErrPgImagePull: "이미지 가져오기 시간이 초과되었습니다. 이미지 가속 구성을 설정하거나 postgres:16.0-alpine 이미지를 수동으로 가져온 후 다시 시도하세요."
# Runtime
ErrDirNotFound: "빌드 폴더가 존재하지 않습니다! 파일의 무결성을 확인하세요!"
ErrFileNotExist: "{{ .detail }} 파일이 존재하지 않습니다! 소스 파일의 무결성을 확인하세요!"
ErrImageBuildErr: "이미지 빌드 실패"
ErrImageExist: "이미지가 이미 존재합니다!"
ErrDelWithWebsite: "운영 환경이 웹사이트와 연결되어 있어 삭제할 수 없습니다."
ErrRuntimeStart: "실행 시작 실패"
ErrPackageJsonNotFound: "package.json 파일이 존재하지 않습니다."
ErrScriptsNotFound: "package.json 에서 스크립트 구성 항목을 찾을 수 없습니다."
ErrContainerNameNotFound: "컨테이너 이름을 가져올 수 없습니다. .env 파일을 확인하세요."
ErrNodeModulesNotFound: "node_modules 폴더가 존재하지 않습니다! 실행 환경을 편집하거나 실행 환경이 성공적으로 시작되기를 기다리세요."
# Setting
ErrBackupInUsed: "백업 계정이 크론 작업에 사용 중이므로 삭제할 수 없습니다."
ErrBackupCheck: "백업 계정 연결 테스트 실패 {{ .err }}"
ErrOSSConn: "최신 버전을 가져올 수 없습니다. 서버가 외부 네트워크에 연결할 수 있는지 확인하세요."
ErrEntrance: "보안 입구 정보 오류. 확인 후 다시 시도하세요!"
# Tool
ErrConfigNotFound: "구성 파일이 존재하지 않습니다."
ErrConfigParse: "구성 파일 형식 오류"
ErrConfigIsNull: "구성 파일은 비워둘 수 없습니다."
ErrConfigDirNotFound: "실행 디렉토리가 존재하지 않습니다."
ErrConfigAlreadyExist: "동일한 이름의 구성 파일이 이미 존재합니다."
ErrUserFindErr: "사용자 {{ .name }} 찾기 실패 {{ .err }}"
# SSH
ErrFirewallNone: "시스템에서 firewalld 또는 ufw 서비스를 감지하지 못했습니다. 확인 후 다시 시도하세요!"
ErrFirewallBoth: "시스템에서 firewalld 와 ufw 서비스가 모두 감지되었습니다. 충돌을 방지하려면 하나를 제거한 후 다시 시도하세요!"
# Cronjob
ErrBashExecute: "스크립트 실행 오류. 작업 출력 텍스트 영역에서 구체적인 정보를 확인하세요."
ErrCutWebsiteLog: "{{ .name }} 웹사이트 로그 자르기 실패, 오류 {{ .err }}"
CutWebsiteLogSuccess: "{{ .name }} 웹사이트 로그 자르기 성공, 백업 경로 {{ .path }}"
# Toolbox
ErrNotExistUser: "현재 사용자가 존재하지 않습니다. 수정 후 다시 시도하세요!"
ErrBanAction: "설정 실패, 현재 {{ .name }} 서비스가 사용할 수 없습니다. 확인 후 다시 시도하세요!"
ErrClamdscanNotFound: "clamdscan 명령을 감지하지 못했습니다. 설치 문서를 참조하세요!"
# WAF
ErrScope: "이 구성의 수정은 지원되지 않습니다."
ErrStateChange: "상태 수정 실패"
ErrRuleExist: "규칙이 이미 존재합니다."
ErrRuleNotExist: "규칙이 존재하지 않습니다."
ErrParseIP: "IP 형식 오류"
ErrDefaultIP: "default 는 예약된 이름입니다. 다른 이름으로 변경하세요."
ErrGroupInUse: "IP 그룹이 블랙/화이트 리스트에서 사용 중이며 삭제할 수 없습니다."
ErrGroupExist: "IP 그룹 이름이 이미 존재합니다."
ErrIPRange: "잘못된 IP 범위"
ErrIPExist: "IP가 이미 존재합니다."
# License
ErrLicense: "라이선스 형식 오류, 확인 후 다시 시도하세요!"
ErrLicenseCheck: "라이선스 검증 실패, 확인 후 다시 시도하세요!"
ErrXpackVersion: "라이선스 검증 실패, 이 라이선스는 버전 제한이 있어 성공적으로 가져올 수 없습니다. 확인 후 다시 시도하세요!"
ErrLicenseSave: "라이선스 정보 저장 실패, 오류 {{ .err }}. 다시 시도하세요!"
ErrLicenseSync: "라이선스 정보 동기화 실패, 데이터베이스에서 라이선스 정보를 감지하지 못했습니다!"
ErrXpackNotFound: "이 섹션은 전문가 버전 기능입니다. Panel 설정 - 라이선스 인터페이스에서 먼저 라이선스를 가져오세요."
ErrXpackNotActive: "이 섹션은 전문가 버전 기능입니다. Panel 설정 - 라이선스 인터페이스에서 먼저 라이선스 상태를 동기화하세요."
ErrXpackOutOfDate: "현재 라이선스가 만료되었습니다. Panel 설정 - 라이선스 인터페이스에서 라이선스를 다시 가져오세요."
ErrXpackLost: "라이선스가 최대 재시도 횟수에 도달했습니다. [설정] - [라이선스] 페이지로 이동하여 동기화 버튼을 수동으로 클릭해 전문가 버전 기능을 정상적으로 작동시키세요."
ErrXpackTimeout: "요청 시간이 초과되었습니다. 네트워크 연결이 불안정할 수 있으니 나중에 다시 시도하세요!"
# Alert
ErrAlert: "알림 정보 형식 오류, 확인 후 다시 시도하세요!"
ErrAlertPush: "알림 전송 오류, 확인 후 다시 시도하세요!"
ErrAlertSave: "알림 저장 오류, 확인 후 다시 시도하세요!"
ErrAlertSync: "알림 동기화 오류, 확인 후 다시 시도하세요!"
ErrAlertRemote: "원격 알림 오류, 확인 후 다시 시도하세요!"
# CMD
AppVersion: "앱 버전"
AppCommands: "앱 관련 명령어"
AppInit: "앱 초기화"
AppKeyVal: "앱 키 (영어만 지원)"
AppCreateFileErr: "파일 {{ .name }} 생성 실패 {{ .err }}"
AppCreateDirErr: "폴더 {{ .name }} 생성 실패 {{ .err }}"
AppMissKey: "앱 키가 없습니다. -k 옵션으로 지정하세요."
AppMissVersion: "앱 버전이 없습니다. -v 옵션으로 지정하세요."
AppVersionExist: "버전이 이미 존재합니다!"
AppCreateSuccessful: "생성 성공!"
AppWriteErr: "파일 {{ .name }} 쓰기 실패 {{ .err }}"
SudoHelper: "{{ .cmd }} 명령을 사용하거나 root 사용자로 전환하세요."
ListenIPCommands: "IP 변경"
ListenIPv4: "IPv4 에서 수신 대기"
ListenIPv6: "IPv6 에서 수신 대기"
ListenChangeSuccessful: "변경 성공! 현재 {{ .value }}에서 수신 대기 중입니다."
ResetCommands: "시스템 정보 초기화"
ResetMFA: "1Panel 이중 인증 취소"
ResetHttps: "1Panel HTTPS 로그인 취소"
ResetEntrance: "1Panel 보안 입구 취소"
ResetIPs: "1Panel 허용 IP 제한 취소"
ResetDomain: "1Panel 도메인 바인딩 취소"
RestoreCommands: "1Panel 서비스 및 데이터 복구"
RestoreNoSuchFile: "복구 가능한 파일이 없습니다."
RestoreStep1: "(1/5) {{ .name }} 디렉토리에서 1Panel 서비스 및 데이터 복구 시작..."
RestoreStep2: "(2/5) 1Panel 바이너리 복구 성공"
RestoreStep3: "(3/5) 1Panel 스크립트 복구 성공"
RestoreStep4: "(4/5) 1Panel 서비스 복구 성공"
RestoreStep5: "(5/5) 1Panel 데이터 복구 성공"
RestoreSuccessful: "복구 성공! 서비스를 다시 시작합니다. 잠시만 기다려주세요..."
UpdateCommands: "패널 정보 업데이트"
UpdateUser: "패널 사용자 업데이트"
UpdatePassword: "패널 비밀번호 업데이트"
UpdatePort: "패널 포트 업데이트"
UpdateUserNull: "오류: 패널 사용자가 비어 있습니다!"
UpdateUserBlank: "오류: 패널 사용자에 공백이 포함되어 있습니다!"
UpdateUserFormat: "오류: 잘못된 패널 사용자 형식! 영어, 중국어, 숫자, _만 지원하며 길이는 3~30자입니다."
UpdateUserErr: "오류: 패널 사용자 업데이트 실패 {{ .err }}"
UpdateSuccessful: "업데이트 성공!"
UpdateUserResult: "패널 사용자: {{ .name }}"
UpdatePasswordRead: "오류: 패널 비밀번호 정보 읽기 실패 {{ .err }}"
UpdatePasswordNull: "오류: 패널 비밀번호가 비어 있습니다!"
UpdateUPasswordBlank: "오류: 패널 비밀번호에 공백이 포함되어 있습니다!"
UpdatePasswordFormat: "오류: 패널 비밀번호는 문자, 숫자, 특수 문자 !@#$%*_,.?만 지원하며 길이는 8~30자입니다!"
UpdatePasswordLen: "오류: 6자 이상의 비밀번호를 입력하세요!"
UpdatePasswordRe: "비밀번호 확인:"
UpdatePasswordErr: "오류: 패널 비밀번호 업데이트 실패 {{ .err }}"
UpdatePasswordSame: "오류: 두 비밀번호가 일치하지 않습니다. 확인 후 다시 시도하세요!"
UpdatePasswordResult: "패널 비밀번호: {{ .name }}"
UpdatePortFormat: "오류: 입력한 포트 번호는 1~65535 사이여야 합니다!"
UpdatePortUsed: "오류: 포트 번호가 이미 사용 중입니다. 확인 후 다시 시도하세요!"
UpdatePortErr: "오류: 패널 포트 업데이트 실패 {{ .err }}"
UpdatePortResult: "패널 포트: {{ .name }}"
UpdatePortFirewallAdd: "방화벽 포트 규칙 추가 실패 {{ .err }}, 방화벽 규칙에 {{ .name }} 포트를 수동으로 추가하세요."
UpdatePortFirewallDel: "오류: 방화벽 포트 삭제 실패 {{ .err }}"
UpdatePortFirewallReload: "방화벽 다시 로드 실패 {{ .err }}, 방화벽을 수동으로 다시 로드하세요."
UserInfo: "패널 정보 가져오기"
UserInfoAddr: "패널 주소: "
UserInfoPassHelp: "팁: 비밀번호를 변경하려면 다음 명령어를 실행할 수 있습니다: "
DBConnErr: "오류: 데이터베이스 연결 초기화 실패 {{ .err }}"
SystemVersion: "버전: "
SystemMode: "모드: "
#ai-tool
ErrOpenrestyInstall: '먼저 Openresty를 설치하세요'
ErrSSL: "인증서 내용이 비어 있습니다. 인증서를 확인하세요!"
#mobile app
ErrVerifyToken: '토큰 검증 오류가 발생했습니다. 재설정 후 다시 스캔해 주세요.'
ErrInvalidToken: '유효하지 않은 토큰입니다. 재설정 후 다시 스캔해 주세요.'
ErrExpiredToken: '토큰이 만료되었습니다. 재설정 후 다시 스캔해 주세요.'
+295
View File
@@ -0,0 +1,295 @@
ErrInvalidParams: "Ralat parameter permintaan: {{ .detail }}"
ErrTokenParse: "Ralat penjanaan token: {{ .detail }}"
ErrInitialPassword: "Ralat kata laluan awal"
ErrInternalServer: "Ralat dalaman perkhidmatan: {{ .detail }}"
ErrRecordExist: "Rekod sudah wujud"
ErrRecordNotFound: "Rekod tidak dijumpai"
ErrStructTransform: "Kegagalan penukaran jenis: {{ .detail }}"
ErrNotLogin: "Pengguna belum log masuk: {{ .detail }}"
ErrPasswordExpired: "Kata laluan semasa telah tamat tempoh: {{ .detail }}"
ErrNotSupportType: "Sistem tidak menyokong jenis semasa: {{ .detail }}"
ErrApiConfigStatusInvalid: "Akses antara muka API dilarang: {{ .detail }}"
ErrApiConfigKeyInvalid: "Ralat kunci antara muka API: {{ .detail }}"
ErrApiConfigIPInvalid: "IP antara muka API tidak berada dalam senarai putih: {{ .detail }}"
ErrApiConfigDisable: "Antara muka ini melarang penggunaan panggilan API: {{ .detail }}"
ErrApiConfigKeyTimeInvalid: "Ralat cap waktu antara muka API: {{ .detail }}"
#common
ErrNameIsExist: "Nama sudah wujud"
ErrDemoEnvironment: "Pelayan demo, operasi ini dilarang!"
ErrCmdTimeout: "Pelaksanaan arahan telah tamat masa!"
ErrCmdIllegal: "Arahan mengandungi aksara tidak sah. Sila ubah dan cuba lagi!"
ErrPortExist: 'Port {{ .port }} sudah digunakan oleh {{ .type }} [{{ .name }}]'
TYPE_APP: "Aplikasi"
TYPE_RUNTIME: "Persekitaran runtime"
TYPE_DOMAIN: "Nama domain"
ErrTypePort: 'Format port {{ .name }} adalah salah'
ErrTypePortRange: 'Julat port perlu berada di antara 1-65535'
Success: "Berjaya"
Failed: "Gagal"
SystemRestart: "Mulakan semula sistem menyebabkan gangguan tugas"
#app
ErrPortInUsed: "Port {{ .detail }} sudah digunakan"
ErrAppLimit: "Aplikasi melebihi had pemasangan"
ErrAppRequired: "Aplikasi {{ .detail }} diperlukan"
ErrNotInstall: "Aplikasi tidak dipasang"
ErrPortInOtherApp: "Port {{ .port }} sudah digunakan oleh aplikasi {{ .apps }}"
ErrDbUserNotValid: "Pangkalan data stok, nama pengguna dan kata laluan tidak sepadan!"
ErrDockerComposeNotValid: "Format fail docker-compose adalah salah!"
ErrUpdateBuWebsite: "Aplikasi berjaya dikemas kini, tetapi pengubahsuaian fail konfigurasi laman web gagal, sila semak konfigurasi!"
Err1PanelNetworkFailed: "Penciptaan rangkaian kontena lalai gagal! {{ .detail }}"
ErrFileParse: "Analisis fail docker-compose aplikasi gagal!"
ErrInstallDirNotFound: "Direktori pemasangan tidak wujud"
AppStoreIsUpToDate: "Terkini"
LocalAppVersionNull: "Aplikasi {{.name}} tidak diselaraskan ke versi! Tidak dapat menambah ke senarai aplikasi"
LocalAppVersionErr: "{{.name}} gagal diselaraskan ke versi {{.version}}! {{.err}}"
ErrFileNotFound: "Fail {{.name}} tidak wujud"
ErrFileParseApp: "Gagal menganalisis fail {{.name}} {{.err}}"
ErrAppDirNull: "Folder versi tidak wujud"
LocalAppErr: "Penyelarasan aplikasi {{.name}} gagal! {{.err}}"
ErrContainerName: "Nama Kontena sudah wujud"
ErrAppSystemRestart: "Pemulangan semula 1Panel menyebabkan tugas terhenti"
ErrCreateHttpClient: "Gagal mencipta permintaan HTTP {{.err}}"
ErrHttpReqTimeOut: "Permintaan tamat masa {{.err}}"
ErrHttpReqFailed: "Permintaan gagal {{.err}}"
ErrHttpReqNotFound: "Fail tidak wujud"
ErrNoSuchHost: "Sambungan rangkaian gagal"
ErrImagePullTimeOut: "Tarik imej tamat masa"
ErrContainerNotFound: "Kontena {{ .name }} tidak wujud"
ErrContainerMsg: "Kontena {{ .name }} bermasalah, sila semak log pada halaman kontena untuk maklumat lanjut"
ErrAppBackup: "Sandaran aplikasi {{ .name }} gagal err {{.err}}"
ErrImagePull: "Tarik imej {{ .name }} gagal err {{.err}}"
ErrVersionTooLow: "Versi 1Panel semasa terlalu rendah untuk mengemas kini gedung aplikasi, sila tingkatkan versi"
ErrAppNameExist: "Nama aplikasi sudah wujud"
AppStoreIsSyncing: "Gedung Aplikasi sedang menyelaraskan, sila cuba lagi nanti"
ErrGetCompose: "Gagal mendapatkan fail docker-compose.yml! {{ .detail }}"
ErrAppWarn: "Status tidak normal, sila semak log"
ErrAppParamKey: "Pengecualian medan parameter {{ .name }}"
ErrAppUpgrade: "Gagal menaik taraf aplikasi {{ .name }} {{ .err }}"
AppRecover: "Aplikasi {{ .name }} telah dikembalikan"
PullImageStart: "Memulakan penarikan imej {{ .name }}"
PullImageSuccess: "Imej berjaya ditarik"
UpgradeAppStart: "Memulakan peningkatan aplikasi {{ .name }}"
UpgradeAppSuccess: "Aplikasi {{ .name }} berjaya dinaik taraf"
#file
ErrFileCanNotRead: "Fail tidak boleh dibaca"
ErrFileToLarge: "Fail terlalu besar"
ErrPathNotFound: "Laluan tidak dijumpai"
ErrMovePathFailed: "Laluan sasaran tidak boleh mengandungi laluan asal!"
ErrLinkPathNotFound: "Laluan sasaran tidak wujud!"
ErrFileIsExist: "Fail atau direktori sudah wujud!"
ErrFileUpload: "Gagal memuat naik fail {{.name}} {{.detail}}"
ErrFileDownloadDir: "Muat turun folder tidak disokong"
ErrCmdNotFound: "Arahan {{ .name }} tidak wujud, sila pasang arahan ini pada hos terlebih dahulu"
ErrSourcePathNotFound: "Direktori sumber tidak wujud"
ErrFavoriteExist: "Laluan ini telah dikumpulkan"
ErrInvalidChar: "Aksara tidak sah adalah dilarang"
ErrPathNotDelete: "Direktori yang dipilih tidak boleh dipadam"
#website
ErrDomainIsExist: "Nama domain sudah wujud"
ErrAliasIsExist: "Alias sudah wujud"
ErrAppDelete: "Laman web lain menggunakan aplikasi ini"
ErrGroupIsUsed: "Kumpulan sedang digunakan dan tidak boleh dipadam"
ErrBackupMatch: "Fail sandaran tidak sepadan dengan data separa laman web semasa: {{ .detail }}"
ErrBackupExist: "Fail sandaran berkaitan dengan sebahagian data asal yang tidak wujud: {{ .detail }}"
ErrPHPResource: "Runtime tempatan tidak menyokong penukaran!"
ErrPathPermission: "Folder dengan kebenaran bukan 1000:1000 dikesan dalam direktori indeks, yang mungkin menyebabkan ralat 'Access denied' semasa mengakses laman web. Sila klik butang simpan di atas"
ErrDomainIsUsed: "Domain sudah digunakan oleh laman web {{ .name }}"
ErrDomainFormat: "Format domain {{ .name }} adalah salah"
ErrDefaultAlias: "default ialah nama kod terpelihara, sila gunakan nama kod lain"
ErrImageNotExist: "Imej persekitaran runtime {{.name}} tidak wujud, sila sunting semula persekitaran runtime"
#ssl
ErrSSLCannotDelete: "Sijil {{ .name }} sedang digunakan oleh laman web dan tidak boleh dihapuskan"
ErrAccountCannotDelete: "Sijil yang dikaitkan dengan akaun tidak boleh dihapuskan"
ErrSSLApply: "Sijil berjaya terus ditandatangani, tetapi reload OpenResty gagal, sila semak konfigurasi!"
ErrEmailIsExist: "Emel sudah wujud"
ErrSSLKeyNotFound: "Fail kunci peribadi tidak wujud"
ErrSSLCertificateNotFound: "Fail sijil tidak wujud"
ErrSSLKeyFormat: "Ralat pengesahan fail kunci peribadi"
ErrSSLCertificateFormat: "Format fail sijil salah, sila gunakan format PEM"
ErrEabKidOrEabHmacKeyCannotBlank: "EabKid atau EabHmacKey tidak boleh kosong"
ErrOpenrestyNotFound: "Mod HTTP memerlukan OpenResty dipasang terlebih dahulu"
ApplySSLStart: "Memulakan permohonan sijil, nama domain [{{ .domain }}], kaedah permohonan [{{ .type }}]"
dnsAccount: "DNS Automatik"
dnsManual: "DNS Manual"
http: "HTTP"
ApplySSLFailed: "Permohonan sijil untuk [{{ .domain }}] gagal, {{.detail}}"
ApplySSLSuccess: "Permohonan sijil untuk [{{ .domain }}] berjaya!"
DNSAccountName: "Akaun DNS [{{ .name }}], pengeluar [{{ .type }}]"
PushDirLog: "Sijil dihantar ke direktori [{{ .path }}] {{ .status }}"
ErrDeleteCAWithSSL: "Terdapat sijil yang telah dikeluarkan di bawah organisasi semasa dan tidak boleh dihapuskan"
ErrDeleteWithPanelSSL: "Konfigurasi SSL panel menggunakan sijil ini dan tidak boleh dihapuskan"
ErrDefaultCA: "Pihak Berkuasa Sijil lalai tidak boleh dihapuskan"
ApplyWebSiteSSLLog: "Memulakan kemas kini sijil laman web {{ .name }}"
ErrUpdateWebsiteSSL: "Sijil laman web {{ .name }} gagal dikemas kini: {{ .err }}"
ApplyWebSiteSSLSuccess: "Sijil laman web berjaya dikemas kini"
ErrExecShell: "Pelaksanaan skrip gagal {{ .err }}"
ExecShellStart: "Memulakan pelaksanaan skrip"
ExecShellSuccess: "Skrip berjaya dilaksanakan"
StartUpdateSystemSSL: "Memulakan kemas kini sijil sistem"
UpdateSystemSSLSuccess: "Sijil sistem berjaya dikemas kini"
#mysql
ErrUserIsExist: "Pengguna semasa sudah wujud. Sila masukkan pengguna baharu"
ErrDatabaseIsExist: "Pangkalan data semasa sudah wujud. Sila masukkan pangkalan data baharu"
ErrExecTimeOut: "Pelaksanaan SQL tamat masa, sila semak pangkalan data"
ErrRemoteExist: "Pangkalan data jauh dengan nama tersebut sudah wujud, sila ubah dan cuba lagi"
ErrLocalExist: "Pangkalan data tempatan dengan nama tersebut sudah wujud, sila ubah dan cuba lagi"
#redis
ErrTypeOfRedis: "Jenis fail pemulihan tidak sepadan dengan mod ketekalan semasa. Sila ubah jenis fail dan cuba lagi."
#container
ErrInUsed: "{{ .detail }} sedang digunakan dan tidak boleh dihapuskan"
ErrObjectInUsed: "Objek ini sedang digunakan dan tidak boleh dihapuskan"
ErrObjectBeDependent: "Imej ini bergantung kepada imej lain dan tidak boleh dihapuskan"
ErrPortRules: "Bilangan port tidak sepadan, sila masukkan semula!"
ErrPgImagePull: "Tarik imej tamat masa. Sila konfigurasikan pecutan imej atau tarik imej postgres:16.0-alpine secara manual dan cuba lagi"
#runtime
ErrDirNotFound: "Folder binaan tidak wujud! Sila semak integriti fail!"
ErrFileNotExist: "Fail {{ .detail }} tidak wujud! Sila semak integriti fail sumber!"
ErrImageBuildErr: "Binaan imej gagal"
ErrImageExist: "Imej sudah wujud!"
ErrDelWithWebsite: "Persekitaran operasi telah dikaitkan dengan laman web dan tidak boleh dihapuskan"
ErrRuntimeStart: "Gagal memulakan"
ErrPackageJsonNotFound: "Fail package.json tidak wujud"
ErrScriptsNotFound: "Tiada item konfigurasi skrip dijumpai dalam package.json"
ErrContainerNameNotFound: "Tidak dapat mendapatkan nama kontena, sila semak fail .env"
ErrNodeModulesNotFound: "Folder node_modules tidak wujud! Sila sunting persekitaran operasi atau tunggu sehingga persekitaran operasi berjaya dimulakan"
#setting
ErrBackupInUsed: "Akaun sandaran sedang digunakan dalam cronjob dan tidak boleh dihapuskan."
ErrBackupCheck: "Ujian sambungan akaun sandaran gagal {{ .err }}"
ErrOSSConn: "Tidak dapat mendapatkan versi terkini, sila semak sama ada pelayan boleh menyambung ke rangkaian luaran."
ErrEntrance: "Ralat maklumat pintu masuk keselamatan. Sila semak dan cuba lagi!"
#tool
ErrConfigNotFound: "Fail konfigurasi tidak wujud"
ErrConfigParse: "Format fail konfigurasi salah"
ErrConfigIsNull: "Fail konfigurasi tidak boleh kosong"
ErrConfigDirNotFound: "Direktori operasi tidak wujud"
ErrConfigAlreadyExist: "Fail konfigurasi dengan nama yang sama sudah wujud"
ErrUserFindErr: "Gagal mencari pengguna {{ .name }} {{ .err }}"
#ssh
ErrFirewallNone: "Tiada perkhidmatan firewalld atau ufw dikesan pada sistem. Sila semak dan cuba lagi!"
ErrFirewallBoth: "Kedua-dua perkhidmatan firewalld dan ufw dikesan pada sistem. Untuk mengelakkan konflik, sila nyahpasang salah satu dan cuba lagi!"
#cronjob
ErrBashExecute: "Ralat pelaksanaan skrip, sila semak maklumat khusus dalam kawasan teks output tugas."
ErrCutWebsiteLog: "Pemotongan log laman web {{ .name }} gagal, ralat {{ .err }}"
CutWebsiteLogSuccess: "Log laman web {{ .name }} berjaya dipotong, laluan sandaran {{ .path }}"
#toolbox
ErrNotExistUser: "Pengguna semasa tidak wujud. Sila ubah dan cuba lagi!"
ErrBanAction: "Tetapan gagal, perkhidmatan {{ .name }} semasa tidak tersedia, sila semak dan cuba lagi!"
ErrClamdscanNotFound: "Perintah clamdscan tidak dikesan, sila rujuk dokumentasi untuk memasangnya!"
#waf
ErrScope: "Pengubahsuaian konfigurasi ini tidak disokong"
ErrStateChange: "Pengubahsuaian status gagal"
ErrRuleExist: "Peraturan sudah wujud"
ErrRuleNotExist: "Peraturan tidak wujud"
ErrParseIP: "Format IP salah"
ErrDefaultIP: "default adalah nama terpelihara, sila tukar kepada nama lain"
ErrGroupInUse: "Kumpulan IP sedang digunakan oleh senarai hitam/putih dan tidak boleh dihapuskan"
ErrGroupExist: "Nama kumpulan IP sudah wujud"
ErrIPRange: "Julat IP salah"
ErrIPExist: "IP sudah wujud"
#license
ErrLicense: "Format lesen salah, sila semak dan cuba lagi!"
ErrLicenseCheck: "Pengesahan lesen gagal, sila semak dan cuba lagi!"
ErrLicenseSave: "Gagal menyimpan maklumat lesen, ralat {{ .err }}, sila cuba lagi!"
ErrLicenseSync: "Gagal menyelaraskan maklumat lesen, tiada maklumat lesen dikesan dalam pangkalan data!"
ErrXpackNotFound: "Bahagian ini adalah ciri edisi profesional, sila import lesen terlebih dahulu dalam Tetapan Panel - Antara Muka Lesen"
ErrXpackNotActive: "Bahagian ini adalah ciri edisi profesional, sila selaraskan status lesen terlebih dahulu dalam Tetapan Panel - Antara Muka Lesen"
ErrXpackOutOfDate: "Lesen semasa telah tamat tempoh, sila import semula lesen dalam Tetapan Panel - Antara Muka Lesen"
ErrXpackLost: "Lesen telah mencapai bilangan maksimum percubaan semula. Sila pergi ke halaman [Tetapan] [Lesen] dan klik butang selaraskan secara manual untuk memastikan ciri versi profesional berfungsi dengan baik."
ErrXpackTimeout: "Permintaan tamat masa, sambungan rangkaian mungkin tidak stabil, sila cuba lagi nanti!"
#license
ErrAlert: "Format maklumat amaran salah, sila semak dan cuba lagi!"
ErrAlertPush: "Ralat penghantaran amaran, sila semak dan cuba lagi!"
ErrAlertSave: "Ralat penyimpanan amaran, sila semak dan cuba lagi!"
ErrAlertSync: "Ralat penyelarasan amaran, sila semak dan cuba lagi!"
ErrAlertRemote: "Ralat amaran jauh, sila semak dan cuba lagi!"
#cmd
AppVersion: "Versi aplikasi"
AppCommands: "Arahan berkaitan aplikasi"
AppInit: "Inisialisasi aplikasi"
AppKeyVal: "Kunci aplikasi (hanya menyokong bahasa Inggeris)"
AppCreateFileErr: "Gagal mencipta fail {{ .name }} {{ .err }}"
AppCreateDirErr: "Gagal mencipta folder {{ .name }} {{ .err }}"
AppMissKey: "Kunci aplikasi hilang, gunakan -k untuk menetapkan"
AppMissVersion: "Versi aplikasi hilang, gunakan -v untuk menetapkan"
AppVersionExist: "Versi sudah wujud!"
AppCreateSuccessful: "Ciptaan berjaya!"
AppWriteErr: "Penulisan fail {{ .name }} gagal {{ .err }}"
SudoHelper: "Sila gunakan {{ .cmd }} atau tukar ke pengguna root"
ListenIPCommands: "Tukar IP mendengar"
ListenIPv4: "Mendengar pada IPv4"
ListenIPv6: "Mendengar pada IPv6"
ListenChangeSuccessful: "Tukar berjaya! Kini mendengar pada {{ .value }}"
ResetCommands: "Tetapkan semula maklumat sistem"
ResetMFA: "Batal pengesahan dua faktor 1Panel"
ResetHttps: "Batal log masuk HTTPS 1Panel"
ResetEntrance: "Batal pintu masuk keselamatan 1Panel"
ResetIPs: "Batal sekatan IP yang dibenarkan 1Panel"
ResetDomain: "Batal pengikatan domain 1Panel"
RestoreCommands: "Pulihkan perkhidmatan dan data 1Panel"
RestoreNoSuchFile: "Tiada fail tersedia untuk pemulihan"
RestoreStep1: "(1/5) Memulakan pemulihan perkhidmatan dan data 1Panel daripada direktori {{ .name }}..."
RestoreStep2: "(2/5) Pemulihan binari 1Panel berjaya"
RestoreStep3: "(3/5) Pemulihan skrip 1Panel berjaya"
RestoreStep4: "(4/5) Pemulihan perkhidmatan 1Panel berjaya"
RestoreStep5: "(5/5) Pemulihan data 1Panel berjaya"
RestoreSuccessful: "Pemulihan berjaya! Memulakan semula perkhidmatan, sila tunggu..."
UpdateCommands: "Kemas kini maklumat panel"
UpdateUser: "Kemas kini pengguna panel"
UpdatePassword: "Kemas kini kata laluan panel"
UpdatePort: "Kemas kini port panel"
UpdateUserNull: "Ralat: Pengguna panel kosong!"
UpdateUserBlank: "Ralat: Pengguna panel mengandungi ruang kosong!"
UpdateUserFormat: "Ralat: Format pengguna panel tidak sah! Hanya menyokong huruf Inggeris, Cina, nombor, dan , dengan panjang 3-30 aksara"
UpdateUserErr: "Ralat: Gagal mengemas kini pengguna panel, {{ .err }}"
UpdateSuccessful: "Kemas kini berjaya!"
UpdateUserResult: "Pengguna panel: {{ .name }}"
UpdatePasswordRead: "Ralat: Gagal membaca maklumat kata laluan panel, {{ .err }}"
UpdatePasswordNull: "Ralat: Kata laluan panel kosong!"
UpdateUPasswordBlank: "Ralat: Kata laluan panel mengandungi ruang kosong!"
UpdatePasswordFormat: "Ralat: Kata laluan panel hanya menyokong huruf, nombor, dan aksara khas !@#$%*,.?, dengan panjang 8-30 aksara!"
UpdatePasswordLen: "Ralat: Sila masukkan kata laluan lebih panjang daripada 6 aksara!"
UpdatePasswordRe: "Sahkan kata laluan:"
UpdatePasswordErr: "Ralat: Gagal mengemas kini kata laluan panel, {{ .err }}"
UpdatePasswordSame: "Ralat: Kedua-dua kata laluan tidak sepadan, sila semak dan cuba lagi!"
UpdatePasswordResult: "Kata laluan panel: {{ .name }}"
UpdatePortFormat: "Ralat: Nombor port yang dimasukkan mesti antara 1 hingga 65535!"
UpdatePortUsed: "Ralat: Nombor port sudah digunakan, sila semak dan cuba lagi!"
UpdatePortErr: "Ralat: Gagal mengemas kini port panel, {{ .err }}"
UpdatePortResult: "Port Panel: {{ .name }}"
UpdatePortFirewallAdd: "Gagal menambah peraturan port firewall, {{ .err }}, sila tambah port {{ .name }} secara manual ke dalam peraturan firewall."
UpdatePortFirewallDel: "Ralat: Gagal memadam port firewall, {{ .err }}"
UpdatePortFirewallReload: "Gagal memuat semula firewall, {{ .err }}, sila muat semula firewall secara manual."
UserInfo: "Dapatkan maklumat panel"
UserInfoAddr: "Alamat panel: "
UserInfoPassHelp: "Petua: Untuk menukar kata laluan, anda boleh menjalankan arahan: "
DBConnErr: "Ralat: Gagal memulakan sambungan pangkalan data, {{ .err }}"
SystemVersion: "Versi: "
SystemMode: "Mod: "
#ai-tool
ErrOpenrestyInstall: 'Sila pasang Openresty terlebih dahulu'
ErrSSL: "Kandungan sijil kosong, sila periksa sijil!"
#mobile app
ErrVerifyToken: 'Ralat pengesahan token, sila tetapkan semula dan imbas semula.'
ErrInvalidToken: 'Token tidak sah, sila tetapkan semula dan imbas semula.'
ErrExpiredToken: 'Token telah tamat tempoh, sila tetapkan semula dan imbas semula.'
+292
View File
@@ -0,0 +1,292 @@
ErrInvalidParams: "Erro nos parâmetros da solicitação: {{ .detail }}"
ErrTokenParse: "Erro na geração do token: {{ .detail }}"
ErrInitialPassword: "Erro na senha inicial"
ErrInternalServer: "Erro interno do serviço: {{ .detail }}"
ErrRecordExist: "Registro já existente"
ErrRecordNotFound: "Registros não encontrados"
ErrStructTransform: "Falha na conversão de tipo: {{ .detail }}"
ErrNotLogin: "Usuário não está logado: {{ .detail }}"
ErrPasswordExpired: "A senha atual expirou: {{ .detail }}"
ErrNotSupportType: "O sistema não suporta o tipo atual: {{ .detail }}"
ErrApiConfigStatusInvalid: "Acesso à interface da API proibido: {{ .detail }}"
ErrApiConfigKeyInvalid: "Erro na chave da interface da API: {{ .detail }}"
ErrApiConfigIPInvalid: "O IP da interface da API não está na lista de permissões: {{ .detail }}"
ErrApiConfigDisable: "Esta interface proíbe o uso de chamadas de API: {{ .detail }}"
#common
ErrNameIsExist: "O nome já existe"
ErrDemoEnvironment: "Servidor de demonstração, operação proibida!"
ErrCmdTimeout: "Tempo limite de execução do comando excedido!"
ErrCmdIllegal: "O comando contém caracteres ilegais. Por favor, modifique e tente novamente!"
ErrPortExist: 'A porta {{ .port }} já está ocupada por {{ .type }} [{{ .name }}]'
TYPE_APP: "Aplicação"
TYPE_RUNTIME: "Ambiente de execução"
TYPE_DOMAIN: "Nome de domínio"
ErrTypePort: 'Erro no formato da porta {{ .name }}'
ErrTypePortRange: 'O intervalo da porta deve estar entre 1-65535'
Success: "Sucesso"
Failed: "Falhou"
SystemRestart: "A reinicialização do sistema causa interrupção da tarefa"
#app
ErrPortInUsed: "A porta {{ .detail }} já está em uso"
ErrAppLimit: "O limite de instalação de aplicativos foi excedido"
ErrAppRequired: "O aplicativo {{ .detail }} é necessário"
ErrNotInstall: "Aplicativo não instalado"
ErrPortInOtherApp: "A porta {{ .port }} já está em uso pelo aplicativo {{ .apps }}"
ErrDbUserNotValid: "Banco de dados padrão, nome de usuário e senha não correspondem!"
ErrDockerComposeNotValid: "Erro no formato do arquivo docker-compose!"
ErrUpdateBuWebsite: "O aplicativo foi atualizado com sucesso, mas a modificação do arquivo de configuração do site falhou. Verifique a configuração!"
Err1PanelNetworkFailed: "Falha ao criar a rede padrão do container! {{ .detail }}"
ErrFileParse: "Falha ao analisar o arquivo docker-compose do aplicativo!"
ErrInstallDirNotFound: "O diretório de instalação não existe"
AppStoreIsUpToDate: "Atualizado"
LocalAppVersionNull: "O aplicativo {{.name}} não está sincronizado com a versão! Não foi possível adicionar à lista de aplicativos"
LocalAppVersionErr: "Falha ao sincronizar a versão {{.version}} do {{.name}}! {{.err}}"
ErrFileNotFound: "O arquivo {{.name}} não existe"
ErrFileParseApp: "Falha ao analisar o arquivo {{.name}} {{.err}}"
ErrAppDirNull: "O diretório da versão não existe"
LocalAppErr: "Falha ao sincronizar o aplicativo {{.name}}! {{.err}}"
ErrContainerName: "O nome do container já existe"
ErrAppSystemRestart: "A reinicialização do 1Panel causa a interrupção da tarefa"
ErrCreateHttpClient: "Falha ao criar a solicitação HTTP {{.err}}"
ErrHttpReqTimeOut: "Tempo limite da solicitação excedido {{.err}}"
ErrHttpReqFailed: "Falha na solicitação {{.err}}"
ErrHttpReqNotFound: "O arquivo não existe"
ErrNoSuchHost: "Falha na conexão de rede"
ErrImagePullTimeOut: "Tempo limite ao puxar a imagem"
ErrContainerNotFound: "O container {{ .name }} não existe"
ErrContainerMsg: "O container {{ .name }} está anormal, verifique o log na página do container para mais detalhes"
ErrAppBackup: "Falha no backup do aplicativo {{ .name }} erro {{.err}}"
ErrImagePull: "Falha ao puxar a imagem {{ .name }} erro {{.err}}"
ErrVersionTooLow: "A versão atual do 1Panel é muito baixa para atualizar a loja de aplicativos, por favor atualize a versão"
ErrAppNameExist: "O nome do aplicativo já existe"
AppStoreIsSyncing: "A loja de aplicativos está sincronizando, tente novamente mais tarde"
ErrGetCompose: "Falha ao obter o arquivo docker-compose.yml! {{ .detail }}"
ErrAppWarn: "Status anormal, verifique o log"
ErrAppParamKey: "Exceção no campo do parâmetro {{ .name }}"
ErrAppUpgrade: "Falha ao atualizar o aplicativo {{ .name }} {{ .err }}"
AppRecover: "Aplicativo {{ .name }} revertido"
PullImageStart: "Iniciando o download da imagem {{ .name }}"
PullImageSuccess: "Imagem baixada com sucesso"
UpgradeAppStart: "Iniciando a atualização do aplicativo {{ .name }}"
UpgradeAppSuccess: "Aplicativo {{ .name }} atualizado com sucesso"
#file
ErrFileCanNotRead: "Não foi possível ler o arquivo"
ErrFileToLarge: "O arquivo é muito grande"
ErrPathNotFound: "Caminho não encontrado"
ErrMovePathFailed: "O caminho de destino não pode conter o caminho original!"
ErrLinkPathNotFound: "O caminho de destino não existe!"
ErrFileIsExist: "O arquivo ou diretório já existe!"
ErrFileUpload: "Falha ao fazer upload do arquivo {{.name}} {{.detail}}"
ErrFileDownloadDir: "Pasta de download não é suportada"
ErrCmdNotFound: "O comando {{ .name }} não existe, por favor, instale este comando no host primeiro"
ErrSourcePathNotFound: "O diretório de origem não existe"
ErrFavoriteExist: "Este caminho já foi adicionado aos favoritos"
ErrInvalidChar: "Caracteres ilegais são proibidos"
ErrPathNotDelete: "O diretório selecionado não pode ser excluído"
#website
ErrDomainIsExist: "O domínio já existe"
ErrAliasIsExist: "O alias já existe"
ErrAppDelete: "Outro site usa este aplicativo"
ErrGroupIsUsed: "O grupo está em uso e não pode ser excluído"
ErrBackupMatch: "O arquivo de backup não corresponde aos dados parciais atuais do site: {{ .detail }}"
ErrBackupExist: "O arquivo de backup corresponde a uma parte dos dados originais que não existe: {{ .detail }}"
ErrPHPResource: "O ambiente local não suporta a troca!"
ErrPathPermission: "Foi detectada uma pasta com permissões diferentes de 1000:1000 no diretório de índice, o que pode causar um erro de acesso negado ao acessar o site. Clique no botão salvar acima"
ErrDomainIsUsed: "O domínio já está sendo usado pelo site {{ .name }}"
ErrDomainFormat: "O formato do domínio {{ .name }} está incorreto"
ErrDefaultAlias: "default é um nome reservado, por favor, use outro nome"
ErrImageNotExist: "A imagem do ambiente de execução {{.name}} não existe, por favor, reconfigure o ambiente"
#ssl
ErrSSLCannotDelete: "O certificado {{ .name }} está sendo usado pelo site e não pode ser removido"
ErrAccountCannotDelete: "O certificado associado à conta não pode ser excluído"
ErrSSLApply: "O certificado foi assinado com sucesso, mas o recarregamento do OpenResty falhou, por favor, verifique a configuração!"
ErrEmailIsExist: "O email já existe"
ErrSSLKeyNotFound: "O arquivo da chave privada não existe"
ErrSSLCertificateNotFound: "O arquivo do certificado não existe"
ErrSSLKeyFormat: "Erro na verificação do arquivo da chave privada"
ErrSSLCertificateFormat: "Erro no formato do arquivo do certificado, por favor, use o formato PEM"
ErrEabKidOrEabHmacKeyCannotBlank: "EabKid ou EabHmacKey não podem estar vazios"
ErrOpenrestyNotFound: "O modo HTTP requer a instalação prévia do OpenResty"
ApplySSLStart: "Iniciando aplicação do certificado, domínio [{{ .domain }}], método de aplicação [{{ .type }}]"
dnsAccount: "DNS Automático"
dnsManual: "DNS Manual"
http: "HTTP"
ApplySSLFailed: "A aplicação do certificado para [{{ .domain }}] falhou, {{.detail}}"
ApplySSLSuccess: "Certificado para [{{ .domain }}] aplicado com sucesso!"
DNSAccountName: "Conta DNS [{{ .name }}], provedor [{{.type}}]"
PushDirLog: "Certificado enviado para o diretório [{{ .path }}] {{ .status }}"
ErrDeleteCAWithSSL: "Há um certificado emitido sob a organização atual, não pode ser excluído"
ErrDeleteWithPanelSSL: "A configuração SSL do painel usa este certificado, não pode ser excluído"
ErrDefaultCA: "A autoridade certificadora padrão não pode ser excluída"
ApplyWebSiteSSLLog: "Iniciando atualização do certificado do site {{ .name }}"
ErrUpdateWebsiteSSL: "Falha ao atualizar o certificado do site {{ .name }}: {{ .err }}"
ApplyWebSiteSSLSuccess: "Certificado do site atualizado com sucesso"
ErrExecShell: "Falha na execução do script {{ .err }}"
ExecShellStart: "Iniciando execução do script"
ExecShellSuccess: "Script executado com sucesso"
StartUpdateSystemSSL: "Iniciando atualização do certificado do sistema"
UpdateSystemSSLSuccess: "Certificado do sistema atualizado com sucesso"
#mysql
ErrUserIsExist: "O usuário atual já existe. Por favor, insira um novo usuário"
ErrDatabaseIsExist: "O banco de dados atual já existe. Por favor, insira um novo banco de dados"
ErrExecTimeOut: "Tempo de execução SQL expirado, por favor, verifique o banco de dados"
ErrRemoteExist: "O banco de dados remoto já existe com este nome, por favor, modifique e tente novamente"
ErrLocalExist: "O banco de dados local já existe com este nome, por favor, modifique e tente novamente"
#redis
ErrTypeOfRedis: "O tipo do arquivo de recuperação não corresponde ao modo de persistência atual. Modifique o tipo do arquivo e tente novamente"
#container
ErrInUsed: "{{ .detail }} está em uso e não pode ser excluído"
ErrObjectInUsed: "Este objeto está em uso e não pode ser excluído"
ErrPortRules: "O número de portas não corresponde. Por favor, insira novamente!"
ErrPgImagePull: "Tempo limite ao tentar puxar a imagem. Configure a aceleração de imagem ou puxe manualmente a imagem postgres:16.0-alpine e tente novamente"
#runtime
ErrDirNotFound: "A pasta de build não existe! Por favor, verifique a integridade dos arquivos!"
ErrFileNotExist: "O arquivo {{ .detail }} não existe! Por favor, verifique a integridade do arquivo de origem!"
ErrImageBuildErr: "Falha ao construir a imagem"
ErrImageExist: "A imagem já existe!"
ErrDelWithWebsite: "O ambiente operacional está associado a um site e não pode ser excluído"
ErrRuntimeStart: "Falha ao iniciar"
ErrPackageJsonNotFound: "O arquivo package.json não existe"
ErrScriptsNotFound: "Nenhum item de configuração de scripts foi encontrado no package.json"
ErrContainerNameNotFound: "Não foi possível obter o nome do contêiner. Por favor, verifique o arquivo .env"
ErrNodeModulesNotFound: "A pasta node_modules não existe! Edite o ambiente de execução ou aguarde até que o ambiente seja iniciado com sucesso"
#setting
ErrBackupInUsed: "A conta de backup já está sendo usada em um cronjob e não pode ser excluída"
ErrBackupCheck: "Falha ao testar a conexão com a conta de backup {{ .err }}"
ErrOSSConn: "Não foi possível recuperar a versão mais recente. Por favor, verifique se o servidor pode se conectar à rede externa."
ErrEntrance: "Erro nas informações da entrada de segurança. Por favor, verifique e tente novamente!"
#tool
ErrConfigNotFound: "O arquivo de configuração não existe"
ErrConfigParse: "Erro no formato do arquivo de configuração"
ErrConfigIsNull: "O arquivo de configuração não pode estar vazio"
ErrConfigDirNotFound: "O diretório de execução não existe"
ErrConfigAlreadyExist: "Um arquivo de configuração com o mesmo nome já existe"
ErrUserFindErr: "Falha ao encontrar o usuário {{ .name }} {{ .err }}"
#ssh
ErrFirewallNone: "Nenhum serviço firewalld ou ufw foi detectado no sistema. Por favor, verifique e tente novamente!"
ErrFirewallBoth: "Os serviços firewalld e ufw foram detectados no sistema. Para evitar conflitos, desinstale um deles e tente novamente!"
#cronjob
ErrBashExecute: "Erro na execução do script. Por favor, verifique as informações específicas na área de saída da tarefa."
ErrCutWebsiteLog: "Falha ao cortar os logs do site {{ .name }}, erro {{ .err }}"
CutWebsiteLogSuccess: "Logs do site {{ .name }} cortados com sucesso, caminho do backup {{ .path }}"
#toolbox
ErrNotExistUser: "O usuário atual não existe. Por favor, modifique e tente novamente!"
ErrBanAction: "Falha na configuração. O serviço {{ .name }} atual está indisponível, por favor, verifique e tente novamente!"
ErrClamdscanNotFound: "O comando clamdscan não foi detectado. Por favor, consulte a documentação para instalá-lo!"
#waf
ErrScope: "A modificação dessa configuração não é suportada"
ErrStateChange: "Falha ao modificar o estado"
ErrRuleExist: "A regra já existe"
ErrRuleNotExist: "A regra não existe"
ErrParseIP: "Erro no formato do IP"
ErrDefaultIP: "default é um nome reservado, por favor, escolha outro nome"
ErrGroupInUse: "O grupo de IPs está sendo usado na lista de bloqueio/permitidos e não pode ser excluído"
ErrGroupExist: "O nome do grupo de IPs já existe"
ErrIPRange: "Intervalo de IP inválido"
ErrIPExist: "O IP já existe"
#license
ErrLicense: "Erro no formato da licença, por favor, verifique e tente novamente!"
ErrLicenseCheck: "Falha na verificação da licença, por favor, verifique e tente novamente!"
ErrLicenseSave: "Falha ao salvar as informações da licença, erro {{ .err }}, por favor, tente novamente!"
ErrLicenseSync: "Falha ao sincronizar as informações da licença, nenhuma informação de licença detectada no banco de dados!"
ErrXpackNotFound: "Esta seção é um recurso da edição profissional. Por favor, importe a licença primeiro na interface Configurações do Painel - Licença."
ErrXpackNotActive: "Esta seção é um recurso da edição profissional. Por favor, sincronize o status da licença primeiro na interface Configurações do Painel - Licença."
ErrXpackOutOfDate: "A licença atual expirou, por favor, reimporte a licença na interface Configurações do Painel - Licença."
ErrXpackLost: "A licença atingiu o número máximo de tentativas de reexecução. Por favor, acesse as páginas [Configurações] [Licença] e clique manualmente no botão de sincronização para garantir que os recursos da versão profissional funcionem corretamente."
ErrXpackTimeout: "Tempo limite de solicitação, a conexão de rede pode estar instável, por favor, tente novamente mais tarde!"
#license
ErrAlert: "Erro no formato das informações do alerta, por favor, verifique e tente novamente!"
ErrAlertPush: "Erro no envio do alerta, por favor, verifique e tente novamente!"
ErrAlertSave: "Erro ao salvar o alerta, por favor, verifique e tente novamente!"
ErrAlertSync: "Erro na sincronização do alerta, por favor, verifique e tente novamente!"
ErrAlertRemote: "Erro de alerta remoto, por favor, verifique e tente novamente!"
#cmd
AppVersion: "Versão do aplicativo"
AppCommands: "Comandos relacionados ao aplicativo"
AppInit: "Inicializar aplicativo"
AppKeyVal: "Chave do aplicativo (somente suporta inglês)"
AppCreateFileErr: "Falha ao criar o arquivo {{ .name }} {{ .err }}"
AppCreateDirErr: "Falha ao criar a pasta {{ .name }} {{ .err }}"
AppMissKey: "Chave do aplicativo ausente, use -k para especificar"
AppMissVersion: "Versão do aplicativo ausente, use -v para especificar"
AppVersionExist: "A versão já existe!"
AppCreateSuccessful: "Criação bem-sucedida!"
AppWriteErr: "Falha ao escrever no arquivo {{ .name }} {{ .err }}"
SudoHelper: "Por favor, use {{ .cmd }} ou altere para o usuário root"
ListenIPCommands: "Trocar IP de escuta"
ListenIPv4: "Escutando em IPv4"
ListenIPv6: "Escutando em IPv6"
ListenChangeSuccessful: "Troca bem-sucedida! Agora escutando em {{ .value }}"
ResetCommands: "Redefinir informações do sistema"
ResetMFA: "Cancelar autenticação de dois fatores do 1Panel"
ResetHttps: "Cancelar login https do 1Panel"
ResetEntrance: "Cancelar entrada segura do 1Panel"
ResetIPs: "Cancelar restrições de IP autorizado do 1Panel"
ResetDomain: "Cancelar vinculação de domínio do 1Panel"
RestoreCommands: "Restaurar serviço e dados do 1Panel"
RestoreNoSuchFile: "Nenhum arquivo disponível para restauração"
RestoreStep1: "(1/5) Iniciando a restauração do serviço e dados do 1Panel a partir do diretório {{ .name }}..."
RestoreStep2: "(2/5) Restauração do binário do 1Panel bem-sucedida"
RestoreStep3: "(3/5) Restauração dos scripts do 1Panel bem-sucedida"
RestoreStep4: "(4/5) Restauração do serviço do 1Panel bem-sucedida"
RestoreStep5: "(5/5) Restauração dos dados do 1Panel bem-sucedida"
RestoreSuccessful: "Restauração bem-sucedida! Reiniciando o serviço, por favor, aguarde..."
UpdateCommands: "Atualizar informações do painel"
UpdateUser: "Atualizar usuário do painel"
UpdatePassword: "Atualizar senha do painel"
UpdatePort: "Atualizar porta do painel"
UpdateUserNull: "Erro: usuário do painel está vazio!"
UpdateUserBlank: "Erro: o usuário do painel contém espaços!"
UpdateUserFormat: "Erro: Formato de usuário do painel inválido! Apenas suporta inglês, chinês, números e _, comprimento de 3-30."
UpdateUserErr: "Erro: Falha ao atualizar o usuário do painel, {{ .err }}"
UpdateSuccessful: "Atualização bem-sucedida!"
UpdateUserResult: "Usuário do painel: {{ .name }}"
UpdatePasswordRead: "Erro: Falha ao ler as informações da senha do painel, {{ .err }}"
UpdatePasswordNull: "Erro: A senha do painel está vazia!"
UpdateUPasswordBlank: "Erro: A senha do painel contém espaços!"
UpdatePasswordFormat: "Erro: A senha do painel suporta apenas letras, números, caracteres especiais !@#$%*_,.?, comprimento de 8-30!"
UpdatePasswordLen: "Erro: Por favor, insira uma senha com mais de 6 caracteres!"
UpdatePasswordRe: "Confirmar senha:"
UpdatePasswordErr: "Erro: Falha ao atualizar a senha do painel, {{ .err }}"
UpdatePasswordSame: "Erro: As duas senhas não correspondem, por favor, verifique e tente novamente!"
UpdatePasswordResult: "Senha do painel: {{ .name }}"
UpdatePortFormat: "Erro: O número da porta deve estar entre 1 e 65535!"
UpdatePortUsed: "Erro: O número da porta já está em uso, por favor, verifique e tente novamente!"
UpdatePortErr: "Erro: Falha ao atualizar a porta do painel, {{ .err }}"
UpdatePortResult: "Porta do painel: {{ .name }}"
UpdatePortFirewallAdd: "Falha ao adicionar regra de porta ao firewall, {{ .err }}, por favor, adicione manualmente a porta {{ .name }} às regras do firewall."
UpdatePortFirewallDel: "Erro: Falha ao excluir a porta do firewall, {{ .err }}"
UpdatePortFirewallReload: "Falha ao recarregar o firewall, {{ .err }}, por favor, recarregue o firewall manualmente."
UserInfo: "Obter informações do painel"
UserInfoAddr: "Endereço do painel: "
UserInfoPassHelp: "Dica: Para alterar a senha, você pode executar o comando: "
DBConnErr: "Erro: Falha ao inicializar a conexão com o banco de dados, {{ .err }}"
SystemVersion: "versão: "
SystemMode: "modo: "
#ai-tool
ErrOpenrestyInstall: 'Por favor, instale o Openresty primeiro'
ErrSSL: "O conteúdo do certificado está vazio, por favor, verifique o certificado!"
#mobile app
ErrVerifyToken: 'Erro de verificação do token, por favor, reinicie e escaneie novamente.'
ErrInvalidToken: 'Token inválido, por favor, reinicie e escaneie novamente.'
ErrExpiredToken: 'O token expirou, por favor, reinicie e escaneie novamente.'
-63
View File
@@ -1,63 +0,0 @@
#cmd
AppVersion: "Versão do aplicativo"
AppCommands: "Comandos relacionados ao aplicativo"
AppInit: "Inicializar aplicativo"
AppKeyVal: "Chave do aplicativo (suporta apenas inglês)"
AppCreateFileErr: "Falha na criação do arquivo {{ .name }} {{ .err }}"
AppCreateDirErr: "Falha na criação da pasta {{ .name }} {{ .err }}"
AppMissKey: "Chave do aplicativo ausente, use -k para especificar"
AppMissVersion: "Versão do aplicativo ausente, use -v para especificar"
AppVersionExist: "Versão já existente!"
AppCreateSuccessful: "Criação bem-sucedida!"
AppWriteErr: "Falha na gravação do arquivo {{ .name }} {{ .err }}"
SudoHelper: "Por favor, use {{ .cmd }} ou troque para o usuário root"
ListenIPCommands: "Alterar IP de escuta"
ListenIPv4: "Escutar no IPv4"
ListenIPv6: "Escutar no IPv6"
ListenChangeSuccessful: "Alteração bem-sucedida! Agora escutando em {{ .value }}"
ResetCommands: "Redefinir informações do sistema"
ResetMFA: "Cancelar autenticação de dois fatores do 1Panel"
ResetHttps: "Cancelar login HTTPS do 1Panel"
ResetEntrance: "Cancelar entrada segura do 1Panel"
ResetIPs: "Cancelar restrições de IP autorizados do 1Panel"
ResetDomain: "Cancelar vinculação de domínio do 1Panel"
RestoreCommands: "Restaurar serviço e dados do 1Panel"
RestoreNoSuchFile: "Nenhum arquivo disponível para restauração"
RestoreStep1: "(1/5) Iniciando a restauração do serviço e dados do 1Panel a partir do diretório {{ .name }}..."
RestoreStep2: "(2/5) Restauração do binário do 1Panel bem-sucedida"
RestoreStep3: "(3/5) Restauração do script do 1Panel bem-sucedida"
RestoreStep4: "(4/5) Restauração do serviço do 1Panel bem-sucedida"
RestoreStep5: "(5/5) Restauração dos dados do 1Panel bem-sucedida"
RestoreSuccessful: "Restauração bem-sucedida! Reiniciando o serviço, aguarde..."
UpdateCommands: "Atualizar informações do painel"
UpdateUser: "Atualizar usuário do painel"
UpdatePassword: "Atualizar senha do painel"
UpdatePort: "Atualizar porta do painel"
UpdateUserNull: "Erro: usuário do painel está vazio!"
UpdateUserBlank: "Erro: usuário do painel contém espaços!"
UpdateUserFormat: "Erro: Formato de usuário inválido! Aceita apenas inglês, chinês, números e _, comprimento de 3-30"
UpdateUserErr: "Erro: Falha ao atualizar usuário do painel, {{ .err }}"
UpdateSuccessful: "Atualização bem-sucedida!"
UpdateUserResult: "Usuário do painel: {{ .name }}"
UpdatePasswordRead: "Erro: Falha ao ler informações da senha do painel, {{ .err }}"
UpdatePasswordNull: "Erro: Senha do painel está vazia!"
UpdateUPasswordBlank: "Erro: Senha do painel contém espaços!"
UpdatePasswordFormat: "Erro: A senha do painel aceita apenas letras, números, caracteres especiais !@#$%*_,.?, comprimento de 8-30!"
UpdatePasswordLen: "Erro: Por favor, insira uma senha com mais de 6 caracteres!"
UpdatePasswordRe: "Confirmar senha:"
UpdatePasswordErr: "Erro: Falha ao atualizar senha do painel, {{ .err }}"
UpdatePasswordSame: "Erro: As duas senhas não coincidem, por favor, verifique e tente novamente!"
UpdatePasswordResult: "Senha do painel: {{ .name }}"
UpdatePortFormat: "Erro: O número da porta deve estar entre 1 e 65535!"
UpdatePortUsed: "Erro: O número da porta já está em uso, por favor, verifique e tente novamente!"
UpdatePortErr: "Erro: Falha ao atualizar a porta do painel, {{ .err }}"
UpdatePortResult: "Porta do painel: {{ .name }}"
UpdatePortFirewallAdd: "Falha ao adicionar regra de porta no firewall, {{ .err }}, adicione manualmente a porta {{ .name }} às regras do firewall."
UpdatePortFirewallDel: "Erro: Falha ao excluir porta do firewall, {{ .err }}"
UpdatePortFirewallReload: "Falha ao recarregar o firewall, {{ .err }}, recarregue o firewall manualmente."
UserInfo: "Obter informações do painel"
UserInfoAddr: "Endereço do painel: "
UserInfoPassHelp: "Dica: Para alterar a senha, execute o comando: "
DBConnErr: "Erro: Falha ao inicializar conexão com o banco de dados, {{ .err }}"
SystemVersion: "versão: "
SystemMode: "modo: "
+295
View File
@@ -0,0 +1,295 @@
ErrInvalidParams: "Ошибка параметра запроса: {{ .detail }}"
ErrTokenParse: "Ошибка генерации токена: {{ .detail }}"
ErrInitialPassword: "Ошибка исходного пароля"
ErrInternalServer: "Внутренняя ошибка сервиса: {{ .detail }}"
ErrRecordExist: "Запись уже существует"
ErrRecordNotFound: "Записи не найдены"
ErrStructTransform: "Ошибка преобразования типа: {{ .detail }}"
ErrNotLogin: "Пользователь не вошел в систему: {{ .detail }}"
ErrPasswordExpired: "Текущий пароль истек: {{ .detail }}"
ErrNotSupportType: "Система не поддерживает текущий тип: {{ .detail }}"
ErrApiConfigStatusInvalid: "Доступ к API интерфейсу запрещен: {{ .detail }}"
ErrApiConfigKeyInvalid: "Ошибка ключа API интерфейса: {{ .detail }}"
ErrApiConfigIPInvalid: "IP API интерфейса отсутствует в белом списке: {{ .detail }}"
ErrApiConfigDisable: "Этот интерфейс запрещает использование вызовов API интерфейса: {{ .detail }}"
ErrApiConfigKeyTimeInvalid: "Ошибка временной метки интерфейса API: {{ .detail }}"
#common
ErrNameIsExist: "Имя уже существует"
ErrDemoEnvironment: "Демо-сервер, операция запрещена!"
ErrCmdTimeout: "Время выполнения команды истекло!"
ErrCmdIllegal: "Команда содержит недопустимые символы. Пожалуйста, измените и попробуйте снова!"
ErrPortExist: "{{ .port }} порт уже занят {{ .type }} [{{ .name }}]"
TYPE_APP: "Приложение"
TYPE_RUNTIME: "Среда выполнения"
TYPE_DOMAIN: "Доменное имя"
ErrTypePort: "Ошибка формата порта {{ .name }}"
ErrTypePortRange: "Диапазон портов должен быть между 1-65535"
Success: "Успех"
Failed: "Неудача"
SystemRestart: "Перезагрузка системы приводит к прерыванию задачи"
#app
ErrPortInUsed: "Порт {{ .detail }} уже используется"
ErrAppLimit: "Превышен лимит установки приложения"
ErrAppRequired: "Требуется приложение {{ .detail }}"
ErrNotInstall: "Приложение не установлено"
ErrPortInOtherApp: "Порт {{ .port }} уже используется приложением {{ .apps }}"
ErrDbUserNotValid: "База данных акций, имя пользователя и пароль не совпадают!"
ErrDockerComposeNotValid: "Ошибка формата файла docker-compose!"
ErrUpdateBuWebsite: "Приложение успешно обновлено, но изменение конфигурационного файла веб-сайта не удалось, пожалуйста, проверьте конфигурацию!"
Err1PanelNetworkFailed: "Не удалось создать сеть контейнера по умолчанию! {{ .detail }}"
ErrFileParse: "Не удалось разобрать файл docker-compose приложения!"
ErrInstallDirNotFound: "Директория установки не существует"
AppStoreIsUpToDate: "Обновлено"
LocalAppVersionNull: "Приложение {{.name}} не синхронизировано с версией! Невозможно добавить в список приложений"
LocalAppVersionErr: "{{.name}} не удалось синхронизировать версию {{.version}}! {{.err}}"
ErrFileNotFound: "Файл {{.name}} не существует"
ErrFileParseApp: "Не удалось проанализировать файл {{.name}} {{.err}}"
ErrAppDirNull: "Папка версии не существует"
LocalAppErr: "Синхронизация приложения {{.name}} не удалась! {{.err}}"
ErrContainerName: "Имя контейнера уже существует"
ErrAppSystemRestart: "Перезапуск 1Panel приводит к завершению задачи"
ErrCreateHttpClient: "Не удалось создать HTTP-запрос {{.err}}"
ErrHttpReqTimeOut: "Превышено время ожидания запроса {{.err}}"
ErrHttpReqFailed: "Запрос не выполнен {{.err}}"
ErrHttpReqNotFound: "Файл не существует"
ErrNoSuchHost: "Сбой сетевого подключения"
ErrImagePullTimeOut: "Тайм-аут загрузки образа"
ErrContainerNotFound: "Контейнер {{ .name }} не существует"
ErrContainerMsg: "Контейнер {{ .name }} работает ненормально, пожалуйста, проверьте журнал на странице контейнера для подробностей"
ErrAppBackup: "Резервное копирование приложения {{ .name }} не удалось, ошибка {{.err}}"
ErrImagePull: "Не удалось загрузить образ {{ .name }}, ошибка {{.err}}"
ErrVersionTooLow: "Текущая версия 1Panel слишком стара для обновления магазина приложений, пожалуйста, обновите версию"
ErrAppNameExist: "Имя приложения уже существует"
AppStoreIsSyncing: "Магазин приложений синхронизируется, пожалуйста, попробуйте позже"
ErrGetCompose: "Не удалось получить файл docker-compose.yml! {{ .detail }}"
ErrAppWarn: "Аномальный статус, пожалуйста, проверьте журнал"
ErrAppParamKey: "Исключение в поле параметра {{ .name }}"
ErrAppUpgrade: "Не удалось обновить приложение {{ .name }} {{ .err }}"
AppRecover: "Приложение {{ .name }} откатилось "
PullImageStart: "Начало загрузки образа {{ .name }}"
PullImageSuccess: "Образ успешно загружен"
UpgradeAppStart: "Начало обновления приложения {{ .name }}"
UpgradeAppSuccess: "Приложение {{ .name }} успешно обновлено"
#file
ErrFileCanNotRead: "Файл недоступен для чтения"
ErrFileToLarge: "Файл слишком большой"
ErrPathNotFound: "Путь не найден"
ErrMovePathFailed: "Целевой путь не может содержать исходный путь!"
ErrLinkPathNotFound: "Целевой путь не существует!"
ErrFileIsExist: "Файл или каталог уже существует!"
ErrFileUpload: "Не удалось загрузить файл {{.name}} {{.detail}}"
ErrFileDownloadDir: "Скачивание папки не поддерживается"
ErrCmdNotFound: "Команда {{ .name}} не существует, пожалуйста, сначала установите эту команду на хосте"
ErrSourcePathNotFound: "Исходный каталог не существует"
ErrFavoriteExist: "Этот путь уже в избранном"
ErrInvalidChar: "Недопустимые символы запрещены"
ErrPathNotDelete: "Выбранный каталог не может быть удален"
#website
ErrDomainIsExist: "Доменное имя уже существует"
ErrAliasIsExist: "Псевдоним уже существует"
ErrAppDelete: "Другой веб-сайт использует это приложение"
ErrGroupIsUsed: "Группа используется и не может быть удалена"
ErrBackupMatch: "файл резервной копии не соответствует текущим данным части сайта: {{ .detail}}"
ErrBackupExist: "файл резервной копии соответствует части исходных данных, которая не существует: {{ .detail}}"
ErrPHPResource: "Локальная среда выполнения не поддерживает переключение!"
ErrPathPermission: "Обнаружена папка с правами доступа не 1000:1000 в каталоге индекса, что может вызвать ошибку отказа в доступе при доступе к веб-сайту. Пожалуйста, нажмите кнопку сохранения выше"
ErrDomainIsUsed: "Домен уже используется веб-сайтом {{ .name }}"
ErrDomainFormat: "Ошибка формата домена {{ .name }}"
ErrDefaultAlias: "default — зарезервированное кодовое имя, пожалуйста, используйте другое кодовое имя"
ErrImageNotExist: "Образ рабочей среды {{.name}} не существует, пожалуйста, перенастройте рабочую среду"
#ssl
ErrSSLCannotDelete: "Сертификат {{ .name }} используется веб-сайтом и не может быть удален"
ErrAccountCannotDelete: "Сертификат, связанный с учетной записью, не может быть удален"
ErrSSLApply: "Сертификат продолжает успешно подписываться, но перезагрузка openresty не удалась, пожалуйста, проверьте конфигурацию!"
ErrEmailIsExist: "Электронная почта уже существует"
ErrSSLKeyNotFound: "Файл закрытого ключа не существует"
ErrSSLCertificateNotFound: "Файл сертификата не существует"
ErrSSLKeyFormat: "Ошибка проверки файла закрытого ключа"
ErrSSLCertificateFormat: "Ошибка формата файла сертификата, пожалуйста, используйте формат pem"
ErrEabKidOrEabHmacKeyCannotBlank: "EabKid или EabHmacKey не могут быть пустыми"
ErrOpenrestyNotFound: "Режим HTTP требует предварительной установки Openresty"
ApplySSLStart: "Начать подачу заявки на сертификат, доменное имя [{{ .domain }}] метод подачи заявки [{{ .type }}] "
dnsAccount: "Автоматический DNS"
dnsManual: "Ручной DNS"
http: "HTTP"
ApplySSLFailed: "Заявка на сертификат для [{{ .domain }}] не удалась, {{.detail}} "
ApplySSLSuccess: "Заявка на сертификат для [{{ .domain }}] успешна! "
DNSAccountName: "Учетная запись DNS [{{ .name }}] производитель [{{.type}}]"
PushDirLog: "Сертификат отправлен в каталог [{{ .path }}] {{ .status }}"
ErrDeleteCAWithSSL: "Существует выданный сертификат под текущей организацией, удаление невозможно"
ErrDeleteWithPanelSSL: "Конфигурация SSL панели использует этот сертификат и не может быть удален"
ErrDefaultCA: "Уполномоченный центр по умолчанию не может быть удален"
ApplyWebSiteSSLLog: "Начать обновление сертификата веб-сайта {{ .name }}"
ErrUpdateWebsiteSSL: "Не удалось обновить сертификат веб-сайта {{ .name }}: {{ .err }}"
ApplyWebSiteSSLSuccess: "Сертификат веб-сайта успешно обновлен"
ErrExecShell: "Не удалось выполнить скрипт {{ .err }}"
ExecShellStart: "Начать выполнение скрипта"
ExecShellSuccess: "Скрипт успешно выполнен"
StartUpdateSystemSSL: "Начать обновление системного сертификата"
UpdateSystemSSLSuccess: "Системный сертификат успешно обновлен"
#mysql
ErrUserIsExist: "Текущий пользователь уже существует. Пожалуйста, введите нового пользователя"
ErrDatabaseIsExist: "Текущая база данных уже существует. Пожалуйста, введите новую базу данных"
ErrExecTimeOut: "Время выполнения SQL запроса истекло, пожалуйста, проверьте базу данных"
ErrRemoteExist: "Удаленная база данных с таким именем уже существует, пожалуйста, измените и попробуйте снова"
ErrLocalExist: "Локальная база данных с таким именем уже существует, пожалуйста, измените и попробуйте снова"
#redis
ErrTypeOfRedis: "Тип восстановленного файла не соответствует текущему режиму сохранения. Измените тип файла и попробуйте снова"
#container
ErrInUsed: "{{ .detail }} используется и не может быть удален"
ErrObjectInUsed: "Этот объект используется и не может быть удален"
ErrObjectBeDependent: "Этот образ зависит от других образов и не может быть удален"
ErrPortRules: "Количество портов не совпадает, пожалуйста, введите заново!"
ErrPgImagePull: "Тайм-аут загрузки образа. Пожалуйста, настройте ускорение загрузки образа или вручную загрузите образ postgres:16.0-alpine и попробуйте снова"
#runtime
ErrDirNotFound: "Папка сборки не существует! Пожалуйста, проверьте целостность файла!"
ErrFileNotExist: "Файл {{ .detail }} не существует! Пожалуйста, проверьте целостность исходного файла!"
ErrImageBuildErr: "Не удалось создать образ"
ErrImageExist: "Образ уже существует!"
ErrDelWithWebsite: "Рабочая среда уже связана с веб-сайтом и не может быть удалена"
ErrRuntimeStart: "Не удалось запустить"
ErrPackageJsonNotFound: "Файл package.json не существует"
ErrScriptsNotFound: "Конфигурационный элемент scripts не найден в package.json"
ErrContainerNameNotFound: "Не удалось получить имя контейнера, пожалуйста, проверьте файл .env"
ErrNodeModulesNotFound: "Папка node_modules не существует! Пожалуйста, отредактируйте среду выполнения или дождитесь успешного запуска среды выполнения"
#setting
ErrBackupInUsed: "Учетная запись резервного копирования уже используется в cronjob и не может быть удалена."
ErrBackupCheck: "Проверка подключения учетной записи резервного копирования не выполнена {{ .err}}"
ErrOSSConn: "Не удалось получить последнюю версию, пожалуйста, проверьте возможность подключения сервера к внешней сети."
ErrEntrance: "Информация о безопасном входе неверна. Пожалуйста, проверьте и попробуйте снова!"
#tool
ErrConfigNotFound: "Конфигурационный файл не существует"
ErrConfigParse: "Ошибка формата конфигурационного файла"
ErrConfigIsNull: "Конфигурационный файл не может быть пустым"
ErrConfigDirNotFound: "Каталог выполнения не существует"
ErrConfigAlreadyExist: "Конфигурационный файл с таким именем уже существует"
ErrUserFindErr: "Не удалось найти пользователя {{ .name }} {{ .err }}"
#ssh
ErrFirewallNone: "На системе не обнаружен сервис firewalld или ufw. Пожалуйста, проверьте и попробуйте снова!"
ErrFirewallBoth: "На системе обнаружены оба сервиса firewalld и ufw. Чтобы избежать конфликтов, удалите один и попробуйте снова!"
#cronjob
ErrBashExecute: "Ошибка выполнения скрипта, пожалуйста, проверьте конкретную информацию в области вывода задачи."
ErrCutWebsiteLog: "Не удалось разрезать лог веб-сайта {{ .name }}, ошибка {{ .err }}"
CutWebsiteLogSuccess: "Лог веб-сайта {{ .name }} успешно разрезан, путь к резервной копии {{ .path }}"
#toolbox
ErrNotExistUser: "Текущий пользователь не существует. Пожалуйста, измените и попробуйте снова!"
ErrBanAction: "Установка не выполнена, текущий сервис {{ .name }} недоступен, пожалуйста, проверьте и попробуйте снова!"
ErrClamdscanNotFound: "Команда clamdscan не обнаружена, пожалуйста, обратитесь к документации для установки!"
#waf
ErrScope: "Изменение этой конфигурации не поддерживается"
ErrStateChange: "Не удалось изменить состояние"
ErrRuleExist: "Правило уже существует"
ErrRuleNotExist: "Правило не существует"
ErrParseIP: "Ошибка формата IP"
ErrDefaultIP: "default — зарезервированное имя, пожалуйста, измените на другое имя"
ErrGroupInUse: "IP-группа используется в черно/белом списке и не может быть удалена"
ErrGroupExist: "Имя IP-группы уже существует"
ErrIPRange: "Неверный диапазон IP"
ErrIPExist: "IP уже существует"
#license
ErrLicense: "Ошибка формата лицензии, пожалуйста, проверьте и попробуйте снова!"
ErrLicenseCheck: "Проверка лицензии не выполнена, пожалуйста, проверьте и попробуйте снова!"
ErrXpackVersion: "Ошибка проверки лицензии, эта лицензия ограничена по версии и не может быть успешно импортирована. Пожалуйста, проверьте и попробуйте снова!"
ErrLicenseSave: "Не удалось сохранить информацию о лицензии, ошибка {{ .err }}, пожалуйста, попробуйте снова!"
ErrLicenseSync: "Не удалось синхронизировать информацию о лицензии, в базе данных не обнаружена информация о лицензии!"
ErrXpackNotFound: "Этот раздел является функцией профессионального издания, пожалуйста, сначала импортируйте лицензию в интерфейсе Настройки панели — Лицензия"
ErrXpackNotActive: "Этот раздел является функцией профессионального издания, пожалуйста, сначала синхронизируйте статус лицензии в интерфейсе Настройки панели — Лицензия"
ErrXpackOutOfDate: "Текущая лицензия истекла, пожалуйста, повторно импортируйте лицензию в интерфейсе Настройки панели — Лицензия"
ErrXpackLost: "Лицензия достигла максимального числа попыток повторной попытки. Пожалуйста, перейдите на страницу [Настройки] [Лицензия] и вручную нажмите кнопку синхронизации, чтобы обеспечить корректную работу функций профессиональной версии."
ErrXpackTimeout: "Превышено время ожидания запроса, возможно, нестабильное сетевое соединение, пожалуйста, повторите попытку позже!"
#license
ErrAlert: "Ошибка формата информации об оповещении, пожалуйста, проверьте и попробуйте снова!"
ErrAlertPush: "Ошибка отправки оповещения, пожалуйста, проверьте и попробуйте снова!"
ErrAlertSave: "Ошибка сохранения оповещения, пожалуйста, проверьте и попробуйте снова!"
ErrAlertSync: "Ошибка синхронизации оповещения, пожалуйста, проверьте и попробуйте снова!"
ErrAlertRemote: "Ошибка удаленного оповещения, пожалуйста, проверьте и попробуйте снова!"
#cmd
AppVersion: "Версия приложения"
AppCommands: "Команды, связанные с приложением"
AppInit: "Инициализировать приложение"
AppKeyVal: "Ключ приложения (поддерживает только английский)"
AppCreateFileErr: "Не удалось создать файл {{ .name }} {{ .err }}"
AppCreateDirErr: "Не удалось создать папку {{ .name }} {{ .err }}"
AppMissKey: "Отсутствует ключ приложения, используйте -k для указания"
AppMissVersion: "Отсутствует версия приложения, используйте -v для указания"
AppVersionExist: "Версия уже существует!"
AppCreateSuccessful: "Создание прошло успешно!"
AppWriteErr: "Ошибка записи файла {{ .name }} {{ .err }}"
SudoHelper: "Пожалуйста, используйте {{ .cmd }} или переключитесь на пользователя root"
ListenIPCommands: "Переключить IP прослушивания"
ListenIPv4: "Прослушивать IPv4"
ListenIPv6: "Прослушивать IPv6"
ListenChangeSuccessful: "Переключение успешно! Теперь прослушивается {{ .value }}"
ResetCommands: "Сбросить информацию системы"
ResetMFA: "Отменить двухфакторную аутентификацию 1Panel"
ResetHttps: "Отменить вход в 1Panel по https"
ResetEntrance: "Отменить безопасный вход в 1Panel"
ResetIPs: "Отменить авторизованные IP-ограничения 1Panel"
ResetDomain: "Отменить привязку домена 1Panel"
RestoreCommands: "Откатить сервис и данные 1Panel"
RestoreNoSuchFile: "Нет доступных файлов для отката"
RestoreStep1: "(1/5) Начало отката сервиса и данных 1Panel из каталога {{ .name }}..."
RestoreStep2: "(2/5) Откат бинарного файла 1Panel успешен"
RestoreStep3: "(3/5) Откат скрипта 1Panel успешен"
RestoreStep4: "(4/5) Откат сервиса 1Panel успешен"
RestoreStep5: "(5/5) Откат данных 1Panel успешен"
RestoreSuccessful: "Откат успешен! Перезапуск службы, пожалуйста, подождите..."
UpdateCommands: "Обновить информацию панели"
UpdateUser: "Обновить пользователя панели"
UpdatePassword: "Обновить пароль панели"
UpdatePort: "Обновить порт панели"
UpdateUserNull: "Ошибка: пользователь панели пуст!"
UpdateUserBlank: "Ошибка: пользователь панели содержит пробелы!"
UpdateUserFormat: "Ошибка: неверный формат пользователя панели! Поддерживаются только английский, китайский, цифры и , длина 3-30"
UpdateUserErr: "Ошибка: не удалось обновить пользователя панели, {{ .err }}"
UpdateSuccessful: "Обновление успешно!"
UpdateUserResult: "Пользователь панели: {{ .name }}"
UpdatePasswordRead: "Ошибка: не удалось прочитать информацию о пароле панели, {{ .err }}"
UpdatePasswordNull: "Ошибка: пароль панели пуст!"
UpdateUPasswordBlank: "Ошибка: пароль панели содержит пробелы!"
UpdatePasswordFormat: "Ошибка: пароль панели поддерживает только буквы, цифры, специальные символы !@#$%* ,., длина 8-30!"
UpdatePasswordLen: "Ошибка: Пожалуйста, введите пароль длиной более 6 символов!"
UpdatePasswordRe: "Подтвердите пароль:"
UpdatePasswordErr: "Ошибка: не удалось обновить пароль панели, {{ .err }}"
UpdatePasswordSame: "Ошибка: два пароля не совпадают, пожалуйста, проверьте и попробуйте снова!"
UpdatePasswordResult: "Пароль панели: {{ .name }}"
UpdatePortFormat: "Ошибка: введенный номер порта должен быть между 1 и 65535!"
UpdatePortUsed: "Ошибка: номер порта уже используется, пожалуйста, проверьте и попробуйте снова!"
UpdatePortErr: "Ошибка: не удалось обновить порт панели, {{ .err }}"
UpdatePortResult: "Порт панели: {{ .name }}"
UpdatePortFirewallAdd: "Не удалось добавить правило порта брандмауэра, {{ .err }}, пожалуйста, вручную добавьте порт {{ .name }} в правила брандмауэра."
UpdatePortFirewallDel: "Ошибка: не удалось удалить порт брандмауэра, {{ .err }}"
UpdatePortFirewallReload: "Не удалось перезагрузить брандмауэр, {{ .err }}, пожалуйста, вручную перезагрузите брандмауэр."
UserInfo: "Получить информацию панели"
UserInfoAddr: "Адрес панели: "
UserInfoPassHelp: "Подсказка: чтобы изменить пароль, вы можете выполнить команду: "
DBConnErr: "Ошибка: не удалось инициализировать подключение к базе данных, {{ .err }}"
SystemVersion: "версия: "
SystemMode: "режим: "
#ai-tool
ErrOpenrestyInstall: "Пожалуйста, установите Openresty сначала"
ErrSSL: "Содержимое сертификата пустое, пожалуйста, проверьте сертификат!"
#mobile app
ErrVerifyToken: 'шибка проверки токена, пожалуйста, сбросьте и отсканируйте снова.'
ErrInvalidToken: 'Неверный токен, пожалуйста, сбросьте и отсканируйте снова.'
ErrExpiredToken: 'Токен истек, пожалуйста, сбросьте и отсканируйте снова.'
+136 -124
View File
@@ -6,18 +6,19 @@ ErrRecordExist: "記錄已存在"
ErrRecordNotFound: "記錄未找到"
ErrStructTransform: "類型轉換失敗: {{ .detail }}"
ErrNotLogin: "用戶未登入: {{ .detail }}"
ErrPasswordExpired: "當前密碼已過期: {{ .detail }}"
ErrNotSupportType: "系統暫不支持當前類型: {{ .detail }}"
ErrApiConfigStatusInvalid: "API 接口禁止訪問: {{ .detail }}"
ErrApiConfigKeyInvalid: "API 接口密钥錯誤: {{ .detail }}"
ErrApiConfigIPInvalid: "调用 API 接口 IP 不在白名单: {{ .detail }}"
ErrApiConfigDisable: "此接口禁止使用 API 接口調用: {{ .detail }}"
ErrPasswordExpired: "目前密碼已過期: {{ .detail }}"
ErrNotSupportType: "系統暫不支援目前類型: {{ .detail }}"
ErrApiConfigStatusInvalid: "API 介面禁止瀏覽: {{ .detail }}"
ErrApiConfigKeyInvalid: "API 介面金鑰錯誤: {{ .detail }}"
ErrApiConfigIPInvalid: "呼叫 API 介面 IP 不在白名單: {{ .detail }}"
ErrApiConfigDisable: "此介面禁止使用 API 介面呼叫: {{ .detail }}"
ErrApiConfigKeyTimeInvalid: "API 介面時間戳記錯誤: {{ .detail }}"
#common
ErrNameIsExist: "名稱已存在"
ErrDemoEnvironment: "演示伺服器,禁止此操作!"
ErrCmdTimeout: "指令執行超時!"
ErrCmdIllegal: "執行命令中存在不合法字符,請修改後重試!"
ErrCmdIllegal: "執行指令中存在不合法字元,請修改後重試!"
ErrPortExist: '{{ .port }} 埠已被 {{ .type }} [{{ .name }}] 佔用'
TYPE_APP: "應用"
TYPE_RUNTIME: "運作環境"
@@ -30,99 +31,99 @@ SystemRestart: "系統重啟導致任務中斷"
ErrInvalidChar: "禁止使用非法字元"
#app
ErrPortInUsed: "{{ .detail }} 端口已被佔用!"
ErrPortInUsed: "{{ .detail }} 埠已被佔用!"
ErrAppLimit: "應用超出安裝數量限制"
ErrAppRequired: "請先安裝 {{ .detail }} 應用"
ErrNotInstall: "應用未安裝"
ErrPortInOtherApp: "{{ .port }} 端口已被應用 {{ .apps }} 佔用!"
ErrPortInOtherApp: "{{ .port }} 埠已被應用 {{ .apps }} 佔用!"
ErrDbUserNotValid: "儲存資料庫,用戶名密碼不匹配!"
ErrDockerComposeNotValid: "docker-compose 文件格式錯誤"
ErrDockerComposeNotValid: "docker-compose 檔案格式錯誤"
ErrUpdateBuWebsite: '應用更新成功,但是網站配置文件修改失敗,請檢查配置!'
Err1PanelNetworkFailed: '默認容器網絡創建失敗!{{ .detail }}'
ErrFileParse: '應用 docker-compose 文件解析失敗!'
Err1PanelNetworkFailed: '預設容器網路建立失敗!{{ .detail }}'
ErrFileParse: '應用 docker-compose 檔案解析失敗!'
ErrInstallDirNotFound: '安裝目錄不存在'
AppStoreIsUpToDate: '應用商店已經是最新版本'
LocalAppVersionNull: '{{.name}} 應用未同步到版本!無法添加到應用列表'
LocalAppVersionErr: '{{.name}} 同步版本 {{.version}} 失敗!{{.err}}'
ErrFileNotFound: '{{.name}} 文件不存在'
ErrFileParseApp: '{{.name}} 文件解析失敗 {{.err}}'
LocalAppVersionNull: '{{ .name }} 應用未同步到版本!無法新增到應用列表'
LocalAppVersionErr: '{{ .name }} 同步版本 {{ .version }} 失敗!{{ .err }}'
ErrFileNotFound: '{{ .name }} 檔案不存在'
ErrFileParseApp: '{{ .name }} 檔案解析失敗 {{ .err }}'
ErrAppDirNull: '版本資料夾不存在'
LocalAppErr: "應用 {{.name}} 同步失敗!{{.err}}"
LocalAppErr: "應用 {{ .name }} 同步失敗!{{ .err }}"
ErrContainerName: "容器名稱已存在"
ErrAppSystemRestart: "1Panel 重啟導致任務中斷"
ErrCreateHttpClient: "創建HTTP請求失敗 {{.err}}"
ErrHttpReqTimeOut: "請求超時 {{.err}}"
ErrHttpReqFailed: "請求失敗 {{.err}}"
ErrHttpReqNotFound: "文件不存在"
ErrNoSuchHost: "網路連接失敗"
ErrCreateHttpClient: "建立HTTP請求失敗 {{ .err }}"
ErrHttpReqTimeOut: "請求超時 {{ .err }}"
ErrHttpReqFailed: "請求失敗 {{ .err }}"
ErrHttpReqNotFound: "檔案不存在"
ErrNoSuchHost: "網路連線失敗"
ErrImagePullTimeOut: "鏡像拉取超時"
ErrContainerNotFound: '{{ .name }} 容器不存在'
ErrContainerMsg: '{{ .name }} 容器異常,具體請在容器頁面查看日誌'
ErrAppBackup: '{{ .name }} 應用備份失敗 err {{.err}}'
ErrImagePull: '{{ .name }} 鏡像拉取失敗 err {{.err}}'
ErrVersionTooLow: '當前 1Panel 版本過低,無法更新應用商店,請升級版本之後操作'
ErrAppBackup: '{{ .name }} 應用備份失敗 err {{ .err }}'
ErrImagePull: '{{ .name }} 鏡像拉取失敗 err {{ .err }}'
ErrVersionTooLow: '目前 1Panel 版本過低,無法更新應用商店,請升級版本之後操作'
ErrAppNameExist: '應用名稱已存在'
AppStoreIsSyncing: '應用程式商店正在同步中,請稍後再試'
ErrGetCompose: "docker-compose.yml 檔案取得失敗!{{ .detail }}"
ErrAppWarn: "狀態異常,請查看日誌"
ErrAppParamKey: "參數 {{ .name }} 欄位異常"
ErrAppUpgrade: "應用程式 {{ .name }} 升級失敗 {{ .err }}"
AppRecover: "應用程式 {{ .name }} 回滾 "
AppRecover: "應用程式 {{ .name }} 轉返 "
PullImageStart: "開始拉取鏡像 {{ .name }}"
PullImageSuccess: "鏡像拉取成功"
UpgradeAppStart: "開始升級應用程式 {{ .name }}"
UpgradeAppSuccess: "應用程式 {{ .name }} 升級成功"
#file
ErrFileCanNotRead: "此文件不支持預覽"
ErrFileToLarge: "文件超過10M,無法打開"
ErrFileCanNotRead: "此檔案不支援預覽"
ErrFileToLarge: "檔案超過10M,無法打開"
ErrPathNotFound: "目錄不存在"
ErrMovePathFailed: "目標路徑不能包含原路徑!"
ErrLinkPathNotFound: "目標路徑不存在!"
ErrFileIsExist: "文件或文件夾已存在!"
ErrFileUpload: "{{ .name }} 上傳文件失敗 {{ .detail}}"
ErrFileDownloadDir: "不支持下載文件夾"
ErrCmdNotFound: "{{ .name}} 命令不存在,請先在宿主機安裝此命令"
ErrFileIsExist: "檔案或資料夾已存在!"
ErrFileUpload: "{{ .name }} 上傳檔案失敗 {{ .detail }}"
ErrFileDownloadDir: "不支援下載資料夾"
ErrCmdNotFound: "{{ .name}} 指令不存在,請先在宿主機安裝此指令"
ErrSourcePathNotFound: "源目錄不存在"
ErrFavoriteExist: "已收藏此路徑"
ErrPathNotDelete: "所選目錄不可删除"
ErrPathNotDelete: "所選目錄不可刪除"
#website
ErrDomainIsExist: "域名已存在"
ErrAliasIsExist: "代號已存在"
ErrAppDelete: '其他網站使用此應用,無法刪除'
ErrAppDelete: '其他網站使用此應用,無法刪除'
ErrGroupIsUsed: '分組正在使用中,無法刪除'
ErrBackupMatch: '該備份文件與當前網站部分數據不匹配: {{ .detail}}'
ErrBackupExist: '該備份文件對應部分原數據不存在: {{ .detail}}'
ErrPHPResource: '本地運行環境不支持切換!'
ErrPathPermission: 'index 目錄下偵測到非 1000:1000 權限資料夾,可能導致網站存取 Access denied 錯誤,請點擊上方儲存按鈕'
ErrBackupMatch: '該備份檔案與目前網站部分資料不匹配: {{ .detail }}'
ErrBackupExist: '該備份檔案對應部分原資料不存在: {{ .detail }}'
ErrPHPResource: '本機執行環境不支援切換!'
ErrPathPermission: 'index 目錄下偵測到非 1000:1000 權限資料夾,可能導致網站存取 Access denied 錯誤,請點選上方儲存按鈕'
ErrDomainIsUsed: "域名已被網站【{{ .name }}】使用"
ErrDomainFormat: "{{ .name }} 域名格式不正確"
ErrDefaultAlias: "default 為保留代號,請使用其他代號"
ErrImageNotExist: "執行環境 {{.name}} 鏡像不存在,請重新編輯執行環境"
ErrImageNotExist: "執行環境 {{ .name }} 鏡像不存在,請重新編輯執行環境"
#ssl
ErrSSLCannotDelete: "{{ .name }} 證書正在被網站使用,無法刪除"
ErrAccountCannotDelete: "帳號關聯證書,無法刪除"
ErrSSLApply: "證書續簽成功,openresty reload失敗,請檢查配置!"
ErrEmailIsExist: '郵箱已存在'
ErrSSLKeyNotFound: '私鑰文件不存在'
ErrSSLCertificateNotFound: '證書文件不存在'
ErrSSLKeyFormat: '私鑰文件校驗錯誤'
ErrSSLCertificateFormat: '證書文件格式錯誤,請使用 pem 格式'
ErrEmailIsExist: '信箱已存在'
ErrSSLKeyNotFound: '私鑰檔案不存在'
ErrSSLCertificateNotFound: '證書檔案不存在'
ErrSSLKeyFormat: '私鑰檔案校驗錯誤'
ErrSSLCertificateFormat: '證書檔案格式錯誤,請使用 pem 格式'
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 或 EabHmacKey 不能為空'
ErrOpenrestyNotFound: 'Http 模式需要先安裝 Openresty'
ApplySSLStart: '開始申請憑證,網域 [{{ .domain }}] 申請方式 [{{ .type }}] '
ApplySSLStart: '開始申請憑證,網域 [{{ .domain }}] 申請方式 [{{ .type }}] '
dnsAccount: "DNS 自動"
dnsManual: "DNS 手排"
http: "HTTP"
ApplySSLFailed: '申請 [{{ .domain }}] 憑證失敗, {{.detail}} '
ApplySSLFailed: '申請 [{{ .domain }}] 憑證失敗, {{ .detail }} '
ApplySSLSuccess: '申請 [{{ .domain }}] 憑證成功! ! '
DNSAccountName: 'DNS 帳號 [{{ .name }}] 廠商 [{{.type}}]'
DNSAccountName: 'DNS 帳號 [{{ .name }}] 廠商 [{{ .type }}]'
PushDirLog: '憑證推送到目錄 [{{ .path }}] {{ .status }}'
ErrDeleteCAWithSSL: "目前機構下存在已簽發證書,無法刪除"
ErrDeleteWithPanelSSL: "面板 SSL 配置使用此證書,無法刪除"
ErrDefaultCA: "默認機構不能刪除"
ErrDefaultCA: "預設機構不能刪除"
ApplyWebSiteSSLLog: "開始更新 {{ .name }} 網站憑證"
ErrUpdateWebsiteSSL: "{{ .name }} 網站更新憑證失敗: {{ .err }}"
ApplyWebSiteSSLSuccess: "更新網站憑證成功"
@@ -133,59 +134,60 @@ StartUpdateSystemSSL: "開始更新系統證書"
UpdateSystemSSLSuccess: "更新系統證書成功"
#mysql
ErrUserIsExist: "當前用戶已存在,請重新輸入"
ErrDatabaseIsExist: "當前資料庫已存在,請重新輸入"
ErrExecTimeOut: "SQL 執行超時,請檢查數據庫"
ErrRemoteExist: "遠程數據庫已存在該名稱,請修改後重試"
ErrLocalExist: "本地數據庫已存在該名稱,請修改後重試"
ErrUserIsExist: "目前用戶已存在,請重新輸入"
ErrDatabaseIsExist: "目前資料庫已存在,請重新輸入"
ErrExecTimeOut: "SQL 執行超時,請檢查資料庫"
ErrRemoteExist: "遠端資料庫已存在該名稱,請修改後重試"
ErrLocalExist: "本機資料庫已存在該名稱,請修改後重試"
#redis
ErrTypeOfRedis: "恢復文件類型與當前持久化方式不符,請修改後重試"
ErrTypeOfRedis: "復原檔案類型與目前持久化方式不匹配,請修改後重試"
#container
ErrInUsed: "{{ .detail }} 正被使用,無法刪除"
ErrObjectInUsed: "該對象正被使用,無法刪除"
ErrPortRules: "端口數目不匹配,請重新輸入!"
ErrObjectInUsed: "該物件正被使用,無法刪除"
ErrObjectBeDependent: "該鏡像依賴於其他鏡像,無法刪除"
ErrPortRules: "埠數目不匹配,請重新輸入!"
ErrPgImagePull: "鏡像拉取超時,請配置鏡像加速或手動拉取 postgres:16.0-alpine 鏡像後重試"
#runtime
ErrDirNotFound: "build 文件夾不存在!請檢查文件完整性!"
ErrFileNotExist: "{{ .detail }} 文件不存在!請檢查源文件完整性!"
ErrDirNotFound: "build 資料夾不存在!請檢查檔案完整性!"
ErrFileNotExist: "{{ .detail }} 檔案不存在!請檢查源文件完整性!"
ErrImageBuildErr: "鏡像 build 失敗"
ErrImageExist: "鏡像已存在!"
ErrDelWithWebsite: "運行環境已經關聯網站,無法刪除"
ErrDelWithWebsite: "執行環境已經關聯網站,無法刪除"
ErrRuntimeStart: "啟動失敗"
ErrPackageJsonNotFound: "package.json 文件不存在"
ErrPackageJsonNotFound: "package.json 檔案不存在"
ErrScriptsNotFound: "沒有在 package.json 中找到 scripts 配置項"
ErrContainerNameNotFound: "無法取得容器名稱,請檢查 .env 文件"
ErrNodeModulesNotFound: "node_modules 文件夾不存在!請編輯運行環境或者等待運行環境啟動成功"
ErrContainerNameNotFound: "無法取得容器名稱,請檢查 .env 檔案"
ErrNodeModulesNotFound: "node_modules 資料夾不存在!請編輯執行環境或者等待執行環境啟動成功"
#setting
ErrBackupInUsed: "該備份帳號已在計劃任務中使用,無法刪除"
ErrBackupCheck: "備份帳號測試連接失敗 {{ .err}}"
ErrOSSConn: "無法獲取最新版本,請確認伺服器是否能夠連接外部網路。"
ErrEntrance: "安全入口信息錯誤,請檢查後重試!"
ErrBackupCheck: "備份帳號測試連線失敗 {{ .err }}"
ErrOSSConn: "無法取得最新版本,請確認伺服器是否能夠連接外部網路。"
ErrEntrance: "安全入口資訊錯誤,請檢查後重試!"
#tool
ErrConfigNotFound: "配置文件不存在"
ErrConfigParse: "配置文件格式有誤"
ErrConfigIsNull: "配置文件不允許為空"
ErrConfigDirNotFound: "運行目錄不存在"
ErrConfigDirNotFound: "執行目錄不存在"
ErrConfigAlreadyExist: "已存在同名配置文件"
ErrUserFindErr: "用戶 {{ .name }} 查找失敗 {{ .err }}"
ErrUserFindErr: "用戶 {{ .name }} 尋找失敗 {{ .err }}"
#ssh
ErrFirewallNone: "未檢測到系統 firewalld 或 ufw 服務,請檢查後重試!"
ErrFirewallBoth: "檢測到系統同時存在 firewalld 或 ufw 服務,為避免衝突,請卸載後重試!"
ErrFirewallBoth: "檢測到系統同時存在 firewalld 或 ufw 服務,為避免衝突,請移除後重試!"
#cronjob
ErrBashExecute: "腳本執行錯誤,請在任務輸出文本域中查看具體信息。"
ErrBashExecute: "腳本執行錯誤,請在任務輸出文字區域中查看具體資訊。"
ErrCutWebsiteLog: "{{ .name }} 網站日誌切割失敗,錯誤 {{ .err }}"
CutWebsiteLogSuccess: "{{ .name }} 網站日誌切割成功,備份路徑 {{ .path }}"
#toolbox
ErrNotExistUser: "當前使用者不存在,請修改後重試!"
ErrBanAction: "設置失敗,當前 {{ .name }} 服務不可用,請檢查後重試!"
ErrNotExistUser: "目前使用者不存在,請修改後重試!"
ErrBanAction: "設定失敗,目前 {{ .name }} 服務不可用,請檢查後重試!"
ErrClamdscanNotFound: "未偵測到 clamdscan 指令,請參考文件安裝!"
#waf
@@ -203,81 +205,91 @@ ErrIPExist: "IP 已存在"
#license
ErrLicense: "許可證格式錯誤,請檢查後重試!"
ErrLicenseCheck: "許可證校驗失敗,請檢查後重試!"
ErrLicenseSave: "許可證信息保存失敗,錯誤 {{ .err }}, 請重試!"
ErrLicenseSync: "許可證信息同步失敗,資料庫中未檢測到許可證信息!"
ErrXpackNotFound: "該部分為專業版功能,請先在 面板設置-許可證 界面導入許可證"
ErrXpackNotActive: "該部分為專業版功能,請先在 面板設置-許可證 界面同步許可證狀態"
ErrXpackOutOfDate: "當前許可證已過期,請重新在 面板設置-許可證 界面導入許可證"
ErrXpackLost: "許可證已達到最大重試次數,請進入【面板設定】【許可證】頁面手動點擊同步按鈕,以確保專業版功能正常使用"
ErrXpackTimeout: "請求超時,網絡連接可能不穩定,請稍後再試!"
ErrXpackVersion: "許可證校驗失敗,該許可證受版本限制,無法成功匯入,請檢查後重試!"
ErrLicenseSave: "許可證資訊儲存失敗,錯誤 {{ .err }}, 請重試!"
ErrLicenseSync: "許可證資訊同步失敗,資料庫中未檢測到許可證資訊!"
ErrXpackNotFound: "該部分為專業版功能,請先在 面板設定-許可證 介面匯入許可證"
ErrXpackNotActive: "該部分為專業版功能,請先在 面板設定-許可證 介面同步許可證狀態"
ErrXpackOutOfDate: "目前許可證已過期,請重新在 面板設定-許可證 介面匯入許可證"
ErrXpackLost: "許可證已達到最大重試次數,請進入【面板設定】【許可證】頁面手動點選同步按鈕,以確保專業版功能正常使用"
ErrXpackTimeout: "請求超時,網路連線可能不穩定,請稍後再試!"
#license
ErrAlert: "告警資訊格式錯誤,請檢查後重試!"
ErrAlertPush: "告警資訊推送錯誤,請檢查後重試!"
ErrAlertSave: "告警資訊保存錯誤,請檢查後重試!"
ErrAlertSave: "告警資訊儲存錯誤,請檢查後重試!"
ErrAlertSync: "告警資訊同步錯誤,請檢查後重試!"
ErrAlertRemote: "告警資訊遠端錯誤,請檢查後重試!"
#cmd
AppVersion: "應用版本"
AppCommands: "應用相關命令"
AppCommands: "應用相關指令"
AppInit: "初始化應用"
AppKeyVal: "應用的 key(僅支持英文)"
AppCreateFileErr: "文件 {{ .name }} 創建失敗 {{ .err }}"
AppCreateDirErr: "資料夾 {{ .name }} 創建失敗 {{ .err }}"
AppKeyVal: "應用的 key(僅支援英文)"
AppCreateFileErr: "檔案 {{ .name }} 建立失敗 {{ .err }}"
AppCreateDirErr: "資料夾 {{ .name }} 建立失敗 {{ .err }}"
AppMissKey: "應用的 key 缺失,使用 -k 指定"
AppMissVersion: "應用版本缺失,使用 -v 指定"
AppVersionExist: "版本已存在!"
AppCreateSuccessful: "創建成功!"
AppWriteErr: "文件 {{ .name }} 寫入失敗 {{ .err }}"
AppCreateSuccessful: "建立成功!"
AppWriteErr: "檔案 {{ .name }} 寫入失敗 {{ .err }}"
SudoHelper: "請使用 {{ .cmd }} 或者切換到 root 用戶"
ListenIPCommands: "切換監聽 IP"
ListenIPv4: "監聽 IPv4"
ListenIPv6: "監聽 IPv6"
ListenChangeSuccessful: "切換成功!已切換至監聽 {{ .value }}"
ResetCommands: "重置系統信息"
ResetCommands: "重設系統資訊"
ResetMFA: "取消 1Panel 兩步驗證"
ResetHttps: "取消 1Panel https 方式登錄"
ResetHttps: "取消 1Panel https 方式登入"
ResetEntrance: "取消 1Panel 安全入口"
ResetIPs: "取消 1Panel 授權 IP 限制"
ResetDomain: "取消 1Panel 訪問域名綁定"
RestoreCommands: "回滾 1Panel 服務及數據"
RestoreNoSuchFile: "暫無可回滾文件"
RestoreStep1: "(1/5)開始從 {{ .name }} 目錄回滾 1Panel 服務及數據... "
RestoreStep2: "(2/5)1Panel 二進制回滾成功"
RestoreStep3: "(3/5)1Panel 腳本回滾成功"
RestoreStep4: "(4/5)1Panel 服務回滾成功"
RestoreStep5: "(5/5)1Panel 數據回滾成功"
RestoreSuccessful: "回滾成功!正在重啟服務,請稍候..."
UpdateCommands: "修改面板信息"
ResetDomain: "取消 1Panel 瀏覽域名綁定"
RestoreCommands: "轉返 1Panel 服務及資料"
RestoreNoSuchFile: "暫無可轉返文件"
RestoreStep1: "(1/5)開始從 {{ .name }} 目錄轉返 1Panel 服務及資料... "
RestoreStep2: "(2/5)1Panel 二進制轉返成功"
RestoreStep3: "(3/5)1Panel 腳本轉返成功"
RestoreStep4: "(4/5)1Panel 服務轉返成功"
RestoreStep5: "(5/5)1Panel 資料轉返成功"
RestoreSuccessful: "轉返成功!正在重啟服務,請稍候..."
UpdateCommands: "修改面板資訊"
UpdateUser: "修改面板用戶"
UpdatePassword: "修改面板密碼"
UpdatePort: "修改面板端口"
UpdateUserNull: "錯誤:輸入面板用戶為空!"
UpdateUserBlank: "錯誤:輸入面板用戶中包含空格字符!"
UpdateUserFormat: "錯誤:輸入面板用戶錯誤!僅支持英文、中文、數字和_,長度3-30"
UpdateUserErr: "錯誤:面板用戶修改失敗,{{ .err }}"
UpdatePort: "修改面板埠"
UpdateUserNull: "錯誤: 輸入面板用戶為空!"
UpdateUserBlank: "錯誤: 輸入面板用戶中包含空格字元!"
UpdateUserFormat: "錯誤: 輸入面板用戶錯誤!僅支援英文、中文、數字和_,長度3-30"
UpdateUserErr: "錯誤: 面板用戶修改失敗,{{ .err }}"
UpdateSuccessful: "修改成功!"
UpdateUserResult: "面板用戶:{{ .name }}"
UpdatePasswordRead: "錯誤:面板密碼信息讀取錯誤,{{ .err }}"
UpdatePasswordNull: "錯誤:輸入面板密碼為空!"
UpdateUPasswordBlank: "錯誤:輸入面板密碼中包含空格字符!"
UpdatePasswordFormat: "錯誤:面板密碼僅支持字母、數字、特殊字符(!@#$%*_,.?),長度 8-30 位!"
UpdatePasswordLen: "錯誤:請輸入 6 位以上密碼!"
UpdatePasswordRe: "確認密碼:"
UpdatePasswordErr: "錯誤:面板密碼修改失敗,{{ .err }}"
UpdatePasswordSame: "錯誤:兩次密碼不匹配,請檢查後重試!"
UpdatePasswordResult: "面板密碼:{{ .name }}"
UpdatePortFormat: "錯誤:輸入的端口號必須在 1 到 65535 之間!"
UpdatePortUsed: "錯誤:該端口號正被佔用,請檢查後重試!"
UpdatePortErr: "錯誤:面板端口修改失敗,{{ .err }}"
UpdatePortResult: "面板端口:{{ .name }}"
UpdatePortFirewallAdd: "添加防火牆端口規則失敗,{{ .err }},請您手動將 {{ .name }} 端口添加至防火牆規則中。"
UpdatePortFirewallDel: "錯誤:防火牆端口刪除失敗,{{ .err }}"
UpdateUserResult: "面板用戶: {{ .name }}"
UpdatePasswordRead: "錯誤: 面板密碼資訊讀取錯誤,{{ .err }}"
UpdatePasswordNull: "錯誤: 輸入面板密碼為空!"
UpdateUPasswordBlank: "錯誤: 輸入面板密碼中包含空格字元!"
UpdatePasswordFormat: "錯誤: 面板密碼僅支援字母、數字、特殊字元(!@#$%*_,.?),長度 8-30 位!"
UpdatePasswordLen: "錯誤: 請輸入 6 位以上密碼!"
UpdatePasswordRe: "確認密碼: "
UpdatePasswordErr: "錯誤: 面板密碼修改失敗,{{ .err }}"
UpdatePasswordSame: "錯誤: 兩次密碼不匹配,請檢查後重試!"
UpdatePasswordResult: "面板密碼: {{ .name }}"
UpdatePortFormat: "錯誤: 輸入的埠號必須在 1 到 65535 之間!"
UpdatePortUsed: "錯誤: 該埠號正被佔用,請檢查後重試!"
UpdatePortErr: "錯誤: 面板埠修改失敗,{{ .err }}"
UpdatePortResult: "面板埠: {{ .name }}"
UpdatePortFirewallAdd: "新增防火牆埠規則失敗,{{ .err }},請您手動將 {{ .name }} 埠新增至防火牆規則中。"
UpdatePortFirewallDel: "錯誤: 防火牆埠刪除失敗,{{ .err }}"
UpdatePortFirewallReload: "防火牆重載失敗,{{ .err }},請您手動重載防火牆。"
UserInfo: "獲取面板信息"
UserInfoAddr: "面板地址:"
UserInfoPassHelp: "提示:修改密碼可執行命令:"
DBConnErr: "錯誤:初始化資料庫連接失敗,{{ .err }}"
SystemVersion: "版本:"
SystemMode: "模式:"
UserInfo: "取得面板資訊"
UserInfoAddr: "面板地址: "
UserInfoPassHelp: "提示: 修改密碼可執行指令: "
DBConnErr: "錯誤: 初始化資料庫連線失敗,{{ .err }}"
SystemVersion: "版本: "
SystemMode: "模式: "
#ai-tool
ErrOpenrestyInstall: "請先安裝 Openresty"
ErrSSL: "證書內容為空,請檢查證書!"
#mobile app
ErrVerifyToken: '令牌驗證錯誤,請重置後再次掃碼'
ErrInvalidToken: '無效的令牌,請重置後再次掃碼'
ErrExpiredToken: '令牌過期,請重置後再次掃碼'
+56 -44
View File
@@ -12,6 +12,7 @@ ErrApiConfigStatusInvalid: "API 接口禁止访问: {{ .detail }}"
ErrApiConfigKeyInvalid: "API 接口密钥错误: {{ .detail }}"
ErrApiConfigIPInvalid: "调用 API 接口 IP 不在白名单: {{ .detail }}"
ErrApiConfigDisable: "此接口禁止使用 API 接口调用: {{ .detail }}"
ErrApiConfigKeyTimeInvalid: "API 接口时间戳错误: {{ .detail }}"
#common
ErrNameIsExist: "名称已存在"
@@ -41,24 +42,24 @@ Err1PanelNetworkFailed: '默认容器网络创建失败!{{ .detail }}'
ErrFileParse: '应用 docker-compose 文件解析失败!'
ErrInstallDirNotFound: '安装目录不存在'
AppStoreIsUpToDate: '应用商店已经是最新版本'
LocalAppVersionNull: '{{.name}} 应用未同步到版本!无法添加到应用列表'
LocalAppVersionErr: '{{.name}} 同步版本 {{.version}} 失败!{{.err}}'
ErrFileNotFound: '{{.name}} 文件不存在'
ErrFileParseApp: '{{.name}} 文件解析失败 {{.err}}'
LocalAppVersionNull: '{{ .name }} 应用未同步到版本!无法添加到应用列表'
LocalAppVersionErr: '{{ .name }} 同步版本 {{ .version }} 失败!{{ .err }}'
ErrFileNotFound: '{{ .name }} 文件不存在'
ErrFileParseApp: '{{ .name }} 文件解析失败 {{ .err }}'
ErrAppDirNull: '版本文件夹不存在'
LocalAppErr: "应用 {{.name}} 同步失败!{{.err}}"
LocalAppErr: "应用 {{ .name }} 同步失败!{{ .err }}"
ErrContainerName: "容器名称已存在"
ErrAppSystemRestart: "1Panel 重启导致任务终止"
ErrCreateHttpClient: "创建HTTP请求失败 {{.err}}"
ErrHttpReqTimeOut: "请求超时 {{.err}}"
ErrHttpReqFailed: "请求失败 {{.err}}"
ErrCreateHttpClient: "创建HTTP请求失败 {{ .err }}"
ErrHttpReqTimeOut: "请求超时 {{ .err }}"
ErrHttpReqFailed: "请求失败 {{ .err }}"
ErrHttpReqNotFound: "文件不存在"
ErrNoSuchHost: "网络连接失败"
ErrImagePullTimeOut: '镜像拉取超时'
ErrContainerNotFound: '{{ .name }} 容器不存在'
ErrContainerMsg: '{{ .name }} 容器异常,具体请在容器页面查看日志'
ErrAppBackup: '{{ .name }} 应用备份失败 err {{.err}}'
ErrImagePull: '镜像拉取失败 {{.err}}'
ErrAppBackup: '{{ .name }} 应用备份失败 err {{ .err }}'
ErrImagePull: '镜像拉取失败 {{ .err }}'
ErrVersionTooLow: '当前 1Panel 版本过低,无法更新应用商店,请升级版本之后操作'
ErrAppNameExist: '应用名称已存在'
AppStoreIsSyncing: '应用商店正在同步中,请稍后再试'
@@ -74,12 +75,12 @@ UpgradeAppSuccess: "应用 {{ .name }} 升级成功"
#file
ErrFileCanNotRead: "此文件不支持预览"
ErrFileToLarge: "文件超过10M,无法打开"
ErrFileToLarge: "文件超过10M,无法打开"
ErrPathNotFound: "目录不存在"
ErrMovePathFailed: "目标路径不能包含原路径!"
ErrLinkPathNotFound: "目标路径不存在!"
ErrFileIsExist: "文件或文件夹已存在!"
ErrFileUpload: "{{ .name }} 上传文件失败 {{ .detail}}"
ErrFileUpload: "{{ .name }} 上传文件失败 {{ .detail }}"
ErrFileDownloadDir: "不支持下载文件夹"
ErrCmdNotFound: "{{ .name}} 命令不存在,请先在宿主机安装此命令"
ErrSourcePathNotFound: "源目录不存在"
@@ -90,16 +91,16 @@ ErrPathNotDelete: "所选目录不可删除"
#website
ErrDomainIsExist: "域名已存在"
ErrAliasIsExist: "代号已存在"
ErrAppDelete: '其他网站使用此应用,无法删除'
ErrAppDelete: '其他网站使用此应用,无法删除'
ErrGroupIsUsed: '分组正在使用中,无法删除'
ErrBackupMatch: '该备份文件与当前网站部分数据不匹配 {{ .detail}}'
ErrBackupExist: '该备份文件对应部分源数据不存在 {{ .detail}}'
ErrBackupMatch: '该备份文件与当前网站部分数据不匹配 {{ .detail }}'
ErrBackupExist: '该备份文件对应部分源数据不存在 {{ .detail }}'
ErrPHPResource: '本地运行环境不支持切换!'
ErrPathPermission: 'index 目录下检测到非 1000:1000 权限文件夹,可能导致网站访问 Access denied 错误,请点击上方保存按钮'
ErrDomainIsUsed: "域名已被网站【{{ .name }}】使用"
ErrDomainFormat: "{{ .name }} 域名格式不正确"
ErrDefaultAlias: "default 为保留代号,请使用其他代号"
ErrImageNotExist: "运行环境 {{.name}} 镜像不存在,请重新编辑运行环境"
ErrImageNotExist: "运行环境 {{ .name }} 镜像不存在,请重新编辑运行环境"
#ssl
ErrSSLCannotDelete: "{{ .name }} 证书正在被网站使用,无法删除"
@@ -112,13 +113,13 @@ ErrSSLKeyFormat: '私钥文件校验失败'
ErrSSLCertificateFormat: '证书文件格式错误,请使用 pem 格式'
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 或 EabHmacKey 不能为空'
ErrOpenrestyNotFound: 'Http 模式需要首先安装 Openresty'
ApplySSLStart: '开始申请证书,域名 [{{ .domain }}] 申请方式 [{{ .type }}] '
ApplySSLStart: '开始申请证书,域名 [{{ .domain }}] 申请方式 [{{ .type }}] '
dnsAccount: "DNS 自动"
dnsManual: "DNS 手动"
http: "HTTP"
ApplySSLFailed: '申请 [{{ .domain }}] 证书失败, {{.detail}} '
ApplySSLFailed: '申请 [{{ .domain }}] 证书失败, {{ .detail }} '
ApplySSLSuccess: '申请 [{{ .domain }}] 证书成功!!'
DNSAccountName: 'DNS 账号 [{{ .name }}] 厂商 [{{.type}}]'
DNSAccountName: 'DNS 账号 [{{ .name }}] 厂商 [{{ .type }}]'
PushDirLog: '证书推送到目录 [{{ .path }}] {{ .status }}'
ErrDeleteCAWithSSL: "当前机构下存在已签发证书,无法删除"
ErrDeleteWithPanelSSL: "面板 SSL 配置使用此证书,无法删除"
@@ -145,6 +146,7 @@ ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后
#container
ErrInUsed: "{{ .detail }} 正被使用,无法删除"
ErrObjectInUsed: "该对象正被使用,无法删除"
ErrObjectBeDependent: "该镜像依赖于其他镜像,无法删除"
ErrPortRules: "端口数目不匹配,请重新输入!"
ErrPgImagePull: "镜像拉取超时,请配置镜像加速或手动拉取 postgres:16.0-alpine 镜像后重试"
@@ -162,7 +164,7 @@ ErrNodeModulesNotFound: "node_modules 文件夹不存在!请编辑运行环境
#setting
ErrBackupInUsed: "该备份账号已在计划任务中使用,无法删除"
ErrBackupCheck: "备份账号测试连接失败 {{ .err}}"
ErrBackupCheck: "备份账号测试连接失败 {{ .err }}"
ErrOSSConn: "无法获取最新版本,请确认服务器是否能够连接外部网络。"
ErrEntrance: "安全入口信息错误,请检查后重试!"
@@ -203,6 +205,7 @@ ErrIPExist: "IP 已存在"
#license
ErrLicense: "许可证格式错误,请检查后重试!"
ErrLicenseCheck: "许可证校验失败,请检查后重试!"
ErrXpackVersion: "许可证校验失败,该许可证受版本限制,无法成功导入,请检查后重试!"
ErrLicenseSave: "许可证信息保存失败,错误 {{ .err }},请重试!"
ErrLicenseSync: "许可证信息同步失败,数据库中未检测到许可证信息!"
ErrXpackNotFound: "该部分为专业版功能,请先在 面板设置-许可证 界面导入许可证"
@@ -253,31 +256,40 @@ UpdateCommands: "修改面板信息"
UpdateUser: "修改面板用户"
UpdatePassword: "修改面板密码"
UpdatePort: "修改面板端口"
UpdateUserNull: "错误:输入面板用户为空!"
UpdateUserBlank: "错误:输入面板用户中包含空格字符!"
UpdateUserFormat: "错误:输入面板用户错误!仅支持英文、中文、数字和_,长度3-30"
UpdateUserErr: "错误:面板用户修改失败,{{ .err }}"
UpdateUserNull: "错误: 输入面板用户为空!"
UpdateUserBlank: "错误: 输入面板用户中包含空格字符!"
UpdateUserFormat: "错误: 输入面板用户错误!仅支持英文、中文、数字和_,长度3-30"
UpdateUserErr: "错误: 面板用户修改失败,{{ .err }}"
UpdateSuccessful: "修改成功!"
UpdateUserResult: "面板用户:{{ .name }}"
UpdatePasswordRead: "错误:面板密码信息读取错误,{{ .err }}"
UpdatePasswordNull: "错误:输入面板密码为空!"
UpdateUPasswordBlank: "错误:输入面板密码中包含空格字符!"
UpdatePasswordFormat: "错误:面板密码仅支持字母、数字、特殊字符(!@#$%*_,.?),长度 8-30 位!"
UpdatePasswordLen: "错误:请输入 6 位以上密码!"
UpdatePasswordRe: "确认密码:"
UpdatePasswordErr: "错误:面板密码修改失败,{{ .err }}"
UpdatePasswordSame: "错误:两次密码不匹配,请检查后重试!"
UpdatePasswordResult: "面板密码:{{ .name }}"
UpdatePortFormat: "错误:输入的端口号必须在 1 到 65535 之间!"
UpdatePortUsed: "错误:该端口号正被占用,请检查后重试!"
UpdatePortErr: "错误:面板端口修改失败,{{ .err }}"
UpdatePortResult: "面板端口:{{ .name }}"
UpdateUserResult: "面板用户: {{ .name }}"
UpdatePasswordRead: "错误: 面板密码信息读取错误,{{ .err }}"
UpdatePasswordNull: "错误: 输入面板密码为空!"
UpdateUPasswordBlank: "错误: 输入面板密码中包含空格字符!"
UpdatePasswordFormat: "错误: 面板密码仅支持字母、数字、特殊字符(!@#$%*_,.?),长度 8-30 位!"
UpdatePasswordLen: "错误: 请输入 6 位以上密码!"
UpdatePasswordRe: "确认密码: "
UpdatePasswordErr: "错误: 面板密码修改失败,{{ .err }}"
UpdatePasswordSame: "错误: 两次密码不匹配,请检查后重试!"
UpdatePasswordResult: "面板密码: {{ .name }}"
UpdatePortFormat: "错误: 输入的端口号必须在 1 到 65535 之间!"
UpdatePortUsed: "错误: 该端口号正被占用,请检查后重试!"
UpdatePortErr: "错误: 面板端口修改失败,{{ .err }}"
UpdatePortResult: "面板端口: {{ .name }}"
UpdatePortFirewallAdd: "添加防火墙端口规则失败,{{ .err }},请您手动将 {{ .name }} 端口添加至防火墙规则中。"
UpdatePortFirewallDel: "错误:防火墙端口删除失败,{{ .err }}"
UpdatePortFirewallDel: "错误: 防火墙端口删除失败,{{ .err }}"
UpdatePortFirewallReload: "防火墙重载失败,{{ .err }},请您手动重载防火墙。"
UserInfo: "获取面板信息"
UserInfoAddr: "面板地址:"
UserInfoPassHelp: "提示:修改密码可执行命令:"
DBConnErr: "错误:初始化数据库连接失败,{{ .err }}"
SystemVersion: "版本:"
SystemMode: "模式:"
UserInfoAddr: "面板地址: "
UserInfoPassHelp: "提示: 修改密码可执行命令: "
DBConnErr: "错误: 初始化数据库连接失败,{{ .err }}"
SystemVersion: "版本: "
SystemMode: "模式: "
#ai-tool
ErrOpenrestyInstall: '请先安装 Openresty'
ErrSSL: "证书内容为空,请检查证书!"
#mobile app
ErrVerifyToken: '令牌验证错误,请重置后再次扫码'
ErrInvalidToken: '无效的令牌,请重置后再次扫码'
ErrExpiredToken: '令牌过期,请重置后再次扫码'
+3 -1
View File
@@ -35,7 +35,9 @@ func Init() {
_ = docker.CreateDefaultDockerNetwork()
if f, err := firewall.NewFirewallClient(); err == nil {
_ = f.EnableForward()
if err = f.EnableForward(); err != nil {
global.LOG.Errorf("init port forward failed, err: %v", err)
}
}
}()
}
+7
View File
@@ -11,6 +11,7 @@ func Init() {
go syncInstalledApp()
go syncRuntime()
go syncSSL()
generateKey()
}
func syncApp() {
@@ -38,3 +39,9 @@ func syncSSL() {
global.LOG.Errorf("sync ssl status error : %s", err.Error())
}
}
func generateKey() {
if err := service.NewISettingService().GenerateRSAKey(); err != nil {
global.LOG.Errorf("generate rsa key error : %s", err.Error())
}
}
+11
View File
@@ -77,11 +77,17 @@ func Init() {
global.LOG.Errorf("load service ip white list from setting failed, err: %v", err)
}
global.CONF.System.IpWhiteList = ipWhiteListSetting.Value
apiKeyValidityTimeSetting, err := settingRepo.Get(settingRepo.WithByKey("ApiKeyValidityTime"))
if err != nil {
global.LOG.Errorf("load service api key validity time from setting failed, err: %v", err)
}
global.CONF.System.ApiKeyValidityTime = apiKeyValidityTimeSetting.Value
}
handleUserInfo(global.CONF.System.ChangeUserInfo, settingRepo)
handleCronjobStatus()
handleOllamaModelStatus()
handleSnapStatus()
loadLocalDir()
initDir()
@@ -145,6 +151,11 @@ func handleSnapStatus() {
}
}
func handleOllamaModelStatus() {
message := "the task was interrupted due to the restart of the 1panel service"
_ = global.DB.Model(&model.OllamaModel{}).Where("status = ?", constant.StatusWaiting).Updates(map[string]interface{}{"status": constant.StatusCanceled, "message": message}).Error
}
func handleCronjobStatus() {
var jobRecords []model.JobRecords
_ = global.DB.Where("status = ?", constant.StatusWaiting).Find(&jobRecords).Error
+7
View File
@@ -98,6 +98,13 @@ func Init() {
migrations.AddAutoRestart,
migrations.AddApiInterfaceConfig,
migrations.AddApiKeyValidityTime,
migrations.UpdateAppTag,
migrations.UpdateApp,
migrations.AddOllamaModel,
migrations.AddAppMenu,
migrations.AddAppPanelName,
})
if err := m.Migrate(); err != nil {
global.LOG.Error(err)
@@ -350,3 +350,101 @@ var AddApiInterfaceConfig = &gormigrate.Migration{
return nil
},
}
var AddApiKeyValidityTime = &gormigrate.Migration{
ID: "20241226-add-api-key-validity-time",
Migrate: func(tx *gorm.DB) error {
if err := tx.Create(&model.Setting{Key: "ApiKeyValidityTime", Value: "120"}).Error; err != nil {
return err
}
return nil
},
}
var UpdateAppTag = &gormigrate.Migration{
ID: "20250114-update-app-tag",
Migrate: func(tx *gorm.DB) error {
if err := tx.AutoMigrate(&model.Tag{}); err != nil {
return err
}
return nil
},
}
var UpdateApp = &gormigrate.Migration{
ID: "20250213-update-app",
Migrate: func(tx *gorm.DB) error {
if err := tx.AutoMigrate(&model.App{}); err != nil {
return err
}
return nil
},
}
var AddOllamaModel = &gormigrate.Migration{
ID: "20250218-add-ollama-model",
Migrate: func(tx *gorm.DB) error {
if err := tx.AutoMigrate(&model.OllamaModel{}); err != nil {
return err
}
return nil
},
}
var AddAppMenu = &gormigrate.Migration{
ID: "20250217-update-xpack-hide-menu",
Migrate: func(tx *gorm.DB) error {
var (
setting model.Setting
menu dto.XpackHideMenu
)
tx.Model(&model.Setting{}).Where("key = ?", "XpackHideMenu").First(&setting)
if err := json.Unmarshal([]byte(setting.Value), &menu); err != nil {
return err
}
var newChildren []dto.XpackHideMenu
for _, item := range menu.Children {
if item.ID != "4" {
newChildren = append(newChildren, item)
}
}
menu.Children = newChildren
appIsCheck := false
for _, item := range menu.Children {
if item.IsCheck {
appIsCheck = true
break
}
}
menu.Children = append(menu.Children, dto.XpackHideMenu{
ID: "8",
Title: "xpack.app.app",
Path: "/xpack/app",
Label: "XApp",
IsCheck: appIsCheck,
})
data, err := json.Marshal(menu)
if err != nil {
return err
}
return tx.Model(&model.Setting{}).Where("key = ?", "XpackHideMenu").Updates(map[string]interface{}{"value": string(data)}).Error
},
}
var AddAppPanelName = &gormigrate.Migration{
ID: "20250218-add-app-panel-name",
Migrate: func(tx *gorm.DB) error {
if err := tx.Create(&model.Setting{Key: "AppPanelName", Value: ""}).Error; err != nil {
return err
}
return nil
},
}

Some files were not shown because too many files have changed in this diff Show More