Compare commits

...

46 Commits

Author SHA1 Message Date
semantic-release-bot 7f3cac3c1c 🔖 chore(release): v1.1.5 [skip ci]
## [1.1.5](https://github.com/perfect-panel/ppanel-web/compare/v1.1.4...v1.1.5) (2025-07-26)

### 🐛 Bug Fixes

* **subscribe**: Filter out items that are not marked as visible in subscription list ([32253e3](https://github.com/perfect-panel/ppanel-web/commit/32253e3))
2025-07-26 10:55:38 +00:00
web 32253e3717 🐛 fix(subscribe): Filter out items that are not marked as visible in subscription list 2025-07-26 03:49:53 -07:00
semantic-release-bot a76471a806 🔖 chore(release): v1.1.4 [skip ci]
## [1.1.4](https://github.com/perfect-panel/ppanel-web/compare/v1.1.3...v1.1.4) (2025-07-25)

### 🐛 Bug Fixes

* **locales**: Simplify "show" label in subscription localization files ([d53a006](https://github.com/perfect-panel/ppanel-web/commit/d53a006))
* **order**: Preserve last successful order on error during order creation ([2fb98be](https://github.com/perfect-panel/ppanel-web/commit/2fb98be))
* **subscribe**: Filter out hidden items in subscription list display ([634be37](https://github.com/perfect-panel/ppanel-web/commit/634be37))
2025-07-25 14:22:31 +00:00
web d53a00611e 🐛 fix(locales): Simplify "show" label in subscription localization files 2025-07-25 07:18:54 -07:00
web 2fb98be591 🐛 fix(order): Preserve last successful order on error during order creation 2025-07-25 07:07:31 -07:00
web 634be371b1 🐛 fix(subscribe): Filter out hidden items in subscription list display 2025-07-25 07:06:53 -07:00
semantic-release-bot ffa5c86d23 🔖 chore(release): v1.1.3 [skip ci]
## [1.1.3](https://github.com/perfect-panel/ppanel-web/compare/v1.1.2...v1.1.3) (2025-07-24)

### 🐛 Bug Fixes

* **auth**: Implement user redirection to dashboard upon authentication ([f84f98c](https://github.com/perfect-panel/ppanel-web/commit/f84f98c))
2025-07-24 17:13:32 +00:00
web f84f98c80f 🐛 fix(auth): Implement user redirection to dashboard upon authentication 2025-07-24 10:10:31 -07:00
semantic-release-bot e8ea597664 🔖 chore(release): v1.1.2 [skip ci]
## [1.1.2](https://github.com/perfect-panel/ppanel-web/compare/v1.1.1...v1.1.2) (2025-07-24)

### 🐛 Bug Fixes

* **billing**: Add display for gift amount in subscription billing ([04af2f9](https://github.com/perfect-panel/ppanel-web/commit/04af2f9))
* **order**: Update subscription cell to display name and quantity ([96eba17](https://github.com/perfect-panel/ppanel-web/commit/96eba17))
* **tool**: Added API for obtaining version, updated version information display logic ([2675034](https://github.com/perfect-panel/ppanel-web/commit/2675034))
2025-07-24 13:00:38 +00:00
web 04af2f9433 🐛 fix(billing): Add display for gift amount in subscription billing 2025-07-24 05:55:56 -07:00
web 96eba171d5 🐛 fix(order): Update subscription cell to display name and quantity 2025-07-24 05:34:57 -07:00
web 2675034b75 🐛 fix(tool): Added API for obtaining version, updated version information display logic 2025-07-24 05:15:38 -07:00
semantic-release-bot 8f772c2364 🔖 chore(release): v1.1.1 [skip ci]
## [1.1.1](https://github.com/perfect-panel/ppanel-web/compare/v1.1.0...v1.1.1) (2025-07-20)

### 🐛 Bug Fixes

* **node-table**: Update translations for headers and no data display ([eec0b12](https://github.com/perfect-panel/ppanel-web/commit/eec0b12))
* **rules**: Change rule type from 'auto' to 'default' and update ([3e290d7](https://github.com/perfect-panel/ppanel-web/commit/3e290d7))
* **rules**: Update rule settings ([3304a55](https://github.com/perfect-panel/ppanel-web/commit/3304a55))
* **subscribe-form**: Optimize discount calculation logic and debounce updates ([166e48f](https://github.com/perfect-panel/ppanel-web/commit/166e48f))
* **tutorial**: Comment out unused getVersion function and simplify getVersionPath ([7cdc6bd](https://github.com/perfect-panel/ppanel-web/commit/7cdc6bd))
* **tutorial**: Return latest version in case of fetch error ([1fb305e](https://github.com/perfect-panel/ppanel-web/commit/1fb305e))
2025-07-20 10:24:58 +00:00
web 166e48f442 🐛 fix(subscribe-form): Optimize discount calculation logic and debounce updates 2025-07-20 03:20:59 -07:00
web eec0b12154 🐛 fix(node-table): Update translations for headers and no data display 2025-07-20 03:00:59 -07:00
web 3e290d7cb5 🐛 fix(rules): Change rule type from 'auto' to 'default' and update 2025-07-17 03:30:12 -07:00
web 3304a55fd4 🐛 fix(rules): Update rule settings 2025-07-16 09:16:33 -07:00
web 7cdc6bdd8f 🐛 fix(tutorial): Comment out unused getVersion function and simplify getVersionPath 2025-07-11 02:58:37 -07:00
web 1fb305e7a1 🐛 fix(tutorial): Return latest version in case of fetch error 2025-07-11 01:56:42 -07:00
semantic-release-bot 7f81de31ab 🔖 chore(release): v1.1.0 [skip ci]
# [1.1.0](https://github.com/perfect-panel/ppanel-web/compare/v1.0.2...v1.1.0) (2025-07-06)

###  Features

* **view**: Add AnyTLS protocol support and enhance node configuration options ([bcfb10a](https://github.com/perfect-panel/ppanel-web/commit/bcfb10a))
2025-07-06 11:59:27 +00:00
web bcfb10a6c7 feat(view): Add AnyTLS protocol support and enhance node configuration options 2025-07-06 04:56:00 -07:00
semantic-release-bot 9235fef3c6 🔖 chore(release): v1.0.2 [skip ci]
## [1.0.2](https://github.com/perfect-panel/ppanel-web/compare/v1.0.1...v1.0.2) (2025-06-29)

### 🐛 Bug Fixes

* **subscription**: User subscription information ([7d18ff6](https://github.com/perfect-panel/ppanel-web/commit/7d18ff6))
2025-06-29 09:19:10 +00:00
web@ppanel ee0c3371f7 Merge branch 'main' into develop 2025-06-29 08:39:58 +00:00
web@ppanel 7d18ff6825 🐛 fix(subscription): User subscription information 2025-06-29 08:33:43 +00:00
semantic-release-bot c86d28f798 🔖 chore(release): v1.0.1 [skip ci]
## [1.0.1](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0...v1.0.1) (2025-04-28)

### 🐛 Bug Fixes

* **payment**: Disable webhook_secret field in PaymentForm component ([d323af8](https://github.com/perfect-panel/ppanel-web/commit/d323af8))
* **recharge**: Set balance prop to false in PaymentMethods component ([356ae5b](https://github.com/perfect-panel/ppanel-web/commit/356ae5b))
2025-04-28 11:54:50 +00:00
web@ppanel d323af8bb6 🐛 fix(payment): Disable webhook_secret field in PaymentForm component 2025-04-28 11:51:41 +00:00
web@ppanel 356ae5b777 🐛 fix(recharge): Set balance prop to false in PaymentMethods component 2025-04-28 11:30:06 +00:00
semantic-release-bot 50bdd2cd21 🔖 chore(release): v1.0.0 [skip ci]
# 1.0.0 (2025-04-24)

### ♻ Code Refactoring

* **api**: Sort and Announcement ([38d5616](https://github.com/perfect-panel/ppanel-web/commit/38d5616))
* **auth**: Refactor user authorization handling and improve error logging ([68bc18f](https://github.com/perfect-panel/ppanel-web/commit/68bc18f))
* **config**: GenerateMetadata ([a0bb101](https://github.com/perfect-panel/ppanel-web/commit/a0bb101))
* **config**: Simplify environment variable handling and improve build script ([cf54d0f](https://github.com/perfect-panel/ppanel-web/commit/cf54d0f))
* **config**: Viewport ([24b8601](https://github.com/perfect-panel/ppanel-web/commit/24b8601))
* **core**: Restructure project for better module separation ([9d0cb8b](https://github.com/perfect-panel/ppanel-web/commit/9d0cb8b))
* **deps**: Update ([19837a1](https://github.com/perfect-panel/ppanel-web/commit/19837a1))
* **empty**: Content ([aa4c667](https://github.com/perfect-panel/ppanel-web/commit/aa4c667))
* **payment**: Reconstruct the payment page ([7109472](https://github.com/perfect-panel/ppanel-web/commit/7109472))
* **sbscribe**: Rename and reorganize components for better structure and clarity ([5e5e4ed](https://github.com/perfect-panel/ppanel-web/commit/5e5e4ed))
* **ui**: Dependencies ([727d779](https://github.com/perfect-panel/ppanel-web/commit/727d779))
* **ui**: Layout ([9262d7d](https://github.com/perfect-panel/ppanel-web/commit/9262d7d))
* **ui**: Optimize document display ([2ca2992](https://github.com/perfect-panel/ppanel-web/commit/2ca2992))
* Enhance user navigation dropdown ui and styling ([d2732e6](https://github.com/perfect-panel/ppanel-web/commit/d2732e6))
* Reduce code complexity and improve readability ([e11f18c](https://github.com/perfect-panel/ppanel-web/commit/e11f18c))

###  Performance Improvements

* **subscribe**: Form discount price ([059a892](https://github.com/perfect-panel/ppanel-web/commit/059a892))

###  Features

* **accounts**: Update third-party account binding and unbinding ([1841552](https://github.com/perfect-panel/ppanel-web/commit/1841552))
* **ad**: Advertise ([b1105cd](https://github.com/perfect-panel/ppanel-web/commit/b1105cd))
* **admin**: Add application and rule management entries to localization files ([8b43e69](https://github.com/perfect-panel/ppanel-web/commit/8b43e69))
* **affiliate**: Add Affiliate component with commission display and invite link functionality ([4aea4e8](https://github.com/perfect-panel/ppanel-web/commit/4aea4e8))
* **affiliate**: Affiliate Detail ([a782c17](https://github.com/perfect-panel/ppanel-web/commit/a782c17))
* **affiliate**: Commission Rate ([5eec430](https://github.com/perfect-panel/ppanel-web/commit/5eec430))
* **affiliate**: Update affiliate component to display total commission and improve data fetching ([cc834ca](https://github.com/perfect-panel/ppanel-web/commit/cc834ca))
* **announcement**: Popup and pinned ([f3680a7](https://github.com/perfect-panel/ppanel-web/commit/f3680a7))
* **api**: Add an interface to obtain user subscription details, update related type definitions and localized text ([cf5c39c](https://github.com/perfect-panel/ppanel-web/commit/cf5c39c))
* **api**: Add CheckoutOrder request and response types, and update user purchase request parameters ([48a1b97](https://github.com/perfect-panel/ppanel-web/commit/48a1b97))
* **api**: Add CheckoutOrder request and response types, and update user purchase request parameters ([dddc21c](https://github.com/perfect-panel/ppanel-web/commit/dddc21c))
* **api**: Add new subscription properties and locale support for deduction ratios and reset cycles ([fec80f5](https://github.com/perfect-panel/ppanel-web/commit/fec80f5))
* **api**: Add Time Period Configuration ([837157c](https://github.com/perfect-panel/ppanel-web/commit/837157c))
* **api**: Telegram ([17ce96a](https://github.com/perfect-panel/ppanel-web/commit/17ce96a))
* **auth-control**: Adding phone number labels to mobile verification configurations in multiple languages ([046740f](https://github.com/perfect-panel/ppanel-web/commit/046740f))
* **auth-control**: Update general ([3883646](https://github.com/perfect-panel/ppanel-web/commit/3883646))
* **auth**: Add email and SMS code sending functionality with localization updates ([57eaa55](https://github.com/perfect-panel/ppanel-web/commit/57eaa55))
* **auth**: Add Oauth configuration for Telegram, Facebook, Google, Github, and Apple ([18ee600](https://github.com/perfect-panel/ppanel-web/commit/18ee600))
* **auth**: Add privacy policy link to the footer ([8e16ef1](https://github.com/perfect-panel/ppanel-web/commit/8e16ef1))
* **auth**: Add SMS and email configuration options to global store and update localization ([4acf7b1](https://github.com/perfect-panel/ppanel-web/commit/4acf7b1))
* **auth**: Add type parameter to SendCode and update related API typings ([4198871](https://github.com/perfect-panel/ppanel-web/commit/4198871))
* **auth**: Enhance user registration with invite handling and logo display ([207bc24](https://github.com/perfect-panel/ppanel-web/commit/207bc24))
* **auth**: Redirect user after OAuth login and add logos icon collection ([aa6dda8](https://github.com/perfect-panel/ppanel-web/commit/aa6dda8))
* **auth**: Refactor mobile authentication config to support whitelist functionality ([c761ec7](https://github.com/perfect-panel/ppanel-web/commit/c761ec7))
* **billing**: Update Billing ([078fc9d](https://github.com/perfect-panel/ppanel-web/commit/078fc9d))
* **cdn**: Add CDN URL configuration and update related references ([0c90733](https://github.com/perfect-panel/ppanel-web/commit/0c90733))
* **config**: Add application selection and encryption settings to configuration form ([88b3504](https://github.com/perfect-panel/ppanel-web/commit/88b3504))
* **config**: FormatBytes ([9251a09](https://github.com/perfect-panel/ppanel-web/commit/9251a09))
* **config**: Protocol type ([a3b45b4](https://github.com/perfect-panel/ppanel-web/commit/a3b45b4))
* **config**: Update encryption fields in configuration form and refactor OAuth callback parameters ([652e032](https://github.com/perfect-panel/ppanel-web/commit/652e032))
* **config**: Webhook Domain ([01e06c6](https://github.com/perfect-panel/ppanel-web/commit/01e06c6))
* **dashboard**: Optimization ([5b3f4b4](https://github.com/perfect-panel/ppanel-web/commit/5b3f4b4))
* **dashboard**: Statistics ([2926abc](https://github.com/perfect-panel/ppanel-web/commit/2926abc))
* **device**: Modify IMEI to device identifier support ([e3f9ef6](https://github.com/perfect-panel/ppanel-web/commit/e3f9ef6))
* **email**: Add traffic exhaustion template ([bb3bd7b](https://github.com/perfect-panel/ppanel-web/commit/bb3bd7b))
* **favicon**: Update SVG favicon design for admin and user interfaces ([1d91738](https://github.com/perfect-panel/ppanel-web/commit/1d91738))
* **formatting**: Update differenceInDays function to return whole days or two decimal places ([bf58f25](https://github.com/perfect-panel/ppanel-web/commit/bf58f25))
* **form**: Make version field optional and set default value; update site domain placeholder for clarity ([42ba9e8](https://github.com/perfect-panel/ppanel-web/commit/42ba9e8))
* **global**: Add custom data ([6dbebd1](https://github.com/perfect-panel/ppanel-web/commit/6dbebd1))
* **global**: Add SMS configuration options to global store ([39a9ce6](https://github.com/perfect-panel/ppanel-web/commit/39a9ce6))
* **header**: Update locales ([bfb6c27](https://github.com/perfect-panel/ppanel-web/commit/bfb6c27))
* **imei**: Add IMEI related internationalization support and menu items ([13c3337](https://github.com/perfect-panel/ppanel-web/commit/13c3337))
* **input**: Add minimum value constraint and enhance number handling in EnhancedInput ([ce31972](https://github.com/perfect-panel/ppanel-web/commit/ce31972))
* **input**: Add minimum value constraint and enhance number handling in EnhancedInput ([94822d9](https://github.com/perfect-panel/ppanel-web/commit/94822d9))
* **loading**: Add loading components and integrate them in Providers ([d5847fa](https://github.com/perfect-panel/ppanel-web/commit/d5847fa))
* **loading**: Replace loading animation with a simpler spinner and loading text ([f72df3a](https://github.com/perfect-panel/ppanel-web/commit/f72df3a))
* **loading**: Replace loading animation with a simpler spinner and loading text ([b8316bb](https://github.com/perfect-panel/ppanel-web/commit/b8316bb))
* **locale**: Add Persian ([93a0a88](https://github.com/perfect-panel/ppanel-web/commit/93a0a88))
* **locales**: Add area code and telephone fields to user forms in multiple languages ([9b8258c](https://github.com/perfect-panel/ppanel-web/commit/9b8258c))
* **locales**: Add description information of communication keys and encryption methods to enhance client configuration capabilities ([d1f5a9b](https://github.com/perfect-panel/ppanel-web/commit/d1f5a9b))
* **locales**: Add kick offline confirmation and success messages in multiple languages ([5db5343](https://github.com/perfect-panel/ppanel-web/commit/5db5343))
* **locales**: Add multiple languages ([b243ab9](https://github.com/perfect-panel/ppanel-web/commit/b243ab9))
* **locales**: Replace 'nodeGroupId' with 'groupId' in multiple language files for consistency ([a4e9d5d](https://github.com/perfect-panel/ppanel-web/commit/a4e9d5d))
* **locales**: Update 'deductBalance' to 'giftAmount' across multiple languages and fix newline in announcement.json ([70497af](https://github.com/perfect-panel/ppanel-web/commit/70497af))
* **locales**: Update 'sms' to 'mobile' in authentication methods across multiple languages ([fea2171](https://github.com/perfect-panel/ppanel-web/commit/fea2171))
* **log**: Add message log retrieval functionality and update related typings ([1c0ecae](https://github.com/perfect-panel/ppanel-web/commit/1c0ecae))
* **node-form**: Update number input fields to enforce step, min, and max values ([3f7b6d1](https://github.com/perfect-panel/ppanel-web/commit/3f7b6d1))
* **node-subscription**: Add copy functionality for columns ([3a81e37](https://github.com/perfect-panel/ppanel-web/commit/3a81e37))
* **node**: Add NodeStatus ([c712624](https://github.com/perfect-panel/ppanel-web/commit/c712624))
* **node**: Add protocol ([301b635](https://github.com/perfect-panel/ppanel-web/commit/301b635))
* **node**: Add serverKey ([25ce37e](https://github.com/perfect-panel/ppanel-web/commit/25ce37e))
* **node**: Add status ([c06372b](https://github.com/perfect-panel/ppanel-web/commit/c06372b))
* **node**: Add tags ([f408fdf](https://github.com/perfect-panel/ppanel-web/commit/f408fdf))
* **node**: Move the node configuration to the server module ([7f0f5ce](https://github.com/perfect-panel/ppanel-web/commit/7f0f5ce))
* **oauth**: Add certification component for handling OAuth login callbacks and improve user authentication flow ([5ed04c0](https://github.com/perfect-panel/ppanel-web/commit/5ed04c0))
* **oauth**: Implement OAuth token retrieval and refactor login callback handling ([40a6f7c](https://github.com/perfect-panel/ppanel-web/commit/40a6f7c))
* **oauth**: Refactor platform parameter handling and improve logout redirection logic ([8346c85](https://github.com/perfect-panel/ppanel-web/commit/8346c85))
* **oauth**: Update OAuth login handling to use callback parameter and improve URL parameter retrieval ([9227411](https://github.com/perfect-panel/ppanel-web/commit/9227411))
* **payment**: Add bank card payment ([7fa3a57](https://github.com/perfect-panel/ppanel-web/commit/7fa3a57))
* **payment**: Add isEdit prop to PaymentForm and disable fields when editing ([85f55de](https://github.com/perfect-panel/ppanel-web/commit/85f55de))
* **platform**: Update platform naming and add keywords and custom HTML fields ([6384237](https://github.com/perfect-panel/ppanel-web/commit/6384237))
* **privacy-policy**: Add privacy policy related text and links ([baa68f0](https://github.com/perfect-panel/ppanel-web/commit/baa68f0))
* **profile**:  Update localization strings and enhance third-party account binding ([2d1effb](https://github.com/perfect-panel/ppanel-web/commit/2d1effb))
* **relay**: Add relay mode configuration and update related schemas ([3cc9477](https://github.com/perfect-panel/ppanel-web/commit/3cc9477))
* **release**: Extend supported platforms for Docker images, closes [#9](https://github.com/perfect-panel/ppanel-web/issues/9) ([e3a31eb](https://github.com/perfect-panel/ppanel-web/commit/e3a31eb))
* **schema**: Add security field to hysteria2 and tuic schemas ([cd59d44](https://github.com/perfect-panel/ppanel-web/commit/cd59d44))
* **site**: Added localization support for custom HTML and keyword fields ([f9d7736](https://github.com/perfect-panel/ppanel-web/commit/f9d7736))
* **sms**: Update locales ([938363b](https://github.com/perfect-panel/ppanel-web/commit/938363b))
* **stats**: Replace dynamic stat fetching with environment constants for user, server, and location counts ([46ae166](https://github.com/perfect-panel/ppanel-web/commit/46ae166))
* **subscribe**: Add 'sold' column to SubscribeTable and update inventory terminology ([19619fd](https://github.com/perfect-panel/ppanel-web/commit/19619fd))
* **subscribe**: Add reset_time to API typings and update unsubscribe logic ([eeea165](https://github.com/perfect-panel/ppanel-web/commit/eeea165))
* **subscribe**: Add subscribe_discount type ([f99c604](https://github.com/perfect-panel/ppanel-web/commit/f99c604))
* **subscribe**: Add subscription credits ([5bc7905](https://github.com/perfect-panel/ppanel-web/commit/5bc7905))
* **subscribe**: Add unit time ([39d07ec](https://github.com/perfect-panel/ppanel-web/commit/39d07ec))
* **subscribe**: Add unsubscribe functionality with confirmation messages and localized strings ([b2a2f42](https://github.com/perfect-panel/ppanel-web/commit/b2a2f42))
* **subscribe**: Improve error handling in subscription forms and update component props ([d28a10b](https://github.com/perfect-panel/ppanel-web/commit/d28a10b))
* **subscribe**: Improve layout and styling in subscription components ([5766376](https://github.com/perfect-panel/ppanel-web/commit/5766376))
* **subscribe**: Move subscription configuration and application to subscription module ([f90d4d2](https://github.com/perfect-panel/ppanel-web/commit/f90d4d2))
* **subscribe**: Update SubscribeTable component to use API.SubscribeItem type and ensure proper type casting ([f26f1c2](https://github.com/perfect-panel/ppanel-web/commit/f26f1c2))
* **subscribe**: Update suffix from 'MB' to 'Mbps' and enhance speed limit display logic ([3547bb1](https://github.com/perfect-panel/ppanel-web/commit/3547bb1))
* **subscription**:  Improve layout and organization of subscription detail tabs ([e4630f8](https://github.com/perfect-panel/ppanel-web/commit/e4630f8))
* **subscription**: Add delete user subscription functionality ([1fc3a10](https://github.com/perfect-panel/ppanel-web/commit/1fc3a10))
* **subscription**: Add localized messages for existing subscriptions and deletion restrictions ([e8a72d5](https://github.com/perfect-panel/ppanel-web/commit/e8a72d5))
* **subscription**: Refactor subscription handling and update imports for better organization ([2215c7f](https://github.com/perfect-panel/ppanel-web/commit/2215c7f))
* **table**: Add sorting support for Node and subscription columns ([27924b0](https://github.com/perfect-panel/ppanel-web/commit/27924b0))
* **table**: Supports drag and drop sorting ([2f56ef5](https://github.com/perfect-panel/ppanel-web/commit/2f56ef5))
* **timeline**: Simplify timeline component layout and remove commented-out code ([fbad3b0](https://github.com/perfect-panel/ppanel-web/commit/fbad3b0))
* **tos**: Display data ([6024454](https://github.com/perfect-panel/ppanel-web/commit/6024454))
* **tutorial**: Add common tutorial list ([872252c](https://github.com/perfect-panel/ppanel-web/commit/872252c))
* **tutorial**: Fetch the latest tutorial version from GitHub API for dynamic URL generation ([28f8c78](https://github.com/perfect-panel/ppanel-web/commit/28f8c78))
* **ui**: System Tool ([1836980](https://github.com/perfect-panel/ppanel-web/commit/1836980))
* **ui**: Update homepage data ([8425b13](https://github.com/perfect-panel/ppanel-web/commit/8425b13))
* **ui**: Update input components and enhance card minimum width for better layout ([8a02310](https://github.com/perfect-panel/ppanel-web/commit/8a02310))
* **user**: Add 'gift_amount' field and update related references in user services and components ([b13c77e](https://github.com/perfect-panel/ppanel-web/commit/b13c77e))
* **user**: Add telephone input with area code selection and update localization ([585b99c](https://github.com/perfect-panel/ppanel-web/commit/585b99c))
* **user**: Add user Detail ([3a3d223](https://github.com/perfect-panel/ppanel-web/commit/3a3d223))
* **user**: Add User Detail ([fdaf11b](https://github.com/perfect-panel/ppanel-web/commit/fdaf11b))
* **user**: Integrate subscription list into user management, update request parameters and types ([8d49dac](https://github.com/perfect-panel/ppanel-web/commit/8d49dac))
* Update Auth Control ([c59742a](https://github.com/perfect-panel/ppanel-web/commit/c59742a))

### 🎫 Chores

* **config**: Entry locale ([5737331](https://github.com/perfect-panel/ppanel-web/commit/5737331))
* **deps**: Update package dependencies across multiple projects for improved stability and performance ([b01a5bc](https://github.com/perfect-panel/ppanel-web/commit/b01a5bc))
* **init**: Project initialization ([829edfa](https://github.com/perfect-panel/ppanel-web/commit/829edfa))
* **merge**: Add advertising module and device settings ([0130e02](https://github.com/perfect-panel/ppanel-web/commit/0130e02))
* **merge**: Bump version to 1.0.0-beta.26 and update changelog ([3222016](https://github.com/perfect-panel/ppanel-web/commit/3222016))
* **release**: V1.0.0-beta.1 [skip ci] ([7284d1c](https://github.com/perfect-panel/ppanel-web/commit/7284d1c))
* **release**: V1.0.0-beta.10 [skip ci] ([5cf573a](https://github.com/perfect-panel/ppanel-web/commit/5cf573a))
* **release**: V1.0.0-beta.11 [skip ci] ([1f29506](https://github.com/perfect-panel/ppanel-web/commit/1f29506))
* **release**: V1.0.0-beta.12 [skip ci] ([4418c47](https://github.com/perfect-panel/ppanel-web/commit/4418c47))
* **release**: V1.0.0-beta.13 [skip ci] ([23c974a](https://github.com/perfect-panel/ppanel-web/commit/23c974a))
* **release**: V1.0.0-beta.14 [skip ci] ([0fb0d8b](https://github.com/perfect-panel/ppanel-web/commit/0fb0d8b))
* **release**: V1.0.0-beta.15 [skip ci] ([b2e8fad](https://github.com/perfect-panel/ppanel-web/commit/b2e8fad))
* **release**: V1.0.0-beta.16 [skip ci] ([c3eff0a](https://github.com/perfect-panel/ppanel-web/commit/c3eff0a))
* **release**: V1.0.0-beta.17 [skip ci] ([5b64389](https://github.com/perfect-panel/ppanel-web/commit/5b64389))
* **release**: V1.0.0-beta.18 [skip ci] ([4a00233](https://github.com/perfect-panel/ppanel-web/commit/4a00233))
* **release**: V1.0.0-beta.19 [skip ci] ([0f15fb8](https://github.com/perfect-panel/ppanel-web/commit/0f15fb8))
* **release**: V1.0.0-beta.2 [skip ci] ([087c36c](https://github.com/perfect-panel/ppanel-web/commit/087c36c))
* **release**: V1.0.0-beta.20 [skip ci] ([bbd44f0](https://github.com/perfect-panel/ppanel-web/commit/bbd44f0))
* **release**: V1.0.0-beta.21 [skip ci] ([ca642c2](https://github.com/perfect-panel/ppanel-web/commit/ca642c2))
* **release**: V1.0.0-beta.22 [skip ci] ([c0fb34f](https://github.com/perfect-panel/ppanel-web/commit/c0fb34f))
* **release**: V1.0.0-beta.23 [skip ci] ([cf1d66d](https://github.com/perfect-panel/ppanel-web/commit/cf1d66d))
* **release**: V1.0.0-beta.24 [skip ci] ([01a3aa0](https://github.com/perfect-panel/ppanel-web/commit/01a3aa0))
* **release**: V1.0.0-beta.25 [skip ci] ([047a698](https://github.com/perfect-panel/ppanel-web/commit/047a698))
* **release**: V1.0.0-beta.26 [skip ci] ([79edea7](https://github.com/perfect-panel/ppanel-web/commit/79edea7))
* **release**: V1.0.0-beta.27 [skip ci] ([092477b](https://github.com/perfect-panel/ppanel-web/commit/092477b))
* **release**: V1.0.0-beta.27 [skip ci] ([85fdc36](https://github.com/perfect-panel/ppanel-web/commit/85fdc36))
* **release**: V1.0.0-beta.28 [skip ci] ([786ba0e](https://github.com/perfect-panel/ppanel-web/commit/786ba0e))
* **release**: V1.0.0-beta.28 [skip ci] ([d10ecc9](https://github.com/perfect-panel/ppanel-web/commit/d10ecc9))
* **release**: V1.0.0-beta.29 [skip ci] ([29bc3c7](https://github.com/perfect-panel/ppanel-web/commit/29bc3c7))
* **release**: V1.0.0-beta.3 [skip ci] ([cd49427](https://github.com/perfect-panel/ppanel-web/commit/cd49427))
* **release**: V1.0.0-beta.30 [skip ci] ([db0d9e0](https://github.com/perfect-panel/ppanel-web/commit/db0d9e0))
* **release**: V1.0.0-beta.31 [skip ci] ([aa1d426](https://github.com/perfect-panel/ppanel-web/commit/aa1d426))
* **release**: V1.0.0-beta.32 [skip ci] ([fa56eb8](https://github.com/perfect-panel/ppanel-web/commit/fa56eb8))
* **release**: V1.0.0-beta.33 [skip ci] ([383638f](https://github.com/perfect-panel/ppanel-web/commit/383638f))
* **release**: V1.0.0-beta.34 [skip ci] ([7023875](https://github.com/perfect-panel/ppanel-web/commit/7023875))
* **release**: V1.0.0-beta.4 [skip ci] ([10d322f](https://github.com/perfect-panel/ppanel-web/commit/10d322f))
* **release**: V1.0.0-beta.5 [skip ci] ([f275f01](https://github.com/perfect-panel/ppanel-web/commit/f275f01))
* **release**: V1.0.0-beta.6 [skip ci] ([dd23279](https://github.com/perfect-panel/ppanel-web/commit/dd23279))
* **release**: V1.0.0-beta.7 [skip ci] ([f60d40c](https://github.com/perfect-panel/ppanel-web/commit/f60d40c))
* **release**: V1.0.0-beta.8 [skip ci], closes [#9](https://github.com/perfect-panel/ppanel-web/issues/9) ([a593eac](https://github.com/perfect-panel/ppanel-web/commit/a593eac))
* **release**: V1.0.0-beta.9 [skip ci] ([855d1b0](https://github.com/perfect-panel/ppanel-web/commit/855d1b0))
* **ui**: Update package dependencies for improved stability and performance ([25da429](https://github.com/perfect-panel/ppanel-web/commit/25da429))
* Merge branch 'beta' into develop ([f219c52](https://github.com/perfect-panel/ppanel-web/commit/f219c52))
* Update changelog, enhance prepare script, and add openapi command ([a93db4e](https://github.com/perfect-panel/ppanel-web/commit/a93db4e))

### 🐛 Bug Fixes

* **admin**: Hidden versions and system upgrades ([64cd842](https://github.com/perfect-panel/ppanel-web/commit/64cd842))
* **admin**: Modify the label type in the rule form to a string array ([a7aa5fe](https://github.com/perfect-panel/ppanel-web/commit/a7aa5fe))
* **affiliate**: Update user identifier ([35f92c9](https://github.com/perfect-panel/ppanel-web/commit/35f92c9))
* **api**: Fix type error in API request and add return URL parameter ([ee286dd](https://github.com/perfect-panel/ppanel-web/commit/ee286dd))
* **api**: PreCreateOrder ([ca747f5](https://github.com/perfect-panel/ppanel-web/commit/ca747f5))
* **api**: Purge ([98c1c30](https://github.com/perfect-panel/ppanel-web/commit/98c1c30))
* **api**: Remove redundant requestType parameter in appleLoginCallback ([0aa5d5b](https://github.com/perfect-panel/ppanel-web/commit/0aa5d5b))
* **api**: Rename app-related functions and types to application for consistency ([9d8b814](https://github.com/perfect-panel/ppanel-web/commit/9d8b814))
* **api**: Replace 'deduction' with 'gift_amount' and add 'commission' field in type definitions ([77edf1d](https://github.com/perfect-panel/ppanel-web/commit/77edf1d))
* **api**: Server and order ([255bd82](https://github.com/perfect-panel/ppanel-web/commit/255bd82))
* **api**: Statistics ([7962162](https://github.com/perfect-panel/ppanel-web/commit/7962162))
* **api**: Subscribe token ([1932ba7](https://github.com/perfect-panel/ppanel-web/commit/1932ba7))
* **api**: Update API type definitions to replace 'deduction' with 'gift_amount' and make 'commission' field optional ([c2af060](https://github.com/perfect-panel/ppanel-web/commit/c2af060))
* **api**: Update Model ([39aaa73](https://github.com/perfect-panel/ppanel-web/commit/39aaa73))
* **api**: Update subscription_protocol to subscribe_type for consistency across services ([b6da51b](https://github.com/perfect-panel/ppanel-web/commit/b6da51b))
* **auth-control**: Fix citation error for platform values ([c940f3c](https://github.com/perfect-panel/ppanel-web/commit/c940f3c))
* **auth-control**: Fix citation error for platform values ([28813d2](https://github.com/perfect-panel/ppanel-web/commit/28813d2))
* **auth-control**: Rename phone_variable to phone_number in mobile verification configuration ([e5455aa](https://github.com/perfect-panel/ppanel-web/commit/e5455aa))
* **auth**: Add error handling to form submission and reset Turnstile on failure ([715d011](https://github.com/perfect-panel/ppanel-web/commit/715d011))
* **auth**: Change Textarea value to defaultValue for client_secret in Apple auth page ([69fc670](https://github.com/perfect-panel/ppanel-web/commit/69fc670))
* **auth**: Refactor forms to use Turnstile ref for reset functionality ([320a7dc](https://github.com/perfect-panel/ppanel-web/commit/320a7dc))
* **auth**: Refactor reset password form to simplify code input and update placeholder text ([23833b4](https://github.com/perfect-panel/ppanel-web/commit/23833b4))
* **auth**: Refactor user authentication forms to remove global store dependency and improve type handling ([12026b0](https://github.com/perfect-panel/ppanel-web/commit/12026b0))
* **auth**: Remove unused telephone code login function and update typings for telephone login requests ([7239685](https://github.com/perfect-panel/ppanel-web/commit/7239685))
* **auth**: Require minimum length for invite string when forced invite is enabled ([a604f28](https://github.com/perfect-panel/ppanel-web/commit/a604f28))
* **auth**: Simplify email verification code input rendering ([6f7bc37](https://github.com/perfect-panel/ppanel-web/commit/6f7bc37))
* **auth**: Update authentication configuration and localization strings ([47f2c58](https://github.com/perfect-panel/ppanel-web/commit/47f2c58))
* **auth**: Update email verification logic to use domain suffix check ([62662bb](https://github.com/perfect-panel/ppanel-web/commit/62662bb))
* **auth**: Update user authentication flow to include email and phone code verification ([5d078fd](https://github.com/perfect-panel/ppanel-web/commit/5d078fd))
* **auth**: Update UserCheckForm to use setInitialValues and modify onSubmit type ([c984c0d](https://github.com/perfect-panel/ppanel-web/commit/c984c0d))
* **billing**: ExpiryDate ([e85e545](https://github.com/perfect-panel/ppanel-web/commit/e85e545))
* **billing**: I18n and styles ([81e0f21](https://github.com/perfect-panel/ppanel-web/commit/81e0f21))
* **changelog**: Update change log style ([cfa3fc0](https://github.com/perfect-panel/ppanel-web/commit/cfa3fc0))
* **config**: AlipayF2F ([6c07107](https://github.com/perfect-panel/ppanel-web/commit/6c07107))
* **config**: Bugs ([f57e40c](https://github.com/perfect-panel/ppanel-web/commit/f57e40c))
* **config**: Checkout Order ([a31e763](https://github.com/perfect-panel/ppanel-web/commit/a31e763))
* **config**: FormatBytes ([bbc2da0](https://github.com/perfect-panel/ppanel-web/commit/bbc2da0))
* **config**: NoStore ([2cc18cf](https://github.com/perfect-panel/ppanel-web/commit/2cc18cf))
* **config**: Runtime env ([a1e4999](https://github.com/perfect-panel/ppanel-web/commit/a1e4999))
* **config**: Status Percentag ([8f322fb](https://github.com/perfect-panel/ppanel-web/commit/8f322fb))
* **config**: SubLink ([1c61966](https://github.com/perfect-panel/ppanel-web/commit/1c61966))
* **config**: Subscribe Link ([11ea821](https://github.com/perfect-panel/ppanel-web/commit/11ea821))
* **content**: Parse subscription description and display features with icons ([3c5542a](https://github.com/perfect-panel/ppanel-web/commit/3c5542a))
* **controller**: Order status ([8c6a097](https://github.com/perfect-panel/ppanel-web/commit/8c6a097))
* **coupon**: Rename 'server' field to 'subscribe' in coupon form and update coupon update request type ([f8b6d82](https://github.com/perfect-panel/ppanel-web/commit/f8b6d82))
* **dashboard**:  Improve URL encoding for subscription links and enhance success message handling ([4983c33](https://github.com/perfect-panel/ppanel-web/commit/4983c33))
* **dashboard**:  Update date display to use start_time if available ([e551232](https://github.com/perfect-panel/ppanel-web/commit/e551232))
* **dashboard**: Correct progress value calculations and update groupId accessor ([36c7667](https://github.com/perfect-panel/ppanel-web/commit/36c7667))
* **dashboard**: Display subscription creation date in user dashboard ([d0e6df0](https://github.com/perfect-panel/ppanel-web/commit/d0e6df0))
* **dashboard**: Format Bytes ([d8b0bd9](https://github.com/perfect-panel/ppanel-web/commit/d8b0bd9))
* **dashboard**: Update icon imports for platform consistency and adjust icon size ([3e8912e](https://github.com/perfect-panel/ppanel-web/commit/3e8912e))
* **dashboard**: Update platform detection logic and improve layout responsiveness ([b0aa364](https://github.com/perfect-panel/ppanel-web/commit/b0aa364))
* **deps**: Remove outdated @iconify/react dependency and add iconify-json packages ([d6fbc38](https://github.com/perfect-panel/ppanel-web/commit/d6fbc38))
* **deps**: Typescript config ([34e24b8](https://github.com/perfect-panel/ppanel-web/commit/34e24b8))
* **deps**: Update clipboard ([5572710](https://github.com/perfect-panel/ppanel-web/commit/5572710))
* **editor**: Change value ([4fdfeb2](https://github.com/perfect-panel/ppanel-web/commit/4fdfeb2))
* **email**: Update platform configuration handling to use current ref for consistency ([c90175b](https://github.com/perfect-panel/ppanel-web/commit/c90175b))
* **footer**: Email address ([a451f44](https://github.com/perfect-panel/ppanel-web/commit/a451f44))
* **forms**: Add step attribute to number inputs for better value control ([b8f4f1e](https://github.com/perfect-panel/ppanel-web/commit/b8f4f1e))
* **icon**: Comment out unused icon collection imports ([f17bf8d](https://github.com/perfect-panel/ppanel-web/commit/f17bf8d))
* **layout**: Remove unnecessary cookie initialization in Logout function ([3065c3a](https://github.com/perfect-panel/ppanel-web/commit/3065c3a))
* **locale**: Default value ([937408f](https://github.com/perfect-panel/ppanel-web/commit/937408f))
* **locale**: Document ([6f0fa20](https://github.com/perfect-panel/ppanel-web/commit/6f0fa20))
* **locale**: Empty ([3832d20](https://github.com/perfect-panel/ppanel-web/commit/3832d20))
* **locale**: Input Placeholder Webhook Domain ([bca0935](https://github.com/perfect-panel/ppanel-web/commit/bca0935))
* **locale**: Language Select ([0befdb0](https://github.com/perfect-panel/ppanel-web/commit/0befdb0))
* **locales**: Add error message for incorrect user information ([52c1d1f](https://github.com/perfect-panel/ppanel-web/commit/52c1d1f))
* **locales**: Add error message for incorrect user information ([3d92902](https://github.com/perfect-panel/ppanel-web/commit/3d92902))
* **locales**: Add logout message to authentication localization files ([1d0d911](https://github.com/perfect-panel/ppanel-web/commit/1d0d911))
* **locales**: Fixed description in multilingual files, updated text related to email registration functionality ([c356bc2](https://github.com/perfect-panel/ppanel-web/commit/c356bc2))
* **locales**: Order recharge related fields ([35210fe](https://github.com/perfect-panel/ppanel-web/commit/35210fe))
* **locales**: Removed language file import to clean up unnecessary language support ([68f6ab2](https://github.com/perfect-panel/ppanel-web/commit/68f6ab2))
* **locales**: Removed multilingual files to clean up unnecessary language support ([5b151cd](https://github.com/perfect-panel/ppanel-web/commit/5b151cd))
* **locale**: Subscription Path Description ([4c67387](https://github.com/perfect-panel/ppanel-web/commit/4c67387))
* **locales**: Update custom HTML description for clarity across multiple languages ([557c5cd](https://github.com/perfect-panel/ppanel-web/commit/557c5cd))
* **locales**: Update custom HTML description in language file, ([87381da](https://github.com/perfect-panel/ppanel-web/commit/87381da))
* **locales**: Update expiration time description from minutes to seconds in multiple languages ([5bac933](https://github.com/perfect-panel/ppanel-web/commit/5bac933))
* **locales**: Update Hong Kong ([6d0d069](https://github.com/perfect-panel/ppanel-web/commit/6d0d069))
* **locales**: Update invite code text to indicate it's optional ([6a34bfb](https://github.com/perfect-panel/ppanel-web/commit/6a34bfb))
* **logs**: Update log display to render key-value pairs and remove badge ([5ea6489](https://github.com/perfect-panel/ppanel-web/commit/5ea6489))
* **metadata**: Global metadata ([15d5ecf](https://github.com/perfect-panel/ppanel-web/commit/15d5ecf))
* **nav**: Comment out unused social login options to simplify navigation configuration ([cefcb31](https://github.com/perfect-panel/ppanel-web/commit/cefcb31))
* **node-config**: Add null checks for time slots and ensure proper handling of undefined values ([1cdb7e7](https://github.com/perfect-panel/ppanel-web/commit/1cdb7e7))
* **node**: Add country and city fields to the form schema and localization files ([8775fb6](https://github.com/perfect-panel/ppanel-web/commit/8775fb6))
* **node**: Handle potential null value for online users count ([fa2fb28](https://github.com/perfect-panel/ppanel-web/commit/fa2fb28))
* **node**: Locale and form ([38be4d5](https://github.com/perfect-panel/ppanel-web/commit/38be4d5))
* **node**: Port config ([a20834a](https://github.com/perfect-panel/ppanel-web/commit/a20834a))
* **node**: Reality config ([fadd17f](https://github.com/perfect-panel/ppanel-web/commit/fadd17f))
* **node**: Service Name config ([d0be685](https://github.com/perfect-panel/ppanel-web/commit/d0be685))
* **node**: TLS config ([57fae12](https://github.com/perfect-panel/ppanel-web/commit/57fae12))
* **node**: Trojan protocol config ([7e1eb90](https://github.com/perfect-panel/ppanel-web/commit/7e1eb90))
* **notify**: Ensure user info is updated after notification settings submission ([9bc3a94](https://github.com/perfect-panel/ppanel-web/commit/9bc3a94))
* **notify**: Set default values for notification settings to false ([3652819](https://github.com/perfect-panel/ppanel-web/commit/3652819))
* **oauth**: Refactor OAuth configuration types and update related API methods ([6227ba9](https://github.com/perfect-panel/ppanel-web/commit/6227ba9))
* **oauth**: Remove redundant checks when updating configuration to simplify logic ([9140b8a](https://github.com/perfect-panel/ppanel-web/commit/9140b8a))
* **payment**: Add notification URL field to payment management interface ([5c710e1](https://github.com/perfect-panel/ppanel-web/commit/5c710e1))
* **payment**: Config and types ([b0c87fb](https://github.com/perfect-panel/ppanel-web/commit/b0c87fb))
* **payment**: Fix payment related type definitions and update payment method references ([c3138a8](https://github.com/perfect-panel/ppanel-web/commit/c3138a8))
* **payment**: Qrcode ([a9a535b](https://github.com/perfect-panel/ppanel-web/commit/a9a535b))
* **payment**: Refactor payment form placeholder and update localization files ([4a4d364](https://github.com/perfect-panel/ppanel-web/commit/4a4d364))
* **payment**: Refactor purchaseCheckout usage and remove redundant code ([a5e2079](https://github.com/perfect-panel/ppanel-web/commit/a5e2079))
* **payment**: Replace window.open with window.location.href for checkout links ([1d8c765](https://github.com/perfect-panel/ppanel-web/commit/1d8c765))
* **payment**: Update checkout type from 'link' to 'url' for consistency ([136a1ab](https://github.com/perfect-panel/ppanel-web/commit/136a1ab))
* **payment**: Update payment information ([70d6a38](https://github.com/perfect-panel/ppanel-web/commit/70d6a38))
* **payment**: Update payment method update logic to include row data ([6752420](https://github.com/perfect-panel/ppanel-web/commit/6752420))
* **phone**: Update SMS expiration time field to use 'sms_expire_time' with default value of 300 ([18b07c7](https://github.com/perfect-panel/ppanel-web/commit/18b07c7))
* **profile**: Restore filter to ensure only valid OAuth accounts are shown ([315c8f9](https://github.com/perfect-panel/ppanel-web/commit/315c8f9))
* **purchasing**: Update payment type to lowercase and add optional chaining for discounts ([c06ea49](https://github.com/perfect-panel/ppanel-web/commit/c06ea49))
* **redirect**: Simplify redirect URL logic by removing unnecessary condition for sessionStorage ([c53ac61](https://github.com/perfect-panel/ppanel-web/commit/c53ac61))
* **redirect**: Update redirect URL logic to ensure proper handling of OAuth and auth paths ([7954762](https://github.com/perfect-panel/ppanel-web/commit/7954762))
* **register**: Adjust user email verification logic to handle domain suffix checks correctly ([686aa2d](https://github.com/perfect-panel/ppanel-web/commit/686aa2d))
* **request**: Add error code 40005 to trigger logout ([71bf002](https://github.com/perfect-panel/ppanel-web/commit/71bf002))
* **request**: Locale ([37d408f](https://github.com/perfect-panel/ppanel-web/commit/37d408f))
* **rule-form**: Remove redundant rule set display ([6e0c9b6](https://github.com/perfect-panel/ppanel-web/commit/6e0c9b6))
* **rules**: Remove unused MATCH rule ([674a01c](https://github.com/perfect-panel/ppanel-web/commit/674a01c))
* **site**: Add image upload functionality for site logo configuration ([4ea6e4a](https://github.com/perfect-panel/ppanel-web/commit/4ea6e4a))
* **site**: Se ref to store site configuration for updates ([0c8f091](https://github.com/perfect-panel/ppanel-web/commit/0c8f091))
* **sort**: Refactor sorting logic in NodeTable and SubscribeTable components for improved clarity and performance ([331bbea](https://github.com/perfect-panel/ppanel-web/commit/331bbea))
* **subscribe**: Add value prop to field in subscription form for proper state management ([328838d](https://github.com/perfect-panel/ppanel-web/commit/328838d))
* **subscribe**: Discount ([35a9f69](https://github.com/perfect-panel/ppanel-web/commit/35a9f69))
* **subscribe**: Extract Domain ([40d61a9](https://github.com/perfect-panel/ppanel-web/commit/40d61a9))
* **subscribe**: Handle optional values in price and discount calculations ([5939763](https://github.com/perfect-panel/ppanel-web/commit/5939763))
* **subscribe**: Jumps and internationalization ([13fdec3](https://github.com/perfect-panel/ppanel-web/commit/13fdec3))
* **subscribe**: Refactor discount calculations and default selection logic in subscription forms ([423b240](https://github.com/perfect-panel/ppanel-web/commit/423b240))
* **subscribe**: Server group id ([90e6764](https://github.com/perfect-panel/ppanel-web/commit/90e6764))
* **subscribe**: Update default selection logic in subscription form to ensure proper state management ([ef15374](https://github.com/perfect-panel/ppanel-web/commit/ef15374))
* **subscribe**: Update forms to include refetch functionality and improve toast messages ([fc55e95](https://github.com/perfect-panel/ppanel-web/commit/fc55e95))
* **subscribe**: Update payment return URL ([2b80496](https://github.com/perfect-panel/ppanel-web/commit/2b80496))
* **subscribe**: Update subscription domain placeholder to include examples; improve site name retrieval in global store ([c65a44c](https://github.com/perfect-panel/ppanel-web/commit/c65a44c))
* **subscribe**: Update value validation to check for number type in subscribe form ([6de29d5](https://github.com/perfect-panel/ppanel-web/commit/6de29d5))
* **subscription**: Add reset functionality for user subscription token ([39e89bf](https://github.com/perfect-panel/ppanel-web/commit/39e89bf))
* **table**: Update privacy policy tab translation key and remove unnecessary requestType from OAuth callback ([14b3af5](https://github.com/perfect-panel/ppanel-web/commit/14b3af5))
* **third-party-accounts**: Remove mobile display logic from third-party accounts component ([b4946f7](https://github.com/perfect-panel/ppanel-web/commit/b4946f7))
* **third-party-accounts**: Update redirect property name in binding response handling ([012e83a](https://github.com/perfect-panel/ppanel-web/commit/012e83a))
* **turnstile**: Turnstile_site_key ([0327b73](https://github.com/perfect-panel/ppanel-web/commit/0327b73))
* **type**: Fix ts type check error ([3cb0629](https://github.com/perfect-panel/ppanel-web/commit/3cb0629))
* **types**: Add 'gift_amount' field to API type definitions ([8f8a12a](https://github.com/perfect-panel/ppanel-web/commit/8f8a12a))
* **types**: Checking ([2992824](https://github.com/perfect-panel/ppanel-web/commit/2992824))
* **types**: Order type ([c7e50a9](https://github.com/perfect-panel/ppanel-web/commit/c7e50a9))
* **ui**: Bugs ([b023d0f](https://github.com/perfect-panel/ppanel-web/commit/b023d0f))
* **ui**: Components ([a7927d7](https://github.com/perfect-panel/ppanel-web/commit/a7927d7))
* **ui**: Fix json formatting ([e1ddd94](https://github.com/perfect-panel/ppanel-web/commit/e1ddd94))
* **ui**: Improve dashboard layout and enhance button functionality; open checkout URLs in a new tab ([fc0da76](https://github.com/perfect-panel/ppanel-web/commit/fc0da76))
* **ui**: Multiple display bugs ([f5d8fd3](https://github.com/perfect-panel/ppanel-web/commit/f5d8fd3))
* **user-nav**: Update user avatar and label to display telephone if email is not available ([7b6bb7b](https://github.com/perfect-panel/ppanel-web/commit/7b6bb7b))
* **user**: Add the 'gift_amount' field to the user service's type definition ([6301409](https://github.com/perfect-panel/ppanel-web/commit/6301409))
* **user**: Refactor user form validation and reset password fields ([6733fc2](https://github.com/perfect-panel/ppanel-web/commit/6733fc2))
* **user**: Update locales ([4e7d249](https://github.com/perfect-panel/ppanel-web/commit/4e7d249))
* **user**: Update notification and verify code settings ([574b043](https://github.com/perfect-panel/ppanel-web/commit/574b043))
* **user**: Update user identifier field and localizations ([1b6befa](https://github.com/perfect-panel/ppanel-web/commit/1b6befa))
* **user**: Update user subscribe display ([3bb714d](https://github.com/perfect-panel/ppanel-web/commit/3bb714d))
* **utils**: Login redirect url ([cbe5f0d](https://github.com/perfect-panel/ppanel-web/commit/cbe5f0d))
* More bugs ([2d88a3a](https://github.com/perfect-panel/ppanel-web/commit/2d88a3a))

### 👷 Build System

* **config**:  Update pm2 config ([d95b425](https://github.com/perfect-panel/ppanel-web/commit/d95b425))

### 💄 Styles

* **dashboard**: Adjust grid layout and update image dimensions in application display ([f3204b7](https://github.com/perfect-panel/ppanel-web/commit/f3204b7))
* **dashboard**: Enhance card components with full height and improved empty state handling ([7e1d551](https://github.com/perfect-panel/ppanel-web/commit/7e1d551))
* **document**: Update ([0a8109b](https://github.com/perfect-panel/ppanel-web/commit/0a8109b))
* **globals**: Refactor delete confirmation button and update badge styles in node and subscribe tables ([30ae781](https://github.com/perfect-panel/ppanel-web/commit/30ae781))
* **locales**: Remove unused subscription labels from multiple locale files ([fb0c510](https://github.com/perfect-panel/ppanel-web/commit/fb0c510))
* **locales**: Update server.json to reorganize relay mode options and improve labels ([701cdee](https://github.com/perfect-panel/ppanel-web/commit/701cdee))
* **node**: Form ([d5f5add](https://github.com/perfect-panel/ppanel-web/commit/d5f5add))
* **node**: Improve layout and spacing in NodeStatusCell component ([136287d](https://github.com/perfect-panel/ppanel-web/commit/136287d))
* **node**: Protocol Tab ([2bcb925](https://github.com/perfect-panel/ppanel-web/commit/2bcb925))
* **time-slot**: Add chart display ([c44ad47](https://github.com/perfect-panel/ppanel-web/commit/c44ad47))
* **ui**: Update mobile style ([eda18bc](https://github.com/perfect-panel/ppanel-web/commit/eda18bc))
* Update node secret UI and add telephone code field to authentication form ([770932e](https://github.com/perfect-panel/ppanel-web/commit/770932e))

### 📝 Documentation

* **readme**: License name ([74cb16b](https://github.com/perfect-panel/ppanel-web/commit/74cb16b))

### 🔧 Continuous Integration

* **github**: Release docker ([5af60aa](https://github.com/perfect-panel/ppanel-web/commit/5af60aa))
* **step**: Update step name ([9eca618](https://github.com/perfect-panel/ppanel-web/commit/9eca618))
2025-04-24 10:14:50 +00:00
web@ppanel 4a4d364f17 🐛 fix(payment): Refactor payment form placeholder and update localization files 2025-04-24 06:11:55 -04:00
web@ppanel 5ea64893e8 🐛 fix(logs): Update log display to render key-value pairs and remove badge 2025-04-24 05:08:03 -04:00
web@ppanel 674a01c813 🐛 fix(rules): Remove unused MATCH rule 2025-04-20 03:51:00 -04:00
web@ppanel 3c5542a3ea 🐛 fix(content): Parse subscription description and display features with icons 2025-04-14 09:16:24 -04:00
web@ppanel 6e0c9b6698 🐛 fix(rule-form): Remove redundant rule set display 2025-04-14 03:09:44 -04:00
web@ppanel 3bb714d15c 🐛 fix(user): Update user subscribe display 2025-04-09 03:27:22 -04:00
semantic-release-bot 7023875548 🔖 chore(release): v1.0.0-beta.34 [skip ci]
# [1.0.0-beta.34](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.33...v1.0.0-beta.34) (2025-04-02)

###  Features

* **admin**: Add application and rule management entries to localization files ([8b43e69](https://github.com/perfect-panel/ppanel-web/commit/8b43e69))
* **api**: Add an interface to obtain user subscription details, update related type definitions and localized text ([cf5c39c](https://github.com/perfect-panel/ppanel-web/commit/cf5c39c))
* **user**: Integrate subscription list into user management, update request parameters and types ([8d49dac](https://github.com/perfect-panel/ppanel-web/commit/8d49dac))

### 🐛 Bug Fixes

* **admin**: Hidden versions and system upgrades ([64cd842](https://github.com/perfect-panel/ppanel-web/commit/64cd842))
* **admin**: Modify the label type in the rule form to a string array ([a7aa5fe](https://github.com/perfect-panel/ppanel-web/commit/a7aa5fe))
* **node**: Handle potential null value for online users count ([fa2fb28](https://github.com/perfect-panel/ppanel-web/commit/fa2fb28))
* **subscribe**: Add value prop to field in subscription form for proper state management ([328838d](https://github.com/perfect-panel/ppanel-web/commit/328838d))
* **subscribe**: Refactor discount calculations and default selection logic in subscription forms ([423b240](https://github.com/perfect-panel/ppanel-web/commit/423b240))
* **subscribe**: Update default selection logic in subscription form to ensure proper state management ([ef15374](https://github.com/perfect-panel/ppanel-web/commit/ef15374))
2025-04-02 08:24:17 +00:00
web@ppanel a7aa5fee3e 🐛 fix(admin): Modify the label type in the rule form to a string array 2025-04-02 11:52:38 +07:00
web@ppanel 64cd842926 🐛 fix(admin): Hidden versions and system upgrades 2025-04-02 00:15:15 +07:00
web@ppanel 8b43e69bfe feat(admin): Add application and rule management entries to localization files 2025-04-02 00:12:02 +07:00
web@ppanel ef153747bd 🐛 fix(subscribe): Update default selection logic in subscription form to ensure proper state management 2025-04-01 12:37:17 +07:00
web@ppanel 328838d754 🐛 fix(subscribe): Add value prop to field in subscription form for proper state management 2025-03-30 20:27:03 +07:00
web@ppanel 423b24077f 🐛 fix(subscribe): Refactor discount calculations and default selection logic in subscription forms 2025-03-30 00:53:47 +07:00
web@ppanel fa2fb2864f 🐛 fix(node): Handle potential null value for online users count 2025-03-29 23:43:21 +07:00
web@ppanel 8d49daca21 feat(user): Integrate subscription list into user management, update request parameters and types 2025-03-26 15:01:43 +07:00
web@ppanel cf5c39cfe5 feat(api): Add an interface to obtain user subscription details, update related type definitions and localized text 2025-03-25 23:55:31 +07:00
semantic-release-bot 383638f702 🔖 chore(release): v1.0.0-beta.33 [skip ci]
# [1.0.0-beta.33](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.32...v1.0.0-beta.33) (2025-03-18)

### 🐛 Bug Fixes

* **subscribe**: Handle optional values in price and discount calculations ([5939763](https://github.com/perfect-panel/ppanel-web/commit/5939763))
2025-03-18 07:53:53 +00:00
web@ppanel 5939763b57 🐛 fix(subscribe): Handle optional values in price and discount calculations 2025-03-18 14:50:48 +07:00
240 changed files with 14616 additions and 821 deletions
+474 -3
View File
@@ -1,13 +1,484 @@
<a name="readme-top"></a> <a name="readme-top"></a>
# Changelog # Changelog
# [1.0.0-beta.32](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.31...v1.0.0-beta.32) (2025-03-17) ## [1.1.5](https://github.com/perfect-panel/ppanel-web/compare/v1.1.4...v1.1.5) (2025-07-26)
### 🐛 Bug Fixes ### 🐛 Bug Fixes
* **forms**: Add step attribute to number inputs for better value control ([b8f4f1e](https://github.com/perfect-panel/ppanel-web/commit/b8f4f1e)) * **subscribe**: Filter out items that are not marked as visible in subscription list ([32253e3](https://github.com/perfect-panel/ppanel-web/commit/32253e3))
* **locales**: Update invite code text to indicate it's optional ([6a34bfb](https://github.com/perfect-panel/ppanel-web/commit/6a34bfb))
## [1.1.4](https://github.com/perfect-panel/ppanel-web/compare/v1.1.3...v1.1.4) (2025-07-25)
### 🐛 Bug Fixes
* **locales**: Simplify "show" label in subscription localization files ([d53a006](https://github.com/perfect-panel/ppanel-web/commit/d53a006))
* **order**: Preserve last successful order on error during order creation ([2fb98be](https://github.com/perfect-panel/ppanel-web/commit/2fb98be))
* **subscribe**: Filter out hidden items in subscription list display ([634be37](https://github.com/perfect-panel/ppanel-web/commit/634be37))
## [1.1.3](https://github.com/perfect-panel/ppanel-web/compare/v1.1.2...v1.1.3) (2025-07-24)
### 🐛 Bug Fixes
* **auth**: Implement user redirection to dashboard upon authentication ([f84f98c](https://github.com/perfect-panel/ppanel-web/commit/f84f98c))
## [1.1.2](https://github.com/perfect-panel/ppanel-web/compare/v1.1.1...v1.1.2) (2025-07-24)
### 🐛 Bug Fixes
* **billing**: Add display for gift amount in subscription billing ([04af2f9](https://github.com/perfect-panel/ppanel-web/commit/04af2f9))
* **order**: Update subscription cell to display name and quantity ([96eba17](https://github.com/perfect-panel/ppanel-web/commit/96eba17))
* **tool**: Added API for obtaining version, updated version information display logic ([2675034](https://github.com/perfect-panel/ppanel-web/commit/2675034))
<a name="readme-top"></a>
# Changelog
## [1.1.1](https://github.com/perfect-panel/ppanel-web/compare/v1.1.0...v1.1.1) (2025-07-20)
### 🐛 Bug Fixes
- **node-table**: Update translations for headers and no data display ([eec0b12](https://github.com/perfect-panel/ppanel-web/commit/eec0b12))
- **rules**: Change rule type from 'auto' to 'default' and update ([3e290d7](https://github.com/perfect-panel/ppanel-web/commit/3e290d7))
- **rules**: Update rule settings ([3304a55](https://github.com/perfect-panel/ppanel-web/commit/3304a55))
- **subscribe-form**: Optimize discount calculation logic and debounce updates ([166e48f](https://github.com/perfect-panel/ppanel-web/commit/166e48f))
- **tutorial**: Comment out unused getVersion function and simplify getVersionPath ([7cdc6bd](https://github.com/perfect-panel/ppanel-web/commit/7cdc6bd))
- **tutorial**: Return latest version in case of fetch error ([1fb305e](https://github.com/perfect-panel/ppanel-web/commit/1fb305e))
<a name="readme-top"></a>
# Changelog
# [1.1.0](https://github.com/perfect-panel/ppanel-web/compare/v1.0.2...v1.1.0) (2025-07-06)
### ✨ Features
- **view**: Add AnyTLS protocol support and enhance node configuration options ([bcfb10a](https://github.com/perfect-panel/ppanel-web/commit/bcfb10a))
<a name="readme-top"></a>
# Changelog
## [1.0.2](https://github.com/perfect-panel/ppanel-web/compare/v1.0.1...v1.0.2) (2025-06-29)
### 🐛 Bug Fixes
- **subscription**: User subscription information ([7d18ff6](https://github.com/perfect-panel/ppanel-web/commit/7d18ff6))
## [1.0.1](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0...v1.0.1) (2025-04-28)
### 🐛 Bug Fixes
- **payment**: Disable webhook_secret field in PaymentForm component ([d323af8](https://github.com/perfect-panel/ppanel-web/commit/d323af8))
- **recharge**: Set balance prop to false in PaymentMethods component ([356ae5b](https://github.com/perfect-panel/ppanel-web/commit/356ae5b))
# 1.0.0 (2025-04-24)
### ♻ Code Refactoring
- **api**: Sort and Announcement ([38d5616](https://github.com/perfect-panel/ppanel-web/commit/38d5616))
- **auth**: Refactor user authorization handling and improve error logging ([68bc18f](https://github.com/perfect-panel/ppanel-web/commit/68bc18f))
- **config**: GenerateMetadata ([a0bb101](https://github.com/perfect-panel/ppanel-web/commit/a0bb101))
- **config**: Simplify environment variable handling and improve build script ([cf54d0f](https://github.com/perfect-panel/ppanel-web/commit/cf54d0f))
- **config**: Viewport ([24b8601](https://github.com/perfect-panel/ppanel-web/commit/24b8601))
- **core**: Restructure project for better module separation ([9d0cb8b](https://github.com/perfect-panel/ppanel-web/commit/9d0cb8b))
- **deps**: Update ([19837a1](https://github.com/perfect-panel/ppanel-web/commit/19837a1))
- **empty**: Content ([aa4c667](https://github.com/perfect-panel/ppanel-web/commit/aa4c667))
- **payment**: Reconstruct the payment page ([7109472](https://github.com/perfect-panel/ppanel-web/commit/7109472))
- **sbscribe**: Rename and reorganize components for better structure and clarity ([5e5e4ed](https://github.com/perfect-panel/ppanel-web/commit/5e5e4ed))
- **ui**: Dependencies ([727d779](https://github.com/perfect-panel/ppanel-web/commit/727d779))
- **ui**: Layout ([9262d7d](https://github.com/perfect-panel/ppanel-web/commit/9262d7d))
- **ui**: Optimize document display ([2ca2992](https://github.com/perfect-panel/ppanel-web/commit/2ca2992))
- Enhance user navigation dropdown ui and styling ([d2732e6](https://github.com/perfect-panel/ppanel-web/commit/d2732e6))
- Reduce code complexity and improve readability ([e11f18c](https://github.com/perfect-panel/ppanel-web/commit/e11f18c))
### ⚡ Performance Improvements
- **subscribe**: Form discount price ([059a892](https://github.com/perfect-panel/ppanel-web/commit/059a892))
### ✨ Features
- **accounts**: Update third-party account binding and unbinding ([1841552](https://github.com/perfect-panel/ppanel-web/commit/1841552))
- **ad**: Advertise ([b1105cd](https://github.com/perfect-panel/ppanel-web/commit/b1105cd))
- **admin**: Add application and rule management entries to localization files ([8b43e69](https://github.com/perfect-panel/ppanel-web/commit/8b43e69))
- **affiliate**: Add Affiliate component with commission display and invite link functionality ([4aea4e8](https://github.com/perfect-panel/ppanel-web/commit/4aea4e8))
- **affiliate**: Affiliate Detail ([a782c17](https://github.com/perfect-panel/ppanel-web/commit/a782c17))
- **affiliate**: Commission Rate ([5eec430](https://github.com/perfect-panel/ppanel-web/commit/5eec430))
- **affiliate**: Update affiliate component to display total commission and improve data fetching ([cc834ca](https://github.com/perfect-panel/ppanel-web/commit/cc834ca))
- **announcement**: Popup and pinned ([f3680a7](https://github.com/perfect-panel/ppanel-web/commit/f3680a7))
- **api**: Add an interface to obtain user subscription details, update related type definitions and localized text ([cf5c39c](https://github.com/perfect-panel/ppanel-web/commit/cf5c39c))
- **api**: Add CheckoutOrder request and response types, and update user purchase request parameters ([48a1b97](https://github.com/perfect-panel/ppanel-web/commit/48a1b97))
- **api**: Add CheckoutOrder request and response types, and update user purchase request parameters ([dddc21c](https://github.com/perfect-panel/ppanel-web/commit/dddc21c))
- **api**: Add new subscription properties and locale support for deduction ratios and reset cycles ([fec80f5](https://github.com/perfect-panel/ppanel-web/commit/fec80f5))
- **api**: Add Time Period Configuration ([837157c](https://github.com/perfect-panel/ppanel-web/commit/837157c))
- **api**: Telegram ([17ce96a](https://github.com/perfect-panel/ppanel-web/commit/17ce96a))
- **auth-control**: Adding phone number labels to mobile verification configurations in multiple languages ([046740f](https://github.com/perfect-panel/ppanel-web/commit/046740f))
- **auth-control**: Update general ([3883646](https://github.com/perfect-panel/ppanel-web/commit/3883646))
- **auth**: Add email and SMS code sending functionality with localization updates ([57eaa55](https://github.com/perfect-panel/ppanel-web/commit/57eaa55))
- **auth**: Add Oauth configuration for Telegram, Facebook, Google, Github, and Apple ([18ee600](https://github.com/perfect-panel/ppanel-web/commit/18ee600))
- **auth**: Add privacy policy link to the footer ([8e16ef1](https://github.com/perfect-panel/ppanel-web/commit/8e16ef1))
- **auth**: Add SMS and email configuration options to global store and update localization ([4acf7b1](https://github.com/perfect-panel/ppanel-web/commit/4acf7b1))
- **auth**: Add type parameter to SendCode and update related API typings ([4198871](https://github.com/perfect-panel/ppanel-web/commit/4198871))
- **auth**: Enhance user registration with invite handling and logo display ([207bc24](https://github.com/perfect-panel/ppanel-web/commit/207bc24))
- **auth**: Redirect user after OAuth login and add logos icon collection ([aa6dda8](https://github.com/perfect-panel/ppanel-web/commit/aa6dda8))
- **auth**: Refactor mobile authentication config to support whitelist functionality ([c761ec7](https://github.com/perfect-panel/ppanel-web/commit/c761ec7))
- **billing**: Update Billing ([078fc9d](https://github.com/perfect-panel/ppanel-web/commit/078fc9d))
- **cdn**: Add CDN URL configuration and update related references ([0c90733](https://github.com/perfect-panel/ppanel-web/commit/0c90733))
- **config**: Add application selection and encryption settings to configuration form ([88b3504](https://github.com/perfect-panel/ppanel-web/commit/88b3504))
- **config**: FormatBytes ([9251a09](https://github.com/perfect-panel/ppanel-web/commit/9251a09))
- **config**: Protocol type ([a3b45b4](https://github.com/perfect-panel/ppanel-web/commit/a3b45b4))
- **config**: Update encryption fields in configuration form and refactor OAuth callback parameters ([652e032](https://github.com/perfect-panel/ppanel-web/commit/652e032))
- **config**: Webhook Domain ([01e06c6](https://github.com/perfect-panel/ppanel-web/commit/01e06c6))
- **dashboard**: Optimization ([5b3f4b4](https://github.com/perfect-panel/ppanel-web/commit/5b3f4b4))
- **dashboard**: Statistics ([2926abc](https://github.com/perfect-panel/ppanel-web/commit/2926abc))
- **device**: Modify IMEI to device identifier support ([e3f9ef6](https://github.com/perfect-panel/ppanel-web/commit/e3f9ef6))
- **email**: Add traffic exhaustion template ([bb3bd7b](https://github.com/perfect-panel/ppanel-web/commit/bb3bd7b))
- **favicon**: Update SVG favicon design for admin and user interfaces ([1d91738](https://github.com/perfect-panel/ppanel-web/commit/1d91738))
- **formatting**: Update differenceInDays function to return whole days or two decimal places ([bf58f25](https://github.com/perfect-panel/ppanel-web/commit/bf58f25))
- **form**: Make version field optional and set default value; update site domain placeholder for clarity ([42ba9e8](https://github.com/perfect-panel/ppanel-web/commit/42ba9e8))
- **global**: Add custom data ([6dbebd1](https://github.com/perfect-panel/ppanel-web/commit/6dbebd1))
- **global**: Add SMS configuration options to global store ([39a9ce6](https://github.com/perfect-panel/ppanel-web/commit/39a9ce6))
- **header**: Update locales ([bfb6c27](https://github.com/perfect-panel/ppanel-web/commit/bfb6c27))
- **imei**: Add IMEI related internationalization support and menu items ([13c3337](https://github.com/perfect-panel/ppanel-web/commit/13c3337))
- **input**: Add minimum value constraint and enhance number handling in EnhancedInput ([ce31972](https://github.com/perfect-panel/ppanel-web/commit/ce31972))
- **input**: Add minimum value constraint and enhance number handling in EnhancedInput ([94822d9](https://github.com/perfect-panel/ppanel-web/commit/94822d9))
- **loading**: Add loading components and integrate them in Providers ([d5847fa](https://github.com/perfect-panel/ppanel-web/commit/d5847fa))
- **loading**: Replace loading animation with a simpler spinner and loading text ([f72df3a](https://github.com/perfect-panel/ppanel-web/commit/f72df3a))
- **loading**: Replace loading animation with a simpler spinner and loading text ([b8316bb](https://github.com/perfect-panel/ppanel-web/commit/b8316bb))
- **locale**: Add Persian ([93a0a88](https://github.com/perfect-panel/ppanel-web/commit/93a0a88))
- **locales**: Add area code and telephone fields to user forms in multiple languages ([9b8258c](https://github.com/perfect-panel/ppanel-web/commit/9b8258c))
- **locales**: Add description information of communication keys and encryption methods to enhance client configuration capabilities ([d1f5a9b](https://github.com/perfect-panel/ppanel-web/commit/d1f5a9b))
- **locales**: Add kick offline confirmation and success messages in multiple languages ([5db5343](https://github.com/perfect-panel/ppanel-web/commit/5db5343))
- **locales**: Add multiple languages ([b243ab9](https://github.com/perfect-panel/ppanel-web/commit/b243ab9))
- **locales**: Replace 'nodeGroupId' with 'groupId' in multiple language files for consistency ([a4e9d5d](https://github.com/perfect-panel/ppanel-web/commit/a4e9d5d))
- **locales**: Update 'deductBalance' to 'giftAmount' across multiple languages and fix newline in announcement.json ([70497af](https://github.com/perfect-panel/ppanel-web/commit/70497af))
- **locales**: Update 'sms' to 'mobile' in authentication methods across multiple languages ([fea2171](https://github.com/perfect-panel/ppanel-web/commit/fea2171))
- **log**: Add message log retrieval functionality and update related typings ([1c0ecae](https://github.com/perfect-panel/ppanel-web/commit/1c0ecae))
- **node-form**: Update number input fields to enforce step, min, and max values ([3f7b6d1](https://github.com/perfect-panel/ppanel-web/commit/3f7b6d1))
- **node-subscription**: Add copy functionality for columns ([3a81e37](https://github.com/perfect-panel/ppanel-web/commit/3a81e37))
- **node**: Add NodeStatus ([c712624](https://github.com/perfect-panel/ppanel-web/commit/c712624))
- **node**: Add protocol ([301b635](https://github.com/perfect-panel/ppanel-web/commit/301b635))
- **node**: Add serverKey ([25ce37e](https://github.com/perfect-panel/ppanel-web/commit/25ce37e))
- **node**: Add status ([c06372b](https://github.com/perfect-panel/ppanel-web/commit/c06372b))
- **node**: Add tags ([f408fdf](https://github.com/perfect-panel/ppanel-web/commit/f408fdf))
- **node**: Move the node configuration to the server module ([7f0f5ce](https://github.com/perfect-panel/ppanel-web/commit/7f0f5ce))
- **oauth**: Add certification component for handling OAuth login callbacks and improve user authentication flow ([5ed04c0](https://github.com/perfect-panel/ppanel-web/commit/5ed04c0))
- **oauth**: Implement OAuth token retrieval and refactor login callback handling ([40a6f7c](https://github.com/perfect-panel/ppanel-web/commit/40a6f7c))
- **oauth**: Refactor platform parameter handling and improve logout redirection logic ([8346c85](https://github.com/perfect-panel/ppanel-web/commit/8346c85))
- **oauth**: Update OAuth login handling to use callback parameter and improve URL parameter retrieval ([9227411](https://github.com/perfect-panel/ppanel-web/commit/9227411))
- **payment**: Add bank card payment ([7fa3a57](https://github.com/perfect-panel/ppanel-web/commit/7fa3a57))
- **payment**: Add isEdit prop to PaymentForm and disable fields when editing ([85f55de](https://github.com/perfect-panel/ppanel-web/commit/85f55de))
- **platform**: Update platform naming and add keywords and custom HTML fields ([6384237](https://github.com/perfect-panel/ppanel-web/commit/6384237))
- **privacy-policy**: Add privacy policy related text and links ([baa68f0](https://github.com/perfect-panel/ppanel-web/commit/baa68f0))
- **profile**: Update localization strings and enhance third-party account binding ([2d1effb](https://github.com/perfect-panel/ppanel-web/commit/2d1effb))
- **relay**: Add relay mode configuration and update related schemas ([3cc9477](https://github.com/perfect-panel/ppanel-web/commit/3cc9477))
- **release**: Extend supported platforms for Docker images, closes [#9](https://github.com/perfect-panel/ppanel-web/issues/9) ([e3a31eb](https://github.com/perfect-panel/ppanel-web/commit/e3a31eb))
- **schema**: Add security field to hysteria2 and tuic schemas ([cd59d44](https://github.com/perfect-panel/ppanel-web/commit/cd59d44))
- **site**: Added localization support for custom HTML and keyword fields ([f9d7736](https://github.com/perfect-panel/ppanel-web/commit/f9d7736))
- **sms**: Update locales ([938363b](https://github.com/perfect-panel/ppanel-web/commit/938363b))
- **stats**: Replace dynamic stat fetching with environment constants for user, server, and location counts ([46ae166](https://github.com/perfect-panel/ppanel-web/commit/46ae166))
- **subscribe**: Add 'sold' column to SubscribeTable and update inventory terminology ([19619fd](https://github.com/perfect-panel/ppanel-web/commit/19619fd))
- **subscribe**: Add reset_time to API typings and update unsubscribe logic ([eeea165](https://github.com/perfect-panel/ppanel-web/commit/eeea165))
- **subscribe**: Add subscribe_discount type ([f99c604](https://github.com/perfect-panel/ppanel-web/commit/f99c604))
- **subscribe**: Add subscription credits ([5bc7905](https://github.com/perfect-panel/ppanel-web/commit/5bc7905))
- **subscribe**: Add unit time ([39d07ec](https://github.com/perfect-panel/ppanel-web/commit/39d07ec))
- **subscribe**: Add unsubscribe functionality with confirmation messages and localized strings ([b2a2f42](https://github.com/perfect-panel/ppanel-web/commit/b2a2f42))
- **subscribe**: Improve error handling in subscription forms and update component props ([d28a10b](https://github.com/perfect-panel/ppanel-web/commit/d28a10b))
- **subscribe**: Improve layout and styling in subscription components ([5766376](https://github.com/perfect-panel/ppanel-web/commit/5766376))
- **subscribe**: Move subscription configuration and application to subscription module ([f90d4d2](https://github.com/perfect-panel/ppanel-web/commit/f90d4d2))
- **subscribe**: Update SubscribeTable component to use API.SubscribeItem type and ensure proper type casting ([f26f1c2](https://github.com/perfect-panel/ppanel-web/commit/f26f1c2))
- **subscribe**: Update suffix from 'MB' to 'Mbps' and enhance speed limit display logic ([3547bb1](https://github.com/perfect-panel/ppanel-web/commit/3547bb1))
- **subscription**: Improve layout and organization of subscription detail tabs ([e4630f8](https://github.com/perfect-panel/ppanel-web/commit/e4630f8))
- **subscription**: Add delete user subscription functionality ([1fc3a10](https://github.com/perfect-panel/ppanel-web/commit/1fc3a10))
- **subscription**: Add localized messages for existing subscriptions and deletion restrictions ([e8a72d5](https://github.com/perfect-panel/ppanel-web/commit/e8a72d5))
- **subscription**: Refactor subscription handling and update imports for better organization ([2215c7f](https://github.com/perfect-panel/ppanel-web/commit/2215c7f))
- **table**: Add sorting support for Node and subscription columns ([27924b0](https://github.com/perfect-panel/ppanel-web/commit/27924b0))
- **table**: Supports drag and drop sorting ([2f56ef5](https://github.com/perfect-panel/ppanel-web/commit/2f56ef5))
- **timeline**: Simplify timeline component layout and remove commented-out code ([fbad3b0](https://github.com/perfect-panel/ppanel-web/commit/fbad3b0))
- **tos**: Display data ([6024454](https://github.com/perfect-panel/ppanel-web/commit/6024454))
- **tutorial**: Add common tutorial list ([872252c](https://github.com/perfect-panel/ppanel-web/commit/872252c))
- **tutorial**: Fetch the latest tutorial version from GitHub API for dynamic URL generation ([28f8c78](https://github.com/perfect-panel/ppanel-web/commit/28f8c78))
- **ui**: System Tool ([1836980](https://github.com/perfect-panel/ppanel-web/commit/1836980))
- **ui**: Update homepage data ([8425b13](https://github.com/perfect-panel/ppanel-web/commit/8425b13))
- **ui**: Update input components and enhance card minimum width for better layout ([8a02310](https://github.com/perfect-panel/ppanel-web/commit/8a02310))
- **user**: Add 'gift_amount' field and update related references in user services and components ([b13c77e](https://github.com/perfect-panel/ppanel-web/commit/b13c77e))
- **user**: Add telephone input with area code selection and update localization ([585b99c](https://github.com/perfect-panel/ppanel-web/commit/585b99c))
- **user**: Add user Detail ([3a3d223](https://github.com/perfect-panel/ppanel-web/commit/3a3d223))
- **user**: Add User Detail ([fdaf11b](https://github.com/perfect-panel/ppanel-web/commit/fdaf11b))
- **user**: Integrate subscription list into user management, update request parameters and types ([8d49dac](https://github.com/perfect-panel/ppanel-web/commit/8d49dac))
- Update Auth Control ([c59742a](https://github.com/perfect-panel/ppanel-web/commit/c59742a))
### 🎫 Chores
- **config**: Entry locale ([5737331](https://github.com/perfect-panel/ppanel-web/commit/5737331))
- **deps**: Update package dependencies across multiple projects for improved stability and performance ([b01a5bc](https://github.com/perfect-panel/ppanel-web/commit/b01a5bc))
- **init**: Project initialization ([829edfa](https://github.com/perfect-panel/ppanel-web/commit/829edfa))
- **merge**: Add advertising module and device settings ([0130e02](https://github.com/perfect-panel/ppanel-web/commit/0130e02))
- **merge**: Bump version to 1.0.0-beta.26 and update changelog ([3222016](https://github.com/perfect-panel/ppanel-web/commit/3222016))
- **release**: V1.0.0-beta.1 [skip ci] ([7284d1c](https://github.com/perfect-panel/ppanel-web/commit/7284d1c))
- **release**: V1.0.0-beta.10 [skip ci] ([5cf573a](https://github.com/perfect-panel/ppanel-web/commit/5cf573a))
- **release**: V1.0.0-beta.11 [skip ci] ([1f29506](https://github.com/perfect-panel/ppanel-web/commit/1f29506))
- **release**: V1.0.0-beta.12 [skip ci] ([4418c47](https://github.com/perfect-panel/ppanel-web/commit/4418c47))
- **release**: V1.0.0-beta.13 [skip ci] ([23c974a](https://github.com/perfect-panel/ppanel-web/commit/23c974a))
- **release**: V1.0.0-beta.14 [skip ci] ([0fb0d8b](https://github.com/perfect-panel/ppanel-web/commit/0fb0d8b))
- **release**: V1.0.0-beta.15 [skip ci] ([b2e8fad](https://github.com/perfect-panel/ppanel-web/commit/b2e8fad))
- **release**: V1.0.0-beta.16 [skip ci] ([c3eff0a](https://github.com/perfect-panel/ppanel-web/commit/c3eff0a))
- **release**: V1.0.0-beta.17 [skip ci] ([5b64389](https://github.com/perfect-panel/ppanel-web/commit/5b64389))
- **release**: V1.0.0-beta.18 [skip ci] ([4a00233](https://github.com/perfect-panel/ppanel-web/commit/4a00233))
- **release**: V1.0.0-beta.19 [skip ci] ([0f15fb8](https://github.com/perfect-panel/ppanel-web/commit/0f15fb8))
- **release**: V1.0.0-beta.2 [skip ci] ([087c36c](https://github.com/perfect-panel/ppanel-web/commit/087c36c))
- **release**: V1.0.0-beta.20 [skip ci] ([bbd44f0](https://github.com/perfect-panel/ppanel-web/commit/bbd44f0))
- **release**: V1.0.0-beta.21 [skip ci] ([ca642c2](https://github.com/perfect-panel/ppanel-web/commit/ca642c2))
- **release**: V1.0.0-beta.22 [skip ci] ([c0fb34f](https://github.com/perfect-panel/ppanel-web/commit/c0fb34f))
- **release**: V1.0.0-beta.23 [skip ci] ([cf1d66d](https://github.com/perfect-panel/ppanel-web/commit/cf1d66d))
- **release**: V1.0.0-beta.24 [skip ci] ([01a3aa0](https://github.com/perfect-panel/ppanel-web/commit/01a3aa0))
- **release**: V1.0.0-beta.25 [skip ci] ([047a698](https://github.com/perfect-panel/ppanel-web/commit/047a698))
- **release**: V1.0.0-beta.26 [skip ci] ([79edea7](https://github.com/perfect-panel/ppanel-web/commit/79edea7))
- **release**: V1.0.0-beta.27 [skip ci] ([092477b](https://github.com/perfect-panel/ppanel-web/commit/092477b))
- **release**: V1.0.0-beta.27 [skip ci] ([85fdc36](https://github.com/perfect-panel/ppanel-web/commit/85fdc36))
- **release**: V1.0.0-beta.28 [skip ci] ([786ba0e](https://github.com/perfect-panel/ppanel-web/commit/786ba0e))
- **release**: V1.0.0-beta.28 [skip ci] ([d10ecc9](https://github.com/perfect-panel/ppanel-web/commit/d10ecc9))
- **release**: V1.0.0-beta.29 [skip ci] ([29bc3c7](https://github.com/perfect-panel/ppanel-web/commit/29bc3c7))
- **release**: V1.0.0-beta.3 [skip ci] ([cd49427](https://github.com/perfect-panel/ppanel-web/commit/cd49427))
- **release**: V1.0.0-beta.30 [skip ci] ([db0d9e0](https://github.com/perfect-panel/ppanel-web/commit/db0d9e0))
- **release**: V1.0.0-beta.31 [skip ci] ([aa1d426](https://github.com/perfect-panel/ppanel-web/commit/aa1d426))
- **release**: V1.0.0-beta.32 [skip ci] ([fa56eb8](https://github.com/perfect-panel/ppanel-web/commit/fa56eb8))
- **release**: V1.0.0-beta.33 [skip ci] ([383638f](https://github.com/perfect-panel/ppanel-web/commit/383638f))
- **release**: V1.0.0-beta.34 [skip ci] ([7023875](https://github.com/perfect-panel/ppanel-web/commit/7023875))
- **release**: V1.0.0-beta.4 [skip ci] ([10d322f](https://github.com/perfect-panel/ppanel-web/commit/10d322f))
- **release**: V1.0.0-beta.5 [skip ci] ([f275f01](https://github.com/perfect-panel/ppanel-web/commit/f275f01))
- **release**: V1.0.0-beta.6 [skip ci] ([dd23279](https://github.com/perfect-panel/ppanel-web/commit/dd23279))
- **release**: V1.0.0-beta.7 [skip ci] ([f60d40c](https://github.com/perfect-panel/ppanel-web/commit/f60d40c))
- **release**: V1.0.0-beta.8 [skip ci], closes [#9](https://github.com/perfect-panel/ppanel-web/issues/9) ([a593eac](https://github.com/perfect-panel/ppanel-web/commit/a593eac))
- **release**: V1.0.0-beta.9 [skip ci] ([855d1b0](https://github.com/perfect-panel/ppanel-web/commit/855d1b0))
- **ui**: Update package dependencies for improved stability and performance ([25da429](https://github.com/perfect-panel/ppanel-web/commit/25da429))
- Merge branch 'beta' into develop ([f219c52](https://github.com/perfect-panel/ppanel-web/commit/f219c52))
- Update changelog, enhance prepare script, and add openapi command ([a93db4e](https://github.com/perfect-panel/ppanel-web/commit/a93db4e))
### 🐛 Bug Fixes
- **admin**: Hidden versions and system upgrades ([64cd842](https://github.com/perfect-panel/ppanel-web/commit/64cd842))
- **admin**: Modify the label type in the rule form to a string array ([a7aa5fe](https://github.com/perfect-panel/ppanel-web/commit/a7aa5fe))
- **affiliate**: Update user identifier ([35f92c9](https://github.com/perfect-panel/ppanel-web/commit/35f92c9))
- **api**: Fix type error in API request and add return URL parameter ([ee286dd](https://github.com/perfect-panel/ppanel-web/commit/ee286dd))
- **api**: PreCreateOrder ([ca747f5](https://github.com/perfect-panel/ppanel-web/commit/ca747f5))
- **api**: Purge ([98c1c30](https://github.com/perfect-panel/ppanel-web/commit/98c1c30))
- **api**: Remove redundant requestType parameter in appleLoginCallback ([0aa5d5b](https://github.com/perfect-panel/ppanel-web/commit/0aa5d5b))
- **api**: Rename app-related functions and types to application for consistency ([9d8b814](https://github.com/perfect-panel/ppanel-web/commit/9d8b814))
- **api**: Replace 'deduction' with 'gift_amount' and add 'commission' field in type definitions ([77edf1d](https://github.com/perfect-panel/ppanel-web/commit/77edf1d))
- **api**: Server and order ([255bd82](https://github.com/perfect-panel/ppanel-web/commit/255bd82))
- **api**: Statistics ([7962162](https://github.com/perfect-panel/ppanel-web/commit/7962162))
- **api**: Subscribe token ([1932ba7](https://github.com/perfect-panel/ppanel-web/commit/1932ba7))
- **api**: Update API type definitions to replace 'deduction' with 'gift_amount' and make 'commission' field optional ([c2af060](https://github.com/perfect-panel/ppanel-web/commit/c2af060))
- **api**: Update Model ([39aaa73](https://github.com/perfect-panel/ppanel-web/commit/39aaa73))
- **api**: Update subscription_protocol to subscribe_type for consistency across services ([b6da51b](https://github.com/perfect-panel/ppanel-web/commit/b6da51b))
- **auth-control**: Fix citation error for platform values ([c940f3c](https://github.com/perfect-panel/ppanel-web/commit/c940f3c))
- **auth-control**: Fix citation error for platform values ([28813d2](https://github.com/perfect-panel/ppanel-web/commit/28813d2))
- **auth-control**: Rename phone_variable to phone_number in mobile verification configuration ([e5455aa](https://github.com/perfect-panel/ppanel-web/commit/e5455aa))
- **auth**: Add error handling to form submission and reset Turnstile on failure ([715d011](https://github.com/perfect-panel/ppanel-web/commit/715d011))
- **auth**: Change Textarea value to defaultValue for client_secret in Apple auth page ([69fc670](https://github.com/perfect-panel/ppanel-web/commit/69fc670))
- **auth**: Refactor forms to use Turnstile ref for reset functionality ([320a7dc](https://github.com/perfect-panel/ppanel-web/commit/320a7dc))
- **auth**: Refactor reset password form to simplify code input and update placeholder text ([23833b4](https://github.com/perfect-panel/ppanel-web/commit/23833b4))
- **auth**: Refactor user authentication forms to remove global store dependency and improve type handling ([12026b0](https://github.com/perfect-panel/ppanel-web/commit/12026b0))
- **auth**: Remove unused telephone code login function and update typings for telephone login requests ([7239685](https://github.com/perfect-panel/ppanel-web/commit/7239685))
- **auth**: Require minimum length for invite string when forced invite is enabled ([a604f28](https://github.com/perfect-panel/ppanel-web/commit/a604f28))
- **auth**: Simplify email verification code input rendering ([6f7bc37](https://github.com/perfect-panel/ppanel-web/commit/6f7bc37))
- **auth**: Update authentication configuration and localization strings ([47f2c58](https://github.com/perfect-panel/ppanel-web/commit/47f2c58))
- **auth**: Update email verification logic to use domain suffix check ([62662bb](https://github.com/perfect-panel/ppanel-web/commit/62662bb))
- **auth**: Update user authentication flow to include email and phone code verification ([5d078fd](https://github.com/perfect-panel/ppanel-web/commit/5d078fd))
- **auth**: Update UserCheckForm to use setInitialValues and modify onSubmit type ([c984c0d](https://github.com/perfect-panel/ppanel-web/commit/c984c0d))
- **billing**: ExpiryDate ([e85e545](https://github.com/perfect-panel/ppanel-web/commit/e85e545))
- **billing**: I18n and styles ([81e0f21](https://github.com/perfect-panel/ppanel-web/commit/81e0f21))
- **changelog**: Update change log style ([cfa3fc0](https://github.com/perfect-panel/ppanel-web/commit/cfa3fc0))
- **config**: AlipayF2F ([6c07107](https://github.com/perfect-panel/ppanel-web/commit/6c07107))
- **config**: Bugs ([f57e40c](https://github.com/perfect-panel/ppanel-web/commit/f57e40c))
- **config**: Checkout Order ([a31e763](https://github.com/perfect-panel/ppanel-web/commit/a31e763))
- **config**: FormatBytes ([bbc2da0](https://github.com/perfect-panel/ppanel-web/commit/bbc2da0))
- **config**: NoStore ([2cc18cf](https://github.com/perfect-panel/ppanel-web/commit/2cc18cf))
- **config**: Runtime env ([a1e4999](https://github.com/perfect-panel/ppanel-web/commit/a1e4999))
- **config**: Status Percentag ([8f322fb](https://github.com/perfect-panel/ppanel-web/commit/8f322fb))
- **config**: SubLink ([1c61966](https://github.com/perfect-panel/ppanel-web/commit/1c61966))
- **config**: Subscribe Link ([11ea821](https://github.com/perfect-panel/ppanel-web/commit/11ea821))
- **content**: Parse subscription description and display features with icons ([3c5542a](https://github.com/perfect-panel/ppanel-web/commit/3c5542a))
- **controller**: Order status ([8c6a097](https://github.com/perfect-panel/ppanel-web/commit/8c6a097))
- **coupon**: Rename 'server' field to 'subscribe' in coupon form and update coupon update request type ([f8b6d82](https://github.com/perfect-panel/ppanel-web/commit/f8b6d82))
- **dashboard**: Improve URL encoding for subscription links and enhance success message handling ([4983c33](https://github.com/perfect-panel/ppanel-web/commit/4983c33))
- **dashboard**: Update date display to use start_time if available ([e551232](https://github.com/perfect-panel/ppanel-web/commit/e551232))
- **dashboard**: Correct progress value calculations and update groupId accessor ([36c7667](https://github.com/perfect-panel/ppanel-web/commit/36c7667))
- **dashboard**: Display subscription creation date in user dashboard ([d0e6df0](https://github.com/perfect-panel/ppanel-web/commit/d0e6df0))
- **dashboard**: Format Bytes ([d8b0bd9](https://github.com/perfect-panel/ppanel-web/commit/d8b0bd9))
- **dashboard**: Update icon imports for platform consistency and adjust icon size ([3e8912e](https://github.com/perfect-panel/ppanel-web/commit/3e8912e))
- **dashboard**: Update platform detection logic and improve layout responsiveness ([b0aa364](https://github.com/perfect-panel/ppanel-web/commit/b0aa364))
- **deps**: Remove outdated @iconify/react dependency and add iconify-json packages ([d6fbc38](https://github.com/perfect-panel/ppanel-web/commit/d6fbc38))
- **deps**: Typescript config ([34e24b8](https://github.com/perfect-panel/ppanel-web/commit/34e24b8))
- **deps**: Update clipboard ([5572710](https://github.com/perfect-panel/ppanel-web/commit/5572710))
- **editor**: Change value ([4fdfeb2](https://github.com/perfect-panel/ppanel-web/commit/4fdfeb2))
- **email**: Update platform configuration handling to use current ref for consistency ([c90175b](https://github.com/perfect-panel/ppanel-web/commit/c90175b))
- **footer**: Email address ([a451f44](https://github.com/perfect-panel/ppanel-web/commit/a451f44))
- **forms**: Add step attribute to number inputs for better value control ([b8f4f1e](https://github.com/perfect-panel/ppanel-web/commit/b8f4f1e))
- **icon**: Comment out unused icon collection imports ([f17bf8d](https://github.com/perfect-panel/ppanel-web/commit/f17bf8d))
- **layout**: Remove unnecessary cookie initialization in Logout function ([3065c3a](https://github.com/perfect-panel/ppanel-web/commit/3065c3a))
- **locale**: Default value ([937408f](https://github.com/perfect-panel/ppanel-web/commit/937408f))
- **locale**: Document ([6f0fa20](https://github.com/perfect-panel/ppanel-web/commit/6f0fa20))
- **locale**: Empty ([3832d20](https://github.com/perfect-panel/ppanel-web/commit/3832d20))
- **locale**: Input Placeholder Webhook Domain ([bca0935](https://github.com/perfect-panel/ppanel-web/commit/bca0935))
- **locale**: Language Select ([0befdb0](https://github.com/perfect-panel/ppanel-web/commit/0befdb0))
- **locales**: Add error message for incorrect user information ([52c1d1f](https://github.com/perfect-panel/ppanel-web/commit/52c1d1f))
- **locales**: Add error message for incorrect user information ([3d92902](https://github.com/perfect-panel/ppanel-web/commit/3d92902))
- **locales**: Add logout message to authentication localization files ([1d0d911](https://github.com/perfect-panel/ppanel-web/commit/1d0d911))
- **locales**: Fixed description in multilingual files, updated text related to email registration functionality ([c356bc2](https://github.com/perfect-panel/ppanel-web/commit/c356bc2))
- **locales**: Order recharge related fields ([35210fe](https://github.com/perfect-panel/ppanel-web/commit/35210fe))
- **locales**: Removed language file import to clean up unnecessary language support ([68f6ab2](https://github.com/perfect-panel/ppanel-web/commit/68f6ab2))
- **locales**: Removed multilingual files to clean up unnecessary language support ([5b151cd](https://github.com/perfect-panel/ppanel-web/commit/5b151cd))
- **locale**: Subscription Path Description ([4c67387](https://github.com/perfect-panel/ppanel-web/commit/4c67387))
- **locales**: Update custom HTML description for clarity across multiple languages ([557c5cd](https://github.com/perfect-panel/ppanel-web/commit/557c5cd))
- **locales**: Update custom HTML description in language file, ([87381da](https://github.com/perfect-panel/ppanel-web/commit/87381da))
- **locales**: Update expiration time description from minutes to seconds in multiple languages ([5bac933](https://github.com/perfect-panel/ppanel-web/commit/5bac933))
- **locales**: Update Hong Kong ([6d0d069](https://github.com/perfect-panel/ppanel-web/commit/6d0d069))
- **locales**: Update invite code text to indicate it's optional ([6a34bfb](https://github.com/perfect-panel/ppanel-web/commit/6a34bfb))
- **logs**: Update log display to render key-value pairs and remove badge ([5ea6489](https://github.com/perfect-panel/ppanel-web/commit/5ea6489))
- **metadata**: Global metadata ([15d5ecf](https://github.com/perfect-panel/ppanel-web/commit/15d5ecf))
- **nav**: Comment out unused social login options to simplify navigation configuration ([cefcb31](https://github.com/perfect-panel/ppanel-web/commit/cefcb31))
- **node-config**: Add null checks for time slots and ensure proper handling of undefined values ([1cdb7e7](https://github.com/perfect-panel/ppanel-web/commit/1cdb7e7))
- **node**: Add country and city fields to the form schema and localization files ([8775fb6](https://github.com/perfect-panel/ppanel-web/commit/8775fb6))
- **node**: Handle potential null value for online users count ([fa2fb28](https://github.com/perfect-panel/ppanel-web/commit/fa2fb28))
- **node**: Locale and form ([38be4d5](https://github.com/perfect-panel/ppanel-web/commit/38be4d5))
- **node**: Port config ([a20834a](https://github.com/perfect-panel/ppanel-web/commit/a20834a))
- **node**: Reality config ([fadd17f](https://github.com/perfect-panel/ppanel-web/commit/fadd17f))
- **node**: Service Name config ([d0be685](https://github.com/perfect-panel/ppanel-web/commit/d0be685))
- **node**: TLS config ([57fae12](https://github.com/perfect-panel/ppanel-web/commit/57fae12))
- **node**: Trojan protocol config ([7e1eb90](https://github.com/perfect-panel/ppanel-web/commit/7e1eb90))
- **notify**: Ensure user info is updated after notification settings submission ([9bc3a94](https://github.com/perfect-panel/ppanel-web/commit/9bc3a94))
- **notify**: Set default values for notification settings to false ([3652819](https://github.com/perfect-panel/ppanel-web/commit/3652819))
- **oauth**: Refactor OAuth configuration types and update related API methods ([6227ba9](https://github.com/perfect-panel/ppanel-web/commit/6227ba9))
- **oauth**: Remove redundant checks when updating configuration to simplify logic ([9140b8a](https://github.com/perfect-panel/ppanel-web/commit/9140b8a))
- **payment**: Add notification URL field to payment management interface ([5c710e1](https://github.com/perfect-panel/ppanel-web/commit/5c710e1))
- **payment**: Config and types ([b0c87fb](https://github.com/perfect-panel/ppanel-web/commit/b0c87fb))
- **payment**: Fix payment related type definitions and update payment method references ([c3138a8](https://github.com/perfect-panel/ppanel-web/commit/c3138a8))
- **payment**: Qrcode ([a9a535b](https://github.com/perfect-panel/ppanel-web/commit/a9a535b))
- **payment**: Refactor payment form placeholder and update localization files ([4a4d364](https://github.com/perfect-panel/ppanel-web/commit/4a4d364))
- **payment**: Refactor purchaseCheckout usage and remove redundant code ([a5e2079](https://github.com/perfect-panel/ppanel-web/commit/a5e2079))
- **payment**: Replace window.open with window.location.href for checkout links ([1d8c765](https://github.com/perfect-panel/ppanel-web/commit/1d8c765))
- **payment**: Update checkout type from 'link' to 'url' for consistency ([136a1ab](https://github.com/perfect-panel/ppanel-web/commit/136a1ab))
- **payment**: Update payment information ([70d6a38](https://github.com/perfect-panel/ppanel-web/commit/70d6a38))
- **payment**: Update payment method update logic to include row data ([6752420](https://github.com/perfect-panel/ppanel-web/commit/6752420))
- **phone**: Update SMS expiration time field to use 'sms_expire_time' with default value of 300 ([18b07c7](https://github.com/perfect-panel/ppanel-web/commit/18b07c7))
- **profile**: Restore filter to ensure only valid OAuth accounts are shown ([315c8f9](https://github.com/perfect-panel/ppanel-web/commit/315c8f9))
- **purchasing**: Update payment type to lowercase and add optional chaining for discounts ([c06ea49](https://github.com/perfect-panel/ppanel-web/commit/c06ea49))
- **redirect**: Simplify redirect URL logic by removing unnecessary condition for sessionStorage ([c53ac61](https://github.com/perfect-panel/ppanel-web/commit/c53ac61))
- **redirect**: Update redirect URL logic to ensure proper handling of OAuth and auth paths ([7954762](https://github.com/perfect-panel/ppanel-web/commit/7954762))
- **register**: Adjust user email verification logic to handle domain suffix checks correctly ([686aa2d](https://github.com/perfect-panel/ppanel-web/commit/686aa2d))
- **request**: Add error code 40005 to trigger logout ([71bf002](https://github.com/perfect-panel/ppanel-web/commit/71bf002))
- **request**: Locale ([37d408f](https://github.com/perfect-panel/ppanel-web/commit/37d408f))
- **rule-form**: Remove redundant rule set display ([6e0c9b6](https://github.com/perfect-panel/ppanel-web/commit/6e0c9b6))
- **rules**: Remove unused MATCH rule ([674a01c](https://github.com/perfect-panel/ppanel-web/commit/674a01c))
- **site**: Add image upload functionality for site logo configuration ([4ea6e4a](https://github.com/perfect-panel/ppanel-web/commit/4ea6e4a))
- **site**: Se ref to store site configuration for updates ([0c8f091](https://github.com/perfect-panel/ppanel-web/commit/0c8f091))
- **sort**: Refactor sorting logic in NodeTable and SubscribeTable components for improved clarity and performance ([331bbea](https://github.com/perfect-panel/ppanel-web/commit/331bbea))
- **subscribe**: Add value prop to field in subscription form for proper state management ([328838d](https://github.com/perfect-panel/ppanel-web/commit/328838d))
- **subscribe**: Discount ([35a9f69](https://github.com/perfect-panel/ppanel-web/commit/35a9f69))
- **subscribe**: Extract Domain ([40d61a9](https://github.com/perfect-panel/ppanel-web/commit/40d61a9))
- **subscribe**: Handle optional values in price and discount calculations ([5939763](https://github.com/perfect-panel/ppanel-web/commit/5939763))
- **subscribe**: Jumps and internationalization ([13fdec3](https://github.com/perfect-panel/ppanel-web/commit/13fdec3))
- **subscribe**: Refactor discount calculations and default selection logic in subscription forms ([423b240](https://github.com/perfect-panel/ppanel-web/commit/423b240))
- **subscribe**: Server group id ([90e6764](https://github.com/perfect-panel/ppanel-web/commit/90e6764))
- **subscribe**: Update default selection logic in subscription form to ensure proper state management ([ef15374](https://github.com/perfect-panel/ppanel-web/commit/ef15374))
- **subscribe**: Update forms to include refetch functionality and improve toast messages ([fc55e95](https://github.com/perfect-panel/ppanel-web/commit/fc55e95))
- **subscribe**: Update payment return URL ([2b80496](https://github.com/perfect-panel/ppanel-web/commit/2b80496))
- **subscribe**: Update subscription domain placeholder to include examples; improve site name retrieval in global store ([c65a44c](https://github.com/perfect-panel/ppanel-web/commit/c65a44c))
- **subscribe**: Update value validation to check for number type in subscribe form ([6de29d5](https://github.com/perfect-panel/ppanel-web/commit/6de29d5))
- **subscription**: Add reset functionality for user subscription token ([39e89bf](https://github.com/perfect-panel/ppanel-web/commit/39e89bf))
- **table**: Update privacy policy tab translation key and remove unnecessary requestType from OAuth callback ([14b3af5](https://github.com/perfect-panel/ppanel-web/commit/14b3af5))
- **third-party-accounts**: Remove mobile display logic from third-party accounts component ([b4946f7](https://github.com/perfect-panel/ppanel-web/commit/b4946f7))
- **third-party-accounts**: Update redirect property name in binding response handling ([012e83a](https://github.com/perfect-panel/ppanel-web/commit/012e83a))
- **turnstile**: Turnstile_site_key ([0327b73](https://github.com/perfect-panel/ppanel-web/commit/0327b73))
- **type**: Fix ts type check error ([3cb0629](https://github.com/perfect-panel/ppanel-web/commit/3cb0629))
- **types**: Add 'gift_amount' field to API type definitions ([8f8a12a](https://github.com/perfect-panel/ppanel-web/commit/8f8a12a))
- **types**: Checking ([2992824](https://github.com/perfect-panel/ppanel-web/commit/2992824))
- **types**: Order type ([c7e50a9](https://github.com/perfect-panel/ppanel-web/commit/c7e50a9))
- **ui**: Bugs ([b023d0f](https://github.com/perfect-panel/ppanel-web/commit/b023d0f))
- **ui**: Components ([a7927d7](https://github.com/perfect-panel/ppanel-web/commit/a7927d7))
- **ui**: Fix json formatting ([e1ddd94](https://github.com/perfect-panel/ppanel-web/commit/e1ddd94))
- **ui**: Improve dashboard layout and enhance button functionality; open checkout URLs in a new tab ([fc0da76](https://github.com/perfect-panel/ppanel-web/commit/fc0da76))
- **ui**: Multiple display bugs ([f5d8fd3](https://github.com/perfect-panel/ppanel-web/commit/f5d8fd3))
- **user-nav**: Update user avatar and label to display telephone if email is not available ([7b6bb7b](https://github.com/perfect-panel/ppanel-web/commit/7b6bb7b))
- **user**: Add the 'gift_amount' field to the user service's type definition ([6301409](https://github.com/perfect-panel/ppanel-web/commit/6301409))
- **user**: Refactor user form validation and reset password fields ([6733fc2](https://github.com/perfect-panel/ppanel-web/commit/6733fc2))
- **user**: Update locales ([4e7d249](https://github.com/perfect-panel/ppanel-web/commit/4e7d249))
- **user**: Update notification and verify code settings ([574b043](https://github.com/perfect-panel/ppanel-web/commit/574b043))
- **user**: Update user identifier field and localizations ([1b6befa](https://github.com/perfect-panel/ppanel-web/commit/1b6befa))
- **user**: Update user subscribe display ([3bb714d](https://github.com/perfect-panel/ppanel-web/commit/3bb714d))
- **utils**: Login redirect url ([cbe5f0d](https://github.com/perfect-panel/ppanel-web/commit/cbe5f0d))
- More bugs ([2d88a3a](https://github.com/perfect-panel/ppanel-web/commit/2d88a3a))
### 👷 Build System
- **config**: Update pm2 config ([d95b425](https://github.com/perfect-panel/ppanel-web/commit/d95b425))
### 💄 Styles
- **dashboard**: Adjust grid layout and update image dimensions in application display ([f3204b7](https://github.com/perfect-panel/ppanel-web/commit/f3204b7))
- **dashboard**: Enhance card components with full height and improved empty state handling ([7e1d551](https://github.com/perfect-panel/ppanel-web/commit/7e1d551))
- **document**: Update ([0a8109b](https://github.com/perfect-panel/ppanel-web/commit/0a8109b))
- **globals**: Refactor delete confirmation button and update badge styles in node and subscribe tables ([30ae781](https://github.com/perfect-panel/ppanel-web/commit/30ae781))
- **locales**: Remove unused subscription labels from multiple locale files ([fb0c510](https://github.com/perfect-panel/ppanel-web/commit/fb0c510))
- **locales**: Update server.json to reorganize relay mode options and improve labels ([701cdee](https://github.com/perfect-panel/ppanel-web/commit/701cdee))
- **node**: Form ([d5f5add](https://github.com/perfect-panel/ppanel-web/commit/d5f5add))
- **node**: Improve layout and spacing in NodeStatusCell component ([136287d](https://github.com/perfect-panel/ppanel-web/commit/136287d))
- **node**: Protocol Tab ([2bcb925](https://github.com/perfect-panel/ppanel-web/commit/2bcb925))
- **time-slot**: Add chart display ([c44ad47](https://github.com/perfect-panel/ppanel-web/commit/c44ad47))
- **ui**: Update mobile style ([eda18bc](https://github.com/perfect-panel/ppanel-web/commit/eda18bc))
- Update node secret UI and add telephone code field to authentication form ([770932e](https://github.com/perfect-panel/ppanel-web/commit/770932e))
### 📝 Documentation
- **readme**: License name ([74cb16b](https://github.com/perfect-panel/ppanel-web/commit/74cb16b))
### 🔧 Continuous Integration
- **github**: Release docker ([5af60aa](https://github.com/perfect-panel/ppanel-web/commit/5af60aa))
- **step**: Update step name ([9eca618](https://github.com/perfect-panel/ppanel-web/commit/9eca618))
<a name="readme-top"></a>
# Changelog
# [1.0.0-beta.34](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.33...v1.0.0-beta.34) (2025-04-02)
### ✨ Features
- **admin**: Add application and rule management entries to localization files ([8b43e69](https://github.com/perfect-panel/ppanel-web/commit/8b43e69))
- **api**: Add an interface to obtain user subscription details, update related type definitions and localized text ([cf5c39c](https://github.com/perfect-panel/ppanel-web/commit/cf5c39c))
- **user**: Integrate subscription list into user management, update request parameters and types ([8d49dac](https://github.com/perfect-panel/ppanel-web/commit/8d49dac))
### 🐛 Bug Fixes
- **admin**: Hidden versions and system upgrades ([64cd842](https://github.com/perfect-panel/ppanel-web/commit/64cd842))
- **admin**: Modify the label type in the rule form to a string array ([a7aa5fe](https://github.com/perfect-panel/ppanel-web/commit/a7aa5fe))
- **node**: Handle potential null value for online users count ([fa2fb28](https://github.com/perfect-panel/ppanel-web/commit/fa2fb28))
- **subscribe**: Add value prop to field in subscription form for proper state management ([328838d](https://github.com/perfect-panel/ppanel-web/commit/328838d))
- **subscribe**: Refactor discount calculations and default selection logic in subscription forms ([423b240](https://github.com/perfect-panel/ppanel-web/commit/423b240))
- **subscribe**: Update default selection logic in subscription form to ensure proper state management ([ef15374](https://github.com/perfect-panel/ppanel-web/commit/ef15374))
<a name="readme-top"></a>
# Changelog
# [1.0.0-beta.33](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.32...v1.0.0-beta.33) (2025-03-18)
### 🐛 Bug Fixes
- **subscribe**: Handle optional values in price and discount calculations ([5939763](https://github.com/perfect-panel/ppanel-web/commit/5939763))
# [1.0.0-beta.32](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.31...v1.0.0-beta.32) (2025-03-17)
### 🐛 Bug Fixes
- **forms**: Add step attribute to number inputs for better value control ([b8f4f1e](https://github.com/perfect-panel/ppanel-web/commit/b8f4f1e))
- **locales**: Update invite code text to indicate it's optional ([6a34bfb](https://github.com/perfect-panel/ppanel-web/commit/6a34bfb))
<a name="readme-top"></a> <a name="readme-top"></a>
+10 -1
View File
@@ -8,13 +8,22 @@ import LoginLottie from '@workspace/ui/lotties/login.json';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import Image from 'next/legacy/image'; import Image from 'next/legacy/image';
import Link from 'next/link'; import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
import EmailAuthForm from './email/auth-form'; import EmailAuthForm from './email/auth-form';
export default function Page() { export default function Page() {
const t = useTranslations('auth'); const t = useTranslations('auth');
const { common } = useGlobalStore(); const { common, user } = useGlobalStore();
const { site } = common; const { site } = common;
const router = useRouter();
useEffect(() => {
if (user) {
router.replace('/dashboard');
}
}, [router, user]);
return ( return (
<main className='bg-muted/50 flex h-full min-h-screen items-center'> <main className='bg-muted/50 flex h-full min-h-screen items-center'>
<div className='flex size-full flex-auto flex-col justify-center lg:flex-row'> <div className='flex size-full flex-auto flex-col justify-center lg:flex-row'>
@@ -232,16 +232,6 @@ export default function SubscribeAppForm<
name: 'is_default', name: 'is_default',
type: 'boolean', type: 'boolean',
placeholder: t('defaultVersion'), placeholder: t('defaultVersion'),
calculateValue: (value) => {
const newField = field.value?.map((item) => {
if (item.is_default) {
item.is_default = false;
}
return item;
});
form.setValue(field.name, newField);
return value;
},
}, },
{ {
name: 'url', name: 'url',
@@ -252,10 +242,32 @@ export default function SubscribeAppForm<
]} ]}
value={field.value} value={field.value}
onChange={(value) => { onChange={(value) => {
form.setValue( const filteredValue = value.filter((item) => item.url);
field.name,
value.filter((item) => item.url), const newDefaultIndex = value.findIndex(
(item, idx) =>
item.is_default &&
(!field.value?.[idx] || !field.value[idx].is_default),
); );
let finalValue = filteredValue;
if (newDefaultIndex >= 0 && filteredValue[newDefaultIndex]) {
finalValue = filteredValue.map((item, index) => ({
...item,
is_default: index === newDefaultIndex,
}));
} else if (
!filteredValue.some((item) => item.is_default) &&
filteredValue.length > 0
) {
finalValue = filteredValue.map((item, index) => ({
...item,
is_default: index === 0,
}));
}
form.setValue(field.name, finalValue as any);
}} }}
/> />
</FormControl> </FormControl>
@@ -136,14 +136,14 @@ export function Register() {
/> />
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow className='flex flex-col'>
<TableCell> <TableCell className='w-full'>
<Label>{t('trialSubscribePlan')}</Label> <Label>{t('trialSubscribePlan')}</Label>
<p className='text-muted-foreground text-xs'> <p className='text-muted-foreground text-xs'>
{t('trialSubscribePlanDescription')} {t('trialSubscribePlanDescription')}
</p> </p>
</TableCell> </TableCell>
<TableCell className='text-right'> <TableCell className='max-w-96'>
<EnhancedInput <EnhancedInput
placeholder={t('trialDuration')} placeholder={t('trialDuration')}
type='number' type='number'
+7 -2
View File
@@ -57,8 +57,13 @@ export default function Page(props: any) {
{ {
accessorKey: 'subscribe_id', accessorKey: 'subscribe_id',
header: t('subscribe'), header: t('subscribe'),
cell: ({ row }) => cell: ({ row }) => {
subscribeList?.find((item) => item.id === row.getValue('subscribe_id'))?.name, const name = subscribeList?.find(
(item) => item.id === row.getValue('subscribe_id'),
)?.name;
const quantity = row.original.quantity;
return name ? `${name} × ${quantity}` : '';
},
}, },
{ {
accessorKey: 'amount', accessorKey: 'amount',
@@ -201,7 +201,7 @@ export default function PaymentForm<T>({
<FormLabel>{t('domain')}</FormLabel> <FormLabel>{t('domain')}</FormLabel>
<FormControl> <FormControl>
<EnhancedInput <EnhancedInput
placeholder={t('domainPlaceholder', { example: 'http(s)://example.com' })} placeholder='http(s)://example.com'
value={field.value} value={field.value}
onValueChange={(value) => form.setValue('domain', value as string)} onValueChange={(value) => form.setValue('domain', value as string)}
/> />
@@ -371,6 +371,7 @@ export default function PaymentForm<T>({
? configValues[fieldKey] ? configValues[fieldKey]
: '' : ''
} }
disabled={fieldKey === 'webhook_secret'}
onValueChange={(value) => { onValueChange={(value) => {
const newConfig = { ...configValues }; const newConfig = { ...configValues };
newConfig[fieldKey] = value; newConfig[fieldKey] = value;
@@ -0,0 +1,240 @@
'use client';
import { createRuleGroup } from '@/services/admin/server';
import { Button } from '@workspace/ui/components/button';
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@workspace/ui/components/dialog';
import { Label } from '@workspace/ui/components/label';
import { Progress } from '@workspace/ui/components/progress';
import { Textarea } from '@workspace/ui/components/textarea';
import { Icon } from '@workspace/ui/custom-components/icon';
import yaml from 'js-yaml';
import { useTranslations } from 'next-intl';
import { useRef, useState } from 'react';
import { toast } from 'sonner';
interface ImportYamlRulesProps {
onImportSuccess?: () => void;
}
interface RuleGroup {
name: string;
rules: string[];
}
export default function ImportYamlRules({ onImportSuccess }: ImportYamlRulesProps) {
const t = useTranslations('rules');
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
const [yamlContent, setYamlContent] = useState('');
const [importProgress, setImportProgress] = useState(0);
const [importTotal, setImportTotal] = useState(0);
const [analyzing, setAnalyzing] = useState(false);
const fileInputRef = useRef<HTMLInputElement>(null);
const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (event) => {
const content = event.target?.result as string;
setYamlContent(content);
setOpen(true);
};
reader.readAsText(file);
e.target.value = '';
};
const processRule = (rule: string): { policyGroup: string; cleanRule: string } | null => {
const parts = rule.split(',');
if (parts.length === 1) {
return null;
}
let policyGroup = 'default';
let cleanRule = rule;
if (parts.length >= 3) {
const thirdPart = parts[2]?.trim();
if (thirdPart) {
policyGroup = thirdPart;
}
}
cleanRule = parts.slice(0, 2).join(',');
return { policyGroup, cleanRule };
};
const parseRulesIntoGroups = (rules: string[]): Record<string, string[]> => {
const groups: Record<string, string[]> = {};
for (const rule of rules) {
if (!rule.trim()) continue;
const result = processRule(rule);
if (result === null) continue;
const { policyGroup, cleanRule } = result;
if (!groups[policyGroup]) {
groups[policyGroup] = [];
}
// 不插入 MATCH 规则,只用于标识默认规则组
if (!rule.trim().startsWith('MATCH,')) {
groups[policyGroup].push(cleanRule);
}
}
return groups;
};
const checkIfDefaultRule = (originalRules: string[], groupName: string): boolean => {
return originalRules.some((rule) => {
const trimmedRule = rule.trim();
if (!trimmedRule.startsWith('MATCH,')) return false;
// 检查 MATCH 规则是否属于当前组
const parts = trimmedRule.split(',');
if (parts.length >= 3) {
const ruleGroup = parts[2]?.trim();
return ruleGroup === groupName;
}
return groupName === 'default';
});
};
const handleImport = async () => {
if (!yamlContent) {
toast.error(t('pleaseUploadFile'));
return;
}
setLoading(true);
setAnalyzing(true);
try {
const parsedYaml = yaml.load(yamlContent) as any;
if (!parsedYaml || !parsedYaml.rules) {
throw new Error(t('invalidYamlFormat'));
}
let allRules: string[] = [];
if (Array.isArray(parsedYaml.rules)) {
allRules = parsedYaml.rules.filter((rule: string) => rule.trim());
}
if (allRules.length === 0) {
throw new Error(t('noValidRules'));
}
const ruleGroups = parseRulesIntoGroups(allRules);
const groups = Object.entries(ruleGroups).map(([name, rules]) => ({
name,
rules,
}));
setImportTotal(groups.length);
setAnalyzing(false);
for (let i = 0; i < groups.length; i++) {
const group = groups[i];
if (!group?.name || !group?.rules.length) continue;
const isDefault = checkIfDefaultRule(allRules, group.name);
await createRuleGroup({
name: group.name,
rules: group?.rules.join('\n'),
enable: false,
tags: [],
icon: '',
type: 'default',
default: isDefault,
});
setImportProgress(i + 1);
}
toast.success(t('importSuccess'));
setOpen(false);
setYamlContent('');
setImportProgress(0);
setImportTotal(0);
onImportSuccess?.();
} catch (error) {
console.error('Import error:', error);
toast.error(error instanceof Error ? error.message : t('importFailed'));
} finally {
setLoading(false);
setAnalyzing(false);
}
};
return (
<>
<input
ref={fileInputRef}
type='file'
accept='.yml,.yaml'
style={{ display: 'none' }}
onChange={handleFileUpload}
/>
<Button variant='default' onClick={() => fileInputRef.current?.click()}>
{t('import')}
</Button>
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent className='sm:max-w-[500px]'>
<DialogHeader>
<DialogTitle>{t('importYamlRules')}</DialogTitle>
<DialogDescription>{t('importYamlDescription')}</DialogDescription>
</DialogHeader>
<div className='grid gap-4 py-4'>
{yamlContent && (
<div className='grid gap-2'>
<Label htmlFor='preview'>{t('preview')}</Label>
<Textarea
id='preview'
value={yamlContent}
readOnly
rows={10}
className='font-mono text-xs'
/>
</div>
)}
{importTotal > 0 && (
<div className='grid gap-2'>
<div className='flex justify-between text-sm'>
<span>{analyzing ? t('analyzing') : t('importing')}</span>
<span>
{importProgress} / {importTotal}
</span>
</div>
<Progress value={(importProgress / importTotal) * 100} />
</div>
)}
</div>
<DialogFooter>
<Button variant='outline' onClick={() => setOpen(false)} disabled={loading}>
{t('cancel')}
</Button>
<Button onClick={handleImport} disabled={loading || !yamlContent}>
{loading && <Icon icon='mdi:loading' className='mr-2 animate-spin' />}
{t('import')}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</>
);
}
+244
View File
@@ -0,0 +1,244 @@
'use client';
import { ProTable, ProTableActions } from '@/components/pro-table';
import {
createRuleGroup,
deleteRuleGroup,
getRuleGroupList,
updateRuleGroup,
} from '@/services/admin/server';
import { Badge } from '@workspace/ui/components/badge';
import { Button } from '@workspace/ui/components/button';
import { Switch } from '@workspace/ui/components/switch';
import { ConfirmButton } from '@workspace/ui/custom-components/confirm-button';
import { formatDate } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl';
import Image from 'next/legacy/image';
import Link from 'next/link';
import { useRef, useState } from 'react';
import { toast } from 'sonner';
import ImportYamlRules from './import-yaml-rules';
import RuleForm from './rule-form';
export default function Page() {
const t = useTranslations('rules');
const [loading, setLoading] = useState(false);
const ref = useRef<ProTableActions>(null);
return (
<ProTable<API.ServerRuleGroup, { query: string }>
action={ref}
header={{
toolbar: (
<div className='flex gap-2'>
<Button variant='default' asChild>
<Link href='/template/rules.yml' target='_blank' download>
{t('downloadTemplate')}
</Link>
</Button>
<ImportYamlRules onImportSuccess={() => ref.current?.refresh()} />
<RuleForm<API.CreateRuleGroupRequest>
trigger={t('create')}
title={t('createRule')}
loading={loading}
onSubmit={async (values) => {
setLoading(true);
try {
await createRuleGroup({
name: values.name,
rules: values.rules || '',
enable: false,
tags: values.tags || [],
icon: values.icon || '',
type: values.type || 'default',
default: false,
});
toast.success(t('createSuccess'));
ref.current?.refresh();
setLoading(false);
return true;
} catch (error) {
setLoading(false);
return false;
}
}}
/>
</div>
),
}}
params={[
{
key: 'search',
placeholder: t('searchRule'),
},
]}
request={async (pagination, filters) => {
const { data } = await getRuleGroupList({
...pagination,
...filters,
});
return {
list: data.data?.list || [],
total: data.data?.total || 0,
};
}}
columns={[
{
accessorKey: 'enable',
header: t('enable'),
cell: ({ row }) => {
return (
<Switch
defaultChecked={row.getValue('enable')}
onCheckedChange={async (checked) => {
await updateRuleGroup({
...row.original,
enable: checked,
} as API.UpdateRuleGroupRequest);
ref.current?.refresh();
}}
/>
);
},
},
{
accessorKey: 'default',
header: t('defaultRule'),
cell: ({ row }) => (
<Switch
defaultChecked={row.original.default}
onCheckedChange={async (checked) => {
await updateRuleGroup({
...row.original,
default: checked,
} as API.UpdateRuleGroupRequest);
ref.current?.refresh();
}}
/>
),
},
{
accessorKey: 'type',
header: t('type'),
cell: ({ row }) => {
const type = row.original.type || 'default';
if (type === 'default') {
return <Badge variant='default'>{t('default')}</Badge>;
}
if (type === 'reject') {
return <Badge variant='destructive'>{t('reject')}</Badge>;
}
if (type === 'direct') {
return <Badge variant='secondary'>{t('direct')}</Badge>;
}
return <Badge variant='default'>{t('default')}</Badge>;
},
},
{
accessorKey: 'name',
header: t('name'),
cell: ({ row }) => (
<div className='flex items-center gap-2'>
{row.original.icon && (
<Image
src={row.original.icon}
alt={row.original.name}
className='h-6 w-6 rounded-md'
width={24}
height={24}
/>
)}
<span>{row.original.name}</span>
</div>
),
},
{
accessorKey: 'tags',
header: t('tags'),
cell: ({ row }) => {
const tags = row.original.tags.filter((item) => item) || [];
if (!tags.length) return '--';
return (
<>
{tags.map((tag) => (
<Badge key={tag} variant='outline' className='mr-1'>
{tag}
</Badge>
))}
</>
);
},
},
{
accessorKey: 'created_at',
header: t('createdAt'),
cell: ({ row }) => formatDate(row.original.created_at),
},
]}
actions={{
render: (row) => [
<RuleForm<API.UpdateRuleGroupRequest>
key='edit'
trigger={t('edit')}
title={t('editRule')}
loading={loading}
initialValues={row}
onSubmit={async (values) => {
setLoading(true);
try {
await updateRuleGroup({
id: row.id,
name: values.name,
tags: values.tags,
rules: values.rules,
enable: row.enable,
icon: values.icon,
type: values.type,
default: row.default,
});
toast.success(t('updateSuccess'));
ref.current?.refresh();
setLoading(false);
return true;
} catch (error) {
setLoading(false);
return false;
}
}}
/>,
<ConfirmButton
key='delete'
trigger={<Button variant='destructive'>{t('delete')}</Button>}
title={t('confirmDelete')}
description={t('deleteWarning')}
onConfirm={async () => {
await deleteRuleGroup({ id: row.id });
toast.success(t('deleteSuccess'));
ref.current?.refresh();
}}
cancelText={t('cancel')}
confirmText={t('confirm')}
/>,
],
batchRender: (rows) => [
<ConfirmButton
key='delete'
trigger={<Button variant='destructive'>{t('delete')}</Button>}
title={t('confirmDelete')}
description={t('deleteWarning')}
onConfirm={async () => {
for (const row of rows) {
await deleteRuleGroup({ id: row.id });
}
toast.success(t('deleteSuccess'));
ref.current?.reset();
ref.current?.refresh();
}}
cancelText={t('cancel')}
confirmText={t('confirm')}
/>,
],
}}
/>
);
}
@@ -0,0 +1,266 @@
'use client';
import { getNodeTagList } from '@/services/admin/server';
import { zodResolver } from '@hookform/resolvers/zod';
import { useQuery } from '@tanstack/react-query';
import { Button } from '@workspace/ui/components/button';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@workspace/ui/components/form';
import { ScrollArea } from '@workspace/ui/components/scroll-area';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@workspace/ui/components/select';
import {
Sheet,
SheetContent,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from '@workspace/ui/components/sheet';
import { Textarea } from '@workspace/ui/components/textarea';
import { Combobox } from '@workspace/ui/custom-components/combobox';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { Icon } from '@workspace/ui/custom-components/icon';
import { UploadImage } from '@workspace/ui/custom-components/upload-image';
import { useTranslations } from 'next-intl';
import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
const formSchema = z.object({
name: z.string().min(1, { message: '请输入规则名称' }),
tags: z.array(z.string()).default([]),
rules: z.string().default(''),
icon: z.string().default(''),
type: z.string().default('default'),
});
interface RuleFormProps<T> {
onSubmit: (data: T) => Promise<boolean> | boolean;
initialValues?: T;
loading?: boolean;
trigger: string;
title: string;
}
export default function RuleForm<T extends Record<string, any>>({
onSubmit,
initialValues,
loading,
trigger,
title,
}: RuleFormProps<T>) {
const t = useTranslations('rules');
const [open, setOpen] = useState(false);
const form = useForm({
resolver: zodResolver(formSchema),
defaultValues: {
...initialValues,
} as any,
});
useEffect(() => {
if (initialValues) {
form.reset(initialValues);
}
}, [form, initialValues]);
async function handleSubmit(data: { [x: string]: any }) {
const bool = await onSubmit(data as T);
if (bool) setOpen(false);
}
const { data: tags } = useQuery({
queryKey: ['getNodeTagList'],
queryFn: async () => {
const { data } = await getNodeTagList();
return data.data?.tags || [];
},
});
return (
<Sheet open={open} onOpenChange={setOpen}>
<SheetTrigger asChild>
<Button
onClick={() => {
form.reset();
setOpen(true);
}}
>
{trigger}
</Button>
</SheetTrigger>
<SheetContent className='w-[500px] max-w-full md:max-w-screen-md'>
<SheetHeader>
<SheetTitle>{title}</SheetTitle>
</SheetHeader>
<ScrollArea className='-mx-6 h-[calc(100vh-48px-36px-36px-env(safe-area-inset-top))]'>
<Form {...form}>
<form onSubmit={form.handleSubmit(handleSubmit)} className='space-y-4 px-6 pt-4'>
<FormField
control={form.control}
name='icon'
render={({ field }) => (
<FormItem>
<FormLabel>{t('appIcon')}</FormLabel>
<FormControl>
<EnhancedInput
placeholder={t('enterIconUrl')}
value={field.value}
suffix={
<UploadImage
className='bg-muted h-9 rounded-none border-none px-2'
onChange={(value) => {
form.setValue(field.name, value as string);
}}
/>
}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='name'
render={({ field }) => (
<FormItem>
<FormLabel>{t('name')}</FormLabel>
<FormControl>
<EnhancedInput
placeholder={t('enterRuleName')}
value={field.value}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='type'
render={({ field }) => (
<FormItem>
<FormLabel>{t('type')}</FormLabel>
<FormControl>
<Select
value={field.value}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
>
<SelectTrigger>
<SelectValue placeholder={t('selectType')} />
</SelectTrigger>
<SelectContent>
<SelectItem value='default'>{t('default')}</SelectItem>
<SelectItem value='reject'>{t('reject')}</SelectItem>
<SelectItem value='direct'>{t('direct')}</SelectItem>
</SelectContent>
</Select>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='tags'
render={({ field }) => (
<FormItem>
<FormLabel>{t('tagsLabel')}</FormLabel>
<FormControl>
<Combobox<string, true>
multiple
placeholder={t('selectTags')}
value={field.value}
onChange={(value) => {
form.setValue(field.name, value);
}}
options={tags?.map((item: string) => ({
value: item,
label: item,
}))}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='rules'
render={({ field }) => (
<FormItem>
<FormLabel>{t('rulesLabel')}</FormLabel>
<FormControl>
<Textarea
placeholder={t('enterRules')}
value={field.value}
rows={10}
onChange={(e) => {
form.setValue(field.name, e.target.value);
}}
/>
</FormControl>
<div className='text-muted-foreground mt-1 text-xs'>
<pre>{t('rulesFormat')}</pre>
<div className='border-muted mt-2 space-y-1 border-l-2 pl-2'>
<p className='font-mono'>DOMAIN,example.com</p>
<p className='font-mono'>DOMAIN-SUFFIX,google.com,DIRECT</p>
<p className='font-mono'>DOMAIN-KEYWORD,amazon,REJECT</p>
<p className='font-mono'>IP-CIDR,192.168.0.0/16</p>
<p className='font-mono'>IP-CIDR6,2001:db8::/32,REJECT</p>
<p className='font-mono'>SRC-IP-CIDR,192.168.1.201/32</p>
<p className='font-mono'>GEOIP,CN,DIRECT</p>
<p className='font-mono'>GEOIP,US</p>
<p className='font-mono'>DST-PORT,80,DIRECT</p>
<p className='font-mono'>SRC-PORT,7777,REJECT</p>
<p className='font-mono'>PROCESS-NAME,telegram</p>
</div>
</div>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
</ScrollArea>
<SheetFooter className='flex-row justify-end gap-2 pt-3'>
<Button
variant='outline'
disabled={loading}
onClick={() => {
setOpen(false);
}}
>
{t('cancel')}
</Button>
<Button disabled={loading} onClick={form.handleSubmit(handleSubmit)}>
{loading && <Icon icon='mdi:loading' className='mr-2 animate-spin' />}
{t('confirm')}
</Button>
</SheetFooter>
</SheetContent>
</Sheet>
);
}
+14 -2
View File
@@ -1,6 +1,6 @@
import { z } from 'zod'; import { z } from 'zod';
export const protocols = ['shadowsocks', 'vmess', 'vless', 'trojan', 'hysteria2', 'tuic']; export const protocols = ['shadowsocks', 'vmess', 'vless', 'trojan', 'hysteria2', 'tuic', 'anytls'];
const nullableString = z.string().nullish(); const nullableString = z.string().nullish();
const portSchema = z.number().max(65535).nullish(); const portSchema = z.number().max(65535).nullish();
@@ -58,7 +58,15 @@ const hysteria2Schema = z.object({
const tuicSchema = z.object({ const tuicSchema = z.object({
port: portSchema, port: portSchema,
security: z.string(), disable_sni: z.boolean().default(false),
reduce_rtt: z.boolean().default(false),
udp_relay_mode: z.string().default('native'),
congestion_controller: z.string().default('bbr'),
security_config: securityConfigSchema,
});
const anytlsSchema = z.object({
port: portSchema,
security_config: securityConfigSchema, security_config: securityConfigSchema,
}); });
@@ -87,6 +95,10 @@ const protocolConfigSchema = z.discriminatedUnion('protocol', [
protocol: z.literal('tuic'), protocol: z.literal('tuic'),
config: tuicSchema, config: tuicSchema,
}), }),
z.object({
protocol: z.literal('anytls'),
config: anytlsSchema,
}),
]); ]);
const baseFormSchema = z.object({ const baseFormSchema = z.object({
+311 -194
View File
@@ -110,7 +110,7 @@ export default function NodeForm<T extends { [x: string]: any }>({
{trigger} {trigger}
</Button> </Button>
</SheetTrigger> </SheetTrigger>
<SheetContent className='w-[520px] max-w-full md:max-w-screen-md'> <SheetContent className='w-[580px] max-w-full md:max-w-screen-md'>
<SheetHeader> <SheetHeader>
<SheetTitle>{title}</SheetTitle> <SheetTitle>{title}</SheetTitle>
</SheetHeader> </SheetHeader>
@@ -290,7 +290,7 @@ export default function NodeForm<T extends { [x: string]: any }>({
value={field.value} value={field.value}
onValueChange={(value) => { onValueChange={(value) => {
form.setValue(field.name, value); form.setValue(field.name, value);
if (['trojan', 'hysteria2', 'tuic'].includes(value)) { if (['trojan', 'hysteria2', 'tuic', 'anytls'].includes(value)) {
form.setValue('config.security', 'tls'); form.setValue('config.security', 'tls');
} }
}} }}
@@ -402,11 +402,11 @@ export default function NodeForm<T extends { [x: string]: any }>({
</div> </div>
)} )}
{['vmess', 'vless', 'trojan', 'hysteria2', 'tuic'].includes(protocol) && ( {['vmess', 'vless', 'trojan', 'hysteria2', 'tuic', 'anytls'].includes(protocol) && (
<div className='grid gap-4'> <div className='grid gap-4'>
<div <div
className={cn('flex gap-4 *:flex-1', { className={cn('flex gap-4 *:flex-1', {
'grid grid-cols-2': ['hysteria2'].includes(protocol), 'grid grid-cols-2': ['hysteria2', 'tuic'].includes(protocol),
})} })}
> >
<FormField <FormField
@@ -524,6 +524,109 @@ export default function NodeForm<T extends { [x: string]: any }>({
/> />
</> </>
)} )}
{protocol === 'tuic' && (
<>
<FormField
control={form.control}
name='config.udp_relay_mode'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.udpRelayMode')}</FormLabel>
<FormControl>
<Select
value={field.value}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder={t('form.pleaseSelect')} />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value='native'>Native</SelectItem>
<SelectItem value='quic'>QUIC</SelectItem>
</SelectContent>
</Select>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='config.congestion_controller'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.congestionController')}</FormLabel>
<FormControl>
<Select
value={field.value}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder={t('form.pleaseSelect')} />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value='bbr'>BBR</SelectItem>
<SelectItem value='cubic'>Cubic</SelectItem>
<SelectItem value='reno'>Reno</SelectItem>
</SelectContent>
</Select>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className='flex gap-2'>
<FormField
control={form.control}
name='config.disable_sni'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.disableSni')}</FormLabel>
<FormControl>
<div className='pt-2'>
<Switch
checked={field.value}
onCheckedChange={(checked) => {
form.setValue(field.name, checked);
}}
/>
</div>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='config.reduce_rtt'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.reduceRtt')}</FormLabel>
<FormControl>
<div className='pt-2'>
<Switch
checked={field.value}
onCheckedChange={(checked) => {
form.setValue(field.name, checked);
}}
/>
</div>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</>
)}
</div> </div>
{['vmess', 'vless', 'trojan'].includes(protocol) && ( {['vmess', 'vless', 'trojan'].includes(protocol) && (
<Card> <Card>
@@ -630,171 +733,17 @@ export default function NodeForm<T extends { [x: string]: any }>({
)} )}
</Card> </Card>
)} )}
<Card> {(['vmess', 'vless', 'trojan'].includes(protocol) ||
<CardHeader className='flex flex-row items-center justify-between p-3'> ['anytls', 'tuic', 'hysteria2'].includes(protocol)) && (
<CardTitle>{t('form.securityConfig')}</CardTitle> <Card>
<FormField <CardHeader className='flex flex-row items-center justify-between p-3'>
control={form.control} <CardTitle>{t('form.securityConfig')}</CardTitle>
name='config.security' {['vmess', 'vless', 'trojan'].includes(protocol) && (
render={({ field }) => (
<FormItem className='!mt-0 min-w-32'>
<Select
value={field.value}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder={t('form.pleaseSelect')} />
</SelectTrigger>
</FormControl>
<SelectContent>
{['vmess', 'vless'].includes(protocol) && (
<SelectItem value='none'>NONE</SelectItem>
)}
<SelectItem value='tls'>TLS</SelectItem>
{protocol === 'vless' && (
<SelectItem value='reality'>Reality</SelectItem>
)}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</CardHeader>
{security !== 'none' && (
<CardContent className='grid grid-cols-2 gap-4 p-3'>
<FormField
control={form.control}
name='config.security_config.sni'
render={({ field }) => (
<FormItem>
<FormLabel>Server Name(SNI)</FormLabel>
<FormControl>
<EnhancedInput
{...field}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
{protocol === 'vless' && security === 'reality' && (
<>
<FormField
control={form.control}
name='config.security_config.reality_server_addr'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.security_config.serverAddress')}</FormLabel>
<FormControl>
<EnhancedInput
{...field}
placeholder={t(
'form.security_config.serverAddressPlaceholder',
)}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='config.security_config.reality_server_port'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.security_config.serverPort')}</FormLabel>
<FormControl>
<EnhancedInput
{...field}
type='number'
min={1}
max={65535}
placeholder={t('form.security_config.serverPortPlaceholder')}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='config.security_config.reality_private_key'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.security_config.privateKey')}</FormLabel>
<FormControl>
<EnhancedInput
{...field}
placeholder={t('form.security_config.privateKeyPlaceholder')}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='config.security_config.reality_public_key'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.security_config.publicKey')}</FormLabel>
<FormControl>
<EnhancedInput
{...field}
placeholder={t('form.security_config.publicKeyPlaceholder')}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='config.security_config.reality_short_id'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.security_config.shortId')}</FormLabel>
<FormControl>
<EnhancedInput
{...field}
placeholder={t('form.security_config.shortIdPlaceholder')}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</>
)}
{protocol === 'vless' && (
<FormField <FormField
control={form.control} control={form.control}
name='config.security_config.fingerprint' name='config.security'
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem className='!mt-0 min-w-32'>
<FormLabel>{t('form.security_config.fingerprint')}</FormLabel>
<Select <Select
value={field.value} value={field.value}
onValueChange={(value) => { onValueChange={(value) => {
@@ -807,45 +756,213 @@ export default function NodeForm<T extends { [x: string]: any }>({
</SelectTrigger> </SelectTrigger>
</FormControl> </FormControl>
<SelectContent> <SelectContent>
<SelectItem value='chrome'>Chrome</SelectItem> {['vmess', 'vless'].includes(protocol) && (
<SelectItem value='firefox'>Firefox</SelectItem> <SelectItem value='none'>NONE</SelectItem>
<SelectItem value='safari'>Safari</SelectItem> )}
<SelectItem value='ios'>IOS</SelectItem> <SelectItem value='tls'>TLS</SelectItem>
<SelectItem value='android'>Android</SelectItem> {protocol === 'vless' && (
<SelectItem value='edge'>edge</SelectItem> <SelectItem value='reality'>Reality</SelectItem>
<SelectItem value='360'>360</SelectItem> )}
<SelectItem value='qq'>QQ</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
<FormMessage /> <FormMessage />
<FormMessage />
</FormItem> </FormItem>
)} )}
/> />
)} )}
<FormField </CardHeader>
control={form.control} {(['anytls', 'tuic', 'hysteria2'].includes(protocol) ||
name='config.security_config.allow_insecure' (['vmess', 'vless', 'trojan'].includes(protocol) &&
render={({ field }) => ( security !== 'none')) && (
<FormItem> <CardContent className='grid grid-cols-2 gap-4 p-3'>
<FormLabel>Allow Insecure</FormLabel> <FormField
<FormControl> control={form.control}
<div className='pt-2'> name='config.security_config.sni'
<Switch render={({ field }) => (
checked={!!field.value} <FormItem>
onCheckedChange={(value) => { <FormLabel>Server Name(SNI)</FormLabel>
<FormControl>
<EnhancedInput
{...field}
onValueChange={(value) => {
form.setValue(field.name, value); form.setValue(field.name, value);
}} }}
/> />
</div> </FormControl>
</FormControl> <FormMessage />
<FormMessage /> </FormItem>
</FormItem> )}
/>
{/* Reality 特殊配置只在 vless + reality 时显示 */}
{protocol === 'vless' && security === 'reality' && (
<>
<FormField
control={form.control}
name='config.security_config.reality_server_addr'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.security_config.serverAddress')}</FormLabel>
<FormControl>
<EnhancedInput
{...field}
placeholder={t(
'form.security_config.serverAddressPlaceholder',
)}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='config.security_config.reality_server_port'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.security_config.serverPort')}</FormLabel>
<FormControl>
<EnhancedInput
{...field}
type='number'
min={1}
max={65535}
placeholder={t(
'form.security_config.serverPortPlaceholder',
)}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='config.security_config.reality_private_key'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.security_config.privateKey')}</FormLabel>
<FormControl>
<EnhancedInput
{...field}
placeholder={t(
'form.security_config.privateKeyPlaceholder',
)}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='config.security_config.reality_public_key'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.security_config.publicKey')}</FormLabel>
<FormControl>
<EnhancedInput
{...field}
placeholder={t('form.security_config.publicKeyPlaceholder')}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='config.security_config.reality_short_id'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.security_config.shortId')}</FormLabel>
<FormControl>
<EnhancedInput
{...field}
placeholder={t('form.security_config.shortIdPlaceholder')}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</>
)} )}
/>
</CardContent> {protocol === 'vless' && (
)} <FormField
</Card> control={form.control}
name='config.security_config.fingerprint'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.security_config.fingerprint')}</FormLabel>
<Select
value={field.value}
onValueChange={(value) => {
form.setValue(field.name, value);
}}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder={t('form.pleaseSelect')} />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value='chrome'>Chrome</SelectItem>
<SelectItem value='firefox'>Firefox</SelectItem>
<SelectItem value='safari'>Safari</SelectItem>
<SelectItem value='ios'>IOS</SelectItem>
<SelectItem value='android'>Android</SelectItem>
<SelectItem value='edge'>edge</SelectItem>
<SelectItem value='360'>360</SelectItem>
<SelectItem value='qq'>QQ</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
)}
<FormField
control={form.control}
name='config.security_config.allow_insecure'
render={({ field }) => (
<FormItem>
<FormLabel>Allow Insecure</FormLabel>
<FormControl>
<div className='pt-2'>
<Switch
checked={!!field.value}
onCheckedChange={(checked) => {
form.setValue(field.name, checked);
}}
/>
</div>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</CardContent>
)}
</Card>
)}
</div> </div>
)} )}
+48 -35
View File
@@ -1,5 +1,11 @@
'use client'; 'use client';
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from '@workspace/ui/components/accordion';
import { Badge } from '@workspace/ui/components/badge'; import { Badge } from '@workspace/ui/components/badge';
import { Progress } from '@workspace/ui/components/progress'; import { Progress } from '@workspace/ui/components/progress';
import { ScrollArea } from '@workspace/ui/components/scroll-area'; import { ScrollArea } from '@workspace/ui/components/scroll-area';
@@ -11,6 +17,8 @@ import {
} from '@workspace/ui/components/tooltip'; } from '@workspace/ui/components/tooltip';
import { formatDate } from '@workspace/ui/utils'; import { formatDate } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useState } from 'react';
import { UserSubscribeDetail } from '../user/user-detail';
export function formatPercentage(value: number): string { export function formatPercentage(value: number): string {
return `${value.toFixed(1)}%`; return `${value.toFixed(1)}%`;
@@ -18,25 +26,19 @@ export function formatPercentage(value: number): string {
export function NodeStatusCell({ status }: { status: API.NodeStatus }) { export function NodeStatusCell({ status }: { status: API.NodeStatus }) {
const t = useTranslations('server.node'); const t = useTranslations('server.node');
const [openItem, setOpenItem] = useState<string | null>(null);
const { const { online, cpu, mem, disk, updated_at } = status || {
last_at, online: {},
online_users, cpu: 0,
status: serverStatus, mem: 0,
} = status || { disk: 0,
online_users: [], updated_at: 0,
status: {
cpu: 0,
mem: 0,
disk: 0,
updated_at: 0,
},
last_at: 0,
}; };
const isOnline = last_at > 0; const isOnline = updated_at > 0;
const badgeVariant = isOnline ? 'default' : 'destructive'; const badgeVariant = isOnline ? 'default' : 'destructive';
const badgeText = isOnline ? t('normal') : t('abnormal'); const badgeText = isOnline ? t('normal') : t('abnormal');
const onlineCount = Array.isArray(online_users) ? online_users?.length : 0; const onlineCount = (online && Object.keys(online).length) || 0;
return ( return (
<TooltipProvider> <TooltipProvider>
@@ -52,45 +54,56 @@ export function NodeStatusCell({ status }: { status: API.NodeStatus }) {
<div className='flex flex-col space-y-1'> <div className='flex flex-col space-y-1'>
<div className='flex justify-between'> <div className='flex justify-between'>
<span>CPU</span> <span>CPU</span>
<span>{formatPercentage(serverStatus?.cpu ?? 0)}</span> <span>{formatPercentage(cpu ?? 0)}</span>
</div> </div>
<Progress value={serverStatus?.cpu ?? 0} className='h-2' max={100} /> <Progress value={cpu ?? 0} className='h-2' max={100} />
</div> </div>
<div className='flex flex-col space-y-1'> <div className='flex flex-col space-y-1'>
<div className='flex justify-between'> <div className='flex justify-between'>
<span>{t('memory')}</span> <span>{t('memory')}</span>
<span>{formatPercentage(serverStatus?.mem ?? 0)}</span> <span>{formatPercentage(mem ?? 0)}</span>
</div> </div>
<Progress value={serverStatus?.mem ?? 0} className='h-2' max={100} /> <Progress value={mem ?? 0} className='h-2' max={100} />
</div> </div>
<div className='flex flex-col space-y-1'> <div className='flex flex-col space-y-1'>
<div className='flex justify-between'> <div className='flex justify-between'>
<span>{t('disk')}</span> <span>{t('disk')}</span>
<span>{formatPercentage(serverStatus?.disk ?? 0)}</span> <span>{formatPercentage(disk ?? 0)}</span>
</div> </div>
<Progress value={serverStatus?.disk ?? 0} className='h-2' max={100} /> <Progress value={disk ?? 0} className='h-2' max={100} />
</div> </div>
{isOnline && ( {isOnline && (
<div> <div>
{t('lastUpdated')}: {formatDate(serverStatus?.updated_at ?? 0)} {t('lastUpdated')}: {formatDate(updated_at ?? 0)}
</div> </div>
)} )}
</div> </div>
</TooltipTrigger> </TooltipTrigger>
{isOnline && onlineCount > 0 && ( {isOnline && onlineCount > 0 && (
<TooltipContent className='bg-muted text-foreground w-80'> <TooltipContent className='bg-card text-foreground w-96'>
<div className='space-y-4'> <ScrollArea className='h-[540px] rounded-md border px-4 py-2'>
<div className='space-y-2'> <h4 className='py-1 text-sm font-semibold'>{t('onlineUsers')}</h4>
<h4 className='text-sm font-semibold'>{t('onlineUsers')}</h4> <Accordion
<ScrollArea className='h-[400px] rounded-md border p-2'> type='single'
{online_users.map((user, index) => ( collapsible
<div key={user.uid} className='py-1 text-xs'> className='w-full'
{user.ip} (UID: {user.uid}) onValueChange={(value) => setOpenItem(value)}
</div> >
))} {Object.entries(online).map(([uid, ips]) => (
</ScrollArea> <AccordionItem key={uid} value={uid}>
</div> <AccordionTrigger>{`[UID: ${uid}] - ${ips[0]}`}</AccordionTrigger>
</div> <AccordionContent>
<ul>
{ips.map((ip: string) => (
<li key={ip}>{ip}</li>
))}
</ul>
<UserSubscribeDetail id={Number(uid)} enabled={openItem === uid} />
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</ScrollArea>
</TooltipContent> </TooltipContent>
)} )}
</Tooltip> </Tooltip>
@@ -73,7 +73,7 @@ export default function NodeTable() {
columns={[ columns={[
{ {
accessorKey: 'id', accessorKey: 'id',
header: 'ID', header: t('id'),
cell: ({ row }) => ( cell: ({ row }) => (
<TooltipProvider> <TooltipProvider>
<Tooltip> <Tooltip>
@@ -87,6 +87,7 @@ export default function NodeTable() {
'bg-yellow-500': row.original.protocol === 'trojan', 'bg-yellow-500': row.original.protocol === 'trojan',
'bg-purple-500': row.original.protocol === 'hysteria2', 'bg-purple-500': row.original.protocol === 'hysteria2',
'bg-cyan-500': row.original.protocol === 'tuic', 'bg-cyan-500': row.original.protocol === 'tuic',
'bg-gray-500': row.original.protocol === 'anytls',
})} })}
> >
{row.getValue('id')} {row.getValue('id')}
@@ -159,7 +160,7 @@ export default function NodeTable() {
header: t('nodeGroup'), header: t('nodeGroup'),
cell: ({ row }) => { cell: ({ row }) => {
const name = groups?.find((group) => group.id === row.getValue('group_id'))?.name; const name = groups?.find((group) => group.id === row.getValue('group_id'))?.name;
return name ? <Badge variant='outline'>{name}</Badge> : '--'; return name ? <Badge variant='outline'>{name}</Badge> : t('noData');
}, },
}, },
{ {
@@ -176,7 +177,7 @@ export default function NodeTable() {
))} ))}
</div> </div>
) : ( ) : (
'--' t('noData')
); );
}, },
}, },
@@ -272,17 +273,17 @@ export default function NodeTable() {
<ConfirmButton <ConfirmButton
key='delete' key='delete'
trigger={<Button variant='destructive'>{t('delete')}</Button>} trigger={<Button variant='destructive'>{t('delete')}</Button>}
title={t('group.confirmDelete')} title={t('confirmDelete')}
description={t('group.deleteWarning')} description={t('deleteWarning')}
onConfirm={async () => { onConfirm={async () => {
await batchDeleteNode({ await batchDeleteNode({
ids: rows.map((item) => item.id), ids: rows.map((item) => item.id),
}); });
toast.success(t('group.deleteSuccess')); toast.success(t('deleteSuccess'));
ref.current?.refresh(); ref.current?.refresh();
}} }}
cancelText={t('group.cancel')} cancelText={t('cancel')}
confirmText={t('group.confirm')} confirmText={t('confirm')}
/>, />,
]; ];
}, },
@@ -2,7 +2,6 @@ import { getTranslations } from 'next-intl/server';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import SubscribeApp from './app/table';
import GroupTable from './group/table'; import GroupTable from './group/table';
import SubscribeConfig from './subscribe-config'; import SubscribeConfig from './subscribe-config';
import SubscribeTable from './subscribe-table'; import SubscribeTable from './subscribe-table';
@@ -16,7 +15,6 @@ export default async function Page() {
<TabsTrigger value='subscribe'>{t('tabs.subscribe')}</TabsTrigger> <TabsTrigger value='subscribe'>{t('tabs.subscribe')}</TabsTrigger>
<TabsTrigger value='group'>{t('tabs.subscribeGroup')}</TabsTrigger> <TabsTrigger value='group'>{t('tabs.subscribeGroup')}</TabsTrigger>
<TabsTrigger value='config'>{t('tabs.subscribeConfig')}</TabsTrigger> <TabsTrigger value='config'>{t('tabs.subscribeConfig')}</TabsTrigger>
<TabsTrigger value='app'>{t('tabs.subscribeApp')}</TabsTrigger>
</TabsList> </TabsList>
<TabsContent value='subscribe'> <TabsContent value='subscribe'>
<SubscribeTable /> <SubscribeTable />
@@ -27,9 +25,6 @@ export default async function Page() {
<TabsContent value='config'> <TabsContent value='config'>
<SubscribeConfig /> <SubscribeConfig />
</TabsContent> </TabsContent>
<TabsContent value='app'>
<SubscribeApp />
</TabsContent>
</Tabs> </Tabs>
); );
} }
@@ -42,7 +42,7 @@ import { evaluateWithPrecision, unitConversion } from '@workspace/ui/utils';
import { CreditCard, Server, Settings } from 'lucide-react'; import { CreditCard, Server, Settings } from 'lucide-react';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { assign, shake } from 'radash'; import { assign, shake } from 'radash';
import { useEffect, useState } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { z } from 'zod'; import { z } from 'zod';
@@ -81,6 +81,7 @@ export default function SubscribeForm<T extends Record<string, any>>({
}: Readonly<SubscribeFormProps<T>>) { }: Readonly<SubscribeFormProps<T>>) {
const t = useTranslations('subscribe'); const t = useTranslations('subscribe');
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const updateTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const formSchema = z.object({ const formSchema = z.object({
name: z.string(), name: z.string(),
@@ -118,12 +119,111 @@ export default function SubscribeForm<T extends Record<string, any>>({
), ),
}); });
const debouncedCalculateDiscount = useCallback(
(values: any[], fieldName: string, lastChangedField?: string, changedIndex?: number) => {
if (updateTimeoutRef.current) {
clearTimeout(updateTimeoutRef.current);
}
updateTimeoutRef.current = setTimeout(() => {
const { unit_price } = form.getValues();
if (!unit_price || !values?.length) return;
let hasChanges = false;
const calculatedValues = values.map((item: any, index: number) => {
const result = { ...item };
if (changedIndex !== undefined && index !== changedIndex) {
return result;
}
const quantity = Number(item.quantity) || 0;
const discount = Number(item.discount) || 0;
const price = Number(item.price) || 0;
switch (lastChangedField) {
case 'quantity':
case 'discount':
if (quantity > 0 && discount > 0) {
const newPrice = evaluateWithPrecision(
`${unit_price} * ${quantity} * ${discount} / 100`,
);
if (Math.abs(newPrice - price) > 0.01) {
result.price = newPrice;
hasChanges = true;
}
}
break;
case 'price':
if (quantity > 0 && price > 0) {
const newDiscount = evaluateWithPrecision(
`${price} / ${quantity} / ${unit_price} * 100`,
);
if (Math.abs(newDiscount - discount) > 0.01) {
result.discount = Math.min(100, Math.max(0, newDiscount));
hasChanges = true;
}
} else if (discount > 0 && price > 0) {
const newQuantity = evaluateWithPrecision(
`${price} / ${unit_price} / ${discount} * 100`,
);
if (Math.abs(newQuantity - quantity) > 0.01 && newQuantity > 0) {
result.quantity = Math.max(1, Math.round(newQuantity));
hasChanges = true;
}
}
break;
default:
if (quantity > 0 && discount > 0 && price === 0) {
result.price = evaluateWithPrecision(
`${unit_price} * ${quantity} * ${discount} / 100`,
);
hasChanges = true;
} else if (quantity > 0 && price > 0 && discount === 0) {
const newDiscount = evaluateWithPrecision(
`${price} / ${quantity} / ${unit_price} * 100`,
);
result.discount = Math.min(100, Math.max(0, newDiscount));
hasChanges = true;
} else if (discount > 0 && price > 0 && quantity === 0) {
const newQuantity = evaluateWithPrecision(
`${price} / ${unit_price} / ${discount} * 100`,
);
if (newQuantity > 0) {
result.quantity = Math.max(1, Math.round(newQuantity));
hasChanges = true;
}
}
break;
}
return result;
});
if (hasChanges) {
form.setValue(fieldName, calculatedValues, { shouldDirty: true });
}
}, 300);
},
[form],
);
useEffect(() => { useEffect(() => {
form?.reset( form?.reset(
assign(defaultValues, shake(initialValues, (value) => value === null) as Record<string, any>), assign(defaultValues, shake(initialValues, (value) => value === null) as Record<string, any>),
); );
}, [form, initialValues]); }, [form, initialValues]);
useEffect(() => {
return () => {
if (updateTimeoutRef.current) {
clearTimeout(updateTimeoutRef.current);
}
};
}, []);
async function handleSubmit(data: { [x: string]: any }) { async function handleSubmit(data: { [x: string]: any }) {
const bool = await onSubmit(data as T); const bool = await onSubmit(data as T);
if (bool) setOpen(false); if (bool) setOpen(false);
@@ -157,6 +257,7 @@ export default function SubscribeForm<T extends Record<string, any>>({
}); });
const unit_time = form.watch('unit_time'); const unit_time = form.watch('unit_time');
const unit_price = form.watch('unit_price');
return ( return (
<Sheet open={open} onOpenChange={setOpen}> <Sheet open={open} onOpenChange={setOpen}>
@@ -543,7 +644,7 @@ export default function SubscribeForm<T extends Record<string, any>>({
<FormItem> <FormItem>
<FormLabel>{t('form.discount')}</FormLabel> <FormLabel>{t('form.discount')}</FormLabel>
<FormControl> <FormControl>
<ArrayInput<API.SubscribeDiscount> <ArrayInput<API.SubscribeDiscount & { price?: number }>
fields={[ fields={[
{ {
name: 'quantity', name: 'quantity',
@@ -555,42 +656,63 @@ export default function SubscribeForm<T extends Record<string, any>>({
{ {
name: 'discount', name: 'discount',
type: 'number', type: 'number',
min: 1, min: 0.01,
max: 100, max: 100,
step: 0.01,
placeholder: t('form.discountPercent'), placeholder: t('form.discountPercent'),
suffix: '%', suffix: '%',
calculateValue: function (data) {
const { unit_price } = form.getValues();
return {
...data,
price: evaluateWithPrecision(
`${unit_price} * ${data.quantity} * ${data.discount} / 100`,
),
};
},
}, },
{ {
name: 'price', name: 'price',
placeholder: t('form.discount_price'), placeholder: t('form.discount_price'),
type: 'number', type: 'number',
min: 0,
step: 0.01,
formatInput: (value) => unitConversion('centsToDollars', value), formatInput: (value) => unitConversion('centsToDollars', value),
formatOutput: (value) => unitConversion('dollarsToCents', value), formatOutput: (value) => unitConversion('dollarsToCents', value),
internal: true,
calculateValue: (data) => {
const { unit_price } = form.getValues();
return {
...data,
discount: evaluateWithPrecision(
`${data.price} / ${data.quantity} / ${unit_price} * 100`,
),
};
},
}, },
]} ]}
value={field.value} value={field.value}
onChange={(value) => { onChange={(
console.log(value); newValues: (API.SubscribeDiscount & { price?: number })[],
form.setValue(field.name, value); ) => {
const oldValues = field.value || [];
let lastChangedField: string | undefined;
let changedIndex: number | undefined;
for (
let i = 0;
i < Math.max(newValues.length, oldValues.length);
i++
) {
const newItem = newValues[i] || {};
const oldItem = oldValues[i] || {};
if ((newItem as any).quantity !== (oldItem as any).quantity) {
lastChangedField = 'quantity';
changedIndex = i;
break;
}
if ((newItem as any).discount !== (oldItem as any).discount) {
lastChangedField = 'discount';
changedIndex = i;
break;
}
if ((newItem as any).price !== (oldItem as any).price) {
lastChangedField = 'price';
changedIndex = i;
break;
}
}
form.setValue(field.name, newValues, { shouldDirty: true });
if (newValues?.length > 0) {
debouncedCalculateDiscount(
newValues,
field.name,
lastChangedField,
changedIndex,
);
}
}} }}
/> />
</FormControl> </FormControl>
+183 -22
View File
@@ -1,6 +1,6 @@
'use client'; 'use client';
import { getSystemLog, restartSystem } from '@/services/admin/tool'; import { getSystemLog, getVersion, restartSystem } from '@/services/admin/tool';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { import {
Accordion, Accordion,
@@ -10,7 +10,6 @@ import {
} from '@workspace/ui/components/accordion'; } from '@workspace/ui/components/accordion';
import { import {
AlertDialog, AlertDialog,
AlertDialogAction,
AlertDialogCancel, AlertDialogCancel,
AlertDialogContent, AlertDialogContent,
AlertDialogDescription, AlertDialogDescription,
@@ -30,8 +29,10 @@ import {
} from '@workspace/ui/components/card'; } from '@workspace/ui/components/card';
import { ScrollArea } from '@workspace/ui/components/scroll-area'; import { ScrollArea } from '@workspace/ui/components/scroll-area';
import { Icon } from '@workspace/ui/custom-components/icon'; import { Icon } from '@workspace/ui/custom-components/icon';
import { formatDate } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useState } from 'react'; import { useState } from 'react';
import packageJson from '../../../../../package.json';
const getLogLevelColor = (level: string) => { const getLogLevelColor = (level: string) => {
const colorMap: { [key: string]: string } = { const colorMap: { [key: string]: string } = {
@@ -59,6 +60,91 @@ export default function Page() {
const [openRestart, setOpenRestart] = useState(false); const [openRestart, setOpenRestart] = useState(false);
const [isRestarting, setIsRestarting] = useState(false); const [isRestarting, setIsRestarting] = useState(false);
const { data: latestReleases } = useQuery({
queryKey: ['getLatestReleases'],
queryFn: async () => {
try {
const [webResponse, serverResponse] = await Promise.all([
fetch('https://api.github.com/repos/perfect-panel/ppanel-web/releases/latest'),
fetch('https://api.github.com/repos/perfect-panel/server/releases/latest'),
]);
const webData = webResponse.ok ? await webResponse.json() : null;
const serverData = serverResponse.ok ? await serverResponse.json() : null;
return {
web: webData
? {
version: webData.tag_name,
url: webData.html_url,
publishedAt: webData.published_at,
}
: null,
server: serverData
? {
version: serverData.tag_name,
url: serverData.html_url,
publishedAt: serverData.published_at,
}
: null,
};
} catch (error) {
console.error('Failed to fetch latest releases:', error);
return { web: null, server: null };
}
},
staleTime: 60 * 60 * 1000,
retry: 1,
retryDelay: 10000,
});
// 检查是否有新版本
const hasNewVersion =
latestReleases?.web && packageJson.version !== latestReleases.web.version.replace(/^v/, '');
const { data: systemInfo } = useQuery({
queryKey: ['getVersion'],
queryFn: async () => {
const { data } = await getVersion();
const versionString = data.data?.version || '';
const releaseVersionRegex = /^[Vv]?\d+\.\d+\.\d+$/;
const timeMatch = versionString.match(/\(([^)]+)\)/);
const timeInBrackets = timeMatch ? timeMatch[1] : '';
const versionWithoutTime = versionString.replace(/\([^)]*\)/, '').trim();
const isDevelopment = !releaseVersionRegex.test(versionWithoutTime);
let baseVersion = versionWithoutTime;
let versionSuffix = '';
let lastUpdated = '';
if (isDevelopment && versionWithoutTime.includes('-')) {
const parts = versionWithoutTime.split('-');
baseVersion = parts[0] || versionWithoutTime;
versionSuffix = parts.slice(1).join('-');
}
lastUpdated = formatDate(new Date(timeInBrackets || Date.now())) || '';
const displayVersion =
baseVersion.startsWith('V') || baseVersion.startsWith('v')
? baseVersion
: `V${baseVersion}`;
return {
isRelease: !isDevelopment,
version: displayVersion,
lastUpdated,
};
},
});
const hasServerNewVersion =
latestReleases?.server &&
systemInfo &&
systemInfo.version.replace(/^V/, '') !== latestReleases.server.version.replace(/^v/, '');
return ( return (
<Card className='border-none'> <Card className='border-none'>
<CardHeader className='flex flex-col items-start justify-between sm:flex-row sm:items-center'> <CardHeader className='flex flex-col items-start justify-between sm:flex-row sm:items-center'>
@@ -67,7 +153,7 @@ export default function Page() {
<CardDescription>{t('viewLogsAndManage')}</CardDescription> <CardDescription>{t('viewLogsAndManage')}</CardDescription>
</div> </div>
<div className='mt-4 flex flex-col space-y-2 sm:mt-0 sm:flex-row sm:space-x-2 sm:space-y-0'> <div className='mt-4 flex flex-col space-y-2 sm:mt-0 sm:flex-row sm:space-x-2 sm:space-y-0'>
<AlertDialog> {/* <AlertDialog>
<AlertDialogTrigger asChild> <AlertDialogTrigger asChild>
<Button>{t('systemUpgrade')}</Button> <Button>{t('systemUpgrade')}</Button>
</AlertDialogTrigger> </AlertDialogTrigger>
@@ -81,7 +167,7 @@ export default function Page() {
<AlertDialogAction>{t('confirmUpgrade')}</AlertDialogAction> <AlertDialogAction>{t('confirmUpgrade')}</AlertDialogAction>
</AlertDialogFooter> </AlertDialogFooter>
</AlertDialogContent> </AlertDialogContent>
</AlertDialog> </AlertDialog> */}
<AlertDialog open={openRestart} onOpenChange={setOpenRestart}> <AlertDialog open={openRestart} onOpenChange={setOpenRestart}>
<AlertDialogTrigger asChild> <AlertDialogTrigger asChild>
<Button variant='destructive'>{t('systemReboot')}</Button> <Button variant='destructive'>{t('systemReboot')}</Button>
@@ -112,13 +198,88 @@ export default function Page() {
</div> </div>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className='space-y-6'> <div className='space-y-4'>
<div className='flex items-center justify-between'> {/* 版本信息紧凑显示 */}
<div className='text-lg font-semibold'> <div className='flex flex-col space-y-2 sm:flex-row sm:space-x-3 sm:space-y-0'>
{t('currentVersion')} <span>V1.0.0</span> {/* 用户端/管理端版本 */}
<div className='bg-muted/30 flex flex-1 items-center justify-between rounded-md p-2'>
<div className='flex items-center'>
<Icon icon='mdi:web' className='mr-2 h-4 w-4 text-green-600' />
<div className='flex items-center space-x-2'>
<span className='text-xs font-medium'>{t('webVersion')}</span>
<Badge variant='default' className='px-1.5 py-0.5 text-xs'>
V{packageJson.version}
</Badge>
{hasNewVersion && (
<Badge variant='destructive' className='animate-pulse px-1.5 py-0.5 text-xs'>
{t('newVersionAvailable')}
</Badge>
)}
</div>
</div>
{hasNewVersion && (
<Button
variant='outline'
size='sm'
className='h-6 px-2 text-xs'
onClick={() =>
window.open(
latestReleases?.web?.url ||
'https://github.com/perfect-panel/ppanel-web/releases',
'_blank',
)
}
>
<Icon icon='mdi:open-in-new' className='mr-1 h-3 w-3' />
{t('viewNewVersion')}
</Button>
)}
</div> </div>
<div className='text-muted-foreground text-sm'>
{t('lastUpdated')} <span>2024-12-16 12:00:00</span> {/* 服务端版本 */}
<div className='bg-muted/30 flex flex-1 items-center justify-between rounded-md p-2'>
<div className='flex items-center'>
<Icon icon='mdi:server' className='mr-2 h-4 w-4 text-blue-600' />
<div className='flex items-center space-x-2'>
<span className='text-xs font-medium'>{t('serverVersion')}</span>
<Badge
variant={!systemInfo?.isRelease ? 'destructive' : 'default'}
className='px-1.5 py-0.5 text-xs'
>
{systemInfo?.version || 'V1.0.0'}
{!systemInfo?.isRelease && (
<span className='ml-1'>{t('developmentVersion')}</span>
)}
</Badge>
{hasServerNewVersion && (
<Badge variant='destructive' className='animate-pulse px-1.5 py-0.5 text-xs'>
{t('newVersionAvailable')}
</Badge>
)}
</div>
</div>
<div className='flex items-center space-x-2'>
{hasServerNewVersion && (
<Button
variant='outline'
size='sm'
className='h-6 px-2 text-xs'
onClick={() =>
window.open(
latestReleases?.server?.url ||
'https://github.com/perfect-panel/server/releases',
'_blank',
)
}
>
<Icon icon='mdi:open-in-new' className='mr-1 h-3 w-3' />
{t('viewNewVersion')}
</Button>
)}
<div className='text-muted-foreground hidden text-right text-xs sm:block'>
<div className='font-mono'>{systemInfo?.lastUpdated || '--'}</div>
</div>
</div>
</div> </div>
</div> </div>
<Card className='overflow-hidden'> <Card className='overflow-hidden'>
@@ -146,20 +307,20 @@ export default function Page() {
<AccordionItem key={index} value={`item-${index}`} className='px-4'> <AccordionItem key={index} value={`item-${index}`} className='px-4'>
<AccordionTrigger className='hover:no-underline'> <AccordionTrigger className='hover:no-underline'>
<div className='flex w-full flex-col items-start space-y-2 sm:flex-row sm:items-center sm:space-x-4 sm:space-y-0'> <div className='flex w-full flex-col items-start space-y-2 sm:flex-row sm:items-center sm:space-x-4 sm:space-y-0'>
<Badge <span className='text-xs font-medium sm:text-sm'>{log.timestamp}</span>
variant='outline'
className={`${getLogLevelColor(log.level)} mb-2 sm:mb-0`}
>
{log.level}
</Badge>
<span className='text-xs font-medium sm:text-sm'>{log.time}</span>
<span className='text-muted-foreground flex-1 truncate text-xs sm:text-sm'>
{log.message}
</span>
</div> </div>
</AccordionTrigger> </AccordionTrigger>
<AccordionContent className='px-2'> <AccordionContent className='px-2'>
<div className='grid grid-cols-1 gap-2 text-xs sm:grid-cols-2 sm:text-sm'> {Object.entries(log).map(([key, value]) => (
<div
key={key}
className='grid grid-cols-1 gap-2 text-xs sm:grid-cols-2 sm:text-sm'
>
<span className='font-medium'>{key}:</span>
<span className='break-all'>{value as string}</span>
</div>
))}
{/* <div className='grid grid-cols-1 gap-2 text-xs sm:grid-cols-2 sm:text-sm'>
<div className='font-medium'>{t('ip')}:</div> <div className='font-medium'>{t('ip')}:</div>
<div>{log.ip}</div> <div>{log.ip}</div>
<div className='font-medium'>{t('request')}:</div> <div className='font-medium'>{t('request')}:</div>
@@ -174,7 +335,7 @@ export default function Page() {
<div className='break-all'>{log.query || t('none')}</div> <div className='break-all'>{log.query || t('none')}</div>
<div className='font-medium'>{t('userAgent')}:</div> <div className='font-medium'>{t('userAgent')}:</div>
<div className='break-all'>{log['user-agent']}</div> <div className='break-all'>{log['user-agent']}</div>
</div> </div> */}
</AccordionContent> </AccordionContent>
</AccordionItem> </AccordionItem>
))} ))}
@@ -45,6 +45,9 @@ const formSchema = z.object({
speed_limit: z.number().optional(), speed_limit: z.number().optional(),
device_limit: z.number().optional(), device_limit: z.number().optional(),
expired_at: z.number().nullish().optional(), expired_at: z.number().nullish().optional(),
upload: z.number().optional(),
download: z.number().optional(),
id: z.number().optional(),
}); });
export function SubscriptionForm({ trigger, title, loading, initialData, onSubmit }: Props) { export function SubscriptionForm({ trigger, title, loading, initialData, onSubmit }: Props) {
+41 -3
View File
@@ -2,7 +2,9 @@
import { Display } from '@/components/display'; import { Display } from '@/components/display';
import { ProTable, ProTableActions } from '@/components/pro-table'; import { ProTable, ProTableActions } from '@/components/pro-table';
import { getSubscribeList } from '@/services/admin/subscribe';
import { createUser, deleteUser, getUserList, updateUserBasicInfo } from '@/services/admin/user'; import { createUser, deleteUser, getUserList, updateUserBasicInfo } from '@/services/admin/user';
import { useQuery } from '@tanstack/react-query';
import { Badge } from '@workspace/ui/components/badge'; import { Badge } from '@workspace/ui/components/badge';
import { Button } from '@workspace/ui/components/button'; import { Button } from '@workspace/ui/components/button';
import { Switch } from '@workspace/ui/components/switch'; import { Switch } from '@workspace/ui/components/switch';
@@ -20,8 +22,19 @@ export default function Page() {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const ref = useRef<ProTableActions>(null); const ref = useRef<ProTableActions>(null);
const { data: subscribeList } = useQuery({
queryKey: ['getSubscribeList', 'all'],
queryFn: async () => {
const { data } = await getSubscribeList({
page: 1,
size: 9999,
});
return data.data?.list as API.SubscribeGroup[];
},
});
return ( return (
<ProTable<API.User, Record<string, unknown>> <ProTable<API.User, API.GetUserListParams>
action={ref} action={ref}
header={{ header={{
title: t('userList'), title: t('userList'),
@@ -132,13 +145,38 @@ export default function Page() {
cell: ({ row }) => formatDate(row.getValue('created_at')), cell: ({ row }) => formatDate(row.getValue('created_at')),
}, },
]} ]}
request={async (pagination) => { request={async (pagination, filter) => {
const { data } = await getUserList(pagination); const { data } = await getUserList({
...pagination,
...filter,
});
return { return {
list: data.data?.list || [], list: data.data?.list || [],
total: data.data?.total || 0, total: data.data?.total || 0,
}; };
}} }}
params={[
{
key: 'subscribe_id',
placeholder: t('subscription'),
options: subscribeList?.map((item) => ({
label: item.name,
value: String(item.id),
})),
},
{
key: 'search',
placeholder: 'Search',
},
{
key: 'user_id',
placeholder: t('userId'),
},
{
key: 'user_subscribe_id',
placeholder: t('subscriptionId'),
},
]}
actions={{ actions={{
render: (row) => { render: (row) => {
return [ return [
+108 -2
View File
@@ -1,15 +1,121 @@
'use client'; 'use client';
import { Display } from '@/components/display'; import { Display } from '@/components/display';
import { getUserDetail } from '@/services/admin/user'; import { getUserDetail, getUserSubscribeById } from '@/services/admin/user';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Button } from '@workspace/ui/components/button'; import { Button } from '@workspace/ui/components/button';
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@workspace/ui/components/hover-card'; import { HoverCard, HoverCardContent, HoverCardTrigger } from '@workspace/ui/components/hover-card';
import { formatDate } from '@workspace/ui/utils'; import { formatBytes, formatDate } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import Link from 'next/link'; import Link from 'next/link';
import { useState } from 'react'; import { useState } from 'react';
export function UserSubscribeDetail({ id, enabled }: { id: number; enabled: boolean }) {
const t = useTranslations('user');
const { data } = useQuery({
enabled: id !== 0 && enabled,
queryKey: ['getUserSubscribeById', id],
queryFn: async () => {
const { data } = await getUserSubscribeById({ id });
return data.data;
},
});
if (!id) return '--';
const usedTraffic = data ? data.upload + data.download : 0;
const totalTraffic = data?.traffic || 0;
return (
<div className='space-y-4'>
<div>
<h3 className='mb-2 text-sm font-medium'>{t('subscriptionInfo')}</h3>
<div className='bg-muted/30 rounded-lg p-3'>
<ul className='grid gap-3'>
<li className='flex items-center justify-between font-semibold'>
<span className='text-muted-foreground'>{t('subscriptionId')}</span>
<span>{data?.id || '--'}</span>
</li>
<li className='flex items-center justify-between'>
<span className='text-muted-foreground'>{t('subscriptionName')}</span>
<span>{data?.subscribe?.name || '--'}</span>
</li>
<li className='flex items-center justify-between'>
<span className='text-muted-foreground'>{t('token')}</span>
<div className='font-mono text-xs' title={data?.token || ''}>
{data?.token || '--'}
</div>
</li>
<li className='flex items-center justify-between'>
<span className='text-muted-foreground'>{t('trafficUsage')}</span>
<span>
{data
? totalTraffic === 0
? `${formatBytes(usedTraffic)} / ${t('unlimited')}`
: `${formatBytes(usedTraffic)} / ${formatBytes(totalTraffic)}`
: '--'}
</span>
</li>
<li className='flex items-center justify-between'>
<span className='text-muted-foreground'>{t('startTime')}</span>
<span>{data?.start_time ? formatDate(data.start_time) : '--'}</span>
</li>
<li className='flex items-center justify-between'>
<span className='text-muted-foreground'>{t('expireTime')}</span>
<span>{data?.expire_time ? formatDate(data.expire_time) : '--'}</span>
</li>
</ul>
</div>
</div>
<div>
<h3 className='mb-2 text-sm font-medium'>
{t('userInfo')}
{data?.user_id && (
<Button
variant='link'
size='sm'
className='text-primary ml-2 h-auto p-0 text-xs'
asChild
>
<Link href={`/dashboard/user/${data.user_id}`}>{t('viewDetails')}</Link>
</Button>
)}
</h3>
<ul className='grid gap-3'>
<li className='flex items-center justify-between font-semibold'>
<span className='text-muted-foreground'>{t('userId')}</span>
<span>{data?.user_id}</span>
</li>
<li className='flex items-center justify-between font-semibold'>
<span className='text-muted-foreground'>{t('balance')}</span>
<span>
<Display type='currency' value={data?.user.balance} />
</span>
</li>
<li className='flex items-center justify-between'>
<span className='text-muted-foreground'>{t('giftAmount')}</span>
<span>
<Display type='currency' value={data?.user?.gift_amount} />
</span>
</li>
<li className='flex items-center justify-between'>
<span className='text-muted-foreground'>{t('commission')}</span>
<span>
<Display type='currency' value={data?.user?.commission} />
</span>
</li>
<li className='flex items-center justify-between'>
<span className='text-muted-foreground'>{t('createdAt')}</span>
<span>{data?.user?.created_at && formatDate(data?.user?.created_at)}</span>
</li>
</ul>
</div>
</div>
);
}
export function UserDetail({ id }: { id: number }) { export function UserDetail({ id }: { id: number }) {
const t = useTranslations('user'); const t = useTranslations('user');
const [shouldFetch, setShouldFetch] = useState(false); const [shouldFetch, setShouldFetch] = useState(false);
+11 -10
View File
@@ -9,20 +9,20 @@ import { NextIntlClientProvider } from 'next-intl';
import { getLocale, getMessages } from 'next-intl/server'; import { getLocale, getMessages } from 'next-intl/server';
import { PublicEnvScript } from 'next-runtime-env'; import { PublicEnvScript } from 'next-runtime-env';
import { unstable_noStore as noStore } from 'next/cache'; import { unstable_noStore as noStore } from 'next/cache';
import { Geist, Geist_Mono } from 'next/font/google'; // import { Geist, Geist_Mono } from 'next/font/google';
import { cookies } from 'next/headers'; import { cookies } from 'next/headers';
import NextTopLoader from 'nextjs-toploader'; import NextTopLoader from 'nextjs-toploader';
import React from 'react'; import React from 'react';
const fontSans = Geist({ // const fontSans = Geist({
subsets: ['latin'], // subsets: ['latin'],
variable: '--font-sans', // variable: '--font-sans',
}); // });
const fontMono = Geist_Mono({ // const fontMono = Geist_Mono({
subsets: ['latin'], // subsets: ['latin'],
variable: '--font-mono', // variable: '--font-mono',
}); // });
export async function generateMetadata(): Promise<Metadata> { export async function generateMetadata(): Promise<Metadata> {
noStore(); noStore();
@@ -111,7 +111,8 @@ export default async function RootLayout({
</head> </head>
<body <body
suppressHydrationWarning suppressHydrationWarning
className={`${fontSans.variable} ${fontMono.variable} size-full min-h-[calc(100dvh-env(safe-area-inset-top))] font-sans antialiased`} // ${fontSans.variable} ${fontMono.variable}
className={`size-full min-h-[calc(100dvh-env(safe-area-inset-top))] font-sans antialiased`}
> >
<NextIntlClientProvider messages={messages}> <NextIntlClientProvider messages={messages}>
<NextTopLoader showSpinner={false} /> <NextTopLoader showSpinner={false} />
+17 -12
View File
@@ -1,5 +1,6 @@
'use client'; 'use client';
import { UserSubscribeDetail } from '@/app/dashboard/user/user-detail';
import { queryServerTotalData, queryTicketWaitReply } from '@/services/admin/console'; import { queryServerTotalData, queryTicketWaitReply } from '@/services/admin/console';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card'; import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card';
@@ -11,6 +12,7 @@ import {
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from '@workspace/ui/components/select'; } from '@workspace/ui/components/select';
import { Separator } from '@workspace/ui/components/separator';
import { Tabs, TabsList, TabsTrigger } from '@workspace/ui/components/tabs'; import { Tabs, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import { Icon } from '@workspace/ui/custom-components/icon'; import { Icon } from '@workspace/ui/custom-components/icon';
import { formatBytes } from '@workspace/ui/utils'; import { formatBytes } from '@workspace/ui/utils';
@@ -59,15 +61,13 @@ export default function Statistics() {
users: { users: {
today: today:
ServerTotal?.user_traffic_ranking_today?.map((item) => ({ ServerTotal?.user_traffic_ranking_today?.map((item) => ({
name: item.user_id, name: item.sid,
traffic: item.download + item.upload, traffic: item.download + item.upload,
email: item.email,
})) || [], })) || [],
yesterday: yesterday:
ServerTotal?.user_traffic_ranking_yesterday?.map((item) => ({ ServerTotal?.user_traffic_ranking_yesterday?.map((item) => ({
name: item.user_id, name: item.sid,
traffic: item.download + item.upload, traffic: item.download + item.upload,
email: item.email,
})) || [], })) || [],
}, },
}; };
@@ -175,10 +175,6 @@ export default function Statistics() {
label: t('type'), label: t('type'),
color: 'hsl(var(--muted))', color: 'hsl(var(--muted))',
}, },
email: {
label: t('email'),
color: 'hsl(var(--muted))',
},
label: { label: {
color: 'hsl(var(--foreground))', color: 'hsl(var(--foreground))',
}, },
@@ -204,13 +200,22 @@ export default function Statistics() {
tickFormatter={(value, index) => String(index + 1)} tickFormatter={(value, index) => String(index + 1)}
/> />
<ChartTooltip <ChartTooltip
trigger='hover'
content={ content={
<ChartTooltipContent <ChartTooltipContent
label={true} label={true}
labelFormatter={(label) => labelFormatter={(label, [payload]) =>
dataType === 'nodes' dataType === 'nodes' ? (
? `${t('nodes')}: ${label}` `${t('nodes')}: ${label}`
: `${t('users')}: ${label}` ) : (
<>
<div className='w-80'>
<UserSubscribeDetail id={payload?.payload.name} enabled={true} />
</div>
<Separator className='my-2' />
<div>{`${t('users')}: ${label}`}</div>
</>
)
} }
formatter={(value) => { formatter={(value) => {
return formatBytes(Number(value) || 0); return formatBytes(Number(value) || 0);
+15 -5
View File
@@ -81,16 +81,26 @@ export const navs = [
url: '/dashboard/server', url: '/dashboard/server',
icon: 'flat-color-icons:data-protection', icon: 'flat-color-icons:data-protection',
}, },
], {
}, title: 'Application Management',
{ url: '/dashboard/application',
title: 'Finance', icon: 'flat-color-icons:touchscreen-smartphone',
items: [ },
{
title: 'Rule Management',
url: '/dashboard/rules',
icon: 'flat-color-icons:ruler',
},
{ {
title: 'Subscribe Management', title: 'Subscribe Management',
url: '/dashboard/subscribe', url: '/dashboard/subscribe',
icon: 'flat-color-icons:shop', icon: 'flat-color-icons:shop',
}, },
],
},
{
title: 'Finance',
items: [
{ {
title: 'Order Management', title: 'Order Management',
url: '/dashboard/order', url: '/dashboard/order',
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "Konfigurace ADS", "ADS Config": "Konfigurace ADS",
"Announcement Management": "Správa oznámení", "Announcement Management": "Správa oznámení",
"Apple": "Apple ID", "Apple": "Apple ID",
"Application Management": "Správa aplikací",
"Auth Control": "Řízení ověřování", "Auth Control": "Řízení ověřování",
"Coupon Management": "Správa kupónů", "Coupon Management": "Správa kupónů",
"Dashboard": "Přístrojová deska", "Dashboard": "Přístrojová deska",
@@ -16,6 +17,7 @@
"Order Management": "Správa objednávek", "Order Management": "Správa objednávek",
"Payment Config": "Konfigurace platby", "Payment Config": "Konfigurace platby",
"Phone Number": "Telefonní číslo", "Phone Number": "Telefonní číslo",
"Rule Management": "Správa pravidel",
"Server": "Server", "Server": "Server",
"Server Management": "Správa serveru", "Server Management": "Správa serveru",
"Settings": "Nastavení", "Settings": "Nastavení",
-1
View File
@@ -22,7 +22,6 @@
"description": "Popis", "description": "Popis",
"descriptionPlaceholder": "Zadejte popis platební metody", "descriptionPlaceholder": "Zadejte popis platební metody",
"domain": "Doména", "domain": "Doména",
"domainPlaceholder": "volitelné, např. {example}",
"edit": "Upravit", "edit": "Upravit",
"editPayment": "Upravit platební metodu", "editPayment": "Upravit platební metodu",
"enable": "Povolit", "enable": "Povolit",
+39
View File
@@ -0,0 +1,39 @@
{
"analyzing": "Analyzuji...",
"appIcon": "Ikona pravidla",
"cancel": "Zrušit",
"confirm": "Potvrdit",
"confirmDelete": "Potvrdit smazání",
"create": "Přidat pravidlo",
"createRule": "Přidat pravidlo",
"createSuccess": "Pravidlo bylo úspěšně vytvořeno",
"createdAt": "Vytvořeno dne",
"delete": "Smazat",
"deleteSuccess": "Pravidlo bylo úspěšně smazáno",
"deleteWarning": "Opravdu chcete smazat toto pravidlo? Tato akce není vratná.",
"downloadTemplate": "Stáhnout šablonu",
"edit": "Upravit",
"editRule": "Upravit pravidlo",
"enable": "Povolit",
"enterIconUrl": "Zadejte nebo nahrajte ikonu",
"enterRuleName": "Zadejte název pravidla",
"enterRules": "Zadejte obsah pravidla, jedno na řádek",
"import": "Importovat",
"importFailed": "Import se nezdařil",
"importSuccess": "Import byl úspěšný",
"importYamlDescription": "Importujte pravidla ze souboru YAML, systém automaticky vytvoří skupiny pravidel na základě názvů skupin politiky",
"importYamlRules": "Importovat YAML pravidla",
"importing": "Importuji...",
"invalidYamlFormat": "Neplatný formát YAML, chybí pole pravidel",
"name": "Název pravidla",
"noValidRules": "Nebyly nalezeny žádné platné pravidla",
"pleaseUploadFile": "Prosím, nahrajte soubor YAML",
"preview": "Náhled",
"rulesFormat": "Formát pravidla: typ pravidla, obsah shody, [politika], kde politika je volitelná.\nPokud politika není specifikována, bude automaticky použito aktuální jméno skupiny pravidel. Příklady:",
"rulesLabel": "Obsah pravidla",
"searchRule": "Hledat název pravidla",
"selectTags": "Vybrat značky uzlu",
"tags": "Značky uzlu",
"tagsLabel": "Značky uzlu",
"updateSuccess": "Pravidlo bylo úspěšně aktualizováno"
}
+1 -1
View File
@@ -145,7 +145,7 @@
"quota": "Limit na nákup/čas", "quota": "Limit na nákup/čas",
"replacement": "Obnovení ceny/krát", "replacement": "Obnovení ceny/krát",
"sell": "Prodej", "sell": "Prodej",
"show": "Zobrazit na hlavní stránce", "show": "Zobrazit",
"sold": "Počet předplatných", "sold": "Počet předplatných",
"subscribe": "Předplatit", "subscribe": "Předplatit",
"subscribeGroup": "Přihlásit se ke skupině", "subscribeGroup": "Přihlásit se ke skupině",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "Potvrdit aktualizaci systému", "confirmSystemUpgrade": "Potvrdit aktualizaci systému",
"confirmUpgrade": "Potvrdit aktualizaci", "confirmUpgrade": "Potvrdit aktualizaci",
"currentVersion": "Aktuální verze systému:", "currentVersion": "Aktuální verze systému:",
"developmentVersion": "Vývojová verze",
"errors": "Chyby", "errors": "Chyby",
"ip": "IP", "ip": "IP adresa",
"lastUpdated": "Poslední aktualizace:", "lastUpdated": "Poslední aktualizace:",
"newVersionAvailable": "Nová verze",
"none": "Žádný", "none": "Žádný",
"query": "Dotaz", "query": "Dotaz",
"rebootDescription": "Opravdu chcete restartovat systém? Tato akce způsobí krátké přerušení služby.", "rebootDescription": "Opravdu chcete restartovat systém? Tato akce způsobí krátké přerušení služby.",
"rebooting": "Systém se restartuje...", "rebooting": "Systém se restartuje...",
"refreshLogs": "Obnovit protokoly", "refreshLogs": "Obnovit protokoly",
"request": "Žádost", "request": "Žádost",
"serverVersion": "Server",
"status": "Stav", "status": "Stav",
"systemLogs": "Systémové protokoly", "systemLogs": "Systémové protokoly",
"systemReboot": "Restart systému", "systemReboot": "Restart systému",
@@ -22,5 +25,8 @@
"systemUpgrade": "Aktualizace systému", "systemUpgrade": "Aktualizace systému",
"upgradeDescription": "Jste si jisti, že chcete provést aktualizaci systému? Tato operace může trvat několik minut a během ní může být systém neodpovídající.", "upgradeDescription": "Jste si jisti, že chcete provést aktualizaci systému? Tato operace může trvat několik minut a během ní může být systém neodpovídající.",
"userAgent": "Uživatelský agent", "userAgent": "Uživatelský agent",
"viewLogsAndManage": "Zobrazit systémové protokoly, provádět aktualizace systému a restartovat operace" "versionInfo": "Informace o verzi",
"viewLogsAndManage": "Zobrazit systémové protokoly, provádět aktualizace systému a restartovat operace",
"viewNewVersion": "Zobrazit novou verzi",
"webVersion": "Web/Admin"
} }
+15 -1
View File
@@ -1,6 +1,7 @@
{ {
"accountEnable": "Povolení účtu", "accountEnable": "Povolení účtu",
"actions": "akce", "actions": "akce",
"active": "Aktivní",
"add": "Přidat", "add": "Přidat",
"administrator": "Administrátor", "administrator": "Administrátor",
"areaCode": "Směrový kód", "areaCode": "Směrový kód",
@@ -41,10 +42,12 @@
"email": "e-mail", "email": "e-mail",
"enable": "Povolit", "enable": "Povolit",
"expireTime": "Čas vypršení", "expireTime": "Čas vypršení",
"expired": "Vypršelo",
"expiredAt": "Platnost vypršela", "expiredAt": "Platnost vypršela",
"failed": "Neúspěch", "failed": "Neúspěch",
"giftAmount": "Částka dárku", "giftAmount": "Částka dárku",
"giftAmountPlaceholder": "Zadejte částku dárku", "giftAmountPlaceholder": "Zadejte částku dárku",
"inactive": "Neaktivní",
"invalidEmailFormat": "Neplatný formát e-mailu", "invalidEmailFormat": "Neplatný formát e-mailu",
"inviteCode": "Pozvánkový kód", "inviteCode": "Pozvánkový kód",
"inviteCodePlaceholder": "Zadejte kód pozvánky (ponechte prázdné pro vygenerování)", "inviteCodePlaceholder": "Zadejte kód pozvánky (ponechte prázdné pro vygenerování)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "Zadejte nové heslo (volitelné)", "passwordPlaceholder": "Zadejte nové heslo (volitelné)",
"permanent": "Trvalý", "permanent": "Trvalý",
"pleaseEnterEmail": "Prosím, zadejte e-mail", "pleaseEnterEmail": "Prosím, zadejte e-mail",
"price": "Cena",
"referer": "Doporučitel", "referer": "Doporučitel",
"refererId": "ID doporučitele", "refererId": "ID doporučitele",
"refererIdPlaceholder": "Zadejte ID doporučitele", "refererIdPlaceholder": "Zadejte ID doporučitele",
@@ -74,8 +78,12 @@
"searchIp": "Vyhledat IP adresu", "searchIp": "Vyhledat IP adresu",
"selectAuthType": "Vyberte typ ověření", "selectAuthType": "Vyberte typ ověření",
"speedLimit": "Rychlostní limit", "speedLimit": "Rychlostní limit",
"startTime": "Čas zahájení",
"status": "Stav",
"subscription": "Předplatné", "subscription": "Předplatné",
"subscriptionDetails": "Podrobnosti o předplatném", "subscriptionDetails": "Podrobnosti o předplatném",
"subscriptionId": "ID předplatného",
"subscriptionInfo": "Informace o předplatném",
"subscriptionList": "Seznam předplatných", "subscriptionList": "Seznam předplatných",
"subscriptionLogs": "Záznamy o předplatném", "subscriptionLogs": "Záznamy o předplatném",
"subscriptionName": "Název předplatného", "subscriptionName": "Název předplatného",
@@ -89,6 +97,8 @@
"tradeNotifications": "Obchodní oznámení", "tradeNotifications": "Obchodní oznámení",
"trafficLimit": "Limit provozu", "trafficLimit": "Limit provozu",
"trafficLogs": "Protokoly provozu", "trafficLogs": "Protokoly provozu",
"trafficUsage": "Využití dat",
"unknown": "Neznámé",
"unlimited": "Neomezený", "unlimited": "Neomezený",
"unverified": "Neověřeno", "unverified": "Neověřeno",
"update": "Aktualizovat", "update": "Aktualizovat",
@@ -98,11 +108,15 @@
"userAgent": "Uživatelský agent", "userAgent": "Uživatelský agent",
"userEmail": "Uživatelský e-mail", "userEmail": "Uživatelský e-mail",
"userEmailPlaceholder": "Zadejte e-mail uživatele", "userEmailPlaceholder": "Zadejte e-mail uživatele",
"userId": "ID uživatele",
"userInfo": "Informace o uživateli",
"userList": "Seznam uživatelů", "userList": "Seznam uživatelů",
"userLogs": "Historie přihlášení", "userLogs": "Historie přihlášení",
"userName": "Identifikátor uživatele", "userName": "Identifikátor uživatele",
"userOrders": "Objednávky", "userOrders": "Objednávky",
"userProfile": "Profil", "userProfile": "Profil",
"userSubscriptions": "Předplatné", "userSubscriptions": "Předplatné",
"verified": "Ověřeno" "username": "Uživatelské jméno",
"verified": "Ověřeno",
"viewDetails": "Zobrazit podrobnosti"
} }
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "ADS-Konfiguration", "ADS Config": "ADS-Konfiguration",
"Announcement Management": "Ankündigungsverwaltung", "Announcement Management": "Ankündigungsverwaltung",
"Apple": "Apple-ID", "Apple": "Apple-ID",
"Application Management": "Anwendungsverwaltung",
"Auth Control": "Authentifizierungskontrolle", "Auth Control": "Authentifizierungskontrolle",
"Coupon Management": "Gutscheinverwaltung", "Coupon Management": "Gutscheinverwaltung",
"Dashboard": "Armaturenbrett", "Dashboard": "Armaturenbrett",
@@ -16,6 +17,7 @@
"Order Management": "Bestellverwaltung", "Order Management": "Bestellverwaltung",
"Payment Config": "Zahlungskonfiguration", "Payment Config": "Zahlungskonfiguration",
"Phone Number": "Telefonnummer", "Phone Number": "Telefonnummer",
"Rule Management": "Regelverwaltung",
"Server": "Dienst", "Server": "Dienst",
"Server Management": "Serververwaltung", "Server Management": "Serververwaltung",
"Settings": "Einstellungen", "Settings": "Einstellungen",
-1
View File
@@ -22,7 +22,6 @@
"description": "Beschreibung", "description": "Beschreibung",
"descriptionPlaceholder": "Geben Sie die Beschreibung der Zahlungsmethode ein", "descriptionPlaceholder": "Geben Sie die Beschreibung der Zahlungsmethode ein",
"domain": "Domain", "domain": "Domain",
"domainPlaceholder": "optional, z.B. {example}",
"edit": "Bearbeiten", "edit": "Bearbeiten",
"editPayment": "Zahlungsmethode bearbeiten", "editPayment": "Zahlungsmethode bearbeiten",
"enable": "Aktivieren", "enable": "Aktivieren",
+39
View File
@@ -0,0 +1,39 @@
{
"analyzing": "Analysiere...",
"appIcon": "Regel-Icon",
"cancel": "Abbrechen",
"confirm": "Bestätigen",
"confirmDelete": "Löschen bestätigen",
"create": "Regel hinzufügen",
"createRule": "Regel hinzufügen",
"createSuccess": "Regel erfolgreich erstellt",
"createdAt": "Erstellt am",
"delete": "Löschen",
"deleteSuccess": "Regel erfolgreich gelöscht",
"deleteWarning": "Sind Sie sicher, dass Sie diese Regel löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.",
"downloadTemplate": "Vorlage herunterladen",
"edit": "Bearbeiten",
"editRule": "Regel bearbeiten",
"enable": "Aktivieren",
"enterIconUrl": "Geben Sie eine URL für das Icon ein oder laden Sie es hoch",
"enterRuleName": "Geben Sie den Regelname ein",
"enterRules": "Geben Sie den Regelinhalt ein, jeweils eine Regel pro Zeile",
"import": "Importieren",
"importFailed": "Import fehlgeschlagen",
"importSuccess": "Import erfolgreich",
"importYamlDescription": "Regeln aus einer YAML-Datei importieren, das System erstellt automatisch Regelgruppen basierend auf den Namen der Richtliniengruppen",
"importYamlRules": "YAML-Regeln importieren",
"importing": "Importiere...",
"invalidYamlFormat": "Ungültiges YAML-Format, das Feld 'Regeln' fehlt",
"name": "Regelname",
"noValidRules": "Keine gültigen Regeln gefunden",
"pleaseUploadFile": "Bitte laden Sie eine YAML-Datei hoch",
"preview": "Vorschau",
"rulesFormat": "Regelformat: Regeltyp, Übereinstimmungsinhalt, [Richtlinie], wobei die Richtlinie optional ist.\nWenn keine Richtlinie angegeben ist, wird automatisch der aktuelle Regelgruppenname verwendet. Beispiele:",
"rulesLabel": "Regelinhalt",
"searchRule": "Regelname suchen",
"selectTags": "Knoten-Tags auswählen",
"tags": "Knoten-Tags",
"tagsLabel": "Knoten-Tags",
"updateSuccess": "Regel erfolgreich aktualisiert"
}
+1 -1
View File
@@ -145,7 +145,7 @@
"quota": "Kaufbeschränkung/pro Einkauf", "quota": "Kaufbeschränkung/pro Einkauf",
"replacement": "Preis pro Zurücksetzung", "replacement": "Preis pro Zurücksetzung",
"sell": "Verkauf", "sell": "Verkauf",
"show": "Startseite anzeigen", "show": "Anzeigen",
"sold": "Abonnentenzahl", "sold": "Abonnentenzahl",
"subscribe": "Abonnieren", "subscribe": "Abonnieren",
"subscribeGroup": "Gruppe abonnieren", "subscribeGroup": "Gruppe abonnieren",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "Systemaktualisierung bestätigen", "confirmSystemUpgrade": "Systemaktualisierung bestätigen",
"confirmUpgrade": "Upgrade bestätigen", "confirmUpgrade": "Upgrade bestätigen",
"currentVersion": "Aktuelle Systemversion:", "currentVersion": "Aktuelle Systemversion:",
"developmentVersion": "Entwicklungsversion",
"errors": "Fehler", "errors": "Fehler",
"ip": "IP", "ip": "IP-Adresse",
"lastUpdated": "Zuletzt aktualisiert:", "lastUpdated": "Zuletzt aktualisiert:",
"newVersionAvailable": "Neue Version",
"none": "Keine", "none": "Keine",
"query": "Abfrage", "query": "Abfrage",
"rebootDescription": "Möchten Sie das System wirklich neu starten? Dieser Vorgang führt zu einer kurzen Unterbrechung des Dienstes.", "rebootDescription": "Möchten Sie das System wirklich neu starten? Dieser Vorgang führt zu einer kurzen Unterbrechung des Dienstes.",
"rebooting": "System wird neu gestartet...", "rebooting": "System wird neu gestartet...",
"refreshLogs": "Protokolle aktualisieren", "refreshLogs": "Protokolle aktualisieren",
"request": "Anfrage", "request": "Anfrage",
"serverVersion": "Server",
"status": "Status", "status": "Status",
"systemLogs": "Systemprotokolle", "systemLogs": "Systemprotokolle",
"systemReboot": "Systemneustart", "systemReboot": "Systemneustart",
@@ -22,5 +25,8 @@
"systemUpgrade": "Systemaktualisierung", "systemUpgrade": "Systemaktualisierung",
"upgradeDescription": "Möchten Sie das System-Upgrade wirklich durchführen? Dieser Vorgang kann einige Minuten dauern, währenddessen das System möglicherweise nicht reagiert.", "upgradeDescription": "Möchten Sie das System-Upgrade wirklich durchführen? Dieser Vorgang kann einige Minuten dauern, währenddessen das System möglicherweise nicht reagiert.",
"userAgent": "Benutzeragent", "userAgent": "Benutzeragent",
"viewLogsAndManage": "Systemprotokolle anzeigen, Systemaktualisierungen durchführen und Neustartvorgänge ausführen" "versionInfo": "Versionsinformationen",
"viewLogsAndManage": "Systemprotokolle anzeigen, Systemaktualisierungen durchführen und Neustartvorgänge ausführen",
"viewNewVersion": "Neue Version anzeigen",
"webVersion": "Web/Admin"
} }
+15 -1
View File
@@ -1,6 +1,7 @@
{ {
"accountEnable": "Konto aktivieren", "accountEnable": "Konto aktivieren",
"actions": "Aktionen", "actions": "Aktionen",
"active": "Aktiv",
"add": "Hinzufügen", "add": "Hinzufügen",
"administrator": "Administrator", "administrator": "Administrator",
"areaCode": "Vorwahl", "areaCode": "Vorwahl",
@@ -41,10 +42,12 @@
"email": "E-Mail", "email": "E-Mail",
"enable": "Aktivieren", "enable": "Aktivieren",
"expireTime": "Ablaufzeit", "expireTime": "Ablaufzeit",
"expired": "Abgelaufen",
"expiredAt": "Abgelaufen am", "expiredAt": "Abgelaufen am",
"failed": "Fehlgeschlagen", "failed": "Fehlgeschlagen",
"giftAmount": "Geschenkbetrag", "giftAmount": "Geschenkbetrag",
"giftAmountPlaceholder": "Geben Sie den Geschenkbetrag ein", "giftAmountPlaceholder": "Geben Sie den Geschenkbetrag ein",
"inactive": "Inaktiv",
"invalidEmailFormat": "Ungültiges E-Mail-Format", "invalidEmailFormat": "Ungültiges E-Mail-Format",
"inviteCode": "Einladungscode", "inviteCode": "Einladungscode",
"inviteCodePlaceholder": "Einladungscode eingeben (leer lassen, um zu generieren)", "inviteCodePlaceholder": "Einladungscode eingeben (leer lassen, um zu generieren)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "Neues Passwort eingeben (optional)", "passwordPlaceholder": "Neues Passwort eingeben (optional)",
"permanent": "Dauerhaft", "permanent": "Dauerhaft",
"pleaseEnterEmail": "Bitte E-Mail eingeben", "pleaseEnterEmail": "Bitte E-Mail eingeben",
"price": "Preis",
"referer": "Empfehler", "referer": "Empfehler",
"refererId": "Referenz-ID", "refererId": "Referenz-ID",
"refererIdPlaceholder": "Geben Sie die Referenz-ID ein", "refererIdPlaceholder": "Geben Sie die Referenz-ID ein",
@@ -74,8 +78,12 @@
"searchIp": "IP-Adresse suchen", "searchIp": "IP-Adresse suchen",
"selectAuthType": "Authentifizierungstyp auswählen", "selectAuthType": "Authentifizierungstyp auswählen",
"speedLimit": "Geschwindigkeitsbegrenzung", "speedLimit": "Geschwindigkeitsbegrenzung",
"startTime": "Startzeit",
"status": "Status",
"subscription": "Abonnement", "subscription": "Abonnement",
"subscriptionDetails": "Abonnementdetails", "subscriptionDetails": "Abonnementdetails",
"subscriptionId": "Abonnement-ID",
"subscriptionInfo": "Abonnement-Informationen",
"subscriptionList": "Abonnementsliste", "subscriptionList": "Abonnementsliste",
"subscriptionLogs": "Abonnementprotokolle", "subscriptionLogs": "Abonnementprotokolle",
"subscriptionName": "Abonnementname", "subscriptionName": "Abonnementname",
@@ -89,6 +97,8 @@
"tradeNotifications": "Handelsbenachrichtigungen", "tradeNotifications": "Handelsbenachrichtigungen",
"trafficLimit": "Verkehrslimit", "trafficLimit": "Verkehrslimit",
"trafficLogs": "Verkehrsprotokolle", "trafficLogs": "Verkehrsprotokolle",
"trafficUsage": "Datenverbrauch",
"unknown": "Unbekannt",
"unlimited": "Unbegrenzt", "unlimited": "Unbegrenzt",
"unverified": "Unbestätigt", "unverified": "Unbestätigt",
"update": "Aktualisieren", "update": "Aktualisieren",
@@ -98,11 +108,15 @@
"userAgent": "Benutzeragent", "userAgent": "Benutzeragent",
"userEmail": "Benutzer-E-Mail", "userEmail": "Benutzer-E-Mail",
"userEmailPlaceholder": "Benutzer-E-Mail eingeben", "userEmailPlaceholder": "Benutzer-E-Mail eingeben",
"userId": "Benutzer-ID",
"userInfo": "Benutzerinformationen",
"userList": "Benutzerliste", "userList": "Benutzerliste",
"userLogs": "Anmeldeverlauf", "userLogs": "Anmeldeverlauf",
"userName": "Benutzerkennung", "userName": "Benutzerkennung",
"userOrders": "Bestellungen", "userOrders": "Bestellungen",
"userProfile": "Profil", "userProfile": "Profil",
"userSubscriptions": "Abonnements", "userSubscriptions": "Abonnements",
"verified": "Verifiziert" "username": "Benutzername",
"verified": "Verifiziert",
"viewDetails": "Details anzeigen"
} }
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "ADS Config", "ADS Config": "ADS Config",
"Announcement Management": "Announcement Management", "Announcement Management": "Announcement Management",
"Apple": "Apple ID", "Apple": "Apple ID",
"Application Management": "Application Management",
"Auth Control": "Auth Control", "Auth Control": "Auth Control",
"Coupon Management": "Coupon Management", "Coupon Management": "Coupon Management",
"Dashboard": "Dashboard", "Dashboard": "Dashboard",
@@ -16,6 +17,7 @@
"Order Management": "Order Management", "Order Management": "Order Management",
"Payment Config": "Payment Config", "Payment Config": "Payment Config",
"Phone Number": "Phone Number", "Phone Number": "Phone Number",
"Rule Management": "Rule Management",
"Server": "Server", "Server": "Server",
"Server Management": "Server Management", "Server Management": "Server Management",
"Settings": "Settings", "Settings": "Settings",
-1
View File
@@ -22,7 +22,6 @@
"description": "Description", "description": "Description",
"descriptionPlaceholder": "Enter payment method description", "descriptionPlaceholder": "Enter payment method description",
"domain": "Domain", "domain": "Domain",
"domainPlaceholder": "optional, e.g. {example}",
"edit": "Edit", "edit": "Edit",
"editPayment": "Edit Payment Method", "editPayment": "Edit Payment Method",
"enable": "Enable", "enable": "Enable",
+45
View File
@@ -0,0 +1,45 @@
{
"analyzing": "Analyzing...",
"appIcon": "Rule Icon",
"cancel": "Cancel",
"confirm": "Confirm",
"confirmDelete": "Confirm Deletion",
"create": "Add Rule",
"createRule": "Add Rule",
"createSuccess": "Rule created successfully",
"createdAt": "Created At",
"default": "Default",
"defaultRule": "Default Rule",
"delete": "Delete",
"deleteSuccess": "Rule deleted successfully",
"deleteWarning": "Are you sure you want to delete this rule? This action cannot be undone.",
"direct": "Direct",
"downloadTemplate": "Download Template",
"edit": "Edit",
"editRule": "Edit Rule",
"enable": "Enable",
"enterIconUrl": "Enter or upload an icon",
"enterRuleName": "Enter rule name",
"enterRules": "Enter rule content, one per line",
"import": "Import",
"importFailed": "Import failed",
"importSuccess": "Import successful",
"importYamlDescription": "Import rules from YAML file, the system will automatically create rule groups based on policy group names",
"importYamlRules": "Import YAML Rules",
"importing": "Importing...",
"invalidYamlFormat": "Invalid YAML format, missing rules field",
"name": "Rule Name",
"noValidRules": "No valid rules found",
"pleaseUploadFile": "Please upload a YAML file",
"preview": "Preview",
"reject": "Reject",
"rulesFormat": "Rule format: rule type,match content,[policy], where policy is optional.\nIf policy is not specified, the current rule group name will be used automatically. Examples:",
"rulesLabel": "Rule Content",
"searchRule": "Search rule name",
"selectTags": "Select node tags",
"selectType": "Select rule type",
"tags": "Node Tags",
"tagsLabel": "Node Tags",
"type": "Rule Type",
"updateSuccess": "Rule updated successfully"
}
+7
View File
@@ -63,16 +63,20 @@
"edit": "Edit", "edit": "Edit",
"editNode": "Edit Node", "editNode": "Edit Node",
"enable": "Enable", "enable": "Enable",
"id": "ID",
"form": { "form": {
"allowInsecure": "Allow Insecure", "allowInsecure": "Allow Insecure",
"cancel": "Cancel", "cancel": "Cancel",
"city": "City", "city": "City",
"confirm": "Confirm", "confirm": "Confirm",
"congestionController": "Congestion Controller",
"country": "Country", "country": "Country",
"disableSni": "Disable SNI",
"edit": "Edit", "edit": "Edit",
"editSecurity": "Edit Security Configuration", "editSecurity": "Edit Security Configuration",
"enableTLS": "Enable TLS", "enableTLS": "Enable TLS",
"encryptionMethod": "Encryption Method", "encryptionMethod": "Encryption Method",
"fingerprint": "Fingerprint",
"flow": "Flow Control Algorithm", "flow": "Flow Control Algorithm",
"groupId": "Node Group", "groupId": "Node Group",
"hopInterval": "Hop Interval", "hopInterval": "Hop Interval",
@@ -85,6 +89,7 @@
"pleaseSelect": "Please Select", "pleaseSelect": "Please Select",
"port": "Server Port", "port": "Server Port",
"protocol": "Protocol", "protocol": "Protocol",
"reduceRtt": "Reduce RTT",
"relayHost": "Relay Host", "relayHost": "Relay Host",
"relayMode": "Relay Mode", "relayMode": "Relay Mode",
"relayModeOptions": { "relayModeOptions": {
@@ -128,6 +133,7 @@
"transport": "Transport Protocol Configuration", "transport": "Transport Protocol Configuration",
"transportConfig": "Transport Protocol Configuration", "transportConfig": "Transport Protocol Configuration",
"transportHost": "Transport Server Address", "transportHost": "Transport Server Address",
"udpRelayMode": "UDP Relay Mode",
"transportPath": "Transport Path", "transportPath": "Transport Path",
"transportServerName": "Transport Server Name" "transportServerName": "Transport Server Name"
}, },
@@ -136,6 +142,7 @@
"name": "Name", "name": "Name",
"node": "Node", "node": "Node",
"nodeGroup": "Node Group", "nodeGroup": "Node Group",
"noData": "--",
"normal": "Normal", "normal": "Normal",
"onlineCount": "Online users", "onlineCount": "Online users",
"onlineUsers": "Online Users", "onlineUsers": "Online Users",
+1 -1
View File
@@ -145,7 +145,7 @@
"quota": "Purchase Limit/Time", "quota": "Purchase Limit/Time",
"replacement": "Reset Price/Time", "replacement": "Reset Price/Time",
"sell": "Sell", "sell": "Sell",
"show": "Home display", "show": "Display",
"sold": "Subscription Count", "sold": "Subscription Count",
"subscribe": "Subscribe", "subscribe": "Subscribe",
"subscribeGroup": "Subscription Group", "subscribeGroup": "Subscription Group",
+7 -1
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "Confirm System Upgrade", "confirmSystemUpgrade": "Confirm System Upgrade",
"confirmUpgrade": "Confirm Upgrade", "confirmUpgrade": "Confirm Upgrade",
"currentVersion": "Current System Version:", "currentVersion": "Current System Version:",
"developmentVersion": "Dev",
"errors": "Errors", "errors": "Errors",
"ip": "IP", "ip": "IP",
"lastUpdated": "Last Updated:", "lastUpdated": "Last Updated:",
"newVersionAvailable": "New Version",
"none": "None", "none": "None",
"query": "Query", "query": "Query",
"rebootDescription": "Are you sure you want to reboot the system? This operation will cause a brief service interruption.", "rebootDescription": "Are you sure you want to reboot the system? This operation will cause a brief service interruption.",
"rebooting": "Rebooting system...", "rebooting": "Rebooting system...",
"refreshLogs": "Refresh Logs", "refreshLogs": "Refresh Logs",
"request": "Request", "request": "Request",
"serverVersion": "Server",
"status": "Status", "status": "Status",
"systemLogs": "System Logs", "systemLogs": "System Logs",
"systemReboot": "System Reboot", "systemReboot": "System Reboot",
@@ -22,5 +25,8 @@
"systemUpgrade": "System Upgrade", "systemUpgrade": "System Upgrade",
"upgradeDescription": "Are you sure you want to perform a system upgrade? This operation may take a few minutes, during which the system may be unresponsive.", "upgradeDescription": "Are you sure you want to perform a system upgrade? This operation may take a few minutes, during which the system may be unresponsive.",
"userAgent": "User Agent", "userAgent": "User Agent",
"viewLogsAndManage": "View system logs, perform system upgrade and reboot operations" "versionInfo": "Version Information",
"viewLogsAndManage": "View system logs, perform system upgrade and reboot operations",
"viewNewVersion": "View New Version",
"webVersion": "Web/Admin"
} }
+15 -1
View File
@@ -1,6 +1,7 @@
{ {
"accountEnable": "Account Enable", "accountEnable": "Account Enable",
"actions": "Actions", "actions": "Actions",
"active": "Active",
"add": "Add", "add": "Add",
"administrator": "Administrator", "administrator": "Administrator",
"areaCode": "Area Code", "areaCode": "Area Code",
@@ -41,10 +42,12 @@
"email": "Email", "email": "Email",
"enable": "Enable", "enable": "Enable",
"expireTime": "Expire Time", "expireTime": "Expire Time",
"expired": "Expired",
"expiredAt": "Expired At", "expiredAt": "Expired At",
"failed": "Failed", "failed": "Failed",
"giftAmount": "Gift Amount", "giftAmount": "Gift Amount",
"giftAmountPlaceholder": "Enter gift amount", "giftAmountPlaceholder": "Enter gift amount",
"inactive": "Inactive",
"invalidEmailFormat": "Invalid email format", "invalidEmailFormat": "Invalid email format",
"inviteCode": "Invite Code", "inviteCode": "Invite Code",
"inviteCodePlaceholder": "Enter invite code (leave blank to generate)", "inviteCodePlaceholder": "Enter invite code (leave blank to generate)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "Enter new password (optional)", "passwordPlaceholder": "Enter new password (optional)",
"permanent": "Permanent", "permanent": "Permanent",
"pleaseEnterEmail": "Please enter email", "pleaseEnterEmail": "Please enter email",
"price": "Price",
"referer": "Referer", "referer": "Referer",
"refererId": "Referer ID", "refererId": "Referer ID",
"refererIdPlaceholder": "Enter referer ID", "refererIdPlaceholder": "Enter referer ID",
@@ -74,8 +78,12 @@
"searchIp": "Search IP address", "searchIp": "Search IP address",
"selectAuthType": "Select auth type", "selectAuthType": "Select auth type",
"speedLimit": "Speed Limit", "speedLimit": "Speed Limit",
"startTime": "Start Time",
"status": "Status",
"subscription": "Subscription", "subscription": "Subscription",
"subscriptionDetails": "Subscription Details", "subscriptionDetails": "Subscription Details",
"subscriptionId": "Subscription ID",
"subscriptionInfo": "Subscription Info",
"subscriptionList": "Subscription List", "subscriptionList": "Subscription List",
"subscriptionLogs": "Subscription Logs", "subscriptionLogs": "Subscription Logs",
"subscriptionName": "Subscription Name", "subscriptionName": "Subscription Name",
@@ -89,6 +97,8 @@
"tradeNotifications": "Trade Notifications", "tradeNotifications": "Trade Notifications",
"trafficLimit": "Traffic Limit", "trafficLimit": "Traffic Limit",
"trafficLogs": "Traffic Logs", "trafficLogs": "Traffic Logs",
"trafficUsage": "Traffic Usage",
"unknown": "Unknown",
"unlimited": "Unlimited", "unlimited": "Unlimited",
"unverified": "Unverified", "unverified": "Unverified",
"update": "Update", "update": "Update",
@@ -98,11 +108,15 @@
"userAgent": "User Agent", "userAgent": "User Agent",
"userEmail": "User Email", "userEmail": "User Email",
"userEmailPlaceholder": "Enter user email", "userEmailPlaceholder": "Enter user email",
"userId": "User ID",
"userInfo": "User Info",
"userList": "User List", "userList": "User List",
"userLogs": "Login History", "userLogs": "Login History",
"userName": "User Identifier", "userName": "User Identifier",
"userOrders": "Orders", "userOrders": "Orders",
"userProfile": "Profile", "userProfile": "Profile",
"userSubscriptions": "Subscriptions", "userSubscriptions": "Subscriptions",
"verified": "Verified" "username": "Username",
"verified": "Verified",
"viewDetails": "View Details"
} }
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "Configuración de ADS", "ADS Config": "Configuración de ADS",
"Announcement Management": "Gestión de Anuncios", "Announcement Management": "Gestión de Anuncios",
"Apple": "ID de Apple", "Apple": "ID de Apple",
"Application Management": "Gestión de Aplicaciones",
"Auth Control": "Control de Autenticación", "Auth Control": "Control de Autenticación",
"Coupon Management": "Gestión de Cupones", "Coupon Management": "Gestión de Cupones",
"Dashboard": "Tablero", "Dashboard": "Tablero",
@@ -16,6 +17,7 @@
"Order Management": "Gestión de Pedidos", "Order Management": "Gestión de Pedidos",
"Payment Config": "Configuración de Pago", "Payment Config": "Configuración de Pago",
"Phone Number": "Número de Teléfono", "Phone Number": "Número de Teléfono",
"Rule Management": "Gestión de Reglas",
"Server": "Servidor", "Server": "Servidor",
"Server Management": "Gestión de Servidores", "Server Management": "Gestión de Servidores",
"Settings": "Configuración", "Settings": "Configuración",
-1
View File
@@ -22,7 +22,6 @@
"description": "Descripción", "description": "Descripción",
"descriptionPlaceholder": "Ingrese la descripción del método de pago", "descriptionPlaceholder": "Ingrese la descripción del método de pago",
"domain": "Dominio", "domain": "Dominio",
"domainPlaceholder": "opcional, p. ej. {example}",
"edit": "Editar", "edit": "Editar",
"editPayment": "Editar Método de Pago", "editPayment": "Editar Método de Pago",
"enable": "Habilitar", "enable": "Habilitar",
+39
View File
@@ -0,0 +1,39 @@
{
"analyzing": "Analizando...",
"appIcon": "Icono de Regla",
"cancel": "Cancelar",
"confirm": "Confirmar",
"confirmDelete": "Confirmar Eliminación",
"create": "Agregar Regla",
"createRule": "Agregar Regla",
"createSuccess": "Regla creada con éxito",
"createdAt": "Creado En",
"delete": "Eliminar",
"deleteSuccess": "Regla eliminada con éxito",
"deleteWarning": "¿Está seguro de que desea eliminar esta regla? Esta acción no se puede deshacer.",
"downloadTemplate": "Descargar Plantilla",
"edit": "Editar",
"editRule": "Editar Regla",
"enable": "Habilitar",
"enterIconUrl": "Ingrese o suba un icono",
"enterRuleName": "Ingrese el nombre de la regla",
"enterRules": "Ingrese el contenido de la regla, uno por línea",
"import": "Importar",
"importFailed": "Importación fallida",
"importSuccess": "Importación exitosa",
"importYamlDescription": "Importar reglas desde un archivo YAML, el sistema creará automáticamente grupos de reglas basados en los nombres de los grupos de políticas",
"importYamlRules": "Importar Reglas YAML",
"importing": "Importando...",
"invalidYamlFormat": "Formato YAML inválido, falta el campo de reglas",
"name": "Nombre de la Regla",
"noValidRules": "No se encontraron reglas válidas",
"pleaseUploadFile": "Por favor, suba un archivo YAML",
"preview": "Vista Previa",
"rulesFormat": "Formato de regla: tipo de regla, contenido de coincidencia, [política], donde la política es opcional.\nSi no se especifica la política, se utilizará automáticamente el nombre del grupo de reglas actual. Ejemplos:",
"rulesLabel": "Contenido de la Regla",
"searchRule": "Buscar nombre de regla",
"selectTags": "Seleccionar etiquetas de nodo",
"tags": "Etiquetas de Nodo",
"tagsLabel": "Etiquetas de Nodo",
"updateSuccess": "Regla actualizada con éxito"
}
+1 -1
View File
@@ -145,7 +145,7 @@
"quota": "Límite de compra/vez", "quota": "Límite de compra/vez",
"replacement": "Restablecer precio/vez", "replacement": "Restablecer precio/vez",
"sell": "Venta", "sell": "Venta",
"show": "Mostrar en la página de inicio", "show": "Mostrar",
"sold": "Conteo de Suscripciones", "sold": "Conteo de Suscripciones",
"subscribe": "Suscribirse", "subscribe": "Suscribirse",
"subscribeGroup": "Suscribirse al grupo", "subscribeGroup": "Suscribirse al grupo",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "Confirmar actualización del sistema", "confirmSystemUpgrade": "Confirmar actualización del sistema",
"confirmUpgrade": "Confirmar actualización", "confirmUpgrade": "Confirmar actualización",
"currentVersion": "Versión actual del sistema:", "currentVersion": "Versión actual del sistema:",
"developmentVersion": "Versión de desarrollo",
"errors": "Errores", "errors": "Errores",
"ip": "IP", "ip": "Dirección IP",
"lastUpdated": "Última actualización:", "lastUpdated": "Última actualización:",
"newVersionAvailable": "Nueva versión",
"none": "Ninguno", "none": "Ninguno",
"query": "Consulta", "query": "Consulta",
"rebootDescription": "¿Está seguro de que desea reiniciar el sistema? Esta acción provocará una breve interrupción del servicio.", "rebootDescription": "¿Está seguro de que desea reiniciar el sistema? Esta acción provocará una breve interrupción del servicio.",
"rebooting": "Reiniciando el sistema...", "rebooting": "Reiniciando el sistema...",
"refreshLogs": "Actualizar registros", "refreshLogs": "Actualizar registros",
"request": "Solicitud", "request": "Solicitud",
"serverVersion": "Servidor",
"status": "Estado", "status": "Estado",
"systemLogs": "Registros del sistema", "systemLogs": "Registros del sistema",
"systemReboot": "Reinicio del sistema", "systemReboot": "Reinicio del sistema",
@@ -22,5 +25,8 @@
"systemUpgrade": "Actualización del sistema", "systemUpgrade": "Actualización del sistema",
"upgradeDescription": "¿Está seguro de que desea realizar la actualización del sistema? Esta operación puede tardar unos minutos, durante los cuales el sistema podría no responder.", "upgradeDescription": "¿Está seguro de que desea realizar la actualización del sistema? Esta operación puede tardar unos minutos, durante los cuales el sistema podría no responder.",
"userAgent": "Agente de Usuario", "userAgent": "Agente de Usuario",
"viewLogsAndManage": "Ver los registros del sistema, realizar actualizaciones del sistema y reiniciar operaciones" "versionInfo": "Información de versión",
"viewLogsAndManage": "Ver los registros del sistema, realizar actualizaciones del sistema y reiniciar operaciones",
"viewNewVersion": "Ver nueva versión",
"webVersion": "Web/Admin"
} }
+15 -1
View File
@@ -1,6 +1,7 @@
{ {
"accountEnable": "Habilitar cuenta", "accountEnable": "Habilitar cuenta",
"actions": "acciones", "actions": "acciones",
"active": "Activo",
"add": "Agregar", "add": "Agregar",
"administrator": "Administrador", "administrator": "Administrador",
"areaCode": "Código de Área", "areaCode": "Código de Área",
@@ -41,10 +42,12 @@
"email": "correo electrónico", "email": "correo electrónico",
"enable": "Habilitar", "enable": "Habilitar",
"expireTime": "Tiempo de Expiración", "expireTime": "Tiempo de Expiración",
"expired": "Caducado",
"expiredAt": "Fecha de vencimiento", "expiredAt": "Fecha de vencimiento",
"failed": "Fallido", "failed": "Fallido",
"giftAmount": "Monto del Regalo", "giftAmount": "Monto del Regalo",
"giftAmountPlaceholder": "Ingrese el monto del regalo", "giftAmountPlaceholder": "Ingrese el monto del regalo",
"inactive": "Inactivo",
"invalidEmailFormat": "Formato de correo electrónico no válido", "invalidEmailFormat": "Formato de correo electrónico no válido",
"inviteCode": "Código de invitación", "inviteCode": "Código de invitación",
"inviteCodePlaceholder": "Introduce el código de invitación (déjalo en blanco para generar uno)", "inviteCodePlaceholder": "Introduce el código de invitación (déjalo en blanco para generar uno)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "Ingrese nueva contraseña (opcional)", "passwordPlaceholder": "Ingrese nueva contraseña (opcional)",
"permanent": "Permanente", "permanent": "Permanente",
"pleaseEnterEmail": "Por favor, introduce el correo electrónico", "pleaseEnterEmail": "Por favor, introduce el correo electrónico",
"price": "Precio",
"referer": "Recomendador", "referer": "Recomendador",
"refererId": "ID del Referente", "refererId": "ID del Referente",
"refererIdPlaceholder": "Ingrese el ID del referente", "refererIdPlaceholder": "Ingrese el ID del referente",
@@ -74,8 +78,12 @@
"searchIp": "Buscar dirección IP", "searchIp": "Buscar dirección IP",
"selectAuthType": "Seleccionar tipo de autenticación", "selectAuthType": "Seleccionar tipo de autenticación",
"speedLimit": "Límite de Velocidad", "speedLimit": "Límite de Velocidad",
"startTime": "Hora de Inicio",
"status": "Estado",
"subscription": "Suscripción", "subscription": "Suscripción",
"subscriptionDetails": "Detalles de la suscripción", "subscriptionDetails": "Detalles de la suscripción",
"subscriptionId": "ID de Suscripción",
"subscriptionInfo": "Información de Suscripción",
"subscriptionList": "Lista de Suscripción", "subscriptionList": "Lista de Suscripción",
"subscriptionLogs": "Registros de Suscripción", "subscriptionLogs": "Registros de Suscripción",
"subscriptionName": "Nombre de la Suscripción", "subscriptionName": "Nombre de la Suscripción",
@@ -89,6 +97,8 @@
"tradeNotifications": "Notificaciones de Comercio", "tradeNotifications": "Notificaciones de Comercio",
"trafficLimit": "Límite de Tráfico", "trafficLimit": "Límite de Tráfico",
"trafficLogs": "Registros de Tráfico", "trafficLogs": "Registros de Tráfico",
"trafficUsage": "Uso de Tráfico",
"unknown": "Desconocido",
"unlimited": "Ilimitado", "unlimited": "Ilimitado",
"unverified": "No verificado", "unverified": "No verificado",
"update": "Actualizar", "update": "Actualizar",
@@ -98,11 +108,15 @@
"userAgent": "Agente de Usuario", "userAgent": "Agente de Usuario",
"userEmail": "Correo Electrónico del Usuario", "userEmail": "Correo Electrónico del Usuario",
"userEmailPlaceholder": "Introduce el correo electrónico del usuario", "userEmailPlaceholder": "Introduce el correo electrónico del usuario",
"userId": "ID de Usuario",
"userInfo": "Información de Usuario",
"userList": "Lista de usuarios", "userList": "Lista de usuarios",
"userLogs": "Historial de inicio de sesión", "userLogs": "Historial de inicio de sesión",
"userName": "Identificador de Usuario", "userName": "Identificador de Usuario",
"userOrders": "Pedidos", "userOrders": "Pedidos",
"userProfile": "Perfil", "userProfile": "Perfil",
"userSubscriptions": "Suscripciones", "userSubscriptions": "Suscripciones",
"verified": "Verificado" "username": "Nombre de Usuario",
"verified": "Verificado",
"viewDetails": "Ver Detalles"
} }
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "Configuración de ADS", "ADS Config": "Configuración de ADS",
"Announcement Management": "Gestión de Anuncios", "Announcement Management": "Gestión de Anuncios",
"Apple": "ID de Apple", "Apple": "ID de Apple",
"Application Management": "Gestión de Aplicaciones",
"Auth Control": "Control de Autenticación", "Auth Control": "Control de Autenticación",
"Coupon Management": "Gestión de Cupones", "Coupon Management": "Gestión de Cupones",
"Dashboard": "Tablero", "Dashboard": "Tablero",
@@ -16,6 +17,7 @@
"Order Management": "Gestión de Pedidos", "Order Management": "Gestión de Pedidos",
"Payment Config": "Configuración de Pago", "Payment Config": "Configuración de Pago",
"Phone Number": "Número de Teléfono", "Phone Number": "Número de Teléfono",
"Rule Management": "Gestión de Reglas",
"Server": "Servidor", "Server": "Servidor",
"Server Management": "Gestión de Servidores", "Server Management": "Gestión de Servidores",
"Settings": "Configuración", "Settings": "Configuración",
-1
View File
@@ -22,7 +22,6 @@
"description": "Descripción", "description": "Descripción",
"descriptionPlaceholder": "Ingresa la descripción del método de pago", "descriptionPlaceholder": "Ingresa la descripción del método de pago",
"domain": "Dominio", "domain": "Dominio",
"domainPlaceholder": "opcional, p. ej. {example}",
"edit": "Editar", "edit": "Editar",
"editPayment": "Editar Método de Pago", "editPayment": "Editar Método de Pago",
"enable": "Habilitar", "enable": "Habilitar",
+39
View File
@@ -0,0 +1,39 @@
{
"analyzing": "Analizando...",
"appIcon": "Ícono de Regla",
"cancel": "Cancelar",
"confirm": "Confirmar",
"confirmDelete": "Confirmar Eliminación",
"create": "Agregar Regla",
"createRule": "Agregar Regla",
"createSuccess": "Regla creada con éxito",
"createdAt": "Creado En",
"delete": "Eliminar",
"deleteSuccess": "Regla eliminada con éxito",
"deleteWarning": "¿Está seguro de que desea eliminar esta regla? Esta acción no se puede deshacer.",
"downloadTemplate": "Descargar Plantilla",
"edit": "Editar",
"editRule": "Editar Regla",
"enable": "Habilitar",
"enterIconUrl": "Ingrese o suba un ícono",
"enterRuleName": "Ingrese el nombre de la regla",
"enterRules": "Ingrese el contenido de la regla, uno por línea",
"import": "Importar",
"importFailed": "Importación fallida",
"importSuccess": "Importación exitosa",
"importYamlDescription": "Importar reglas desde un archivo YAML, el sistema creará automáticamente grupos de reglas basados en los nombres de los grupos de políticas",
"importYamlRules": "Importar Reglas YAML",
"importing": "Importando...",
"invalidYamlFormat": "Formato YAML inválido, falta el campo de reglas",
"name": "Nombre de la Regla",
"noValidRules": "No se encontraron reglas válidas",
"pleaseUploadFile": "Por favor, suba un archivo YAML",
"preview": "Vista Previa",
"rulesFormat": "Formato de regla: tipo de regla, contenido de coincidencia, [política], donde la política es opcional.\nSi no se especifica la política, se utilizará automáticamente el nombre del grupo de reglas actual. Ejemplos:",
"rulesLabel": "Contenido de la Regla",
"searchRule": "Buscar nombre de regla",
"selectTags": "Seleccionar etiquetas de nodo",
"tags": "Etiquetas de Nodo",
"tagsLabel": "Etiquetas de Nodo",
"updateSuccess": "Regla actualizada con éxito"
}
+1 -1
View File
@@ -145,7 +145,7 @@
"quota": "Límite de compra/vez", "quota": "Límite de compra/vez",
"replacement": "Restablecer precio/vez", "replacement": "Restablecer precio/vez",
"sell": "venta", "sell": "venta",
"show": "Mostrar en la página de inicio", "show": "Mostrar",
"sold": "Conteo de Suscripciones", "sold": "Conteo de Suscripciones",
"subscribe": "Suscribirse", "subscribe": "Suscribirse",
"subscribeGroup": "Suscribirse al grupo", "subscribeGroup": "Suscribirse al grupo",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "Confirmar actualización del sistema", "confirmSystemUpgrade": "Confirmar actualización del sistema",
"confirmUpgrade": "Confirmar actualización", "confirmUpgrade": "Confirmar actualización",
"currentVersion": "Versión actual del sistema:", "currentVersion": "Versión actual del sistema:",
"developmentVersion": "Versión de desarrollo",
"errors": "Errores", "errors": "Errores",
"ip": "IP", "ip": "Dirección IP",
"lastUpdated": "Última actualización:", "lastUpdated": "Última actualización:",
"newVersionAvailable": "Nueva versión",
"none": "Ninguno", "none": "Ninguno",
"query": "Consulta", "query": "Consulta",
"rebootDescription": "¿Está seguro de que desea reiniciar el sistema? Esta acción provocará una breve interrupción del servicio.", "rebootDescription": "¿Está seguro de que desea reiniciar el sistema? Esta acción provocará una breve interrupción del servicio.",
"rebooting": "Reiniciando el sistema...", "rebooting": "Reiniciando el sistema...",
"refreshLogs": "Actualizar registros", "refreshLogs": "Actualizar registros",
"request": "Solicitud", "request": "Solicitud",
"serverVersion": "Servidor",
"status": "Estado", "status": "Estado",
"systemLogs": "Registros del sistema", "systemLogs": "Registros del sistema",
"systemReboot": "Reinicio del sistema", "systemReboot": "Reinicio del sistema",
@@ -22,5 +25,8 @@
"systemUpgrade": "Actualización del sistema", "systemUpgrade": "Actualización del sistema",
"upgradeDescription": "¿Está seguro de que desea realizar la actualización del sistema? Esta operación puede tardar unos minutos, durante los cuales el sistema podría no responder.", "upgradeDescription": "¿Está seguro de que desea realizar la actualización del sistema? Esta operación puede tardar unos minutos, durante los cuales el sistema podría no responder.",
"userAgent": "Agente de Usuario", "userAgent": "Agente de Usuario",
"viewLogsAndManage": "Ver los registros del sistema, realizar actualizaciones del sistema y reiniciar operaciones" "versionInfo": "Información de versión",
"viewLogsAndManage": "Ver los registros del sistema, realizar actualizaciones del sistema y reiniciar operaciones",
"viewNewVersion": "Ver nueva versión",
"webVersion": "Web/Admin"
} }
+15 -1
View File
@@ -1,6 +1,7 @@
{ {
"accountEnable": "Habilitar Cuenta", "accountEnable": "Habilitar Cuenta",
"actions": "acciones", "actions": "acciones",
"active": "Activo",
"add": "Agregar", "add": "Agregar",
"administrator": "Administrador", "administrator": "Administrador",
"areaCode": "Código de Área", "areaCode": "Código de Área",
@@ -41,10 +42,12 @@
"email": "correo electrónico", "email": "correo electrónico",
"enable": "Habilitar", "enable": "Habilitar",
"expireTime": "Tiempo de Expiración", "expireTime": "Tiempo de Expiración",
"expired": "Expirado",
"expiredAt": "Fecha de vencimiento", "expiredAt": "Fecha de vencimiento",
"failed": "Fallido", "failed": "Fallido",
"giftAmount": "Monto del Regalo", "giftAmount": "Monto del Regalo",
"giftAmountPlaceholder": "Ingrese el monto del regalo", "giftAmountPlaceholder": "Ingrese el monto del regalo",
"inactive": "Inactivo",
"invalidEmailFormat": "Formato de correo electrónico no válido", "invalidEmailFormat": "Formato de correo electrónico no válido",
"inviteCode": "Código de Invitación", "inviteCode": "Código de Invitación",
"inviteCodePlaceholder": "Ingresa el código de invitación (déjalo en blanco para generar uno)", "inviteCodePlaceholder": "Ingresa el código de invitación (déjalo en blanco para generar uno)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "Ingresa nueva contraseña (opcional)", "passwordPlaceholder": "Ingresa nueva contraseña (opcional)",
"permanent": "Permanente", "permanent": "Permanente",
"pleaseEnterEmail": "Por favor, ingresa el correo electrónico", "pleaseEnterEmail": "Por favor, ingresa el correo electrónico",
"price": "Precio",
"referer": "Recomendador", "referer": "Recomendador",
"refererId": "ID del Referente", "refererId": "ID del Referente",
"refererIdPlaceholder": "Ingrese ID del referente", "refererIdPlaceholder": "Ingrese ID del referente",
@@ -74,8 +78,12 @@
"searchIp": "Buscar dirección IP", "searchIp": "Buscar dirección IP",
"selectAuthType": "Seleccionar tipo de autenticación", "selectAuthType": "Seleccionar tipo de autenticación",
"speedLimit": "Límite de Velocidad", "speedLimit": "Límite de Velocidad",
"startTime": "Hora de Inicio",
"status": "Estado",
"subscription": "Suscripción", "subscription": "Suscripción",
"subscriptionDetails": "Detalles de la Suscripción", "subscriptionDetails": "Detalles de la Suscripción",
"subscriptionId": "ID de Suscripción",
"subscriptionInfo": "Información de Suscripción",
"subscriptionList": "Lista de Suscripción", "subscriptionList": "Lista de Suscripción",
"subscriptionLogs": "Registros de Suscripción", "subscriptionLogs": "Registros de Suscripción",
"subscriptionName": "Nombre de la Suscripción", "subscriptionName": "Nombre de la Suscripción",
@@ -89,6 +97,8 @@
"tradeNotifications": "Notificaciones de Comercio", "tradeNotifications": "Notificaciones de Comercio",
"trafficLimit": "Límite de Tráfico", "trafficLimit": "Límite de Tráfico",
"trafficLogs": "Registros de Tráfico", "trafficLogs": "Registros de Tráfico",
"trafficUsage": "Uso de Tráfico",
"unknown": "Desconocido",
"unlimited": "Ilimitado", "unlimited": "Ilimitado",
"unverified": "No verificado", "unverified": "No verificado",
"update": "Actualizar", "update": "Actualizar",
@@ -98,11 +108,15 @@
"userAgent": "Agente de Usuario", "userAgent": "Agente de Usuario",
"userEmail": "Correo Electrónico del Usuario", "userEmail": "Correo Electrónico del Usuario",
"userEmailPlaceholder": "Ingresa el correo electrónico del usuario", "userEmailPlaceholder": "Ingresa el correo electrónico del usuario",
"userId": "ID de Usuario",
"userInfo": "Información de Usuario",
"userList": "Lista de usuarios", "userList": "Lista de usuarios",
"userLogs": "Historial de Inicio de Sesión", "userLogs": "Historial de Inicio de Sesión",
"userName": "Identificador de Usuario", "userName": "Identificador de Usuario",
"userOrders": "Pedidos", "userOrders": "Pedidos",
"userProfile": "Perfil", "userProfile": "Perfil",
"userSubscriptions": "Suscripciones", "userSubscriptions": "Suscripciones",
"verified": "Verificado" "username": "Nombre de Usuario",
"verified": "Verificado",
"viewDetails": "Ver Detalles"
} }
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "تنظیمات ADS", "ADS Config": "تنظیمات ADS",
"Announcement Management": "مدیریت اطلاعیه‌ها", "Announcement Management": "مدیریت اطلاعیه‌ها",
"Apple": "شناسه اپل", "Apple": "شناسه اپل",
"Application Management": "مدیریت برنامه",
"Auth Control": "کنترل احراز هویت", "Auth Control": "کنترل احراز هویت",
"Coupon Management": "مدیریت کوپن", "Coupon Management": "مدیریت کوپن",
"Dashboard": "داشبورد", "Dashboard": "داشبورد",
@@ -16,6 +17,7 @@
"Order Management": "مدیریت سفارش", "Order Management": "مدیریت سفارش",
"Payment Config": "پیکربندی پرداخت", "Payment Config": "پیکربندی پرداخت",
"Phone Number": "شماره تلفن", "Phone Number": "شماره تلفن",
"Rule Management": "مدیریت قوانین",
"Server": "سرور", "Server": "سرور",
"Server Management": "مدیریت سرور", "Server Management": "مدیریت سرور",
"Settings": "تنظیمات", "Settings": "تنظیمات",
-1
View File
@@ -22,7 +22,6 @@
"description": "توضیحات", "description": "توضیحات",
"descriptionPlaceholder": "توضیحات روش پرداخت را وارد کنید", "descriptionPlaceholder": "توضیحات روش پرداخت را وارد کنید",
"domain": "دامنه", "domain": "دامنه",
"domainPlaceholder": "اختیاری، به عنوان مثال {example}",
"edit": "ویرایش", "edit": "ویرایش",
"editPayment": "ویرایش روش پرداخت", "editPayment": "ویرایش روش پرداخت",
"enable": "فعال کردن", "enable": "فعال کردن",
+39
View File
@@ -0,0 +1,39 @@
{
"analyzing": "در حال تجزیه و تحلیل...",
"appIcon": "آیکون قانون",
"cancel": "لغو",
"confirm": "تأیید",
"confirmDelete": "تأیید حذف",
"create": "افزودن قانون",
"createRule": "افزودن قانون",
"createSuccess": "قانون با موفقیت ایجاد شد",
"createdAt": "تاریخ ایجاد",
"delete": "حذف",
"deleteSuccess": "قانون با موفقیت حذف شد",
"deleteWarning": "آیا مطمئن هستید که می‌خواهید این قانون را حذف کنید؟ این عمل قابل بازگشت نیست.",
"downloadTemplate": "دانلود الگو",
"edit": "ویرایش",
"editRule": "ویرایش قانون",
"enable": "فعال‌سازی",
"enterIconUrl": "آدرس یا بارگذاری آیکون را وارد کنید",
"enterRuleName": "نام قانون را وارد کنید",
"enterRules": "محتوای قانون را وارد کنید، هر کدام در یک خط",
"import": "وارد کردن",
"importFailed": "وارد کردن ناموفق بود",
"importSuccess": "وارد کردن با موفقیت انجام شد",
"importYamlDescription": "وارد کردن قوانین از فایل YAML، سیستم به طور خودکار گروه‌های قانونی را بر اساس نام‌های گروه سیاست ایجاد خواهد کرد",
"importYamlRules": "وارد کردن قوانین YAML",
"importing": "در حال وارد کردن...",
"invalidYamlFormat": "فرمت YAML نامعتبر است، فیلد قوانین گم شده است",
"name": "نام قانون",
"noValidRules": "هیچ قانونی یافت نشد",
"pleaseUploadFile": "لطفاً یک فایل YAML بارگذاری کنید",
"preview": "پیش‌نمایش",
"rulesFormat": "فرمت قانون: نوع قانون، محتوای تطابق، [سیاست]، که سیاست اختیاری است.\nاگر سیاست مشخص نشود، نام گروه قانونی فعلی به طور خودکار استفاده خواهد شد. مثال‌ها:",
"rulesLabel": "محتوای قانون",
"searchRule": "جستجوی نام قانون",
"selectTags": "انتخاب برچسب‌های گره",
"tags": "برچسب‌های گره",
"tagsLabel": "برچسب‌های گره",
"updateSuccess": "قانون با موفقیت به‌روزرسانی شد"
}
+1 -1
View File
@@ -145,7 +145,7 @@
"quota": "محدودیت خرید/زمان", "quota": "محدودیت خرید/زمان",
"replacement": "تنظیم مجدد قیمت/زمان", "replacement": "تنظیم مجدد قیمت/زمان",
"sell": "فروش", "sell": "فروش",
"show": "نمایش خانه", "show": "نمایش",
"sold": "تعداد اشتراک", "sold": "تعداد اشتراک",
"subscribe": "اشتراک", "subscribe": "اشتراک",
"subscribeGroup": "گروه اشتراک", "subscribeGroup": "گروه اشتراک",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "تأیید ارتقاء سیستم", "confirmSystemUpgrade": "تأیید ارتقاء سیستم",
"confirmUpgrade": "تأیید ارتقاء", "confirmUpgrade": "تأیید ارتقاء",
"currentVersion": "نسخه فعلی سیستم:", "currentVersion": "نسخه فعلی سیستم:",
"developmentVersion": "نسخه توسعه",
"errors": "خطاها", "errors": "خطاها",
"ip": "آی‌پی", "ip": درس آی‌پی",
"lastUpdated": "آخرین به‌روزرسانی:", "lastUpdated": "آخرین به‌روزرسانی:",
"newVersionAvailable": "نسخه جدید",
"none": "هیچ", "none": "هیچ",
"query": "پرس و جو", "query": "پرس و جو",
"rebootDescription": "آیا مطمئن هستید که می‌خواهید سیستم را راه‌اندازی مجدد کنید؟ این عملیات باعث وقفه کوتاهی در خدمات خواهد شد.", "rebootDescription": "آیا مطمئن هستید که می‌خواهید سیستم را راه‌اندازی مجدد کنید؟ این عملیات باعث وقفه کوتاهی در خدمات خواهد شد.",
"rebooting": "در حال راه‌اندازی مجدد سیستم...", "rebooting": "در حال راه‌اندازی مجدد سیستم...",
"refreshLogs": "تازه‌سازی گزارش‌ها", "refreshLogs": "تازه‌سازی گزارش‌ها",
"request": "درخواست", "request": "درخواست",
"serverVersion": "سرور",
"status": "وضعیت", "status": "وضعیت",
"systemLogs": "گزارش‌های سیستم", "systemLogs": "گزارش‌های سیستم",
"systemReboot": "راه‌اندازی مجدد سیستم", "systemReboot": "راه‌اندازی مجدد سیستم",
@@ -22,5 +25,8 @@
"systemUpgrade": "ارتقاء سیستم", "systemUpgrade": "ارتقاء سیستم",
"upgradeDescription": "آیا مطمئن هستید که می‌خواهید ارتقاء سیستم را انجام دهید؟ این عملیات ممکن است چند دقیقه طول بکشد و در این مدت سیستم ممکن است پاسخگو نباشد.", "upgradeDescription": "آیا مطمئن هستید که می‌خواهید ارتقاء سیستم را انجام دهید؟ این عملیات ممکن است چند دقیقه طول بکشد و در این مدت سیستم ممکن است پاسخگو نباشد.",
"userAgent": "عامل کاربر", "userAgent": "عامل کاربر",
"viewLogsAndManage": "مشاهده گزارش‌های سیستم، انجام ارتقاء سیستم و عملیات راه‌اندازی مجدد" "versionInfo": "اطلاعات نسخه",
"viewLogsAndManage": "مشاهده گزارش‌های سیستم، انجام ارتقاء سیستم و عملیات راه‌اندازی مجدد",
"viewNewVersion": "مشاهده نسخه جدید",
"webVersion": "وب/مدیریت"
} }
+15 -1
View File
@@ -1,6 +1,7 @@
{ {
"accountEnable": "فعال‌سازی حساب", "accountEnable": "فعال‌سازی حساب",
"actions": "اقدامات", "actions": "اقدامات",
"active": "فعال",
"add": "افزودن", "add": "افزودن",
"administrator": "مدیر", "administrator": "مدیر",
"areaCode": "کد منطقه", "areaCode": "کد منطقه",
@@ -41,10 +42,12 @@
"email": "ایمیل", "email": "ایمیل",
"enable": "فعال کردن", "enable": "فعال کردن",
"expireTime": "زمان انقضا", "expireTime": "زمان انقضا",
"expired": "منقضی شده",
"expiredAt": "منقضی شده در", "expiredAt": "منقضی شده در",
"failed": "ناموفق", "failed": "ناموفق",
"giftAmount": "مقدار هدیه", "giftAmount": "مقدار هدیه",
"giftAmountPlaceholder": "مبلغ هدیه را وارد کنید", "giftAmountPlaceholder": "مبلغ هدیه را وارد کنید",
"inactive": "غیرفعال",
"invalidEmailFormat": "فرمت ایمیل نامعتبر است", "invalidEmailFormat": "فرمت ایمیل نامعتبر است",
"inviteCode": "کد دعوت", "inviteCode": "کد دعوت",
"inviteCodePlaceholder": "کد دعوت را وارد کنید (برای تولید خالی بگذارید)", "inviteCodePlaceholder": "کد دعوت را وارد کنید (برای تولید خالی بگذارید)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "رمز عبور جدید را وارد کنید (اختیاری)", "passwordPlaceholder": "رمز عبور جدید را وارد کنید (اختیاری)",
"permanent": "دائمی", "permanent": "دائمی",
"pleaseEnterEmail": "لطفاً ایمیل خود را وارد کنید", "pleaseEnterEmail": "لطفاً ایمیل خود را وارد کنید",
"price": "قیمت",
"referer": "ارجاع‌دهنده", "referer": "ارجاع‌دهنده",
"refererId": "شناسه معرف", "refererId": "شناسه معرف",
"refererIdPlaceholder": "شناسه معرف را وارد کنید", "refererIdPlaceholder": "شناسه معرف را وارد کنید",
@@ -74,8 +78,12 @@
"searchIp": "جستجوی آدرس IP", "searchIp": "جستجوی آدرس IP",
"selectAuthType": "نوع احراز هویت را انتخاب کنید", "selectAuthType": "نوع احراز هویت را انتخاب کنید",
"speedLimit": "محدودیت سرعت", "speedLimit": "محدودیت سرعت",
"startTime": "زمان شروع",
"status": "وضعیت",
"subscription": "اشتراک", "subscription": "اشتراک",
"subscriptionDetails": "جزئیات اشتراک", "subscriptionDetails": "جزئیات اشتراک",
"subscriptionId": "شناسه اشتراک",
"subscriptionInfo": "اطلاعات اشتراک",
"subscriptionList": "لیست اشتراک", "subscriptionList": "لیست اشتراک",
"subscriptionLogs": "گزارش‌های اشتراک", "subscriptionLogs": "گزارش‌های اشتراک",
"subscriptionName": "نام اشتراک", "subscriptionName": "نام اشتراک",
@@ -89,6 +97,8 @@
"tradeNotifications": "اعلان‌های تجارت", "tradeNotifications": "اعلان‌های تجارت",
"trafficLimit": "محدودیت ترافیک", "trafficLimit": "محدودیت ترافیک",
"trafficLogs": "گزارش‌های ترافیک", "trafficLogs": "گزارش‌های ترافیک",
"trafficUsage": "استفاده از ترافیک",
"unknown": "نامشخص",
"unlimited": "نامحدود", "unlimited": "نامحدود",
"unverified": "تأیید نشده", "unverified": "تأیید نشده",
"update": "به‌روزرسانی", "update": "به‌روزرسانی",
@@ -98,11 +108,15 @@
"userAgent": "عامل کاربر", "userAgent": "عامل کاربر",
"userEmail": "ایمیل کاربر", "userEmail": "ایمیل کاربر",
"userEmailPlaceholder": "ایمیل کاربر را وارد کنید", "userEmailPlaceholder": "ایمیل کاربر را وارد کنید",
"userId": "شناسه کاربر",
"userInfo": "اطلاعات کاربر",
"userList": "فهرست کاربران", "userList": "فهرست کاربران",
"userLogs": "تاریخچه ورود", "userLogs": "تاریخچه ورود",
"userName": "شناسه کاربر", "userName": "شناسه کاربر",
"userOrders": "سفارش‌ها", "userOrders": "سفارش‌ها",
"userProfile": "پروفایل", "userProfile": "پروفایل",
"userSubscriptions": "اشتراک‌ها", "userSubscriptions": "اشتراک‌ها",
"verified": "تأیید شده" "username": "نام کاربری",
"verified": "تأیید شده",
"viewDetails": "مشاهده جزئیات"
} }
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "ADS-asetukset", "ADS Config": "ADS-asetukset",
"Announcement Management": "Ilmoitusten hallinta", "Announcement Management": "Ilmoitusten hallinta",
"Apple": "Apple ID", "Apple": "Apple ID",
"Application Management": "Sovellushallinta",
"Auth Control": "Todennuksen hallinta", "Auth Control": "Todennuksen hallinta",
"Coupon Management": "Kuponkien hallinta", "Coupon Management": "Kuponkien hallinta",
"Dashboard": "Kojelauta", "Dashboard": "Kojelauta",
@@ -16,6 +17,7 @@
"Order Management": "Tilausten hallinta", "Order Management": "Tilausten hallinta",
"Payment Config": "Maksukonfiguraatio", "Payment Config": "Maksukonfiguraatio",
"Phone Number": "Puhelinnumero", "Phone Number": "Puhelinnumero",
"Rule Management": "Sääntöhallinta",
"Server": "Palvelu", "Server": "Palvelu",
"Server Management": "Palvelimen hallinta", "Server Management": "Palvelimen hallinta",
"Settings": "Asetukset", "Settings": "Asetukset",
-1
View File
@@ -22,7 +22,6 @@
"description": "Kuvaus", "description": "Kuvaus",
"descriptionPlaceholder": "Syötä maksutavan kuvaus", "descriptionPlaceholder": "Syötä maksutavan kuvaus",
"domain": "Verkkotunnus", "domain": "Verkkotunnus",
"domainPlaceholder": "valinnainen, esim. {esimerkki}",
"edit": "Muokkaa", "edit": "Muokkaa",
"editPayment": "Muokkaa maksutapaa", "editPayment": "Muokkaa maksutapaa",
"enable": "Ota käyttöön", "enable": "Ota käyttöön",
+39
View File
@@ -0,0 +1,39 @@
{
"analyzing": "Analysoidaan...",
"appIcon": "Sääntökuvake",
"cancel": "Peruuta",
"confirm": "Vahvista",
"confirmDelete": "Vahvista poisto",
"create": "Lisää sääntö",
"createRule": "Lisää sääntö",
"createSuccess": "Sääntö luotiin onnistuneesti",
"createdAt": "Luotu",
"delete": "Poista",
"deleteSuccess": "Sääntö poistettiin onnistuneesti",
"deleteWarning": "Oletko varma, että haluat poistaa tämän säännön? Tätä toimintoa ei voi peruuttaa.",
"downloadTemplate": "Lataa malli",
"edit": "Muokkaa",
"editRule": "Muokkaa sääntöä",
"enable": "Ota käyttöön",
"enterIconUrl": "Syötä tai lataa kuvake",
"enterRuleName": "Syötä säännön nimi",
"enterRules": "Syötä sääntöjen sisältö, yksi per rivi",
"import": "Tuoda",
"importFailed": "Tuonti epäonnistui",
"importSuccess": "Tuonti onnistui",
"importYamlDescription": "Tuo sääntöjä YAML-tiedostosta, järjestelmä luo automaattisesti sääntöryhmiä politiikkaryhmän nimien perusteella",
"importYamlRules": "Tuo YAML-säännöt",
"importing": "Tuodaan...",
"invalidYamlFormat": "Virheellinen YAML-muoto, puuttuu sääntöjen kenttä",
"name": "Säännön nimi",
"noValidRules": "Ei voimassa olevia sääntöjä löytynyt",
"pleaseUploadFile": "Lataa YAML-tiedosto",
"preview": "Esikatselu",
"rulesFormat": "Sääntömuoto: sääntötyyppi, vastaavuus, [politiikka], jossa politiikka on valinnainen.\nJos politiikkaa ei ole määritelty, nykyistä sääntöryhmän nimeä käytetään automaattisesti. Esimerkkejä:",
"rulesLabel": "Säännön sisältö",
"searchRule": "Etsi säännön nimeä",
"selectTags": "Valitse solmun tunnisteet",
"tags": "Solmun tunnisteet",
"tagsLabel": "Solmun tunnisteet",
"updateSuccess": "Sääntö päivitettiin onnistuneesti"
}
+1 -1
View File
@@ -145,7 +145,7 @@
"quota": "Ostorajoitus/kerta", "quota": "Ostorajoitus/kerta",
"replacement": "Nollaa hinta/kerta", "replacement": "Nollaa hinta/kerta",
"sell": "myydä", "sell": "myydä",
"show": "Etusivun näyt", "show": "Näytä",
"sold": "Tilausmäärä", "sold": "Tilausmäärä",
"subscribe": "Tilaa", "subscribe": "Tilaa",
"subscribeGroup": "Tilaa ryhmä", "subscribeGroup": "Tilaa ryhmä",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "Vahvista järjestelmän päivitys", "confirmSystemUpgrade": "Vahvista järjestelmän päivitys",
"confirmUpgrade": "Vahvista päivitys", "confirmUpgrade": "Vahvista päivitys",
"currentVersion": "Nykyinen järjestelmäversio:", "currentVersion": "Nykyinen järjestelmäversio:",
"developmentVersion": "Kehitysversio",
"errors": "Virheet", "errors": "Virheet",
"ip": "IP", "ip": "IP-osoite",
"lastUpdated": "Viimeksi päivitetty:", "lastUpdated": "Viimeksi päivitetty:",
"newVersionAvailable": "Uusi versio",
"none": "Ei mitään", "none": "Ei mitään",
"query": "Kysely", "query": "Kysely",
"rebootDescription": "Oletko varma, että haluat käynnistää järjestelmän uudelleen? Tämä toimenpide aiheuttaa lyhyen palvelukatkon.", "rebootDescription": "Oletko varma, että haluat käynnistää järjestelmän uudelleen? Tämä toimenpide aiheuttaa lyhyen palvelukatkon.",
"rebooting": "Järjestelmä käynnistyy uudelleen...", "rebooting": "Järjestelmä käynnistyy uudelleen...",
"refreshLogs": "Päivitä lokit", "refreshLogs": "Päivitä lokit",
"request": "Pyyntö", "request": "Pyyntö",
"serverVersion": "Palvelin",
"status": "Tila", "status": "Tila",
"systemLogs": "Järjestelmän lokit", "systemLogs": "Järjestelmän lokit",
"systemReboot": "Järjestelmän uudelleenkäynnistys", "systemReboot": "Järjestelmän uudelleenkäynnistys",
@@ -22,5 +25,8 @@
"systemUpgrade": "Järjestelmän päivitys", "systemUpgrade": "Järjestelmän päivitys",
"upgradeDescription": "Haluatko varmasti suorittaa järjestelmäpäivityksen? Tämä toimenpide voi kestää muutaman minuutin, ja sen aikana järjestelmä ei välttämättä vastaa.", "upgradeDescription": "Haluatko varmasti suorittaa järjestelmäpäivityksen? Tämä toimenpide voi kestää muutaman minuutin, ja sen aikana järjestelmä ei välttämättä vastaa.",
"userAgent": "Käyttäjäagentti", "userAgent": "Käyttäjäagentti",
"viewLogsAndManage": "Tarkastele järjestelmän lokitietoja, suorita järjestelmäpäivityksiä ja uudelleenkäynnistyksiä" "versionInfo": "Versiotiedot",
"viewLogsAndManage": "Tarkastele järjestelmän lokitietoja, suorita järjestelmäpäivityksiä ja uudelleenkäynnistyksiä",
"viewNewVersion": "Näytä uusi versio",
"webVersion": "Web/Admin"
} }
+15 -1
View File
@@ -1,6 +1,7 @@
{ {
"accountEnable": "Tilin aktivointi", "accountEnable": "Tilin aktivointi",
"actions": "toiminnot", "actions": "toiminnot",
"active": "Aktiivinen",
"add": "Lisää", "add": "Lisää",
"administrator": "Ylläpitäjä", "administrator": "Ylläpitäjä",
"areaCode": "Alueen koodi", "areaCode": "Alueen koodi",
@@ -41,10 +42,12 @@
"email": "sähköposti", "email": "sähköposti",
"enable": "Ota käyttöön", "enable": "Ota käyttöön",
"expireTime": "Vanhentumisaika", "expireTime": "Vanhentumisaika",
"expired": "Vanhentunut",
"expiredAt": "Vanhentunut", "expiredAt": "Vanhentunut",
"failed": "Epäonnistui", "failed": "Epäonnistui",
"giftAmount": "Lahjan määrä", "giftAmount": "Lahjan määrä",
"giftAmountPlaceholder": "Syötä lahjan määrä", "giftAmountPlaceholder": "Syötä lahjan määrä",
"inactive": "Epäaktiivinen",
"invalidEmailFormat": "Virheellinen sähköpostimuoto", "invalidEmailFormat": "Virheellinen sähköpostimuoto",
"inviteCode": "Kutsukoodi", "inviteCode": "Kutsukoodi",
"inviteCodePlaceholder": "Syötä kutsukoodi (jätä tyhjäksi luodaksesi uuden)", "inviteCodePlaceholder": "Syötä kutsukoodi (jätä tyhjäksi luodaksesi uuden)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "Syötä uusi salasana (valinnainen)", "passwordPlaceholder": "Syötä uusi salasana (valinnainen)",
"permanent": "Pysyvä", "permanent": "Pysyvä",
"pleaseEnterEmail": "Ole hyvä ja syötä sähköpostiosoite", "pleaseEnterEmail": "Ole hyvä ja syötä sähköpostiosoite",
"price": "Hinta",
"referer": "Suosittelija", "referer": "Suosittelija",
"refererId": "Viittaajan ID", "refererId": "Viittaajan ID",
"refererIdPlaceholder": "Syötä suosittelijan ID", "refererIdPlaceholder": "Syötä suosittelijan ID",
@@ -74,8 +78,12 @@
"searchIp": "Etsi IP-osoite", "searchIp": "Etsi IP-osoite",
"selectAuthType": "Valitse todennustyyppi", "selectAuthType": "Valitse todennustyyppi",
"speedLimit": "Nopeusrajoitus", "speedLimit": "Nopeusrajoitus",
"startTime": "Aloitusaika",
"status": "Tila",
"subscription": "Tilaus", "subscription": "Tilaus",
"subscriptionDetails": "Tilaustiedot", "subscriptionDetails": "Tilaustiedot",
"subscriptionId": "Tilauksen ID",
"subscriptionInfo": "Tilauksen tiedot",
"subscriptionList": "Tilauksen lista", "subscriptionList": "Tilauksen lista",
"subscriptionLogs": "Tilaushistoria", "subscriptionLogs": "Tilaushistoria",
"subscriptionName": "Tilauksen nimi", "subscriptionName": "Tilauksen nimi",
@@ -89,6 +97,8 @@
"tradeNotifications": "Kauppailmoitukset", "tradeNotifications": "Kauppailmoitukset",
"trafficLimit": "Liikenteen rajoitus", "trafficLimit": "Liikenteen rajoitus",
"trafficLogs": "Liikennelokit", "trafficLogs": "Liikennelokit",
"trafficUsage": "Liikenteen käyttö",
"unknown": "Tuntematon",
"unlimited": "Rajoittamaton", "unlimited": "Rajoittamaton",
"unverified": "Vahvistamaton", "unverified": "Vahvistamaton",
"update": "Päivitä", "update": "Päivitä",
@@ -98,11 +108,15 @@
"userAgent": "Käyttäjäagentti", "userAgent": "Käyttäjäagentti",
"userEmail": "Käyttäjän sähköposti", "userEmail": "Käyttäjän sähköposti",
"userEmailPlaceholder": "Syötä käyttäjän sähköpostiosoite", "userEmailPlaceholder": "Syötä käyttäjän sähköpostiosoite",
"userId": "Käyttäjän ID",
"userInfo": "Käyttäjän tiedot",
"userList": "Käyttäjälista", "userList": "Käyttäjälista",
"userLogs": "Kirjautumishistoria", "userLogs": "Kirjautumishistoria",
"userName": "Käyttäjän tunniste", "userName": "Käyttäjän tunniste",
"userOrders": "Tilaukset", "userOrders": "Tilaukset",
"userProfile": "Profiili", "userProfile": "Profiili",
"userSubscriptions": "Tilaukset", "userSubscriptions": "Tilaukset",
"verified": "Vahvistettu" "username": "Käyttäjänimi",
"verified": "Vahvistettu",
"viewDetails": "Näytä tiedot"
} }
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "Configuration ADS", "ADS Config": "Configuration ADS",
"Announcement Management": "Gestion des annonces", "Announcement Management": "Gestion des annonces",
"Apple": "Identifiant Apple", "Apple": "Identifiant Apple",
"Application Management": "Gestion des applications",
"Auth Control": "Contrôle d'authentification", "Auth Control": "Contrôle d'authentification",
"Coupon Management": "Gestion des coupons", "Coupon Management": "Gestion des coupons",
"Dashboard": "Tableau de bord", "Dashboard": "Tableau de bord",
@@ -16,6 +17,7 @@
"Order Management": "Gestion des commandes", "Order Management": "Gestion des commandes",
"Payment Config": "Configuration de paiement", "Payment Config": "Configuration de paiement",
"Phone Number": "Numéro de téléphone", "Phone Number": "Numéro de téléphone",
"Rule Management": "Gestion des règles",
"Server": "Serveur", "Server": "Serveur",
"Server Management": "Gestion des services", "Server Management": "Gestion des services",
"Settings": "Paramètres", "Settings": "Paramètres",
-1
View File
@@ -22,7 +22,6 @@
"description": "Description", "description": "Description",
"descriptionPlaceholder": "Entrez la description du mode de paiement", "descriptionPlaceholder": "Entrez la description du mode de paiement",
"domain": "Domaine", "domain": "Domaine",
"domainPlaceholder": "facultatif, par exemple {exemple}",
"edit": "Modifier", "edit": "Modifier",
"editPayment": "Modifier le mode de paiement", "editPayment": "Modifier le mode de paiement",
"enable": "Activer", "enable": "Activer",
+39
View File
@@ -0,0 +1,39 @@
{
"analyzing": "Analyse en cours...",
"appIcon": "Icône de règle",
"cancel": "Annuler",
"confirm": "Confirmer",
"confirmDelete": "Confirmer la suppression",
"create": "Ajouter une règle",
"createRule": "Ajouter une règle",
"createSuccess": "Règle créée avec succès",
"createdAt": "Créé le",
"delete": "Supprimer",
"deleteSuccess": "Règle supprimée avec succès",
"deleteWarning": "Êtes-vous sûr de vouloir supprimer cette règle ? Cette action ne peut pas être annulée.",
"downloadTemplate": "Télécharger le modèle",
"edit": "Modifier",
"editRule": "Modifier la règle",
"enable": "Activer",
"enterIconUrl": "Entrez ou téléchargez une icône",
"enterRuleName": "Entrez le nom de la règle",
"enterRules": "Entrez le contenu de la règle, un par ligne",
"import": "Importer",
"importFailed": "Échec de l'importation",
"importSuccess": "Importation réussie",
"importYamlDescription": "Importer des règles à partir d'un fichier YAML, le système créera automatiquement des groupes de règles en fonction des noms de groupes de politiques",
"importYamlRules": "Importer des règles YAML",
"importing": "Importation en cours...",
"invalidYamlFormat": "Format YAML invalide, champ de règles manquant",
"name": "Nom de la règle",
"noValidRules": "Aucune règle valide trouvée",
"pleaseUploadFile": "Veuillez télécharger un fichier YAML",
"preview": "Aperçu",
"rulesFormat": "Format de la règle : type de règle, contenu de correspondance, [politique], où la politique est optionnelle.\nSi la politique n'est pas spécifiée, le nom du groupe de règles actuel sera utilisé automatiquement. Exemples :",
"rulesLabel": "Contenu de la règle",
"searchRule": "Rechercher le nom de la règle",
"selectTags": "Sélectionner des balises de nœud",
"tags": "Balises de nœud",
"tagsLabel": "Balises de nœud",
"updateSuccess": "Règle mise à jour avec succès"
}
+1 -1
View File
@@ -145,7 +145,7 @@
"quota": "Limite d'achat/par fois", "quota": "Limite d'achat/par fois",
"replacement": "Réinitialiser le prix/par fois", "replacement": "Réinitialiser le prix/par fois",
"sell": "Vente", "sell": "Vente",
"show": "Afficher sur la page d'accueil", "show": "Afficher",
"sold": "Nombre d'abonnements", "sold": "Nombre d'abonnements",
"subscribe": "S'abonner", "subscribe": "S'abonner",
"subscribeGroup": "S'abonner au groupe", "subscribeGroup": "S'abonner au groupe",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "Confirmer la mise à niveau du système", "confirmSystemUpgrade": "Confirmer la mise à niveau du système",
"confirmUpgrade": "Confirmer la mise à niveau", "confirmUpgrade": "Confirmer la mise à niveau",
"currentVersion": "Version actuelle du système :", "currentVersion": "Version actuelle du système :",
"developmentVersion": "Version de développement",
"errors": "Erreurs", "errors": "Erreurs",
"ip": "IP", "ip": "Adresse IP",
"lastUpdated": "Dernière mise à jour :", "lastUpdated": "Dernière mise à jour :",
"newVersionAvailable": "Nouvelle version",
"none": "Aucun", "none": "Aucun",
"query": "Requête", "query": "Requête",
"rebootDescription": "Êtes-vous sûr de vouloir redémarrer le système ? Cette opération entraînera une interruption temporaire du service.", "rebootDescription": "Êtes-vous sûr de vouloir redémarrer le système ? Cette opération entraînera une interruption temporaire du service.",
"rebooting": "Redémarrage du système...", "rebooting": "Redémarrage du système...",
"refreshLogs": "Rafraîchir les journaux", "refreshLogs": "Rafraîchir les journaux",
"request": "Demande", "request": "Demande",
"serverVersion": "Serveur",
"status": "Statut", "status": "Statut",
"systemLogs": "Journaux système", "systemLogs": "Journaux système",
"systemReboot": "Redémarrage du système", "systemReboot": "Redémarrage du système",
@@ -22,5 +25,8 @@
"systemUpgrade": "Mise à niveau du système", "systemUpgrade": "Mise à niveau du système",
"upgradeDescription": "Êtes-vous sûr de vouloir effectuer la mise à niveau du système ? Cette opération peut prendre quelques minutes, pendant lesquelles le système peut ne pas répondre.", "upgradeDescription": "Êtes-vous sûr de vouloir effectuer la mise à niveau du système ? Cette opération peut prendre quelques minutes, pendant lesquelles le système peut ne pas répondre.",
"userAgent": "Agent utilisateur", "userAgent": "Agent utilisateur",
"viewLogsAndManage": "Afficher les journaux système, effectuer des mises à niveau et redémarrer le système" "versionInfo": "Informations de version",
"viewLogsAndManage": "Afficher les journaux système, effectuer des mises à niveau et redémarrer le système",
"viewNewVersion": "Voir la nouvelle version",
"webVersion": "Web/Admin"
} }
+15 -1
View File
@@ -1,6 +1,7 @@
{ {
"accountEnable": "Activation du compte", "accountEnable": "Activation du compte",
"actions": "actions", "actions": "actions",
"active": "Actif",
"add": "Ajouter", "add": "Ajouter",
"administrator": "Administrateur", "administrator": "Administrateur",
"areaCode": "Indicatif régional", "areaCode": "Indicatif régional",
@@ -41,10 +42,12 @@
"email": "e-mail", "email": "e-mail",
"enable": "Activer", "enable": "Activer",
"expireTime": "Date d'expiration", "expireTime": "Date d'expiration",
"expired": "Expiré",
"expiredAt": "Expiré le", "expiredAt": "Expiré le",
"failed": "Échoué", "failed": "Échoué",
"giftAmount": "Montant du cadeau", "giftAmount": "Montant du cadeau",
"giftAmountPlaceholder": "Entrez le montant du cadeau", "giftAmountPlaceholder": "Entrez le montant du cadeau",
"inactive": "Inactif",
"invalidEmailFormat": "Format d'email invalide", "invalidEmailFormat": "Format d'email invalide",
"inviteCode": "Code d'invitation", "inviteCode": "Code d'invitation",
"inviteCodePlaceholder": "Entrez le code d'invitation (laissez vide pour générer)", "inviteCodePlaceholder": "Entrez le code d'invitation (laissez vide pour générer)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "Entrez un nouveau mot de passe (facultatif)", "passwordPlaceholder": "Entrez un nouveau mot de passe (facultatif)",
"permanent": "Permanent", "permanent": "Permanent",
"pleaseEnterEmail": "Veuillez entrer votre adresse e-mail", "pleaseEnterEmail": "Veuillez entrer votre adresse e-mail",
"price": "Prix",
"referer": "Référent", "referer": "Référent",
"refererId": "ID du référent", "refererId": "ID du référent",
"refererIdPlaceholder": "Entrez l'ID du référent", "refererIdPlaceholder": "Entrez l'ID du référent",
@@ -74,8 +78,12 @@
"searchIp": "Rechercher une adresse IP", "searchIp": "Rechercher une adresse IP",
"selectAuthType": "Sélectionner le type d'authentification", "selectAuthType": "Sélectionner le type d'authentification",
"speedLimit": "Limite de vitesse", "speedLimit": "Limite de vitesse",
"startTime": "Date de début",
"status": "Statut",
"subscription": "Abonnement", "subscription": "Abonnement",
"subscriptionDetails": "Détails de l'abonnement", "subscriptionDetails": "Détails de l'abonnement",
"subscriptionId": "ID d'abonnement",
"subscriptionInfo": "Informations sur l'abonnement",
"subscriptionList": "Liste des abonnements", "subscriptionList": "Liste des abonnements",
"subscriptionLogs": "Journaux d'abonnement", "subscriptionLogs": "Journaux d'abonnement",
"subscriptionName": "Nom de l'abonnement", "subscriptionName": "Nom de l'abonnement",
@@ -89,6 +97,8 @@
"tradeNotifications": "Notifications de commerce", "tradeNotifications": "Notifications de commerce",
"trafficLimit": "Limite de trafic", "trafficLimit": "Limite de trafic",
"trafficLogs": "Journaux de trafic", "trafficLogs": "Journaux de trafic",
"trafficUsage": "Utilisation du trafic",
"unknown": "Inconnu",
"unlimited": "Illimité", "unlimited": "Illimité",
"unverified": "Non vérifié", "unverified": "Non vérifié",
"update": "Mettre à jour", "update": "Mettre à jour",
@@ -98,11 +108,15 @@
"userAgent": "Agent utilisateur", "userAgent": "Agent utilisateur",
"userEmail": "E-mail de l'utilisateur", "userEmail": "E-mail de l'utilisateur",
"userEmailPlaceholder": "Entrez l'email de l'utilisateur", "userEmailPlaceholder": "Entrez l'email de l'utilisateur",
"userId": "ID utilisateur",
"userInfo": "Informations sur l'utilisateur",
"userList": "Liste des utilisateurs", "userList": "Liste des utilisateurs",
"userLogs": "Historique des connexions", "userLogs": "Historique des connexions",
"userName": "Identifiant Utilisateur", "userName": "Identifiant Utilisateur",
"userOrders": "Commandes", "userOrders": "Commandes",
"userProfile": "Profil", "userProfile": "Profil",
"userSubscriptions": "Abonnements", "userSubscriptions": "Abonnements",
"verified": "Vérifié" "username": "Nom d'utilisateur",
"verified": "Vérifié",
"viewDetails": "Voir les détails"
} }
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "एडीएस कॉन्फ़िग", "ADS Config": "एडीएस कॉन्फ़िग",
"Announcement Management": "घोषणा प्रबंधन", "Announcement Management": "घोषणा प्रबंधन",
"Apple": "एप्पल आईडी", "Apple": "एप्पल आईडी",
"Application Management": "ऐप्लिकेशन प्रबंधन",
"Auth Control": "प्रमाणिकरण नियंत्रण", "Auth Control": "प्रमाणिकरण नियंत्रण",
"Coupon Management": "कूपन प्रबंधन", "Coupon Management": "कूपन प्रबंधन",
"Dashboard": "डैशबोर्ड", "Dashboard": "डैशबोर्ड",
@@ -16,6 +17,7 @@
"Order Management": "ऑर्डर प्रबंधन", "Order Management": "ऑर्डर प्रबंधन",
"Payment Config": "भुगतान कॉन्फ़िगरेशन", "Payment Config": "भुगतान कॉन्फ़िगरेशन",
"Phone Number": "फ़ोन नंबर", "Phone Number": "फ़ोन नंबर",
"Rule Management": "नियम प्रबंधन",
"Server": "सर्वर", "Server": "सर्वर",
"Server Management": "सर्वर प्रबंधन", "Server Management": "सर्वर प्रबंधन",
"Settings": "सेटिंग्स", "Settings": "सेटिंग्स",
-1
View File
@@ -22,7 +22,6 @@
"description": "विवरण", "description": "विवरण",
"descriptionPlaceholder": "भुगतान विधि का विवरण दर्ज करें", "descriptionPlaceholder": "भुगतान विधि का विवरण दर्ज करें",
"domain": "डोमेन", "domain": "डोमेन",
"domainPlaceholder": "वैकल्पिक, जैसे कि {example}",
"edit": "संपादित करें", "edit": "संपादित करें",
"editPayment": "भुगतान विधि संपादित करें", "editPayment": "भुगतान विधि संपादित करें",
"enable": "सक्षम करें", "enable": "सक्षम करें",
+39
View File
@@ -0,0 +1,39 @@
{
"analyzing": "विश्लेषण कर रहा है...",
"appIcon": "नियम आइकन",
"cancel": "रद्द करें",
"confirm": "पुष्टि करें",
"confirmDelete": "हटाने की पुष्टि करें",
"create": "नियम जोड़ें",
"createRule": "नियम जोड़ें",
"createSuccess": "नियम सफलतापूर्वक बनाया गया",
"createdAt": "बनाया गया",
"delete": "हटाएं",
"deleteSuccess": "नियम सफलतापूर्वक हटाया गया",
"deleteWarning": "क्या आप वाकई इस नियम को हटाना चाहते हैं? यह क्रिया पूर्ववत नहीं की जा सकती।",
"downloadTemplate": "टेम्पलेट डाउनलोड करें",
"edit": "संपादित करें",
"editRule": "नियम संपादित करें",
"enable": "सक्षम करें",
"enterIconUrl": "एक आइकन दर्ज करें या अपलोड करें",
"enterRuleName": "नियम का नाम दर्ज करें",
"enterRules": "नियम की सामग्री दर्ज करें, एक प्रति पंक्ति",
"import": "आयात करें",
"importFailed": "आयात विफल",
"importSuccess": "आयात सफल",
"importYamlDescription": "YAML फ़ाइल से नियम आयात करें, प्रणाली स्वचालित रूप से नीति समूह नामों के आधार पर नियम समूह बनाएगी",
"importYamlRules": "YAML नियम आयात करें",
"importing": "आयात कर रहा है...",
"invalidYamlFormat": "अमान्य YAML प्रारूप, नियम फ़ील्ड गायब है",
"name": "नियम का नाम",
"noValidRules": "कोई मान्य नियम नहीं मिला",
"pleaseUploadFile": "कृपया एक YAML फ़ाइल अपलोड करें",
"preview": "पूर्वावलोकन",
"rulesFormat": "नियम प्रारूप: नियम प्रकार, मिलान सामग्री, [नीति], जहाँ नीति वैकल्पिक है।\nयदि नीति निर्दिष्ट नहीं की गई है, तो वर्तमान नियम समूह का नाम स्वचालित रूप से उपयोग किया जाएगा। उदाहरण:",
"rulesLabel": "नियम सामग्री",
"searchRule": "नियम नाम खोजें",
"selectTags": "नोड टैग चुनें",
"tags": "नोड टैग",
"tagsLabel": "नोड टैग",
"updateSuccess": "नियम सफलतापूर्वक अपडेट किया गया"
}
+1 -1
View File
@@ -145,7 +145,7 @@
"quota": "प्रति खरीद सीमा", "quota": "प्रति खरीद सीमा",
"replacement": "मूल्य/प्रति बार रीसेट करें", "replacement": "मूल्य/प्रति बार रीसेट करें",
"sell": "बिक्री", "sell": "बिक्री",
"show": "मुखपृष्ठ पर दिखाएं", "show": "दिखाएं",
"sold": "सदस्यता गणना", "sold": "सदस्यता गणना",
"subscribe": "सदस्यता लें", "subscribe": "सदस्यता लें",
"subscribeGroup": "सदस्यता समूह", "subscribeGroup": "सदस्यता समूह",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "सिस्टम उन्नयन की पुष्टि करें", "confirmSystemUpgrade": "सिस्टम उन्नयन की पुष्टि करें",
"confirmUpgrade": "उन्नयन की पुष्टि करें", "confirmUpgrade": "उन्नयन की पुष्टि करें",
"currentVersion": "वर्तमान सिस्टम संस्करण:", "currentVersion": "वर्तमान सिस्टम संस्करण:",
"developmentVersion": "विकास संस्करण",
"errors": "त्रुटियाँ", "errors": "त्रुटियाँ",
"ip": "आईपी", "ip": "आईपी पता",
"lastUpdated": "अंतिम अपडेट:", "lastUpdated": "अंतिम अपडेट:",
"newVersionAvailable": "नया संस्करण",
"none": "कोई नहीं", "none": "कोई नहीं",
"query": "प्रश्न", "query": "प्रश्न",
"rebootDescription": "क्या आप वाकई सिस्टम को पुनः आरंभ करना चाहते हैं? इस क्रिया से थोड़े समय के लिए सेवा में बाधा आ सकती है।", "rebootDescription": "क्या आप वाकई सिस्टम को पुनः आरंभ करना चाहते हैं? इस क्रिया से थोड़े समय के लिए सेवा में बाधा आ सकती है।",
"rebooting": "सिस्टम को पुनः आरंभ किया जा रहा है...", "rebooting": "सिस्टम को पुनः आरंभ किया जा रहा है...",
"refreshLogs": "लॉग्स को ताज़ा करें", "refreshLogs": "लॉग्स को ताज़ा करें",
"request": "अनुरोध", "request": "अनुरोध",
"serverVersion": "सर्वर",
"status": "स्थिति", "status": "स्थिति",
"systemLogs": "सिस्टम लॉग्स", "systemLogs": "सिस्टम लॉग्स",
"systemReboot": "सिस्टम पुनरारंभ", "systemReboot": "सिस्टम पुनरारंभ",
@@ -22,5 +25,8 @@
"systemUpgrade": "सिस्टम उन्नयन", "systemUpgrade": "सिस्टम उन्नयन",
"upgradeDescription": "क्या आप वाकई सिस्टम अपग्रेड करना चाहते हैं? इस प्रक्रिया में कुछ मिनट लग सकते हैं और इस दौरान सिस्टम प्रतिक्रिया नहीं दे सकता है।", "upgradeDescription": "क्या आप वाकई सिस्टम अपग्रेड करना चाहते हैं? इस प्रक्रिया में कुछ मिनट लग सकते हैं और इस दौरान सिस्टम प्रतिक्रिया नहीं दे सकता है।",
"userAgent": "उपयोगकर्ता एजेंट", "userAgent": "उपयोगकर्ता एजेंट",
"viewLogsAndManage": "सिस्टम लॉग देखें, सिस्टम अपग्रेड और पुनरारंभ संचालन करें" "versionInfo": "संस्करण जानकारी",
"viewLogsAndManage": "सिस्टम लॉग देखें, सिस्टम अपग्रेड और पुनरारंभ संचालन करें",
"viewNewVersion": "नया संस्करण देखें",
"webVersion": "वेब/एडमिन"
} }
+15 -1
View File
@@ -1,6 +1,7 @@
{ {
"accountEnable": "खाता सक्षम करें", "accountEnable": "खाता सक्षम करें",
"actions": "क्रियाएँ", "actions": "क्रियाएँ",
"active": "सक्रिय",
"add": "जोड़ें", "add": "जोड़ें",
"administrator": "प्रशासक", "administrator": "प्रशासक",
"areaCode": "क्षेत्र कोड", "areaCode": "क्षेत्र कोड",
@@ -41,10 +42,12 @@
"email": "ईमेल", "email": "ईमेल",
"enable": "सक्षम करें", "enable": "सक्षम करें",
"expireTime": "समाप्ति समय", "expireTime": "समाप्ति समय",
"expired": "समाप्त",
"expiredAt": "समाप्ति तिथि", "expiredAt": "समाप्ति तिथि",
"failed": "असफल", "failed": "असफल",
"giftAmount": "उपहार राशि", "giftAmount": "उपहार राशि",
"giftAmountPlaceholder": "उपहार राशि दर्ज करें", "giftAmountPlaceholder": "उपहार राशि दर्ज करें",
"inactive": "निष्क्रिय",
"invalidEmailFormat": "अमान्य ईमेल प्रारूप", "invalidEmailFormat": "अमान्य ईमेल प्रारूप",
"inviteCode": "आमंत्रण कोड", "inviteCode": "आमंत्रण कोड",
"inviteCodePlaceholder": "आमंत्रण कोड दर्ज करें (उत्पन्न करने के लिए खाली छोड़ें)", "inviteCodePlaceholder": "आमंत्रण कोड दर्ज करें (उत्पन्न करने के लिए खाली छोड़ें)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "नया पासवर्ड दर्ज करें (वैकल्पिक)", "passwordPlaceholder": "नया पासवर्ड दर्ज करें (वैकल्पिक)",
"permanent": "स्थायी", "permanent": "स्थायी",
"pleaseEnterEmail": "कृपया ईमेल दर्ज करें", "pleaseEnterEmail": "कृपया ईमेल दर्ज करें",
"price": "कीमत",
"referer": "सिफारिशकर्ता", "referer": "सिफारिशकर्ता",
"refererId": "रेफरर आईडी", "refererId": "रेफरर आईडी",
"refererIdPlaceholder": "रेफरर आईडी दर्ज करें", "refererIdPlaceholder": "रेफरर आईडी दर्ज करें",
@@ -74,8 +78,12 @@
"searchIp": "आईपी पता खोजें", "searchIp": "आईपी पता खोजें",
"selectAuthType": "प्रमाणीकरण प्रकार चुनें", "selectAuthType": "प्रमाणीकरण प्रकार चुनें",
"speedLimit": "गति सीमा", "speedLimit": "गति सीमा",
"startTime": "शुरुआत का समय",
"status": "स्थिति",
"subscription": "सदस्यता", "subscription": "सदस्यता",
"subscriptionDetails": "सदस्यता विवरण", "subscriptionDetails": "सदस्यता विवरण",
"subscriptionId": "सदस्यता आईडी",
"subscriptionInfo": "सदस्यता जानकारी",
"subscriptionList": "सदस्यता सूची", "subscriptionList": "सदस्यता सूची",
"subscriptionLogs": "सदस्यता लॉग्स", "subscriptionLogs": "सदस्यता लॉग्स",
"subscriptionName": "सदस्यता नाम", "subscriptionName": "सदस्यता नाम",
@@ -89,6 +97,8 @@
"tradeNotifications": "व्यापार सूचनाएं", "tradeNotifications": "व्यापार सूचनाएं",
"trafficLimit": "ट्रैफिक सीमा", "trafficLimit": "ट्रैफिक सीमा",
"trafficLogs": "ट्रैफिक लॉग्स", "trafficLogs": "ट्रैफिक लॉग्स",
"trafficUsage": "ट्रैफ़िक उपयोग",
"unknown": "अज्ञात",
"unlimited": "असीमित", "unlimited": "असीमित",
"unverified": "असत्यापित", "unverified": "असत्यापित",
"update": "अपडेट", "update": "अपडेट",
@@ -98,11 +108,15 @@
"userAgent": "उपयोगकर्ता एजेंट", "userAgent": "उपयोगकर्ता एजेंट",
"userEmail": "उपयोगकर्ता ईमेल", "userEmail": "उपयोगकर्ता ईमेल",
"userEmailPlaceholder": "उपयोगकर्ता ईमेल दर्ज करें", "userEmailPlaceholder": "उपयोगकर्ता ईमेल दर्ज करें",
"userId": "उपयोगकर्ता आईडी",
"userInfo": "उपयोगकर्ता जानकारी",
"userList": "उपयोगकर्ता सूची", "userList": "उपयोगकर्ता सूची",
"userLogs": "लॉगिन इतिहास", "userLogs": "लॉगिन इतिहास",
"userName": "उपयोगकर्ता पहचानकर्ता", "userName": "उपयोगकर्ता पहचानकर्ता",
"userOrders": "ऑर्डर", "userOrders": "ऑर्डर",
"userProfile": "प्रोफ़ाइल", "userProfile": "प्रोफ़ाइल",
"userSubscriptions": "सदस्यताएँ", "userSubscriptions": "सदस्यताएँ",
"verified": "सत्यापित" "username": "उपयोगकर्ता नाम",
"verified": "सत्यापित",
"viewDetails": "विवरण देखें"
} }
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "ADS konfiguráció", "ADS Config": "ADS konfiguráció",
"Announcement Management": "Hirdetménykezelés", "Announcement Management": "Hirdetménykezelés",
"Apple": "Apple ID", "Apple": "Apple ID",
"Application Management": "Alkalmazáskezelés",
"Auth Control": "Hitelesítési vezérlés", "Auth Control": "Hitelesítési vezérlés",
"Coupon Management": "Kuponkezelés", "Coupon Management": "Kuponkezelés",
"Dashboard": "Irányítópult", "Dashboard": "Irányítópult",
@@ -16,6 +17,7 @@
"Order Management": "Rendeléskezelés", "Order Management": "Rendeléskezelés",
"Payment Config": "Fizetési beállítások", "Payment Config": "Fizetési beállítások",
"Phone Number": "Telefonszám", "Phone Number": "Telefonszám",
"Rule Management": "Szabálykezelés",
"Server": "Szolgáltatás", "Server": "Szolgáltatás",
"Server Management": "Szerverkezelés", "Server Management": "Szerverkezelés",
"Settings": "Beállítások", "Settings": "Beállítások",
-1
View File
@@ -22,7 +22,6 @@
"description": "Leírás", "description": "Leírás",
"descriptionPlaceholder": "Írja be a fizetési mód leírását", "descriptionPlaceholder": "Írja be a fizetési mód leírását",
"domain": "Domain", "domain": "Domain",
"domainPlaceholder": "opcionális, pl. {példa}",
"edit": "Szerkesztés", "edit": "Szerkesztés",
"editPayment": "Fizetési mód szerkesztése", "editPayment": "Fizetési mód szerkesztése",
"enable": "Engedélyezés", "enable": "Engedélyezés",
+39
View File
@@ -0,0 +1,39 @@
{
"analyzing": "Elemzés...",
"appIcon": "Szabály Ikon",
"cancel": "Mégse",
"confirm": "Megerősít",
"confirmDelete": "Törlés megerősítése",
"create": "Szabály hozzáadása",
"createRule": "Szabály hozzáadása",
"createSuccess": "A szabály sikeresen létrejött",
"createdAt": "Létrehozva",
"delete": "Törlés",
"deleteSuccess": "A szabály sikeresen törölve",
"deleteWarning": "Biztosan törölni szeretné ezt a szabályt? Ez a művelet nem vonható vissza.",
"downloadTemplate": "Sablon letöltése",
"edit": "Szerkesztés",
"editRule": "Szabály szerkesztése",
"enable": "Engedélyezés",
"enterIconUrl": "Adja meg vagy töltse fel az ikont",
"enterRuleName": "Adja meg a szabály nevét",
"enterRules": "Adja meg a szabály tartalmát, soronként egyet",
"import": "Importálás",
"importFailed": "Importálás sikertelen",
"importSuccess": "Importálás sikeres",
"importYamlDescription": "Szabályok importálása YAML fájlból, a rendszer automatikusan létrehozza a szabálycsoportokat a politikai csoportnevek alapján",
"importYamlRules": "YAML szabályok importálása",
"importing": "Importálás...",
"invalidYamlFormat": "Érvénytelen YAML formátum, hiányzik a szabályok mező",
"name": "Szabály neve",
"noValidRules": "Nincsenek érvényes szabályok",
"pleaseUploadFile": "Kérjük, töltsön fel egy YAML fájlt",
"preview": "Előnézet",
"rulesFormat": "Szabály formátum: szabály típusa, egyezési tartalom, [politika], ahol a politika opcionális.\nHa a politika nincs megadva, az aktuális szabálycsoport neve automatikusan felhasználásra kerül. Példák:",
"rulesLabel": "Szabály tartalom",
"searchRule": "Szabály név keresése",
"selectTags": "Válassza ki a csomópont címkéket",
"tags": "Csomópont címkék",
"tagsLabel": "Csomópont címkék",
"updateSuccess": "A szabály sikeresen frissítve"
}
+1 -1
View File
@@ -145,7 +145,7 @@
"quota": "Vásárlási korlát/alkalom", "quota": "Vásárlási korlát/alkalom",
"replacement": "Ár visszaállítása/alkalom", "replacement": "Ár visszaállítása/alkalom",
"sell": "eladás", "sell": "eladás",
"show": "Kezdőlap megjelenítése", "show": "Megjelenítés",
"sold": "Előfizetések száma", "sold": "Előfizetések száma",
"subscribe": "Feliratkozás", "subscribe": "Feliratkozás",
"subscribeGroup": "Feliratkozási csoport", "subscribeGroup": "Feliratkozási csoport",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "Rendszerfrissítés megerősítése", "confirmSystemUpgrade": "Rendszerfrissítés megerősítése",
"confirmUpgrade": "Megerősítés frissítése", "confirmUpgrade": "Megerősítés frissítése",
"currentVersion": "Jelenlegi rendszerverzió:", "currentVersion": "Jelenlegi rendszerverzió:",
"developmentVersion": "Fejlesztői verzió",
"errors": "Hibák", "errors": "Hibák",
"ip": "IP", "ip": "IP-cím",
"lastUpdated": "Utoljára frissítve:", "lastUpdated": "Utoljára frissítve:",
"newVersionAvailable": "Új verzió",
"none": "Nincs", "none": "Nincs",
"query": "Lekérdezés", "query": "Lekérdezés",
"rebootDescription": "Biztosan újra akarja indítani a rendszert? Ez a művelet rövid idejű szolgáltatáskimaradást okoz.", "rebootDescription": "Biztosan újra akarja indítani a rendszert? Ez a művelet rövid idejű szolgáltatáskimaradást okoz.",
"rebooting": "A rendszer újraindítása folyamatban...", "rebooting": "A rendszer újraindítása folyamatban...",
"refreshLogs": "Naplók frissítése", "refreshLogs": "Naplók frissítése",
"request": "Kérés", "request": "Kérés",
"serverVersion": "Szerver",
"status": "Állapot", "status": "Állapot",
"systemLogs": "Rendszernaplók", "systemLogs": "Rendszernaplók",
"systemReboot": "Rendszer újraindítása", "systemReboot": "Rendszer újraindítása",
@@ -22,5 +25,8 @@
"systemUpgrade": "Rendszerfrissítés", "systemUpgrade": "Rendszerfrissítés",
"upgradeDescription": "Biztosan végre akarja hajtani a rendszerfrissítést? Ez a művelet néhány percet vehet igénybe, és ezalatt a rendszer esetleg nem fog válaszolni.", "upgradeDescription": "Biztosan végre akarja hajtani a rendszerfrissítést? Ez a művelet néhány percet vehet igénybe, és ezalatt a rendszer esetleg nem fog válaszolni.",
"userAgent": "Felhasználói ügynök", "userAgent": "Felhasználói ügynök",
"viewLogsAndManage": "Tekintse meg a rendszer naplóit, hajtsa végre a rendszerfrissítéseket és az újraindítási műveleteket" "versionInfo": "Verzióinformáció",
"viewLogsAndManage": "Tekintse meg a rendszer naplóit, hajtsa végre a rendszerfrissítéseket és az újraindítási műveleteket",
"viewNewVersion": "Új verzió megtekintése",
"webVersion": "Web/Admin"
} }
+15 -1
View File
@@ -1,6 +1,7 @@
{ {
"accountEnable": "Fiók engedélyezése", "accountEnable": "Fiók engedélyezése",
"actions": "műveletek", "actions": "műveletek",
"active": "Aktív",
"add": "Hozzáadás", "add": "Hozzáadás",
"administrator": "Rendszergazda", "administrator": "Rendszergazda",
"areaCode": "Körzetszám", "areaCode": "Körzetszám",
@@ -41,10 +42,12 @@
"email": "e-mail", "email": "e-mail",
"enable": "Engedélyezés", "enable": "Engedélyezés",
"expireTime": "Lejárati idő", "expireTime": "Lejárati idő",
"expired": "Lejárt",
"expiredAt": "Lejárati dátum", "expiredAt": "Lejárati dátum",
"failed": "Sikertelen", "failed": "Sikertelen",
"giftAmount": "Ajándék Összeg", "giftAmount": "Ajándék Összeg",
"giftAmountPlaceholder": "Adja meg az ajándék összegét", "giftAmountPlaceholder": "Adja meg az ajándék összegét",
"inactive": "Inaktív",
"invalidEmailFormat": "Érvénytelen e-mail formátum", "invalidEmailFormat": "Érvénytelen e-mail formátum",
"inviteCode": "Meghívókód", "inviteCode": "Meghívókód",
"inviteCodePlaceholder": "Adja meg a meghívó kódot (hagyja üresen a generáláshoz)", "inviteCodePlaceholder": "Adja meg a meghívó kódot (hagyja üresen a generáláshoz)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "Adjon meg új jelszót (opcionális)", "passwordPlaceholder": "Adjon meg új jelszót (opcionális)",
"permanent": "Állandó", "permanent": "Állandó",
"pleaseEnterEmail": "Kérjük, adja meg az e-mail címet", "pleaseEnterEmail": "Kérjük, adja meg az e-mail címet",
"price": "Ár",
"referer": "Ajánló", "referer": "Ajánló",
"refererId": "Hivatkozó azonosító", "refererId": "Hivatkozó azonosító",
"refererIdPlaceholder": "Adja meg az ajánló azonosítóját", "refererIdPlaceholder": "Adja meg az ajánló azonosítóját",
@@ -74,8 +78,12 @@
"searchIp": "IP-cím keresése", "searchIp": "IP-cím keresése",
"selectAuthType": "Válassza ki az azonosítás típusát", "selectAuthType": "Válassza ki az azonosítás típusát",
"speedLimit": "Sebességhatár", "speedLimit": "Sebességhatár",
"startTime": "Kezdési idő",
"status": "Állapot",
"subscription": "Előfizetés", "subscription": "Előfizetés",
"subscriptionDetails": "Előfizetési részletek", "subscriptionDetails": "Előfizetési részletek",
"subscriptionId": "Előfizetés azonosítója",
"subscriptionInfo": "Előfizetés információ",
"subscriptionList": "Előfizetési lista", "subscriptionList": "Előfizetési lista",
"subscriptionLogs": "Előfizetési naplók", "subscriptionLogs": "Előfizetési naplók",
"subscriptionName": "Előfizetés neve", "subscriptionName": "Előfizetés neve",
@@ -89,6 +97,8 @@
"tradeNotifications": "Kereskedelmi értesítések", "tradeNotifications": "Kereskedelmi értesítések",
"trafficLimit": "Forgalmi korlát", "trafficLimit": "Forgalmi korlát",
"trafficLogs": "Forgalmi naplók", "trafficLogs": "Forgalmi naplók",
"trafficUsage": "Forgalmi használat",
"unknown": "Ismeretlen",
"unlimited": "Korlátlan", "unlimited": "Korlátlan",
"unverified": "Nem ellenőrzött", "unverified": "Nem ellenőrzött",
"update": "Frissítés", "update": "Frissítés",
@@ -98,11 +108,15 @@
"userAgent": "Felhasználói ügynök", "userAgent": "Felhasználói ügynök",
"userEmail": "Felhasználó e-mail", "userEmail": "Felhasználó e-mail",
"userEmailPlaceholder": "Adja meg a felhasználó e-mail címét", "userEmailPlaceholder": "Adja meg a felhasználó e-mail címét",
"userId": "Felhasználói azonosító",
"userInfo": "Felhasználói információ",
"userList": "Felhasználói lista", "userList": "Felhasználói lista",
"userLogs": "Bejelentkezési előzmények", "userLogs": "Bejelentkezési előzmények",
"userName": "Felhasználói azonosító", "userName": "Felhasználói azonosító",
"userOrders": "Rendelések", "userOrders": "Rendelések",
"userProfile": "Profil", "userProfile": "Profil",
"userSubscriptions": "Előfizetések", "userSubscriptions": "Előfizetések",
"verified": "Ellenőrzött" "username": "Felhasználónév",
"verified": "Ellenőrzött",
"viewDetails": "Részletek megtekintése"
} }
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "ADS設定", "ADS Config": "ADS設定",
"Announcement Management": "お知らせ管理", "Announcement Management": "お知らせ管理",
"Apple": "Apple ID", "Apple": "Apple ID",
"Application Management": "アプリケーション管理",
"Auth Control": "認証管理", "Auth Control": "認証管理",
"Coupon Management": "クーポン管理", "Coupon Management": "クーポン管理",
"Dashboard": "ダッシュボード", "Dashboard": "ダッシュボード",
@@ -16,6 +17,7 @@
"Order Management": "注文管理", "Order Management": "注文管理",
"Payment Config": "支払い設定", "Payment Config": "支払い設定",
"Phone Number": "電話番号", "Phone Number": "電話番号",
"Rule Management": "ルール管理",
"Server": "サーバー", "Server": "サーバー",
"Server Management": "サーバー管理", "Server Management": "サーバー管理",
"Settings": "設定", "Settings": "設定",
-1
View File
@@ -22,7 +22,6 @@
"description": "説明", "description": "説明",
"descriptionPlaceholder": "支払い方法の説明を入力してください", "descriptionPlaceholder": "支払い方法の説明を入力してください",
"domain": "ドメイン", "domain": "ドメイン",
"domainPlaceholder": "任意、例:{example}",
"edit": "編集", "edit": "編集",
"editPayment": "支払い方法を編集", "editPayment": "支払い方法を編集",
"enable": "有効", "enable": "有効",
+42
View File
@@ -0,0 +1,42 @@
{
"analyzing": "分析中...",
"appIcon": "ルールアイコン",
"cancel": "キャンセル",
"confirm": "確認",
"confirmDelete": "削除の確認",
"create": "ルールを追加",
"createRule": "ルールを追加",
"createSuccess": "ルールが正常に作成されました",
"createdAt": "作成日時",
"defaultRule": "デフォルトルール",
"delete": "削除",
"deleteSuccess": "ルールが正常に削除されました",
"deleteWarning": "このルールを削除してもよろしいですか?この操作は元に戻せません。",
"downloadTemplate": "テンプレートをダウンロード",
"edit": "編集",
"editRule": "ルールを編集",
"enable": "有効化",
"enterIconUrl": "アイコンのURLを入力またはアップロード",
"enterRuleName": "ルール名を入力",
"enterRules": "ルールの内容を入力してください(1行ごと)",
"import": "インポート",
"importFailed": "インポートに失敗しました",
"importSuccess": "インポートが成功しました",
"importYamlDescription": "YAMLファイルからルールをインポートします。システムはポリシーグループ名に基づいてルールグループを自動的に作成します。",
"importYamlRules": "YAMLルールをインポート",
"importing": "インポート中...",
"invalidYamlFormat": "無効なYAML形式です。ルールフィールドが欠けています。",
"name": "ルール名",
"noValidRules": "有効なルールが見つかりません",
"pleaseUploadFile": "YAMLファイルをアップロードしてください",
"preview": "プレビュー",
"rulesFormat": "ルール形式: ルールタイプ, マッチ内容, [ポリシー](ポリシーはオプションです)。\nポリシーが指定されていない場合、現在のルールグループ名が自動的に使用されます。例:",
"rulesLabel": "ルールの内容",
"searchRule": "ルール名を検索",
"selectTags": "ノードタグを選択",
"selectType": "ルールタイプを選択",
"tags": "ノードタグ",
"tagsLabel": "ノードタグ",
"type": "ルールタイプ",
"updateSuccess": "ルールが正常に更新されました"
}
+1 -1
View File
@@ -145,7 +145,7 @@
"quota": "購入制限/回", "quota": "購入制限/回",
"replacement": "リセット価格/回", "replacement": "リセット価格/回",
"sell": "販売", "sell": "販売",
"show": "ホームページ表示", "show": "表示",
"sold": "サブスクリプション数", "sold": "サブスクリプション数",
"subscribe": "購読", "subscribe": "購読",
"subscribeGroup": "グループを購読する", "subscribeGroup": "グループを購読する",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "システムアップグレードを確認", "confirmSystemUpgrade": "システムアップグレードを確認",
"confirmUpgrade": "アップグレードを確認", "confirmUpgrade": "アップグレードを確認",
"currentVersion": "現在のシステムバージョン:", "currentVersion": "現在のシステムバージョン:",
"developmentVersion": "開発版",
"errors": "エラー", "errors": "エラー",
"ip": "IP", "ip": "IPアドレス",
"lastUpdated": "最終更新:", "lastUpdated": "最終更新:",
"newVersionAvailable": "新版利用可能",
"none": "なし", "none": "なし",
"query": "クエリ", "query": "クエリ",
"rebootDescription": "システムを再起動してもよろしいですか?この操作は一時的なサービス中断を引き起こします。", "rebootDescription": "システムを再起動してもよろしいですか?この操作は一時的なサービス中断を引き起こします。",
"rebooting": "システムを再起動しています...", "rebooting": "システムを再起動しています...",
"refreshLogs": "ログを更新", "refreshLogs": "ログを更新",
"request": "リクエスト", "request": "リクエスト",
"serverVersion": "サーバー",
"status": "ステータス", "status": "ステータス",
"systemLogs": "システムログ", "systemLogs": "システムログ",
"systemReboot": "システム再起動", "systemReboot": "システム再起動",
@@ -22,5 +25,8 @@
"systemUpgrade": "システムアップグレード", "systemUpgrade": "システムアップグレード",
"upgradeDescription": "システムのアップグレードを実行してもよろしいですか?この操作には数分かかる場合があり、その間システムが応答しない可能性があります。", "upgradeDescription": "システムのアップグレードを実行してもよろしいですか?この操作には数分かかる場合があり、その間システムが応答しない可能性があります。",
"userAgent": "ユーザーエージェント", "userAgent": "ユーザーエージェント",
"viewLogsAndManage": "システムログを表示し、システムのアップグレードと再起動を実行する" "versionInfo": "バージョン情報",
"viewLogsAndManage": "システムログを表示し、システムのアップグレードと再起動を実行する",
"viewNewVersion": "新版を表示",
"webVersion": "ウェブ/管理者"
} }
+15 -1
View File
@@ -1,6 +1,7 @@
{ {
"accountEnable": "アカウント有効化", "accountEnable": "アカウント有効化",
"actions": "アクション", "actions": "アクション",
"active": "アクティブ",
"add": "追加", "add": "追加",
"administrator": "管理者", "administrator": "管理者",
"areaCode": "市外局番", "areaCode": "市外局番",
@@ -41,10 +42,12 @@
"email": "メールアドレス", "email": "メールアドレス",
"enable": "有効", "enable": "有効",
"expireTime": "有効期限", "expireTime": "有効期限",
"expired": "期限切れ",
"expiredAt": "有効期限", "expiredAt": "有効期限",
"failed": "失敗しました", "failed": "失敗しました",
"giftAmount": "ギフト金額", "giftAmount": "ギフト金額",
"giftAmountPlaceholder": "ギフト金額を入力してください", "giftAmountPlaceholder": "ギフト金額を入力してください",
"inactive": "非アクティブ",
"invalidEmailFormat": "無効なメール形式です", "invalidEmailFormat": "無効なメール形式です",
"inviteCode": "招待コード", "inviteCode": "招待コード",
"inviteCodePlaceholder": "招待コードを入力してください(生成するには空白のままにしてください)", "inviteCodePlaceholder": "招待コードを入力してください(生成するには空白のままにしてください)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "新しいパスワードを入力してください(任意)", "passwordPlaceholder": "新しいパスワードを入力してください(任意)",
"permanent": "永久", "permanent": "永久",
"pleaseEnterEmail": "メールアドレスを入力してください", "pleaseEnterEmail": "メールアドレスを入力してください",
"price": "価格",
"referer": "推薦者", "referer": "推薦者",
"refererId": "リファラーID", "refererId": "リファラーID",
"refererIdPlaceholder": "紹介者IDを入力してください", "refererIdPlaceholder": "紹介者IDを入力してください",
@@ -74,8 +78,12 @@
"searchIp": "IPアドレスを検索", "searchIp": "IPアドレスを検索",
"selectAuthType": "認証タイプを選択", "selectAuthType": "認証タイプを選択",
"speedLimit": "速度制限", "speedLimit": "速度制限",
"startTime": "開始時間",
"status": "ステータス",
"subscription": "サブスクリプション", "subscription": "サブスクリプション",
"subscriptionDetails": "サブスクリプションの詳細", "subscriptionDetails": "サブスクリプションの詳細",
"subscriptionId": "サブスクリプションID",
"subscriptionInfo": "サブスクリプション情報",
"subscriptionList": "購読リスト", "subscriptionList": "購読リスト",
"subscriptionLogs": "サブスクリプションログ", "subscriptionLogs": "サブスクリプションログ",
"subscriptionName": "サブスクリプション名", "subscriptionName": "サブスクリプション名",
@@ -89,6 +97,8 @@
"tradeNotifications": "取引通知", "tradeNotifications": "取引通知",
"trafficLimit": "トラフィック制限", "trafficLimit": "トラフィック制限",
"trafficLogs": "トラフィックログ", "trafficLogs": "トラフィックログ",
"trafficUsage": "トラフィック使用量",
"unknown": "不明",
"unlimited": "無制限", "unlimited": "無制限",
"unverified": "未確認", "unverified": "未確認",
"update": "更新", "update": "更新",
@@ -98,11 +108,15 @@
"userAgent": "ユーザーエージェント", "userAgent": "ユーザーエージェント",
"userEmail": "ユーザーのメール", "userEmail": "ユーザーのメール",
"userEmailPlaceholder": "ユーザーのメールアドレスを入力してください", "userEmailPlaceholder": "ユーザーのメールアドレスを入力してください",
"userId": "ユーザーID",
"userInfo": "ユーザー情報",
"userList": "ユーザーリスト", "userList": "ユーザーリスト",
"userLogs": "ログイン履歴", "userLogs": "ログイン履歴",
"userName": "ユーザー識別子", "userName": "ユーザー識別子",
"userOrders": "注文", "userOrders": "注文",
"userProfile": "プロフィール", "userProfile": "プロフィール",
"userSubscriptions": "サブスクリプション", "userSubscriptions": "サブスクリプション",
"verified": "確認済み" "username": "ユーザー名",
"verified": "確認済み",
"viewDetails": "詳細を見る"
} }
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "ADS 구성", "ADS Config": "ADS 구성",
"Announcement Management": "공지 관리", "Announcement Management": "공지 관리",
"Apple": "Apple ID", "Apple": "Apple ID",
"Application Management": "애플리케이션 관리",
"Auth Control": "인증 제어", "Auth Control": "인증 제어",
"Coupon Management": "쿠폰 관리", "Coupon Management": "쿠폰 관리",
"Dashboard": "대시보드", "Dashboard": "대시보드",
@@ -16,6 +17,7 @@
"Order Management": "주문 관리", "Order Management": "주문 관리",
"Payment Config": "결제 구성", "Payment Config": "결제 구성",
"Phone Number": "전화번호", "Phone Number": "전화번호",
"Rule Management": "규칙 관리",
"Server": "서버", "Server": "서버",
"Server Management": "서버 관리", "Server Management": "서버 관리",
"Settings": "설정", "Settings": "설정",
-1
View File
@@ -22,7 +22,6 @@
"description": "설명", "description": "설명",
"descriptionPlaceholder": "결제 수단 설명을 입력하세요", "descriptionPlaceholder": "결제 수단 설명을 입력하세요",
"domain": "도메인", "domain": "도메인",
"domainPlaceholder": "선택 사항, 예: {example}",
"edit": "편집", "edit": "편집",
"editPayment": "결제 수단 편집", "editPayment": "결제 수단 편집",
"enable": "사용", "enable": "사용",
+39
View File
@@ -0,0 +1,39 @@
{
"analyzing": "분석 중...",
"appIcon": "규칙 아이콘",
"cancel": "취소",
"confirm": "확인",
"confirmDelete": "삭제 확인",
"create": "규칙 추가",
"createRule": "규칙 추가",
"createSuccess": "규칙이 성공적으로 생성되었습니다",
"createdAt": "생성일",
"delete": "삭제",
"deleteSuccess": "규칙이 성공적으로 삭제되었습니다",
"deleteWarning": "이 규칙을 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.",
"downloadTemplate": "템플릿 다운로드",
"edit": "편집",
"editRule": "규칙 편집",
"enable": "활성화",
"enterIconUrl": "아이콘 URL을 입력하거나 업로드하세요",
"enterRuleName": "규칙 이름을 입력하세요",
"enterRules": "규칙 내용을 입력하세요, 한 줄에 하나씩",
"import": "가져오기",
"importFailed": "가져오기에 실패했습니다",
"importSuccess": "가져오기가 성공적으로 완료되었습니다",
"importYamlDescription": "YAML 파일에서 규칙을 가져오며, 시스템이 정책 그룹 이름에 따라 규칙 그룹을 자동으로 생성합니다",
"importYamlRules": "YAML 규칙 가져오기",
"importing": "가져오는 중...",
"invalidYamlFormat": "잘못된 YAML 형식, 규칙 필드가 누락되었습니다",
"name": "규칙 이름",
"noValidRules": "유효한 규칙이 없습니다",
"pleaseUploadFile": "YAML 파일을 업로드해 주세요",
"preview": "미리보기",
"rulesFormat": "규칙 형식: 규칙 유형, 일치하는 내용, [정책], 여기서 정책은 선택 사항입니다.\n정책이 지정되지 않으면 현재 규칙 그룹 이름이 자동으로 사용됩니다. 예시:",
"rulesLabel": "규칙 내용",
"searchRule": "규칙 이름 검색",
"selectTags": "노드 태그 선택",
"tags": "노드 태그",
"tagsLabel": "노드 태그",
"updateSuccess": "규칙이 성공적으로 업데이트되었습니다"
}
+1 -1
View File
@@ -145,7 +145,7 @@
"quota": "구매 제한/회", "quota": "구매 제한/회",
"replacement": "가격 재설정/회", "replacement": "가격 재설정/회",
"sell": "판매", "sell": "판매",
"show": "홈 화면 표시", "show": "표시",
"sold": "구독 수", "sold": "구독 수",
"subscribe": "구독", "subscribe": "구독",
"subscribeGroup": "구독 그룹", "subscribeGroup": "구독 그룹",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "시스템 업그레이드를 확인", "confirmSystemUpgrade": "시스템 업그레이드를 확인",
"confirmUpgrade": "업그레이드 확인", "confirmUpgrade": "업그레이드 확인",
"currentVersion": "현재 시스템 버전:", "currentVersion": "현재 시스템 버전:",
"developmentVersion": "개발 버전",
"errors": "오류", "errors": "오류",
"ip": "IP", "ip": "IP 주소",
"lastUpdated": "마지막 업데이트:", "lastUpdated": "마지막 업데이트:",
"newVersionAvailable": "새 버전",
"none": "없음", "none": "없음",
"query": "쿼리", "query": "쿼리",
"rebootDescription": "시스템을 재부팅하시겠습니까? 이 작업은 일시적인 서비스 중단을 초래할 수 있습니다.", "rebootDescription": "시스템을 재부팅하시겠습니까? 이 작업은 일시적인 서비스 중단을 초래할 수 있습니다.",
"rebooting": "시스템을 재부팅 중입니다...", "rebooting": "시스템을 재부팅 중입니다...",
"refreshLogs": "로그 새로고침", "refreshLogs": "로그 새로고침",
"request": "요청", "request": "요청",
"serverVersion": "서버",
"status": "상태", "status": "상태",
"systemLogs": "시스템 로그", "systemLogs": "시스템 로그",
"systemReboot": "시스템 재부팅", "systemReboot": "시스템 재부팅",
@@ -22,5 +25,8 @@
"systemUpgrade": "시스템 업그레이드", "systemUpgrade": "시스템 업그레이드",
"upgradeDescription": "시스템 업그레이드를 수행하시겠습니까? 이 작업은 몇 분이 소요될 수 있으며, 그 동안 시스템이 응답하지 않을 수 있습니다.", "upgradeDescription": "시스템 업그레이드를 수행하시겠습니까? 이 작업은 몇 분이 소요될 수 있으며, 그 동안 시스템이 응답하지 않을 수 있습니다.",
"userAgent": "사용자 에이전트", "userAgent": "사용자 에이전트",
"viewLogsAndManage": "시스템 로그를 보고 시스템 업그레이드 및 재시작 작업을 수행합니다" "versionInfo": "버전 정보",
"viewLogsAndManage": "시스템 로그를 보고 시스템 업그레이드 및 재시작 작업을 수행합니다",
"viewNewVersion": "새 버전 보기",
"webVersion": "웹/관리자"
} }
+15 -1
View File
@@ -1,6 +1,7 @@
{ {
"accountEnable": "계정 활성화", "accountEnable": "계정 활성화",
"actions": "작업", "actions": "작업",
"active": "활성",
"add": "추가", "add": "추가",
"administrator": "관리자", "administrator": "관리자",
"areaCode": "지역 코드", "areaCode": "지역 코드",
@@ -41,10 +42,12 @@
"email": "이메일", "email": "이메일",
"enable": "사용", "enable": "사용",
"expireTime": "만료 시간", "expireTime": "만료 시간",
"expired": "만료됨",
"expiredAt": "만료일", "expiredAt": "만료일",
"failed": "실패", "failed": "실패",
"giftAmount": "선물 금액", "giftAmount": "선물 금액",
"giftAmountPlaceholder": "선물 금액 입력", "giftAmountPlaceholder": "선물 금액 입력",
"inactive": "비활성",
"invalidEmailFormat": "잘못된 이메일 형식입니다", "invalidEmailFormat": "잘못된 이메일 형식입니다",
"inviteCode": "초대 코드", "inviteCode": "초대 코드",
"inviteCodePlaceholder": "초대 코드를 입력하세요 (생성을 원하시면 비워두세요)", "inviteCodePlaceholder": "초대 코드를 입력하세요 (생성을 원하시면 비워두세요)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "새 비밀번호 입력 (선택 사항)", "passwordPlaceholder": "새 비밀번호 입력 (선택 사항)",
"permanent": "영구적인", "permanent": "영구적인",
"pleaseEnterEmail": "이메일을 입력하세요", "pleaseEnterEmail": "이메일을 입력하세요",
"price": "가격",
"referer": "추천인", "referer": "추천인",
"refererId": "추천인 ID", "refererId": "추천인 ID",
"refererIdPlaceholder": "추천인 ID를 입력하세요", "refererIdPlaceholder": "추천인 ID를 입력하세요",
@@ -74,8 +78,12 @@
"searchIp": "IP 주소 검색", "searchIp": "IP 주소 검색",
"selectAuthType": "인증 유형 선택", "selectAuthType": "인증 유형 선택",
"speedLimit": "속도 제한", "speedLimit": "속도 제한",
"startTime": "시작 시간",
"status": "상태",
"subscription": "구독", "subscription": "구독",
"subscriptionDetails": "구독 세부 정보", "subscriptionDetails": "구독 세부 정보",
"subscriptionId": "구독 ID",
"subscriptionInfo": "구독 정보",
"subscriptionList": "구독 목록", "subscriptionList": "구독 목록",
"subscriptionLogs": "구독 로그", "subscriptionLogs": "구독 로그",
"subscriptionName": "구독 이름", "subscriptionName": "구독 이름",
@@ -89,6 +97,8 @@
"tradeNotifications": "거래 알림", "tradeNotifications": "거래 알림",
"trafficLimit": "트래픽 제한", "trafficLimit": "트래픽 제한",
"trafficLogs": "트래픽 로그", "trafficLogs": "트래픽 로그",
"trafficUsage": "트래픽 사용량",
"unknown": "알 수 없음",
"unlimited": "무제한", "unlimited": "무제한",
"unverified": "확인되지 않음", "unverified": "확인되지 않음",
"update": "업데이트", "update": "업데이트",
@@ -98,11 +108,15 @@
"userAgent": "사용자 에이전트", "userAgent": "사용자 에이전트",
"userEmail": "사용자 이메일", "userEmail": "사용자 이메일",
"userEmailPlaceholder": "사용자 이메일 입력", "userEmailPlaceholder": "사용자 이메일 입력",
"userId": "사용자 ID",
"userInfo": "사용자 정보",
"userList": "사용자 목록", "userList": "사용자 목록",
"userLogs": "로그인 기록", "userLogs": "로그인 기록",
"userName": "사용자 식별자", "userName": "사용자 식별자",
"userOrders": "주문", "userOrders": "주문",
"userProfile": "프로필", "userProfile": "프로필",
"userSubscriptions": "구독", "userSubscriptions": "구독",
"verified": "검증됨" "username": "사용자 이름",
"verified": "검증됨",
"viewDetails": "세부 정보 보기"
} }
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "ADS-konfigurasjon", "ADS Config": "ADS-konfigurasjon",
"Announcement Management": "Kunngjøringsadministrasjon", "Announcement Management": "Kunngjøringsadministrasjon",
"Apple": "Apple-ID", "Apple": "Apple-ID",
"Application Management": "Applikasjonsadministrasjon",
"Auth Control": "Autentiseringskontroll", "Auth Control": "Autentiseringskontroll",
"Coupon Management": "Kupongadministrasjon", "Coupon Management": "Kupongadministrasjon",
"Dashboard": "Dashbord", "Dashboard": "Dashbord",
@@ -16,6 +17,7 @@
"Order Management": "Bestillingsadministrasjon", "Order Management": "Bestillingsadministrasjon",
"Payment Config": "Betalingskonfigurasjon", "Payment Config": "Betalingskonfigurasjon",
"Phone Number": "Telefonnummer", "Phone Number": "Telefonnummer",
"Rule Management": "Regeladministrasjon",
"Server": "Tjeneste", "Server": "Tjeneste",
"Server Management": "Serveradministrasjon", "Server Management": "Serveradministrasjon",
"Settings": "Innstillinger", "Settings": "Innstillinger",
-1
View File
@@ -22,7 +22,6 @@
"description": "Beskrivelse", "description": "Beskrivelse",
"descriptionPlaceholder": "Skriv inn beskrivelse av betalingsmetode", "descriptionPlaceholder": "Skriv inn beskrivelse av betalingsmetode",
"domain": "Domene", "domain": "Domene",
"domainPlaceholder": "valgfritt, f.eks. {example}",
"edit": "Rediger", "edit": "Rediger",
"editPayment": "Rediger betalingsmetode", "editPayment": "Rediger betalingsmetode",
"enable": "Aktiver", "enable": "Aktiver",
+39
View File
@@ -0,0 +1,39 @@
{
"analyzing": "Analyserer...",
"appIcon": "Regelikon",
"cancel": "Avbryt",
"confirm": "Bekreft",
"confirmDelete": "Bekreft sletting",
"create": "Legg til regel",
"createRule": "Legg til regel",
"createSuccess": "Regel opprettet med suksess",
"createdAt": "Opprettet den",
"delete": "Slett",
"deleteSuccess": "Regel slettet med suksess",
"deleteWarning": "Er du sikker på at du vil slette denne regelen? Denne handlingen kan ikke angres.",
"downloadTemplate": "Last ned mal",
"edit": "Rediger",
"editRule": "Rediger regel",
"enable": "Aktiver",
"enterIconUrl": "Skriv inn eller last opp et ikon",
"enterRuleName": "Skriv inn regelnavn",
"enterRules": "Skriv inn regelinnhold, en per linje",
"import": "Importer",
"importFailed": "Import mislyktes",
"importSuccess": "Import vellykket",
"importYamlDescription": "Importer regler fra YAML-fil, systemet vil automatisk opprette regelgrupper basert på policygruppens navn",
"importYamlRules": "Importer YAML-regler",
"importing": "Importer...",
"invalidYamlFormat": "Ugyldig YAML-format, mangler reglerfelt",
"name": "Regelnavn",
"noValidRules": "Ingen gyldige regler funnet",
"pleaseUploadFile": "Vennligst last opp en YAML-fil",
"preview": "Forhåndsvisning",
"rulesFormat": "Regelformat: regeltype, matchinnhold, [policy], der policy er valgfritt.\nHvis policy ikke er spesifisert, vil det nåværende regelgruppens navn bli brukt automatisk. Eksempler:",
"rulesLabel": "Regelinnhold",
"searchRule": "Søk etter regelnavn",
"selectTags": "Velg nodetagger",
"tags": "Nodetagger",
"tagsLabel": "Nodetagger",
"updateSuccess": "Regel oppdatert med suksess"
}

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