Compare commits

..

57 Commits

Author SHA1 Message Date
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
semantic-release-bot fa56eb8293 ЁЯФЦ chore(release): v1.0.0-beta.32 [skip ci]
# [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))
2025-03-17 15:53:15 +00:00
web@ppanel 6a34bfb78d ЁЯРЫ fix(locales): Update invite code text to indicate it's optional 2025-03-17 22:50:21 +07:00
web@ppanel b8f4f1e694 ЁЯРЫ fix(forms): Add step attribute to number inputs for better value control 2025-03-17 22:47:42 +07:00
semantic-release-bot aa1d42651d ЁЯФЦ chore(release): v1.0.0-beta.31 [skip ci]
# [1.0.0-beta.31](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.30...v1.0.0-beta.31) (2025-03-15)

### ЁЯРЫ Bug Fixes

* **site**: Se ref to store site configuration for updates ([0c8f091](https://github.com/perfect-panel/ppanel-web/commit/0c8f091))
2025-03-15 15:51:45 +00:00
web@ppanel 0c8f0911c7 ЁЯРЫ fix(site): Se ref to store site configuration for updates 2025-03-15 22:47:19 +07:00
semantic-release-bot db0d9e003e ЁЯФЦ chore(release): v1.0.0-beta.30 [skip ci]
# [1.0.0-beta.30](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.29...v1.0.0-beta.30) (2025-03-15)

### тЬи Features

* **api**: Add CheckoutOrder request and response types, and update user purchase request parameters ([48a1b97](https://github.com/perfect-panel/ppanel-web/commit/48a1b97))
* **email**: Add traffic exhaustion template ([bb3bd7b](https://github.com/perfect-panel/ppanel-web/commit/bb3bd7b))
* **formatting**: Update differenceInDays function to return whole days or two decimal places ([bf58f25](https://github.com/perfect-panel/ppanel-web/commit/bf58f25))
* **global**: Add custom data ([6dbebd1](https://github.com/perfect-panel/ppanel-web/commit/6dbebd1))
* **input**: Add minimum value constraint and enhance number handling in EnhancedInput ([ce31972](https://github.com/perfect-panel/ppanel-web/commit/ce31972))
* **loading**: Replace loading animation with a simpler spinner and loading text ([f72df3a](https://github.com/perfect-panel/ppanel-web/commit/f72df3a))
* **node-form**: Update number input fields to enforce step, min, and max values ([3f7b6d1](https://github.com/perfect-panel/ppanel-web/commit/3f7b6d1))
* **payment**: Add isEdit prop to PaymentForm and disable fields when editing ([85f55de](https://github.com/perfect-panel/ppanel-web/commit/85f55de))
* **timeline**: Simplify timeline component layout and remove commented-out code ([fbad3b0](https://github.com/perfect-panel/ppanel-web/commit/fbad3b0))

### ЁЯОл Chores

* **release**: V1.0.0-beta.27 [skip ci] ([092477b](https://github.com/perfect-panel/ppanel-web/commit/092477b))
* **release**: V1.0.0-beta.28 [skip ci] ([786ba0e](https://github.com/perfect-panel/ppanel-web/commit/786ba0e))
* Merge branch 'beta' into develop ([f219c52](https://github.com/perfect-panel/ppanel-web/commit/f219c52))

### ЁЯРЫ Bug Fixes

* **dashboard**:  Update date display to use start_time if available ([e551232](https://github.com/perfect-panel/ppanel-web/commit/e551232))
2025-03-15 09:02:24 +00:00
web@ppanel f219c52306 ЁЯФз chore: Merge branch 'beta' into develop 2025-03-15 15:58:37 +07:00
web@ppanel 3f7b6d16ed тЬи feat(node-form): Update number input fields to enforce step, min, and max values 2025-03-15 15:48:59 +07:00
web@ppanel 6dbebd152d тЬи feat(global): Add custom data 2025-03-15 15:39:55 +07:00
web@ppanel bb3bd7b50c тЬи feat(email): Add traffic exhaustion template 2025-03-14 23:28:36 +07:00
web@ppanel fbad3b0e51 тЬи feat(timeline): Simplify timeline component layout and remove commented-out code 2025-03-14 23:21:17 +07:00
web@ppanel e551232564 ЁЯРЫ fix(dashboard): Update date display to use start_time if available 2025-03-14 22:10:24 +07:00
web@ppanel bf58f25072 тЬи feat(formatting): Update differenceInDays function to return whole days or two decimal places 2025-03-14 20:51:17 +07:00
web@ppanel 85f55def2e тЬи feat(payment): Add isEdit prop to PaymentForm and disable fields when editing 2025-03-14 14:04:10 +07:00
web@ppanel f72df3a5e8 тЬи feat(loading): Replace loading animation with a simpler spinner and loading text 2025-03-14 13:42:58 +07:00
web@ppanel 48a1b97051 тЬи feat(api): Add CheckoutOrder request and response types, and update user purchase request parameters 2025-03-14 13:42:58 +07:00
semantic-release-bot 786ba0e41c ЁЯФЦ chore(release): v1.0.0-beta.28 [skip ci]
# [1.0.0-beta.28](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.27...v1.0.0-beta.28) (2025-03-13)

### тЬи Features

* **input**: Add minimum value constraint and enhance number handling in EnhancedInput ([94822d9](https://github.com/perfect-panel/ppanel-web/commit/94822d9))
2025-03-14 13:42:58 +07:00
web@ppanel ce3197298d тЬи feat(input): Add minimum value constraint and enhance number handling in EnhancedInput 2025-03-14 13:42:58 +07:00
semantic-release-bot 092477b2d3 ЁЯФЦ chore(release): v1.0.0-beta.27 [skip ci]
* **payment**: Reconstruct the payment page ([7109472](https://github.com/perfect-panel/ppanel-web/commit/7109472))
* Enhance user navigation dropdown ui and styling ([d2732e6](https://github.com/perfect-panel/ppanel-web/commit/d2732e6))

* **cdn**: Add CDN URL configuration and update related references ([0c90733](https://github.com/perfect-panel/ppanel-web/commit/0c90733))
* **payment**: Add bank card payment ([7fa3a57](https://github.com/perfect-panel/ppanel-web/commit/7fa3a57))
* **subscription**:  Improve layout and organization of subscription detail tabs ([e4630f8](https://github.com/perfect-panel/ppanel-web/commit/e4630f8))
* **subscription**: Refactor subscription handling and update imports for better organization ([2215c7f](https://github.com/perfect-panel/ppanel-web/commit/2215c7f))

* **merge**: Bump version to 1.0.0-beta.26 and update changelog ([3222016](https://github.com/perfect-panel/ppanel-web/commit/3222016))

* **affiliate**: Update user identifier ([35f92c9](https://github.com/perfect-panel/ppanel-web/commit/35f92c9))
* **changelog**: Update change log style ([cfa3fc0](https://github.com/perfect-panel/ppanel-web/commit/cfa3fc0))
* **payment**: Add notification URL field to payment management interface ([5c710e1](https://github.com/perfect-panel/ppanel-web/commit/5c710e1))
* **payment**: Fix payment related type definitions and update payment method references ([c3138a8](https://github.com/perfect-panel/ppanel-web/commit/c3138a8))
* **payment**: Refactor purchaseCheckout usage and remove redundant code ([a5e2079](https://github.com/perfect-panel/ppanel-web/commit/a5e2079))
* **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))
* **purchasing**: Update payment type to lowercase and add optional chaining for discounts ([c06ea49](https://github.com/perfect-panel/ppanel-web/commit/c06ea49))
* **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))
2025-03-14 13:42:58 +07:00
294 changed files with 14849 additions and 839 deletions
+537 -2
View File
@@ -1,13 +1,548 @@
<a name="readme-top"></a>
# Changelog
## [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>
# Changelog
# [1.0.0-beta.31](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.30...v1.0.0-beta.31) (2025-03-15)
### ЁЯРЫ Bug Fixes
- **site**: Se ref to store site configuration for updates ([0c8f091](https://github.com/perfect-panel/ppanel-web/commit/0c8f091))
# [1.0.0-beta.30](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.29...v1.0.0-beta.30) (2025-03-15)
### тЬи Features
- **api**: Add CheckoutOrder request and response types, and update user purchase request parameters ([48a1b97](https://github.com/perfect-panel/ppanel-web/commit/48a1b97))
- **email**: Add traffic exhaustion template ([bb3bd7b](https://github.com/perfect-panel/ppanel-web/commit/bb3bd7b))
- **formatting**: Update differenceInDays function to return whole days or two decimal places ([bf58f25](https://github.com/perfect-panel/ppanel-web/commit/bf58f25))
- **global**: Add custom data ([6dbebd1](https://github.com/perfect-panel/ppanel-web/commit/6dbebd1))
- **input**: Add minimum value constraint and enhance number handling in EnhancedInput ([ce31972](https://github.com/perfect-panel/ppanel-web/commit/ce31972))
- **loading**: Replace loading animation with a simpler spinner and loading text ([f72df3a](https://github.com/perfect-panel/ppanel-web/commit/f72df3a))
- **node-form**: Update number input fields to enforce step, min, and max values ([3f7b6d1](https://github.com/perfect-panel/ppanel-web/commit/3f7b6d1))
- **payment**: Add isEdit prop to PaymentForm and disable fields when editing ([85f55de](https://github.com/perfect-panel/ppanel-web/commit/85f55de))
- **timeline**: Simplify timeline component layout and remove commented-out code ([fbad3b0](https://github.com/perfect-panel/ppanel-web/commit/fbad3b0))
### ЁЯОл Chores
- **release**: V1.0.0-beta.27 [skip ci] ([092477b](https://github.com/perfect-panel/ppanel-web/commit/092477b))
- **release**: V1.0.0-beta.28 [skip ci] ([786ba0e](https://github.com/perfect-panel/ppanel-web/commit/786ba0e))
- Merge branch 'beta' into develop ([f219c52](https://github.com/perfect-panel/ppanel-web/commit/f219c52))
### ЁЯРЫ Bug Fixes
- **dashboard**: Update date display to use start_time if available ([e551232](https://github.com/perfect-panel/ppanel-web/commit/e551232))
<a name="readme-top"></a>
# Changelog
# [1.0.0-beta.29](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.28...v1.0.0-beta.29) (2025-03-14)
### тЬи Features
- **api**: Add CheckoutOrder request and response types, and update user purchase request parameters ([dddc21c](https://github.com/perfect-panel/ppanel-web/commit/dddc21c))
- **loading**: Replace loading animation with a simpler spinner and loading text ([b8316bb](https://github.com/perfect-panel/ppanel-web/commit/b8316bb))
<a name="readme-top"></a>
# Changelog
# [1.0.0-beta.28](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.27...v1.0.0-beta.28) (2025-03-13)
### тЬи Features
* **api**: Add CheckoutOrder request and response types, and update user purchase request parameters ([dddc21c](https://github.com/perfect-panel/ppanel-web/commit/dddc21c))
* **loading**: Replace loading animation with a simpler spinner and loading text ([b8316bb](https://github.com/perfect-panel/ppanel-web/commit/b8316bb))
- **input**: Add minimum value constraint and enhance number handling in EnhancedInput ([94822d9](https://github.com/perfect-panel/ppanel-web/commit/94822d9))
# [1.0.0-beta.27](https://github.com/perfect-panel/ppanel-web/compare/v1.0.0-beta.26...v1.0.0-beta.27) (2025-03-13)
### тЩ╗ Code Refactoring
- **payment**: Reconstruct the payment page ([7109472](https://github.com/perfect-panel/ppanel-web/commit/7109472))
- Enhance user navigation dropdown ui and styling ([d2732e6](https://github.com/perfect-panel/ppanel-web/commit/d2732e6))
### тЬи Features
- **cdn**: Add CDN URL configuration and update related references ([0c90733](https://github.com/perfect-panel/ppanel-web/commit/0c90733))
- **payment**: Add bank card payment ([7fa3a57](https://github.com/perfect-panel/ppanel-web/commit/7fa3a57))
- **subscription**: Improve layout and organization of subscription detail tabs ([e4630f8](https://github.com/perfect-panel/ppanel-web/commit/e4630f8))
- **subscription**: Refactor subscription handling and update imports for better organization ([2215c7f](https://github.com/perfect-panel/ppanel-web/commit/2215c7f))
### ЁЯОл Chores
- **merge**: Bump version to 1.0.0-beta.26 and update changelog ([3222016](https://github.com/perfect-panel/ppanel-web/commit/3222016))
### ЁЯРЫ Bug Fixes
- **affiliate**: Update user identifier ([35f92c9](https://github.com/perfect-panel/ppanel-web/commit/35f92c9))
- **changelog**: Update change log style ([cfa3fc0](https://github.com/perfect-panel/ppanel-web/commit/cfa3fc0))
- **payment**: Add notification URL field to payment management interface ([5c710e1](https://github.com/perfect-panel/ppanel-web/commit/5c710e1))
- **payment**: Fix payment related type definitions and update payment method references ([c3138a8](https://github.com/perfect-panel/ppanel-web/commit/c3138a8))
- **payment**: Refactor purchaseCheckout usage and remove redundant code ([a5e2079](https://github.com/perfect-panel/ppanel-web/commit/a5e2079))
- **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))
- **purchasing**: Update payment type to lowercase and add optional chaining for discounts ([c06ea49](https://github.com/perfect-panel/ppanel-web/commit/c06ea49))
- **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))
<a name="readme-top"></a>
@@ -232,16 +232,6 @@ export default function SubscribeAppForm<
name: 'is_default',
type: 'boolean',
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',
@@ -252,10 +242,32 @@ export default function SubscribeAppForm<
]}
value={field.value}
onChange={(value) => {
form.setValue(
field.name,
value.filter((item) => item.url),
const filteredValue = 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>
@@ -286,31 +286,34 @@ export default function Page() {
</TabsContent>
<TabsContent value='template'>
<div className='grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3'>
{['verify_email_template', 'expiration_email_template', 'maintenance_email_template'].map(
(templateKey) => (
<Card key={templateKey}>
<CardHeader>
<CardTitle>{t(`${templateKey}`)}</CardTitle>
<CardDescription>
{t(`${templateKey}Description`, { after: '{{', before: '}}' })}
</CardDescription>
</CardHeader>
<CardContent>
<HTMLEditor
placeholder={t('inputPlaceholder')}
value={data?.config?.[templateKey] as string}
onBlur={(value) =>
updateConfig('config', {
...data?.config,
[templateKey]: value,
})
}
/>
</CardContent>
</Card>
),
)}
<div className='grid grid-cols-1 gap-4 md:grid-cols-2'>
{[
'verify_email_template',
'expiration_email_template',
'maintenance_email_template',
'traffic_exceed_email_template',
].map((templateKey) => (
<Card key={templateKey}>
<CardHeader>
<CardTitle>{t(`${templateKey}`)}</CardTitle>
<CardDescription>
{t(`${templateKey}Description`, { after: '{{', before: '}}' })}
</CardDescription>
</CardHeader>
<CardContent>
<HTMLEditor
placeholder={t('inputPlaceholder')}
value={data?.config?.[templateKey] as string}
onBlur={(value) =>
updateConfig('config', {
...data?.config,
[templateKey]: value,
})
}
/>
</CardContent>
</Card>
))}
</div>
</TabsContent>
@@ -136,14 +136,14 @@ export function Register() {
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<TableRow className='flex flex-col'>
<TableCell className='w-full'>
<Label>{t('trialSubscribePlan')}</Label>
<p className='text-muted-foreground text-xs'>
{t('trialSubscribePlanDescription')}
</p>
</TableCell>
<TableCell className='text-right'>
<TableCell className='max-w-96'>
<EnhancedInput
placeholder={t('trialDuration')}
type='number'
@@ -307,6 +307,7 @@ export default function CouponForm<T extends Record<string, any>>({
<EnhancedInput
placeholder={t('form.countPlaceholder')}
type='number'
step={1}
{...field}
onValueChange={(value) => {
form.setValue(field.name, value);
@@ -327,6 +328,7 @@ export default function CouponForm<T extends Record<string, any>>({
<EnhancedInput
placeholder={t('form.userLimitPlaceholder')}
type='number'
step={1}
{...field}
onValueChange={(value) => {
form.setValue(field.name, value);
+7 -2
View File
@@ -57,8 +57,13 @@ export default function Page(props: any) {
{
accessorKey: 'subscribe_id',
header: t('subscribe'),
cell: ({ row }) =>
subscribeList?.find((item) => item.id === row.getValue('subscribe_id'))?.name,
cell: ({ row }) => {
const name = subscribeList?.find(
(item) => item.id === row.getValue('subscribe_id'),
)?.name;
const quantity = row.original.quantity;
return name ? `${name} ├Ч ${quantity}` : '';
},
},
{
accessorKey: 'amount',
@@ -45,6 +45,7 @@ interface PaymentFormProps<T> {
loading?: boolean;
initialValues?: T;
onSubmit: (values: T) => Promise<boolean>;
isEdit?: boolean;
}
export default function PaymentForm<T>({
@@ -53,6 +54,7 @@ export default function PaymentForm<T>({
loading,
initialValues,
onSubmit,
isEdit,
}: PaymentFormProps<T>) {
const t = useTranslations('payment');
const { common } = useGlobalStore();
@@ -199,7 +201,7 @@ export default function PaymentForm<T>({
<FormLabel>{t('domain')}</FormLabel>
<FormControl>
<EnhancedInput
placeholder={t('domainPlaceholder', { example: 'http(s)://example.com' })}
placeholder='http(s)://example.com'
value={field.value}
onValueChange={(value) => form.setValue('domain', value as string)}
/>
@@ -317,6 +319,8 @@ export default function PaymentForm<T>({
}}
defaultValue={field.value}
value={field.value}
// @ts-expect-error
disabled={isEdit && Boolean(initialValues?.platform)}
>
<FormControl>
<SelectTrigger>
@@ -367,6 +371,7 @@ export default function PaymentForm<T>({
? configValues[fieldKey]
: ''
}
disabled={fieldKey === 'webhook_secret'}
onValueChange={(value) => {
const newConfig = { ...configValues };
newConfig[fieldKey] = value;
@@ -136,6 +136,7 @@ export default function PaymentTable() {
actions={{
render: (row) => [
<PaymentForm<API.UpdatePaymentMethodRequest>
isEdit
key='edit'
trigger={<Button>{t('edit')}</Button>}
title={t('editPayment')}
@@ -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';
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 portSchema = z.number().max(65535).nullish();
@@ -58,7 +58,15 @@ const hysteria2Schema = z.object({
const tuicSchema = z.object({
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,
});
@@ -87,6 +95,10 @@ const protocolConfigSchema = z.discriminatedUnion('protocol', [
protocol: z.literal('tuic'),
config: tuicSchema,
}),
z.object({
protocol: z.literal('anytls'),
config: anytlsSchema,
}),
]);
const baseFormSchema = z.object({
+317 -195
View File
@@ -110,7 +110,7 @@ export default function NodeForm<T extends { [x: string]: any }>({
{trigger}
</Button>
</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>
<SheetTitle>{title}</SheetTitle>
</SheetHeader>
@@ -290,7 +290,7 @@ export default function NodeForm<T extends { [x: string]: any }>({
value={field.value}
onValueChange={(value) => {
form.setValue(field.name, value);
if (['trojan', 'hysteria2', 'tuic'].includes(value)) {
if (['trojan', 'hysteria2', 'tuic', 'anytls'].includes(value)) {
form.setValue('config.security', 'tls');
}
}}
@@ -362,9 +362,10 @@ export default function NodeForm<T extends { [x: string]: any }>({
<EnhancedInput
{...field}
type='number'
placeholder='1-65535'
step={1}
min={1}
max={65535}
placeholder='1-65535'
onValueChange={(value) => {
form.setValue(field.name, value);
}}
@@ -401,11 +402,11 @@ export default function NodeForm<T extends { [x: string]: any }>({
</div>
)}
{['vmess', 'vless', 'trojan', 'hysteria2', 'tuic'].includes(protocol) && (
{['vmess', 'vless', 'trojan', 'hysteria2', 'tuic', 'anytls'].includes(protocol) && (
<div className='grid gap-4'>
<div
className={cn('flex gap-4 *:flex-1', {
'grid grid-cols-2': ['hysteria2'].includes(protocol),
'grid grid-cols-2': ['hysteria2', 'tuic'].includes(protocol),
})}
>
<FormField
@@ -418,6 +419,9 @@ export default function NodeForm<T extends { [x: string]: any }>({
<EnhancedInput
{...field}
type='number'
step={1}
min={1}
max={65535}
placeholder='1-65535'
onValueChange={(value) => {
form.setValue(field.name, value);
@@ -520,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>
{['vmess', 'vless', 'trojan'].includes(protocol) && (
<Card>
@@ -626,171 +733,17 @@ export default function NodeForm<T extends { [x: string]: any }>({
)}
</Card>
)}
<Card>
<CardHeader className='flex flex-row items-center justify-between p-3'>
<CardTitle>{t('form.securityConfig')}</CardTitle>
<FormField
control={form.control}
name='config.security'
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' && (
{(['vmess', 'vless', 'trojan'].includes(protocol) ||
['anytls', 'tuic', 'hysteria2'].includes(protocol)) && (
<Card>
<CardHeader className='flex flex-row items-center justify-between p-3'>
<CardTitle>{t('form.securityConfig')}</CardTitle>
{['vmess', 'vless', 'trojan'].includes(protocol) && (
<FormField
control={form.control}
name='config.security_config.fingerprint'
name='config.security'
render={({ field }) => (
<FormItem>
<FormLabel>{t('form.security_config.fingerprint')}</FormLabel>
<FormItem className='!mt-0 min-w-32'>
<Select
value={field.value}
onValueChange={(value) => {
@@ -803,45 +756,213 @@ export default function NodeForm<T extends { [x: string]: any }>({
</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>
{['vmess', 'vless'].includes(protocol) && (
<SelectItem value='none'>NONE</SelectItem>
)}
<SelectItem value='tls'>TLS</SelectItem>
{protocol === 'vless' && (
<SelectItem value='reality'>Reality</SelectItem>
)}
</SelectContent>
</Select>
<FormMessage />
<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={(value) => {
</CardHeader>
{(['anytls', 'tuic', 'hysteria2'].includes(protocol) ||
(['vmess', 'vless', 'trojan'].includes(protocol) &&
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);
}}
/>
</div>
</FormControl>
<FormMessage />
</FormItem>
</FormControl>
<FormMessage />
</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>
)}
</Card>
{protocol === 'vless' && (
<FormField
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>
)}
@@ -899,6 +1020,7 @@ export default function NodeForm<T extends { [x: string]: any }>({
{
name: 'port',
type: 'number',
step: 1,
min: 1,
max: 65535,
placeholder: t('form.relayPort'),
+48 -35
View File
@@ -1,5 +1,11 @@
'use client';
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from '@workspace/ui/components/accordion';
import { Badge } from '@workspace/ui/components/badge';
import { Progress } from '@workspace/ui/components/progress';
import { ScrollArea } from '@workspace/ui/components/scroll-area';
@@ -11,6 +17,8 @@ import {
} from '@workspace/ui/components/tooltip';
import { formatDate } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl';
import { useState } from 'react';
import { UserSubscribeDetail } from '../user/user-detail';
export function formatPercentage(value: number): string {
return `${value.toFixed(1)}%`;
@@ -18,25 +26,19 @@ export function formatPercentage(value: number): string {
export function NodeStatusCell({ status }: { status: API.NodeStatus }) {
const t = useTranslations('server.node');
const [openItem, setOpenItem] = useState<string | null>(null);
const {
last_at,
online_users,
status: serverStatus,
} = status || {
online_users: [],
status: {
cpu: 0,
mem: 0,
disk: 0,
updated_at: 0,
},
last_at: 0,
const { online, cpu, mem, disk, updated_at } = status || {
online: {},
cpu: 0,
mem: 0,
disk: 0,
updated_at: 0,
};
const isOnline = last_at > 0;
const isOnline = updated_at > 0;
const badgeVariant = isOnline ? 'default' : 'destructive';
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 (
<TooltipProvider>
@@ -52,45 +54,56 @@ export function NodeStatusCell({ status }: { status: API.NodeStatus }) {
<div className='flex flex-col space-y-1'>
<div className='flex justify-between'>
<span>CPU</span>
<span>{formatPercentage(serverStatus?.cpu ?? 0)}</span>
<span>{formatPercentage(cpu ?? 0)}</span>
</div>
<Progress value={serverStatus?.cpu ?? 0} className='h-2' max={100} />
<Progress value={cpu ?? 0} className='h-2' max={100} />
</div>
<div className='flex flex-col space-y-1'>
<div className='flex justify-between'>
<span>{t('memory')}</span>
<span>{formatPercentage(serverStatus?.mem ?? 0)}</span>
<span>{formatPercentage(mem ?? 0)}</span>
</div>
<Progress value={serverStatus?.mem ?? 0} className='h-2' max={100} />
<Progress value={mem ?? 0} className='h-2' max={100} />
</div>
<div className='flex flex-col space-y-1'>
<div className='flex justify-between'>
<span>{t('disk')}</span>
<span>{formatPercentage(serverStatus?.disk ?? 0)}</span>
<span>{formatPercentage(disk ?? 0)}</span>
</div>
<Progress value={serverStatus?.disk ?? 0} className='h-2' max={100} />
<Progress value={disk ?? 0} className='h-2' max={100} />
</div>
{isOnline && (
<div>
{t('lastUpdated')}: {formatDate(serverStatus?.updated_at ?? 0)}
{t('lastUpdated')}: {formatDate(updated_at ?? 0)}
</div>
)}
</div>
</TooltipTrigger>
{isOnline && onlineCount > 0 && (
<TooltipContent className='bg-muted text-foreground w-80'>
<div className='space-y-4'>
<div className='space-y-2'>
<h4 className='text-sm font-semibold'>{t('onlineUsers')}</h4>
<ScrollArea className='h-[400px] rounded-md border p-2'>
{online_users.map((user, index) => (
<div key={user.uid} className='py-1 text-xs'>
{user.ip} (UID: {user.uid})
</div>
))}
</ScrollArea>
</div>
</div>
<TooltipContent className='bg-card text-foreground w-96'>
<ScrollArea className='h-[540px] rounded-md border px-4 py-2'>
<h4 className='py-1 text-sm font-semibold'>{t('onlineUsers')}</h4>
<Accordion
type='single'
collapsible
className='w-full'
onValueChange={(value) => setOpenItem(value)}
>
{Object.entries(online).map(([uid, ips]) => (
<AccordionItem key={uid} value={uid}>
<AccordionTrigger>{`[UID: ${uid}] - ${ips[0]}`}</AccordionTrigger>
<AccordionContent>
<ul>
{ips.map((ip: string) => (
<li key={ip}>{ip}</li>
))}
</ul>
<UserSubscribeDetail id={Number(uid)} enabled={openItem === uid} />
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</ScrollArea>
</TooltipContent>
)}
</Tooltip>
@@ -73,7 +73,7 @@ export default function NodeTable() {
columns={[
{
accessorKey: 'id',
header: 'ID',
header: t('id'),
cell: ({ row }) => (
<TooltipProvider>
<Tooltip>
@@ -87,6 +87,7 @@ export default function NodeTable() {
'bg-yellow-500': row.original.protocol === 'trojan',
'bg-purple-500': row.original.protocol === 'hysteria2',
'bg-cyan-500': row.original.protocol === 'tuic',
'bg-gray-500': row.original.protocol === 'anytls',
})}
>
{row.getValue('id')}
@@ -159,7 +160,7 @@ export default function NodeTable() {
header: t('nodeGroup'),
cell: ({ row }) => {
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>
) : (
'--'
t('noData')
);
},
},
@@ -272,17 +273,17 @@ export default function NodeTable() {
<ConfirmButton
key='delete'
trigger={<Button variant='destructive'>{t('delete')}</Button>}
title={t('group.confirmDelete')}
description={t('group.deleteWarning')}
title={t('confirmDelete')}
description={t('deleteWarning')}
onConfirm={async () => {
await batchDeleteNode({
ids: rows.map((item) => item.id),
});
toast.success(t('group.deleteSuccess'));
toast.success(t('deleteSuccess'));
ref.current?.refresh();
}}
cancelText={t('group.cancel')}
confirmText={t('group.confirm')}
cancelText={t('cancel')}
confirmText={t('confirm')}
/>,
];
},
@@ -2,7 +2,6 @@ import { getTranslations } from 'next-intl/server';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import SubscribeApp from './app/table';
import GroupTable from './group/table';
import SubscribeConfig from './subscribe-config';
import SubscribeTable from './subscribe-table';
@@ -16,7 +15,6 @@ export default async function Page() {
<TabsTrigger value='subscribe'>{t('tabs.subscribe')}</TabsTrigger>
<TabsTrigger value='group'>{t('tabs.subscribeGroup')}</TabsTrigger>
<TabsTrigger value='config'>{t('tabs.subscribeConfig')}</TabsTrigger>
<TabsTrigger value='app'>{t('tabs.subscribeApp')}</TabsTrigger>
</TabsList>
<TabsContent value='subscribe'>
<SubscribeTable />
@@ -27,9 +25,6 @@ export default async function Page() {
<TabsContent value='config'>
<SubscribeConfig />
</TabsContent>
<TabsContent value='app'>
<SubscribeApp />
</TabsContent>
</Tabs>
);
}
@@ -42,7 +42,7 @@ import { evaluateWithPrecision, unitConversion } from '@workspace/ui/utils';
import { CreditCard, Server, Settings } from 'lucide-react';
import { useTranslations } from 'next-intl';
import { assign, shake } from 'radash';
import { useEffect, useState } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';
import { z } from 'zod';
@@ -81,6 +81,7 @@ export default function SubscribeForm<T extends Record<string, any>>({
}: Readonly<SubscribeFormProps<T>>) {
const t = useTranslations('subscribe');
const [open, setOpen] = useState(false);
const updateTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const formSchema = z.object({
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(() => {
form?.reset(
assign(defaultValues, shake(initialValues, (value) => value === null) as Record<string, any>),
);
}, [form, initialValues]);
useEffect(() => {
return () => {
if (updateTimeoutRef.current) {
clearTimeout(updateTimeoutRef.current);
}
};
}, []);
async function handleSubmit(data: { [x: string]: any }) {
const bool = await onSubmit(data as T);
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_price = form.watch('unit_price');
return (
<Sheet open={open} onOpenChange={setOpen}>
@@ -298,6 +399,7 @@ export default function SubscribeForm<T extends Record<string, any>>({
<EnhancedInput
placeholder={t('form.noLimit')}
type='number'
step={1}
{...field}
onValueChange={(value) => {
form.setValue(field.name, value);
@@ -321,7 +423,8 @@ export default function SubscribeForm<T extends Record<string, any>>({
<EnhancedInput
placeholder={t('form.noLimit')}
type='number'
value={field.value === -1 ? 0 : field.value}
step={1}
value={field.value}
min={0}
onValueChange={(value) => {
form.setValue(field.name, value);
@@ -343,6 +446,7 @@ export default function SubscribeForm<T extends Record<string, any>>({
<EnhancedInput
placeholder={t('form.noLimit')}
type='number'
step={1}
{...field}
onValueChange={(value) => {
form.setValue(field.name, value);
@@ -540,53 +644,75 @@ export default function SubscribeForm<T extends Record<string, any>>({
<FormItem>
<FormLabel>{t('form.discount')}</FormLabel>
<FormControl>
<ArrayInput<API.SubscribeDiscount>
<ArrayInput<API.SubscribeDiscount & { price?: number }>
fields={[
{
name: 'quantity',
type: 'number',
step: 1,
min: 1,
suffix: unit_time && t(`form.${unit_time}`),
},
{
name: 'discount',
type: 'number',
min: 1,
min: 0.01,
max: 100,
step: 0.01,
placeholder: t('form.discountPercent'),
suffix: '%',
calculateValue: function (data) {
const { unit_price } = form.getValues();
return {
...data,
price: evaluateWithPrecision(
`${unit_price} * ${data.quantity} * ${data.discount} / 100`,
),
};
},
},
{
name: 'price',
placeholder: t('form.discount_price'),
type: 'number',
min: 0,
step: 0.01,
formatInput: (value) => unitConversion('centsToDollars', 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}
onChange={(value) => {
form.setValue(field.name, value);
onChange={(
newValues: (API.SubscribeDiscount & { price?: number })[],
) => {
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>
+48 -2
View File
@@ -5,18 +5,21 @@ import { useQuery } from '@tanstack/react-query';
import { Label } from '@workspace/ui/components/label';
import { Table, TableBody, TableCell, TableRow } from '@workspace/ui/components/table';
import { Textarea } from '@workspace/ui/components/textarea';
import { JSONEditor } from '@workspace/ui/custom-components/editor';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import { UploadImage } from '@workspace/ui/custom-components/upload-image';
import { useTranslations } from 'next-intl';
import { useRef } from 'react';
import { toast } from 'sonner';
export default function Site() {
const t = useTranslations('system.site');
const ref = useRef<API.SiteConfig | undefined>(undefined);
const { data, refetch } = useQuery({
queryKey: ['getSiteConfig'],
queryFn: async () => {
const { data } = await getSiteConfig();
ref.current = data.data;
return data.data;
},
});
@@ -25,7 +28,7 @@ export default function Site() {
if (data?.[key] === value) return;
try {
await updateSiteConfig({
...data,
...ref.current,
[key]: value,
} as API.SiteConfig);
toast.success(t('saveSuccess'));
@@ -130,6 +133,49 @@ export default function Site() {
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('customData')}</Label>
<p className='text-muted-foreground text-xs'>{t('customDataDescription')}</p>
</TableCell>
<TableCell className='w-1/2 text-right'>
<JSONEditor
schema={{
type: 'object',
additionalProperties: true,
properties: {
website: { type: 'string', title: 'Website' },
contacts: {
type: 'object',
title: 'Contacts',
additionalProperties: true,
properties: {
email: { type: 'string', title: 'Email' },
telephone: { type: 'string', title: 'Telephone' },
address: { type: 'string', title: 'Address' },
},
},
community: {
type: 'object',
title: 'Community',
additionalProperties: true,
properties: {
telegram: { type: 'string', title: 'Telegram' },
twitter: { type: 'string', title: 'Twitter' },
discord: { type: 'string', title: 'Discord' },
instagram: { type: 'string', title: 'Instagram' },
linkedin: { type: 'string', title: 'Linkedin' },
facebook: { type: 'string', title: 'Facebook' },
github: { type: 'string', title: 'Github' },
},
},
},
}}
value={data?.custom_data}
onBlur={(value) => updateConfig('custom_data', value)}
/>
</TableCell>
</TableRow>
</TableBody>
</Table>
);
+183 -22
View File
@@ -1,6 +1,6 @@
'use client';
import { getSystemLog, restartSystem } from '@/services/admin/tool';
import { getSystemLog, getVersion, restartSystem } from '@/services/admin/tool';
import { useQuery } from '@tanstack/react-query';
import {
Accordion,
@@ -10,7 +10,6 @@ import {
} from '@workspace/ui/components/accordion';
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
@@ -30,8 +29,10 @@ import {
} from '@workspace/ui/components/card';
import { ScrollArea } from '@workspace/ui/components/scroll-area';
import { Icon } from '@workspace/ui/custom-components/icon';
import { formatDate } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl';
import { useState } from 'react';
import packageJson from '../../../../../package.json';
const getLogLevelColor = (level: string) => {
const colorMap: { [key: string]: string } = {
@@ -59,6 +60,91 @@ export default function Page() {
const [openRestart, setOpenRestart] = 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 (
<Card className='border-none'>
<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>
</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'>
<AlertDialog>
{/* <AlertDialog>
<AlertDialogTrigger asChild>
<Button>{t('systemUpgrade')}</Button>
</AlertDialogTrigger>
@@ -81,7 +167,7 @@ export default function Page() {
<AlertDialogAction>{t('confirmUpgrade')}</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</AlertDialog> */}
<AlertDialog open={openRestart} onOpenChange={setOpenRestart}>
<AlertDialogTrigger asChild>
<Button variant='destructive'>{t('systemReboot')}</Button>
@@ -112,13 +198,88 @@ export default function Page() {
</div>
</CardHeader>
<CardContent>
<div className='space-y-6'>
<div className='flex items-center justify-between'>
<div className='text-lg font-semibold'>
{t('currentVersion')} <span>V1.0.0</span>
<div className='space-y-4'>
{/* чЙИцЬмф┐бцБпч┤зхЗСцШ╛чд║ */}
<div className='flex flex-col space-y-2 sm:flex-row sm:space-x-3 sm:space-y-0'>
{/* чФицИ╖члп/чобчРЖчлпчЙИцЬм */}
<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 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>
<Card className='overflow-hidden'>
@@ -146,20 +307,20 @@ export default function Page() {
<AccordionItem key={index} value={`item-${index}`} className='px-4'>
<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'>
<Badge
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>
<span className='text-xs font-medium sm:text-sm'>{log.timestamp}</span>
</div>
</AccordionTrigger>
<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>{log.ip}</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='font-medium'>{t('userAgent')}:</div>
<div className='break-all'>{log['user-agent']}</div>
</div>
</div> */}
</AccordionContent>
</AccordionItem>
))}
@@ -45,6 +45,9 @@ const formSchema = z.object({
speed_limit: z.number().optional(),
device_limit: z.number().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) {
+55 -4
View File
@@ -2,7 +2,9 @@
import { Display } from '@/components/display';
import { ProTable, ProTableActions } from '@/components/pro-table';
import { getSubscribeList } from '@/services/admin/subscribe';
import { createUser, deleteUser, getUserList, updateUserBasicInfo } from '@/services/admin/user';
import { useQuery } from '@tanstack/react-query';
import { Badge } from '@workspace/ui/components/badge';
import { Button } from '@workspace/ui/components/button';
import { Switch } from '@workspace/ui/components/switch';
@@ -20,8 +22,19 @@ export default function Page() {
const [loading, setLoading] = useState(false);
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 (
<ProTable<API.User, Record<string, unknown>>
<ProTable<API.User, API.GetUserListParams>
action={ref}
header={{
title: t('userList'),
@@ -58,8 +71,21 @@ export default function Page() {
<Switch
defaultChecked={row.getValue('enable')}
onCheckedChange={async (checked) => {
const {
auth_methods,
user_devices,
enable_balance_notify,
enable_login_notify,
enable_subscribe_notify,
enable_trade_notify,
updated_at,
created_at,
id,
...rest
} = row.original;
await updateUserBasicInfo({
...row.original,
user_id: id,
...rest,
enable: checked,
} as unknown as API.UpdateUserBasiceInfoRequest);
toast.success(t('updateSuccess'));
@@ -119,13 +145,38 @@ export default function Page() {
cell: ({ row }) => formatDate(row.getValue('created_at')),
},
]}
request={async (pagination) => {
const { data } = await getUserList(pagination);
request={async (pagination, filter) => {
const { data } = await getUserList({
...pagination,
...filter,
});
return {
list: data.data?.list || [],
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={{
render: (row) => {
return [
+108 -2
View File
@@ -1,15 +1,121 @@
'use client';
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 { Button } from '@workspace/ui/components/button';
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 Link from 'next/link';
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 }) {
const t = useTranslations('user');
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 { PublicEnvScript } from 'next-runtime-env';
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 NextTopLoader from 'nextjs-toploader';
import React from 'react';
const fontSans = Geist({
subsets: ['latin'],
variable: '--font-sans',
});
// const fontSans = Geist({
// subsets: ['latin'],
// variable: '--font-sans',
// });
const fontMono = Geist_Mono({
subsets: ['latin'],
variable: '--font-mono',
});
// const fontMono = Geist_Mono({
// subsets: ['latin'],
// variable: '--font-mono',
// });
export async function generateMetadata(): Promise<Metadata> {
noStore();
@@ -111,7 +111,8 @@ export default async function RootLayout({
</head>
<body
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}>
<NextTopLoader showSpinner={false} />
+17 -12
View File
@@ -1,5 +1,6 @@
'use client';
import { UserSubscribeDetail } from '@/app/dashboard/user/user-detail';
import { queryServerTotalData, queryTicketWaitReply } from '@/services/admin/console';
import { useQuery } from '@tanstack/react-query';
import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card';
@@ -11,6 +12,7 @@ import {
SelectTrigger,
SelectValue,
} from '@workspace/ui/components/select';
import { Separator } from '@workspace/ui/components/separator';
import { Tabs, TabsList, TabsTrigger } from '@workspace/ui/components/tabs';
import { Icon } from '@workspace/ui/custom-components/icon';
import { formatBytes } from '@workspace/ui/utils';
@@ -59,15 +61,13 @@ export default function Statistics() {
users: {
today:
ServerTotal?.user_traffic_ranking_today?.map((item) => ({
name: item.user_id,
name: item.sid,
traffic: item.download + item.upload,
email: item.email,
})) || [],
yesterday:
ServerTotal?.user_traffic_ranking_yesterday?.map((item) => ({
name: item.user_id,
name: item.sid,
traffic: item.download + item.upload,
email: item.email,
})) || [],
},
};
@@ -175,10 +175,6 @@ export default function Statistics() {
label: t('type'),
color: 'hsl(var(--muted))',
},
email: {
label: t('email'),
color: 'hsl(var(--muted))',
},
label: {
color: 'hsl(var(--foreground))',
},
@@ -204,13 +200,22 @@ export default function Statistics() {
tickFormatter={(value, index) => String(index + 1)}
/>
<ChartTooltip
trigger='hover'
content={
<ChartTooltipContent
label={true}
labelFormatter={(label) =>
dataType === 'nodes'
? `${t('nodes')}: ${label}`
: `${t('users')}: ${label}`
labelFormatter={(label, [payload]) =>
dataType === 'nodes' ? (
`${t('nodes')}: ${label}`
) : (
<>
<div className='w-80'>
<UserSubscribeDetail id={payload?.payload.name} enabled={true} />
</div>
<Separator className='my-2' />
<div>{`${t('users')}: ${label}`}</div>
</>
)
}
formatter={(value) => {
return formatBytes(Number(value) || 0);
+15 -5
View File
@@ -81,16 +81,26 @@ export const navs = [
url: '/dashboard/server',
icon: 'flat-color-icons:data-protection',
},
],
},
{
title: 'Finance',
items: [
{
title: 'Application Management',
url: '/dashboard/application',
icon: 'flat-color-icons:touchscreen-smartphone',
},
{
title: 'Rule Management',
url: '/dashboard/rules',
icon: 'flat-color-icons:ruler',
},
{
title: 'Subscribe Management',
url: '/dashboard/subscribe',
icon: 'flat-color-icons:shop',
},
],
},
{
title: 'Finance',
items: [
{
title: 'Order Management',
url: '/dashboard/order',
+1
View File
@@ -16,6 +16,7 @@ export const useGlobalStore = create<GlobalStore>((set) => ({
site_logo: '',
keywords: '',
custom_html: '',
custom_data: '',
},
verify: {
turnstile_site_key: '',
+1 -1
View File
@@ -28,7 +28,7 @@
"email": "Zadejte platnou e-mailovou adresu.",
"existingAccount": "Ji┼╛ m├бte ├║─Нet?",
"get": "Z├нskat",
"invite": "Pozv├бnkov├╜ k├│d",
"invite": "Pozv├бnkov├╜ k├│d (voliteln├й)",
"message": "#### V├б┼╛en├╜ u┼╛ivateli,\n\nD─Ыkujeme za v├б┼б z├бjem a podporu. V d┼пsledku ├║pravy provozn├н strategie jsme uzav┼Щeli registraci nov├╜ch u┼╛ivatel┼п. B─Ыhem t├йto doby nebude pou┼╛├нv├бn├н st├бvaj├нc├нch ├║─Нt┼п nijak ovlivn─Ыno.\n\nSna┼╛├нme se v├бm poskytnout lep┼б├н slu┼╛by a z├б┼╛itky, a proto b─Ыhem uzav┼Щen├н registrace provedeme komplexn├н optimalizaci syst├йmu a aktualizaci funkc├н. V budoucnu v├бs p┼Щiv├нt├бme s kvalitn─Ыj┼б├нm obsahem a slu┼╛bami.\n\nSledujte na┼бe webov├й str├бnky a soci├бln├н m├йdia pro nejnov─Ыj┼б├н aktualizace a ozn├бmen├н. D─Ыkujeme za va┼бe pochopen├н a podporu.\n\nPokud m├бte jak├йkoli dotazy nebo pot┼Щebujete pomoc, nev├бhejte kontaktovat n├б┼б z├бkaznick├╜ servis.\n\n**Je┼бt─Ы jednou d─Ыkujeme za va┼бi podporu a pochopen├н.**",
"passwordMismatch": "Hesla se neshoduj├н",
"success": "Registrace ├║sp─Ы┼бn├б, automaticky p┼Щihl├б┼бeno!",
+2
View File
@@ -39,6 +39,8 @@
"status": "Stav",
"subject": "P┼Щedm─Ыt",
"template": "┼аablona",
"traffic_exceed_email_template": "┼аablona ozn├бmen├н o p┼Щekro─Нen├н provozu",
"traffic_exceed_email_templateDescription": "Z├бstupn├й symboly {after}.variable{before} budou nahrazeny skute─Нn├╜mi daty. Ujist─Ыte se, ┼╛e tyto prom─Ыnn├й zachov├бte.",
"verify_email_template": "┼аablona ov─Ы┼Щovac├нho e-mailu",
"verify_email_templateDescription": "Z├бstupn├й symboly {after}.variable{before} budou nahrazeny skute─Нn├╜mi daty. Ujist─Ыte se, ┼╛e tyto prom─Ыnn├й zachov├бte.",
"whitelistSuffixes": "Povolen├й p┼Щ├нpony",
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "Konfigurace ADS",
"Announcement Management": "Spr├бva ozn├бmen├н",
"Apple": "Apple ID",
"Application Management": "Spr├бva aplikac├н",
"Auth Control": "┼Ш├нzen├н ov─Ы┼Щov├бn├н",
"Coupon Management": "Spr├бva kup├│n┼п",
"Dashboard": "P┼Щ├нstrojov├б deska",
@@ -16,6 +17,7 @@
"Order Management": "Spr├бva objedn├бvek",
"Payment Config": "Konfigurace platby",
"Phone Number": "Telefonn├н ─Н├нslo",
"Rule Management": "Spr├бva pravidel",
"Server": "Server",
"Server Management": "Spr├бva serveru",
"Settings": "Nastaven├н",
-1
View File
@@ -22,7 +22,6 @@
"description": "Popis",
"descriptionPlaceholder": "Zadejte popis platebn├н metody",
"domain": "Dom├йna",
"domainPlaceholder": "voliteln├й, nap┼Щ. {example}",
"edit": "Upravit",
"editPayment": "Upravit platebn├н metodu",
"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"
}
+2
View File
@@ -13,6 +13,8 @@
"title": "Z├бsady ochrany osobn├нch ├║daj┼п"
},
"site": {
"customData": "Vlastn├н data",
"customDataDescription": "Vlastn├н data, pou┼╛├нvan├б pro vlastn├н data webu",
"customHtml": "Vlastn├н HTML",
"customHtmlDescription": "Vlastn├н HTML k├│d, kter├╜ bude vlo┼╛en na konec tagu body na str├бnce.",
"keywords": "Kl├н─Нov├б slova",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "Potvrdit aktualizaci syst├йmu",
"confirmUpgrade": "Potvrdit aktualizaci",
"currentVersion": "Aktu├бln├н verze syst├йmu:",
"developmentVersion": "V├╜vojov├б verze",
"errors": "Chyby",
"ip": "IP",
"ip": "IP adresa",
"lastUpdated": "Posledn├н aktualizace:",
"newVersionAvailable": "Nov├б verze",
"none": "┼╜├бdn├╜",
"query": "Dotaz",
"rebootDescription": "Opravdu chcete restartovat syst├йm? Tato akce zp┼пsob├н kr├бtk├й p┼Щeru┼бen├н slu┼╛by.",
"rebooting": "Syst├йm se restartuje...",
"refreshLogs": "Obnovit protokoly",
"request": "┼╜├бdost",
"serverVersion": "Server",
"status": "Stav",
"systemLogs": "Syst├йmov├й protokoly",
"systemReboot": "Restart syst├йmu",
@@ -22,5 +25,8 @@
"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├н.",
"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",
"actions": "akce",
"active": "Aktivn├н",
"add": "P┼Щidat",
"administrator": "Administr├бtor",
"areaCode": "Sm─Ыrov├╜ k├│d",
@@ -41,10 +42,12 @@
"email": "e-mail",
"enable": "Povolit",
"expireTime": "─Мas vypr┼бen├н",
"expired": "Vypr┼бelo",
"expiredAt": "Platnost vypr┼бela",
"failed": "Ne├║sp─Ыch",
"giftAmount": "─М├бstka d├бrku",
"giftAmountPlaceholder": "Zadejte ─Н├бstku d├бrku",
"inactive": "Neaktivn├н",
"invalidEmailFormat": "Neplatn├╜ form├бt e-mailu",
"inviteCode": "Pozv├бnkov├╜ k├│d",
"inviteCodePlaceholder": "Zadejte k├│d pozv├бnky (ponechte pr├бzdn├й pro vygenerov├бn├н)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "Zadejte nov├й heslo (voliteln├й)",
"permanent": "Trval├╜",
"pleaseEnterEmail": "Pros├нm, zadejte e-mail",
"price": "Cena",
"referer": "Doporu─Нitel",
"refererId": "ID doporu─Нitele",
"refererIdPlaceholder": "Zadejte ID doporu─Нitele",
@@ -74,8 +78,12 @@
"searchIp": "Vyhledat IP adresu",
"selectAuthType": "Vyberte typ ov─Ы┼Щen├н",
"speedLimit": "Rychlostn├н limit",
"startTime": "─Мas zah├бjen├н",
"status": "Stav",
"subscription": "P┼Щedplatn├й",
"subscriptionDetails": "Podrobnosti o p┼Щedplatn├йm",
"subscriptionId": "ID p┼Щedplatn├йho",
"subscriptionInfo": "Informace o p┼Щedplatn├йm",
"subscriptionList": "Seznam p┼Щedplatn├╜ch",
"subscriptionLogs": "Z├бznamy o p┼Щedplatn├йm",
"subscriptionName": "N├бzev p┼Щedplatn├йho",
@@ -89,6 +97,8 @@
"tradeNotifications": "Obchodn├н ozn├бmen├н",
"trafficLimit": "Limit provozu",
"trafficLogs": "Protokoly provozu",
"trafficUsage": "Vyu┼╛it├н dat",
"unknown": "Nezn├бm├й",
"unlimited": "Neomezen├╜",
"unverified": "Neov─Ы┼Щeno",
"update": "Aktualizovat",
@@ -98,11 +108,15 @@
"userAgent": "U┼╛ivatelsk├╜ agent",
"userEmail": "U┼╛ivatelsk├╜ e-mail",
"userEmailPlaceholder": "Zadejte e-mail u┼╛ivatele",
"userId": "ID u┼╛ivatele",
"userInfo": "Informace o u┼╛ivateli",
"userList": "Seznam u┼╛ivatel┼п",
"userLogs": "Historie p┼Щihl├б┼бen├н",
"userName": "Identifik├бtor u┼╛ivatele",
"userOrders": "Objedn├бvky",
"userProfile": "Profil",
"userSubscriptions": "P┼Щedplatn├й",
"verified": "Ov─Ы┼Щeno"
"username": "U┼╛ivatelsk├й jm├йno",
"verified": "Ov─Ы┼Щeno",
"viewDetails": "Zobrazit podrobnosti"
}
+1 -1
View File
@@ -28,7 +28,7 @@
"email": "Bitte geben Sie eine g├╝ltige E-Mail-Adresse ein.",
"existingAccount": "Bereits ein Konto?",
"get": "Erhalten",
"invite": "Einladungscode",
"invite": "Einladungscode (optional)",
"message": "#### Sehr geehrter Nutzer,\n\nVielen Dank f├╝r Ihr Interesse und Ihre Unterst├╝tzung. Aufgrund einer Anpassung unserer Betriebsstrategie haben wir die Registrierung f├╝r neue Nutzer geschlossen. W├дhrend dieser Zeit wird die Nutzung f├╝r bestehende Nutzer nicht beeintr├дchtigt.\n\nWir sind bestrebt, Ihnen einen besseren Service und ein besseres Erlebnis zu bieten, und werden daher w├дhrend der Schlie├Яung der Registrierung umfassende Systemoptimierungen und Funktionsupgrades durchf├╝hren. In Zukunft werden wir Sie mit hochwertigeren Inhalten und Dienstleistungen willkommen hei├Яen.\n\nBitte folgen Sie unserer Website und unseren Social-Media-Plattformen, um die neuesten Updates und Benachrichtigungen zu erhalten. Vielen Dank f├╝r Ihr Verst├дndnis und Ihre Unterst├╝tzung.\n\nBei Fragen oder wenn Sie Hilfe ben├╢tigen, kontaktieren Sie bitte jederzeit unser Kundenserviceteam.\n\n**Nochmals vielen Dank f├╝r Ihre Unterst├╝tzung und Ihr Verst├дndnis.**",
"passwordMismatch": "Die eingegebenen Passw├╢rter stimmen nicht ├╝berein",
"success": "Registrierung erfolgreich, Sie sind automatisch eingeloggt!",
+2
View File
@@ -39,6 +39,8 @@
"status": "Status",
"subject": "Betreff",
"template": "Vorlage",
"traffic_exceed_email_template": "Benachrichtigung ├╝ber ├╝berschreitenden Verkehr",
"traffic_exceed_email_templateDescription": "Die Platzhalter {after}.variable{before} werden durch tats├дchliche Daten ersetzt. Stellen Sie sicher, dass Sie diese Variablen beibehalten.",
"verify_email_template": "E-Mail-Best├дtigungsvorlage",
"verify_email_templateDescription": "Die Platzhalter {after}.variable{before} werden durch tats├дchliche Daten ersetzt. Stellen Sie sicher, dass diese Variablen beibehalten werden.",
"whitelistSuffixes": "Whitelist-Suffixe",
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "ADS-Konfiguration",
"Announcement Management": "Ank├╝ndigungsverwaltung",
"Apple": "Apple-ID",
"Application Management": "Anwendungsverwaltung",
"Auth Control": "Authentifizierungskontrolle",
"Coupon Management": "Gutscheinverwaltung",
"Dashboard": "Armaturenbrett",
@@ -16,6 +17,7 @@
"Order Management": "Bestellverwaltung",
"Payment Config": "Zahlungskonfiguration",
"Phone Number": "Telefonnummer",
"Rule Management": "Regelverwaltung",
"Server": "Dienst",
"Server Management": "Serververwaltung",
"Settings": "Einstellungen",
-1
View File
@@ -22,7 +22,6 @@
"description": "Beschreibung",
"descriptionPlaceholder": "Geben Sie die Beschreibung der Zahlungsmethode ein",
"domain": "Domain",
"domainPlaceholder": "optional, z.B. {example}",
"edit": "Bearbeiten",
"editPayment": "Zahlungsmethode bearbeiten",
"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"
}
+2
View File
@@ -13,6 +13,8 @@
"title": "Datenschutzrichtlinie"
},
"site": {
"customData": "Benutzerdefinierte Daten",
"customDataDescription": "Benutzerdefinierte Daten, die f├╝r benutzerdefinierte Daten der Website verwendet werden",
"customHtml": "Benutzerdefiniertes HTML",
"customHtmlDescription": "Benutzerdefinierter HTML-Code, der am Ende des body-Tags der Seite eingef├╝gt werden soll.",
"keywords": "Schl├╝sselw├╢rter",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "Systemaktualisierung best├дtigen",
"confirmUpgrade": "Upgrade best├дtigen",
"currentVersion": "Aktuelle Systemversion:",
"developmentVersion": "Entwicklungsversion",
"errors": "Fehler",
"ip": "IP",
"ip": "IP-Adresse",
"lastUpdated": "Zuletzt aktualisiert:",
"newVersionAvailable": "Neue Version",
"none": "Keine",
"query": "Abfrage",
"rebootDescription": "M├╢chten Sie das System wirklich neu starten? Dieser Vorgang f├╝hrt zu einer kurzen Unterbrechung des Dienstes.",
"rebooting": "System wird neu gestartet...",
"refreshLogs": "Protokolle aktualisieren",
"request": "Anfrage",
"serverVersion": "Server",
"status": "Status",
"systemLogs": "Systemprotokolle",
"systemReboot": "Systemneustart",
@@ -22,5 +25,8 @@
"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.",
"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",
"actions": "Aktionen",
"active": "Aktiv",
"add": "Hinzuf├╝gen",
"administrator": "Administrator",
"areaCode": "Vorwahl",
@@ -41,10 +42,12 @@
"email": "E-Mail",
"enable": "Aktivieren",
"expireTime": "Ablaufzeit",
"expired": "Abgelaufen",
"expiredAt": "Abgelaufen am",
"failed": "Fehlgeschlagen",
"giftAmount": "Geschenkbetrag",
"giftAmountPlaceholder": "Geben Sie den Geschenkbetrag ein",
"inactive": "Inaktiv",
"invalidEmailFormat": "Ung├╝ltiges E-Mail-Format",
"inviteCode": "Einladungscode",
"inviteCodePlaceholder": "Einladungscode eingeben (leer lassen, um zu generieren)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "Neues Passwort eingeben (optional)",
"permanent": "Dauerhaft",
"pleaseEnterEmail": "Bitte E-Mail eingeben",
"price": "Preis",
"referer": "Empfehler",
"refererId": "Referenz-ID",
"refererIdPlaceholder": "Geben Sie die Referenz-ID ein",
@@ -74,8 +78,12 @@
"searchIp": "IP-Adresse suchen",
"selectAuthType": "Authentifizierungstyp ausw├дhlen",
"speedLimit": "Geschwindigkeitsbegrenzung",
"startTime": "Startzeit",
"status": "Status",
"subscription": "Abonnement",
"subscriptionDetails": "Abonnementdetails",
"subscriptionId": "Abonnement-ID",
"subscriptionInfo": "Abonnement-Informationen",
"subscriptionList": "Abonnementsliste",
"subscriptionLogs": "Abonnementprotokolle",
"subscriptionName": "Abonnementname",
@@ -89,6 +97,8 @@
"tradeNotifications": "Handelsbenachrichtigungen",
"trafficLimit": "Verkehrslimit",
"trafficLogs": "Verkehrsprotokolle",
"trafficUsage": "Datenverbrauch",
"unknown": "Unbekannt",
"unlimited": "Unbegrenzt",
"unverified": "Unbest├дtigt",
"update": "Aktualisieren",
@@ -98,11 +108,15 @@
"userAgent": "Benutzeragent",
"userEmail": "Benutzer-E-Mail",
"userEmailPlaceholder": "Benutzer-E-Mail eingeben",
"userId": "Benutzer-ID",
"userInfo": "Benutzerinformationen",
"userList": "Benutzerliste",
"userLogs": "Anmeldeverlauf",
"userName": "Benutzerkennung",
"userOrders": "Bestellungen",
"userProfile": "Profil",
"userSubscriptions": "Abonnements",
"verified": "Verifiziert"
"username": "Benutzername",
"verified": "Verifiziert",
"viewDetails": "Details anzeigen"
}
+1 -1
View File
@@ -28,7 +28,7 @@
"email": "Please enter a valid email address.",
"existingAccount": "Already have an account?",
"get": "Get",
"invite": "Invitation code",
"invite": "Invitation code (optional)",
"message": "#### Dear User, Hello!\n\nThank you for your attention and support. Due to adjustments in site operation strategy, we have closed the new user registration function. During this period, existing users will not be affected.\n\nWe are committed to providing you with better service and experience, so we will conduct comprehensive system optimization and feature upgrades during the registration closure. In the future, we will welcome you with better content and services.\n\nPlease follow our website and social media platforms to get the latest updates and notifications. Thank you for your understanding and support.\n\nIf you have any questions or need assistance, please feel free to contact our customer service team.\n\n**Thank you again for your support and understanding.**",
"passwordMismatch": "Passwords do not match",
"success": "Registration successful, automatically logged in!",
+2
View File
@@ -39,6 +39,8 @@
"status": "Status",
"subject": "Subject",
"template": "Template",
"traffic_exceed_email_template": "Traffic Exceed Notice Template",
"traffic_exceed_email_templateDescription": "The {after}.variable{before} placeholders will be replaced with actual data. Ensure to keep these variables.",
"verify_email_template": "Verification Email Template",
"verify_email_templateDescription": "The {after}.variable{before} placeholders will be replaced with actual data. Ensure to keep these variables.",
"whitelistSuffixes": "Whitelist Suffixes",
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "ADS Config",
"Announcement Management": "Announcement Management",
"Apple": "Apple ID",
"Application Management": "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": "Rule Management",
"Server": "Server",
"Server Management": "Server Management",
"Settings": "Settings",
-1
View File
@@ -22,7 +22,6 @@
"description": "Description",
"descriptionPlaceholder": "Enter payment method description",
"domain": "Domain",
"domainPlaceholder": "optional, e.g. {example}",
"edit": "Edit",
"editPayment": "Edit Payment Method",
"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",
"editNode": "Edit Node",
"enable": "Enable",
"id": "ID",
"form": {
"allowInsecure": "Allow Insecure",
"cancel": "Cancel",
"city": "City",
"confirm": "Confirm",
"congestionController": "Congestion Controller",
"country": "Country",
"disableSni": "Disable SNI",
"edit": "Edit",
"editSecurity": "Edit Security Configuration",
"enableTLS": "Enable TLS",
"encryptionMethod": "Encryption Method",
"fingerprint": "Fingerprint",
"flow": "Flow Control Algorithm",
"groupId": "Node Group",
"hopInterval": "Hop Interval",
@@ -85,6 +89,7 @@
"pleaseSelect": "Please Select",
"port": "Server Port",
"protocol": "Protocol",
"reduceRtt": "Reduce RTT",
"relayHost": "Relay Host",
"relayMode": "Relay Mode",
"relayModeOptions": {
@@ -128,6 +133,7 @@
"transport": "Transport Protocol Configuration",
"transportConfig": "Transport Protocol Configuration",
"transportHost": "Transport Server Address",
"udpRelayMode": "UDP Relay Mode",
"transportPath": "Transport Path",
"transportServerName": "Transport Server Name"
},
@@ -136,6 +142,7 @@
"name": "Name",
"node": "Node",
"nodeGroup": "Node Group",
"noData": "--",
"normal": "Normal",
"onlineCount": "Online users",
"onlineUsers": "Online Users",
+2
View File
@@ -13,6 +13,8 @@
"title": "Privacy Policy"
},
"site": {
"customData": "Custom Data",
"customDataDescription": "Custom Data, used for custom data of the site",
"customHtml": "Custom HTML",
"customHtmlDescription": "Custom HTML code to be injected into the bottom of the site's body tag.",
"keywords": "Keywords",
+7 -1
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "Confirm System Upgrade",
"confirmUpgrade": "Confirm Upgrade",
"currentVersion": "Current System Version:",
"developmentVersion": "Dev",
"errors": "Errors",
"ip": "IP",
"lastUpdated": "Last Updated:",
"newVersionAvailable": "New Version",
"none": "None",
"query": "Query",
"rebootDescription": "Are you sure you want to reboot the system? This operation will cause a brief service interruption.",
"rebooting": "Rebooting system...",
"refreshLogs": "Refresh Logs",
"request": "Request",
"serverVersion": "Server",
"status": "Status",
"systemLogs": "System Logs",
"systemReboot": "System Reboot",
@@ -22,5 +25,8 @@
"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.",
"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",
"actions": "Actions",
"active": "Active",
"add": "Add",
"administrator": "Administrator",
"areaCode": "Area Code",
@@ -41,10 +42,12 @@
"email": "Email",
"enable": "Enable",
"expireTime": "Expire Time",
"expired": "Expired",
"expiredAt": "Expired At",
"failed": "Failed",
"giftAmount": "Gift Amount",
"giftAmountPlaceholder": "Enter gift amount",
"inactive": "Inactive",
"invalidEmailFormat": "Invalid email format",
"inviteCode": "Invite Code",
"inviteCodePlaceholder": "Enter invite code (leave blank to generate)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "Enter new password (optional)",
"permanent": "Permanent",
"pleaseEnterEmail": "Please enter email",
"price": "Price",
"referer": "Referer",
"refererId": "Referer ID",
"refererIdPlaceholder": "Enter referer ID",
@@ -74,8 +78,12 @@
"searchIp": "Search IP address",
"selectAuthType": "Select auth type",
"speedLimit": "Speed Limit",
"startTime": "Start Time",
"status": "Status",
"subscription": "Subscription",
"subscriptionDetails": "Subscription Details",
"subscriptionId": "Subscription ID",
"subscriptionInfo": "Subscription Info",
"subscriptionList": "Subscription List",
"subscriptionLogs": "Subscription Logs",
"subscriptionName": "Subscription Name",
@@ -89,6 +97,8 @@
"tradeNotifications": "Trade Notifications",
"trafficLimit": "Traffic Limit",
"trafficLogs": "Traffic Logs",
"trafficUsage": "Traffic Usage",
"unknown": "Unknown",
"unlimited": "Unlimited",
"unverified": "Unverified",
"update": "Update",
@@ -98,11 +108,15 @@
"userAgent": "User Agent",
"userEmail": "User Email",
"userEmailPlaceholder": "Enter user email",
"userId": "User ID",
"userInfo": "User Info",
"userList": "User List",
"userLogs": "Login History",
"userName": "User Identifier",
"userOrders": "Orders",
"userProfile": "Profile",
"userSubscriptions": "Subscriptions",
"verified": "Verified"
"username": "Username",
"verified": "Verified",
"viewDetails": "View Details"
}
+1 -1
View File
@@ -28,7 +28,7 @@
"email": "Por favor, introduce una direcci├│n de correo electr├│nico v├бlida.",
"existingAccount": "┬┐Ya tienes una cuenta?",
"get": "Obtener",
"invite": "C├│digo de invitaci├│n",
"invite": "C├│digo de invitaci├│n (opcional)",
"message": "#### ┬бEstimado usuario!\n\nGracias por su inter├йs y apoyo. Debido a un ajuste en la estrategia de operaci├│n del sitio, hemos cerrado la funci├│n de registro para nuevos usuarios. Durante este per├нodo, el uso por parte de los usuarios existentes no se ver├б afectado.\n\nNos comprometemos a brindarle un mejor servicio y experiencia, por lo que realizaremos una optimizaci├│n completa del sistema y una actualizaci├│n de funciones durante el cierre del registro. En el futuro, le daremos la bienvenida con contenido y servicios de mayor calidad.\n\nPor favor, siga nuestro sitio web y plataformas de redes sociales para obtener las ├║ltimas actualizaciones y notificaciones. Agradecemos su comprensi├│n y apoyo.\n\nSi tiene alguna pregunta o necesita ayuda, no dude en ponerse en contacto con nuestro equipo de atenci├│n al cliente.\n\n**Nuevamente, gracias por su apoyo y comprensi├│n.**",
"passwordMismatch": "Las contrase├▒as no coinciden",
"success": "┬бRegistro exitoso, sesi├│n iniciada autom├бticamente!",
+2
View File
@@ -39,6 +39,8 @@
"status": "Estado",
"subject": "Asunto",
"template": "Plantilla",
"traffic_exceed_email_template": "Plantilla de Notificaci├│n de Exceso de Tr├бfico",
"traffic_exceed_email_templateDescription": "Los marcadores de posici├│n {after}.variable{before} ser├бn reemplazados con datos reales. Aseg├║rate de mantener estas variables.",
"verify_email_template": "Plantilla de Correo Electr├│nico de Verificaci├│n",
"verify_email_templateDescription": "Los marcadores de posici├│n {after}.variable{before} ser├бn reemplazados con datos reales. Aseg├║rese de mantener estas variables.",
"whitelistSuffixes": "Sufijos de la lista blanca",
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "Configuraci├│n de ADS",
"Announcement Management": "Gesti├│n de Anuncios",
"Apple": "ID de Apple",
"Application Management": "Gesti├│n de Aplicaciones",
"Auth Control": "Control de Autenticaci├│n",
"Coupon Management": "Gesti├│n de Cupones",
"Dashboard": "Tablero",
@@ -16,6 +17,7 @@
"Order Management": "Gesti├│n de Pedidos",
"Payment Config": "Configuraci├│n de Pago",
"Phone Number": "N├║mero de Tel├йfono",
"Rule Management": "Gesti├│n de Reglas",
"Server": "Servidor",
"Server Management": "Gesti├│n de Servidores",
"Settings": "Configuraci├│n",
-1
View File
@@ -22,7 +22,6 @@
"description": "Descripci├│n",
"descriptionPlaceholder": "Ingrese la descripci├│n del m├йtodo de pago",
"domain": "Dominio",
"domainPlaceholder": "opcional, p. ej. {example}",
"edit": "Editar",
"editPayment": "Editar M├йtodo de Pago",
"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"
}
+2
View File
@@ -13,6 +13,8 @@
"title": "Pol├нtica de Privacidad"
},
"site": {
"customData": "Datos Personalizados",
"customDataDescription": "Datos Personalizados, utilizados para datos personalizados del sitio",
"customHtml": "HTML personalizado",
"customHtmlDescription": "C├│digo HTML personalizado que se inyectar├б en la parte inferior de la etiqueta body del sitio.",
"keywords": "Palabras clave",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "Confirmar actualizaci├│n del sistema",
"confirmUpgrade": "Confirmar actualizaci├│n",
"currentVersion": "Versi├│n actual del sistema:",
"developmentVersion": "Versi├│n de desarrollo",
"errors": "Errores",
"ip": "IP",
"ip": "Direcci├│n IP",
"lastUpdated": "├Ъltima actualizaci├│n:",
"newVersionAvailable": "Nueva versi├│n",
"none": "Ninguno",
"query": "Consulta",
"rebootDescription": "┬┐Est├б seguro de que desea reiniciar el sistema? Esta acci├│n provocar├б una breve interrupci├│n del servicio.",
"rebooting": "Reiniciando el sistema...",
"refreshLogs": "Actualizar registros",
"request": "Solicitud",
"serverVersion": "Servidor",
"status": "Estado",
"systemLogs": "Registros del sistema",
"systemReboot": "Reinicio del sistema",
@@ -22,5 +25,8 @@
"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.",
"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",
"actions": "acciones",
"active": "Activo",
"add": "Agregar",
"administrator": "Administrador",
"areaCode": "C├│digo de ├Бrea",
@@ -41,10 +42,12 @@
"email": "correo electr├│nico",
"enable": "Habilitar",
"expireTime": "Tiempo de Expiraci├│n",
"expired": "Caducado",
"expiredAt": "Fecha de vencimiento",
"failed": "Fallido",
"giftAmount": "Monto del Regalo",
"giftAmountPlaceholder": "Ingrese el monto del regalo",
"inactive": "Inactivo",
"invalidEmailFormat": "Formato de correo electr├│nico no v├бlido",
"inviteCode": "C├│digo de invitaci├│n",
"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)",
"permanent": "Permanente",
"pleaseEnterEmail": "Por favor, introduce el correo electr├│nico",
"price": "Precio",
"referer": "Recomendador",
"refererId": "ID del Referente",
"refererIdPlaceholder": "Ingrese el ID del referente",
@@ -74,8 +78,12 @@
"searchIp": "Buscar direcci├│n IP",
"selectAuthType": "Seleccionar tipo de autenticaci├│n",
"speedLimit": "L├нmite de Velocidad",
"startTime": "Hora de Inicio",
"status": "Estado",
"subscription": "Suscripci├│n",
"subscriptionDetails": "Detalles de la suscripci├│n",
"subscriptionId": "ID de Suscripci├│n",
"subscriptionInfo": "Informaci├│n de Suscripci├│n",
"subscriptionList": "Lista de Suscripci├│n",
"subscriptionLogs": "Registros de Suscripci├│n",
"subscriptionName": "Nombre de la Suscripci├│n",
@@ -89,6 +97,8 @@
"tradeNotifications": "Notificaciones de Comercio",
"trafficLimit": "L├нmite de Tr├бfico",
"trafficLogs": "Registros de Tr├бfico",
"trafficUsage": "Uso de Tr├бfico",
"unknown": "Desconocido",
"unlimited": "Ilimitado",
"unverified": "No verificado",
"update": "Actualizar",
@@ -98,11 +108,15 @@
"userAgent": "Agente de Usuario",
"userEmail": "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",
"userLogs": "Historial de inicio de sesi├│n",
"userName": "Identificador de Usuario",
"userOrders": "Pedidos",
"userProfile": "Perfil",
"userSubscriptions": "Suscripciones",
"verified": "Verificado"
"username": "Nombre de Usuario",
"verified": "Verificado",
"viewDetails": "Ver Detalles"
}
+1 -1
View File
@@ -28,7 +28,7 @@
"email": "Por favor, ingresa una direcci├│n de correo electr├│nico v├бlida.",
"existingAccount": "┬┐Ya tienes una cuenta?",
"get": "Obtener",
"invite": "C├│digo de invitaci├│n",
"invite": "C├│digo de invitaci├│n (opcional)",
"message": "#### Estimado usuario,\n\nGracias por su inter├йs y apoyo. Debido a un ajuste en la estrategia de operaci├│n del sitio, hemos cerrado la funci├│n de registro para nuevos usuarios. Durante este per├нodo, el uso por parte de los usuarios existentes no se ver├б afectado.\n\nNos comprometemos a ofrecerle un mejor servicio y experiencia, por lo que realizaremos una optimizaci├│n completa del sistema y una actualizaci├│n de funciones durante el cierre del registro. En el futuro, le daremos la bienvenida con contenido y servicios de mayor calidad.\n\nPor favor, siga nuestro sitio web y plataformas de redes sociales para obtener las ├║ltimas actualizaciones y notificaciones. Agradecemos su comprensi├│n y apoyo.\n\nSi tiene alguna pregunta o necesita ayuda, no dude en ponerse en contacto con nuestro equipo de atenci├│n al cliente.\n\n**Nuevamente, gracias por su apoyo y comprensi├│n.**",
"passwordMismatch": "Las contrase├▒as no coinciden",
"success": "┬бRegistro exitoso, has iniciado sesi├│n autom├бticamente!",
+2
View File
@@ -39,6 +39,8 @@
"status": "Estado",
"subject": "Asunto",
"template": "Plantilla",
"traffic_exceed_email_template": "Plantilla de Notificaci├│n de Exceso de Tr├бfico",
"traffic_exceed_email_templateDescription": "Los marcadores de posici├│n {after}.variable{before} ser├бn reemplazados con datos reales. Aseg├║rate de mantener estas variables.",
"verify_email_template": "Plantilla de Correo Electr├│nico de Verificaci├│n",
"verify_email_templateDescription": "Los marcadores de posici├│n {after}.variable{before} ser├бn reemplazados con datos reales. Aseg├║rate de mantener estas variables.",
"whitelistSuffixes": "Sufijos de Lista Blanca",
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "Configuraci├│n de ADS",
"Announcement Management": "Gesti├│n de Anuncios",
"Apple": "ID de Apple",
"Application Management": "Gesti├│n de Aplicaciones",
"Auth Control": "Control de Autenticaci├│n",
"Coupon Management": "Gesti├│n de Cupones",
"Dashboard": "Tablero",
@@ -16,6 +17,7 @@
"Order Management": "Gesti├│n de Pedidos",
"Payment Config": "Configuraci├│n de Pago",
"Phone Number": "N├║mero de Tel├йfono",
"Rule Management": "Gesti├│n de Reglas",
"Server": "Servidor",
"Server Management": "Gesti├│n de Servidores",
"Settings": "Configuraci├│n",
-1
View File
@@ -22,7 +22,6 @@
"description": "Descripci├│n",
"descriptionPlaceholder": "Ingresa la descripci├│n del m├йtodo de pago",
"domain": "Dominio",
"domainPlaceholder": "opcional, p. ej. {example}",
"edit": "Editar",
"editPayment": "Editar M├йtodo de Pago",
"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"
}
+2
View File
@@ -13,6 +13,8 @@
"title": "Pol├нtica de Privacidad"
},
"site": {
"customData": "Datos Personalizados",
"customDataDescription": "Datos Personalizados, utilizados para datos personalizados del sitio",
"customHtml": "HTML personalizado",
"customHtmlDescription": "C├│digo HTML personalizado que se inyectar├б al final de la etiqueta body del sitio.",
"keywords": "Palabras clave",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "Confirmar actualizaci├│n del sistema",
"confirmUpgrade": "Confirmar actualizaci├│n",
"currentVersion": "Versi├│n actual del sistema:",
"developmentVersion": "Versi├│n de desarrollo",
"errors": "Errores",
"ip": "IP",
"ip": "Direcci├│n IP",
"lastUpdated": "├Ъltima actualizaci├│n:",
"newVersionAvailable": "Nueva versi├│n",
"none": "Ninguno",
"query": "Consulta",
"rebootDescription": "┬┐Est├б seguro de que desea reiniciar el sistema? Esta acci├│n provocar├б una breve interrupci├│n del servicio.",
"rebooting": "Reiniciando el sistema...",
"refreshLogs": "Actualizar registros",
"request": "Solicitud",
"serverVersion": "Servidor",
"status": "Estado",
"systemLogs": "Registros del sistema",
"systemReboot": "Reinicio del sistema",
@@ -22,5 +25,8 @@
"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.",
"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",
"actions": "acciones",
"active": "Activo",
"add": "Agregar",
"administrator": "Administrador",
"areaCode": "C├│digo de ├Бrea",
@@ -41,10 +42,12 @@
"email": "correo electr├│nico",
"enable": "Habilitar",
"expireTime": "Tiempo de Expiraci├│n",
"expired": "Expirado",
"expiredAt": "Fecha de vencimiento",
"failed": "Fallido",
"giftAmount": "Monto del Regalo",
"giftAmountPlaceholder": "Ingrese el monto del regalo",
"inactive": "Inactivo",
"invalidEmailFormat": "Formato de correo electr├│nico no v├бlido",
"inviteCode": "C├│digo de Invitaci├│n",
"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)",
"permanent": "Permanente",
"pleaseEnterEmail": "Por favor, ingresa el correo electr├│nico",
"price": "Precio",
"referer": "Recomendador",
"refererId": "ID del Referente",
"refererIdPlaceholder": "Ingrese ID del referente",
@@ -74,8 +78,12 @@
"searchIp": "Buscar direcci├│n IP",
"selectAuthType": "Seleccionar tipo de autenticaci├│n",
"speedLimit": "L├нmite de Velocidad",
"startTime": "Hora de Inicio",
"status": "Estado",
"subscription": "Suscripci├│n",
"subscriptionDetails": "Detalles de la Suscripci├│n",
"subscriptionId": "ID de Suscripci├│n",
"subscriptionInfo": "Informaci├│n de Suscripci├│n",
"subscriptionList": "Lista de Suscripci├│n",
"subscriptionLogs": "Registros de Suscripci├│n",
"subscriptionName": "Nombre de la Suscripci├│n",
@@ -89,6 +97,8 @@
"tradeNotifications": "Notificaciones de Comercio",
"trafficLimit": "L├нmite de Tr├бfico",
"trafficLogs": "Registros de Tr├бfico",
"trafficUsage": "Uso de Tr├бfico",
"unknown": "Desconocido",
"unlimited": "Ilimitado",
"unverified": "No verificado",
"update": "Actualizar",
@@ -98,11 +108,15 @@
"userAgent": "Agente de Usuario",
"userEmail": "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",
"userLogs": "Historial de Inicio de Sesi├│n",
"userName": "Identificador de Usuario",
"userOrders": "Pedidos",
"userProfile": "Perfil",
"userSubscriptions": "Suscripciones",
"verified": "Verificado"
"username": "Nombre de Usuario",
"verified": "Verificado",
"viewDetails": "Ver Detalles"
}
+1 -1
View File
@@ -28,7 +28,7 @@
"email": "┘Д╪╖┘Б╪з┘Л █М┌й ╪в╪п╪▒╪│ ╪з█М┘Е█М┘Д ┘Е╪╣╪к╪и╪▒ ┘И╪з╪▒╪п ┌й┘Ж█М╪п.",
"existingAccount": "╪в█М╪з ┘В╪и┘Д╪з┘Л ╪н╪│╪з╪и ┌й╪з╪▒╪и╪▒█М ╪п╪з╪▒█М╪п╪Я",
"get": "╪п╪▒█М╪з┘Б╪к",
"invite": "┌й╪п ╪п╪╣┘И╪к",
"invite": "┌й╪п ╪п╪╣┘И╪к (╪з╪о╪к█М╪з╪▒█М)",
"message": "#### ┌й╪з╪▒╪и╪▒ ┌п╪▒╪з┘Е█М╪М ╪│┘Д╪з┘Е!\n\n╪з╪▓ ╪к┘И╪м┘З ┘И ╪н┘Е╪з█М╪к ╪┤┘Е╪з ╪│┘╛╪з╪│┌п╪▓╪з╪▒█М┘Е. ╪и┘З ╪п┘Д█М┘Д ╪к╪║█М█М╪▒╪з╪к ╪п╪▒ ╪з╪│╪к╪▒╪з╪к┌Ш█М ╪╣┘Е┘Д█М╪з╪к█М ╪│╪з█М╪к╪М ╪╣┘Е┘Д┌й╪▒╪п ╪л╪и╪ктАМ┘Ж╪з┘Е ┌й╪з╪▒╪и╪▒╪з┘Ж ╪м╪п█М╪п ╪▒╪з ┘Е╪к┘И┘В┘Б ┌й╪▒╪п┘ЗтАМ╪з█М┘Е. ╪п╪▒ ╪з█М┘Ж ┘Е╪п╪к╪М ┌й╪з╪▒╪и╪▒╪з┘Ж ┘Б╪╣┘Д█М ╪к╪н╪к ╪к╪г╪л█М╪▒ ┘В╪▒╪з╪▒ ┘Ж╪о┘И╪з┘З┘Ж╪п ┌п╪▒┘Б╪к.\n\n┘Е╪з ┘Е╪к╪╣┘З╪п ╪и┘З ╪з╪▒╪з╪ж┘З ╪о╪п┘Е╪з╪к ┘И ╪к╪м╪▒╪и┘З ╪и┘З╪к╪▒ ╪и┘З ╪┤┘Е╪з ┘З╪│╪к█М┘Е╪М ╪и┘Ж╪з╪и╪▒╪з█М┘Ж ╪п╪▒ ╪╖┘И┘Д ╪з█М┘Ж ╪п┘И╪▒┘З╪М ╪и┘З█М┘Ж┘ЗтАМ╪│╪з╪▓█М ╪м╪з┘Е╪╣ ╪│█М╪│╪к┘Е ┘И ╪з╪▒╪к┘В╪з╪б ┘И█М┌Ш┌п█МтАМ┘З╪з ╪▒╪з ╪з┘Ж╪м╪з┘Е ╪о┘И╪з┘З█М┘Е ╪п╪з╪п. ╪п╪▒ ╪в█М┘Ж╪п┘З╪М ╪и╪з ┘Е╪н╪к┘И╪з█М ┘И ╪о╪п┘Е╪з╪к ╪и┘З╪к╪▒ ╪з╪▓ ╪┤┘Е╪з ╪з╪│╪к┘В╪и╪з┘Д ╪о┘И╪з┘З█М┘Е ┌й╪▒╪п.\n\n┘Д╪╖┘Б╪з┘Л ╪и╪▒╪з█М ╪п╪▒█М╪з┘Б╪к ╪в╪о╪▒█М┘Ж ╪и┘ЗтАМ╪▒┘И╪▓╪▒╪│╪з┘Ж█МтАМ┘З╪з ┘И ╪з╪╖┘Д╪з╪╣█М┘ЗтАМ┘З╪з╪М ┘И╪итАМ╪│╪з█М╪к ┘И ┘╛┘Д╪к┘Б╪▒┘ЕтАМ┘З╪з█М ╪з╪м╪к┘Е╪з╪╣█М ┘Е╪з ╪▒╪з ╪п┘Ж╪и╪з┘Д ┌й┘Ж█М╪п. ╪з╪▓ ╪п╪▒┌й ┘И ╪н┘Е╪з█М╪к ╪┤┘Е╪з ╪│┘╛╪з╪│┌п╪▓╪з╪▒█М┘Е.\n\n╪з┌п╪▒ ╪│┘И╪з┘Д█М ╪п╪з╪▒█М╪п █М╪з ╪и┘З ┌й┘Е┌й ┘Ж█М╪з╪▓ ╪п╪з╪▒█М╪п╪М ┘Д╪╖┘Б╪з┘Л ╪и╪з ╪к█М┘Е ╪о╪п┘Е╪з╪к ┘Е╪┤╪к╪▒█М ┘Е╪з ╪к┘Е╪з╪│ ╪и┌п█М╪▒█М╪п.\n\n**╪и╪з╪▒ ╪п█М┌п╪▒ ╪з╪▓ ╪н┘Е╪з█М╪к ┘И ╪п╪▒┌й ╪┤┘Е╪з ╪│┘╛╪з╪│┌п╪▓╪з╪▒█М┘Е.**",
"passwordMismatch": "╪▒┘Е╪▓┘З╪з█М ╪╣╪и┘И╪▒ ┘Е╪╖╪з╪и┘В╪к ┘Ж╪п╪з╪▒┘Ж╪п",
"success": "╪л╪и╪ктАМ┘Ж╪з┘Е ┘Е┘И┘Б┘В█М╪ктАМ╪в┘Е█М╪▓ ╪и┘И╪п╪М ╪и┘ЗтАМ╪╖┘И╪▒ ╪о┘И╪п┌й╪з╪▒ ┘И╪з╪▒╪п ╪┤╪п█М╪п!",
+2
View File
@@ -39,6 +39,8 @@
"status": "┘И╪╢╪╣█М╪к",
"subject": "┘Е┘И╪╢┘И╪╣",
"template": "╪з┘Д┌п┘И",
"traffic_exceed_email_template": "╪з┘Д┌п┘И█М ╪з╪╣┘Д╪з┘Ж ╪к╪▒╪з┘Б█М┌й ╪и█М╪┤ ╪з╪▓ ╪н╪п",
"traffic_exceed_email_templateDescription": "╪м╪з█М┌п╪▓█М┘ЖтАМ┘З╪з█М {after}.variable{before} ╪и╪з ╪п╪з╪п┘ЗтАМ┘З╪з█М ┘И╪з┘В╪╣█М ╪о┘И╪з┘З╪п ╪┤╪п. ╪з╪╖┘Е█М┘Ж╪з┘Ж ╪н╪з╪╡┘Д ┌й┘Ж█М╪п ┌й┘З ╪з█М┘Ж ┘Е╪к╪║█М╪▒┘З╪з ╪▒╪з ╪н┘Б╪╕ ┌й┘Ж█М╪п.",
"verify_email_template": "┘В╪з┘Д╪и ╪з█М┘Е█М┘Д ╪к╪г█М█М╪п",
"verify_email_templateDescription": "╪м╪з█МтАМ┌п╪░╪з╪▒█МтАМ┘З╪з█М {after}.variable{before} ╪и╪з ╪п╪з╪п┘ЗтАМ┘З╪з█М ┘И╪з┘В╪╣█М ╪м╪з█М┌п╪▓█М┘Ж ╪о┘И╪з┘З┘Ж╪п ╪┤╪п. ╪з╪╖┘Е█М┘Ж╪з┘Ж ╪н╪з╪╡┘Д ┌й┘Ж█М╪п ┌й┘З ╪з█М┘Ж ┘Е╪к╪║█М╪▒┘З╪з ╪▒╪з ╪н┘Б╪╕ ┌й┘Ж█М╪п.",
"whitelistSuffixes": "┘╛╪│┘И┘Ж╪п┘З╪з█М ┘Д█М╪│╪к ╪│┘Б█М╪п",
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "╪к┘Ж╪╕█М┘Е╪з╪к ADS",
"Announcement Management": "┘Е╪п█М╪▒█М╪к ╪з╪╖┘Д╪з╪╣█М┘ЗтАМ┘З╪з",
"Apple": "╪┤┘Ж╪з╪│┘З ╪з┘╛┘Д",
"Application Management": "┘Е╪п█М╪▒█М╪к ╪и╪▒┘Ж╪з┘Е┘З",
"Auth Control": "┌й┘Ж╪к╪▒┘Д ╪з╪н╪▒╪з╪▓ ┘З┘И█М╪к",
"Coupon Management": "┘Е╪п█М╪▒█М╪к ┌й┘И┘╛┘Ж",
"Dashboard": "╪п╪з╪┤╪и┘И╪▒╪п",
@@ -16,6 +17,7 @@
"Order Management": "┘Е╪п█М╪▒█М╪к ╪│┘Б╪з╪▒╪┤",
"Payment Config": "┘╛█М┌й╪▒╪и┘Ж╪п█М ┘╛╪▒╪п╪з╪о╪к",
"Phone Number": "╪┤┘Е╪з╪▒┘З ╪к┘Д┘Б┘Ж",
"Rule Management": "┘Е╪п█М╪▒█М╪к ┘В┘И╪з┘Ж█М┘Ж",
"Server": "╪│╪▒┘И╪▒",
"Server Management": "┘Е╪п█М╪▒█М╪к ╪│╪▒┘И╪▒",
"Settings": "╪к┘Ж╪╕█М┘Е╪з╪к",
-1
View File
@@ -22,7 +22,6 @@
"description": "╪к┘И╪╢█М╪н╪з╪к",
"descriptionPlaceholder": "╪к┘И╪╢█М╪н╪з╪к ╪▒┘И╪┤ ┘╛╪▒╪п╪з╪о╪к ╪▒╪з ┘И╪з╪▒╪п ┌й┘Ж█М╪п",
"domain": "╪п╪з┘Е┘Ж┘З",
"domainPlaceholder": "╪з╪о╪к█М╪з╪▒█М╪М ╪и┘З ╪╣┘Ж┘И╪з┘Ж ┘Е╪л╪з┘Д {example}",
"edit": "┘И█М╪▒╪з█М╪┤",
"editPayment": "┘И█М╪▒╪з█М╪┤ ╪▒┘И╪┤ ┘╛╪▒╪п╪з╪о╪к",
"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": "┘В╪з┘Ж┘И┘Ж ╪и╪з ┘Е┘И┘Б┘В█М╪к ╪и┘ЗтАМ╪▒┘И╪▓╪▒╪│╪з┘Ж█М ╪┤╪п"
}
+2
View File
@@ -13,6 +13,8 @@
"title": "╪│█М╪з╪│╪к ╪н┘Б╪╕ ╪н╪▒█М┘Е ╪о╪╡┘И╪╡█М"
},
"site": {
"customData": "╪п╪з╪п┘ЗтАМ┘З╪з█М ╪│┘Б╪з╪▒╪┤█М",
"customDataDescription": "╪п╪з╪п┘ЗтАМ┘З╪з█М ╪│┘Б╪з╪▒╪┤█М╪М ╪з╪│╪к┘Б╪з╪п┘З ╪┤╪п┘З ╪и╪▒╪з█М ╪п╪з╪п┘ЗтАМ┘З╪з█М ╪│┘Б╪з╪▒╪┤█М ╪│╪з█М╪к",
"customHtml": "HTML ╪│┘Б╪з╪▒╪┤█М",
"customHtmlDescription": "┌й╪п HTML ╪│┘Б╪з╪▒╪┤█М ┌й┘З ╪и╪з█М╪п ╪п╪▒ ╪з┘Ж╪к┘З╪з█М ╪к┌п body ╪│╪з█М╪к ┘И╪з╪▒╪п ╪┤┘И╪п.",
"keywords": "┌й┘Д┘Е╪з╪к ┌й┘Д█М╪п█М",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "╪к╪г█М█М╪п ╪з╪▒╪к┘В╪з╪б ╪│█М╪│╪к┘Е",
"confirmUpgrade": "╪к╪г█М█М╪п ╪з╪▒╪к┘В╪з╪б",
"currentVersion": "┘Ж╪│╪о┘З ┘Б╪╣┘Д█М ╪│█М╪│╪к┘Е:",
"developmentVersion": "┘Ж╪│╪о┘З ╪к┘И╪│╪╣┘З",
"errors": "╪о╪╖╪з┘З╪з",
"ip": "╪в█МтАМ┘╛█М",
"ip": "╪в╪п╪▒╪│ ╪в█МтАМ┘╛█М",
"lastUpdated": "╪в╪о╪▒█М┘Ж ╪и┘ЗтАМ╪▒┘И╪▓╪▒╪│╪з┘Ж█М:",
"newVersionAvailable": "┘Ж╪│╪о┘З ╪м╪п█М╪п",
"none": "┘З█М┌Ж",
"query": "┘╛╪▒╪│ ┘И ╪м┘И",
"rebootDescription": "╪в█М╪з ┘Е╪╖┘Е╪ж┘Ж ┘З╪│╪к█М╪п ┌й┘З ┘Е█МтАМ╪о┘И╪з┘З█М╪п ╪│█М╪│╪к┘Е ╪▒╪з ╪▒╪з┘ЗтАМ╪з┘Ж╪п╪з╪▓█М ┘Е╪м╪п╪п ┌й┘Ж█М╪п╪Я ╪з█М┘Ж ╪╣┘Е┘Д█М╪з╪к ╪и╪з╪╣╪л ┘И┘В┘Б┘З ┌й┘И╪к╪з┘З█М ╪п╪▒ ╪о╪п┘Е╪з╪к ╪о┘И╪з┘З╪п ╪┤╪п.",
"rebooting": "╪п╪▒ ╪н╪з┘Д ╪▒╪з┘ЗтАМ╪з┘Ж╪п╪з╪▓█М ┘Е╪м╪п╪п ╪│█М╪│╪к┘Е...",
"refreshLogs": "╪к╪з╪▓┘ЗтАМ╪│╪з╪▓█М ┌п╪▓╪з╪▒╪┤тАМ┘З╪з",
"request": "╪п╪▒╪о┘И╪з╪│╪к",
"serverVersion": "╪│╪▒┘И╪▒",
"status": "┘И╪╢╪╣█М╪к",
"systemLogs": "┌п╪▓╪з╪▒╪┤тАМ┘З╪з█М ╪│█М╪│╪к┘Е",
"systemReboot": "╪▒╪з┘ЗтАМ╪з┘Ж╪п╪з╪▓█М ┘Е╪м╪п╪п ╪│█М╪│╪к┘Е",
@@ -22,5 +25,8 @@
"systemUpgrade": "╪з╪▒╪к┘В╪з╪б ╪│█М╪│╪к┘Е",
"upgradeDescription": "╪в█М╪з ┘Е╪╖┘Е╪ж┘Ж ┘З╪│╪к█М╪п ┌й┘З ┘Е█МтАМ╪о┘И╪з┘З█М╪п ╪з╪▒╪к┘В╪з╪б ╪│█М╪│╪к┘Е ╪▒╪з ╪з┘Ж╪м╪з┘Е ╪п┘З█М╪п╪Я ╪з█М┘Ж ╪╣┘Е┘Д█М╪з╪к ┘Е┘Е┌й┘Ж ╪з╪│╪к ┌Ж┘Ж╪п ╪п┘В█М┘В┘З ╪╖┘И┘Д ╪и┌й╪┤╪п ┘И ╪п╪▒ ╪з█М┘Ж ┘Е╪п╪к ╪│█М╪│╪к┘Е ┘Е┘Е┌й┘Ж ╪з╪│╪к ┘╛╪з╪│╪о┌п┘И ┘Ж╪и╪з╪┤╪п.",
"userAgent": "╪╣╪з┘Е┘Д ┌й╪з╪▒╪и╪▒",
"viewLogsAndManage": "┘Е╪┤╪з┘З╪п┘З ┌п╪▓╪з╪▒╪┤тАМ┘З╪з█М ╪│█М╪│╪к┘Е╪М ╪з┘Ж╪м╪з┘Е ╪з╪▒╪к┘В╪з╪б ╪│█М╪│╪к┘Е ┘И ╪╣┘Е┘Д█М╪з╪к ╪▒╪з┘ЗтАМ╪з┘Ж╪п╪з╪▓█М ┘Е╪м╪п╪п"
"versionInfo": "╪з╪╖┘Д╪з╪╣╪з╪к ┘Ж╪│╪о┘З",
"viewLogsAndManage": "┘Е╪┤╪з┘З╪п┘З ┌п╪▓╪з╪▒╪┤тАМ┘З╪з█М ╪│█М╪│╪к┘Е╪М ╪з┘Ж╪м╪з┘Е ╪з╪▒╪к┘В╪з╪б ╪│█М╪│╪к┘Е ┘И ╪╣┘Е┘Д█М╪з╪к ╪▒╪з┘ЗтАМ╪з┘Ж╪п╪з╪▓█М ┘Е╪м╪п╪п",
"viewNewVersion": "┘Е╪┤╪з┘З╪п┘З ┘Ж╪│╪о┘З ╪м╪п█М╪п",
"webVersion": "┘И╪и/┘Е╪п█М╪▒█М╪к"
}
+15 -1
View File
@@ -1,6 +1,7 @@
{
"accountEnable": "┘Б╪╣╪з┘ДтАМ╪│╪з╪▓█М ╪н╪│╪з╪и",
"actions": "╪з┘В╪п╪з┘Е╪з╪к",
"active": "┘Б╪╣╪з┘Д",
"add": "╪з┘Б╪▓┘И╪п┘Ж",
"administrator": "┘Е╪п█М╪▒",
"areaCode": "┌й╪п ┘Е┘Ж╪╖┘В┘З",
@@ -41,10 +42,12 @@
"email": "╪з█М┘Е█М┘Д",
"enable": "┘Б╪╣╪з┘Д ┌й╪▒╪п┘Ж",
"expireTime": "╪▓┘Е╪з┘Ж ╪з┘Ж┘В╪╢╪з",
"expired": "┘Е┘Ж┘В╪╢█М ╪┤╪п┘З",
"expiredAt": "┘Е┘Ж┘В╪╢█М ╪┤╪п┘З ╪п╪▒",
"failed": "┘Ж╪з┘Е┘И┘Б┘В",
"giftAmount": "┘Е┘В╪п╪з╪▒ ┘З╪п█М┘З",
"giftAmountPlaceholder": "┘Е╪и┘Д╪║ ┘З╪п█М┘З ╪▒╪з ┘И╪з╪▒╪п ┌й┘Ж█М╪п",
"inactive": "╪║█М╪▒┘Б╪╣╪з┘Д",
"invalidEmailFormat": "┘Б╪▒┘Е╪к ╪з█М┘Е█М┘Д ┘Ж╪з┘Е╪╣╪к╪и╪▒ ╪з╪│╪к",
"inviteCode": "┌й╪п ╪п╪╣┘И╪к",
"inviteCodePlaceholder": "┌й╪п ╪п╪╣┘И╪к ╪▒╪з ┘И╪з╪▒╪п ┌й┘Ж█М╪п (╪и╪▒╪з█М ╪к┘И┘Д█М╪п ╪о╪з┘Д█М ╪и┌п╪░╪з╪▒█М╪п)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "╪▒┘Е╪▓ ╪╣╪и┘И╪▒ ╪м╪п█М╪п ╪▒╪з ┘И╪з╪▒╪п ┌й┘Ж█М╪п (╪з╪о╪к█М╪з╪▒█М)",
"permanent": "╪п╪з╪ж┘Е█М",
"pleaseEnterEmail": "┘Д╪╖┘Б╪з┘Л ╪з█М┘Е█М┘Д ╪о┘И╪п ╪▒╪з ┘И╪з╪▒╪п ┌й┘Ж█М╪п",
"price": "┘В█М┘Е╪к",
"referer": "╪з╪▒╪м╪з╪╣тАМ╪п┘З┘Ж╪п┘З",
"refererId": "╪┤┘Ж╪з╪│┘З ┘Е╪╣╪▒┘Б",
"refererIdPlaceholder": "╪┤┘Ж╪з╪│┘З ┘Е╪╣╪▒┘Б ╪▒╪з ┘И╪з╪▒╪п ┌й┘Ж█М╪п",
@@ -74,8 +78,12 @@
"searchIp": "╪м╪│╪к╪м┘И█М ╪в╪п╪▒╪│ IP",
"selectAuthType": "┘Ж┘И╪╣ ╪з╪н╪▒╪з╪▓ ┘З┘И█М╪к ╪▒╪з ╪з┘Ж╪к╪о╪з╪и ┌й┘Ж█М╪п",
"speedLimit": "┘Е╪н╪п┘И╪п█М╪к ╪│╪▒╪╣╪к",
"startTime": "╪▓┘Е╪з┘Ж ╪┤╪▒┘И╪╣",
"status": "┘И╪╢╪╣█М╪к",
"subscription": "╪з╪┤╪к╪▒╪з┌й",
"subscriptionDetails": "╪м╪▓╪ж█М╪з╪к ╪з╪┤╪к╪▒╪з┌й",
"subscriptionId": "╪┤┘Ж╪з╪│┘З ╪з╪┤╪к╪▒╪з┌й",
"subscriptionInfo": "╪з╪╖┘Д╪з╪╣╪з╪к ╪з╪┤╪к╪▒╪з┌й",
"subscriptionList": "┘Д█М╪│╪к ╪з╪┤╪к╪▒╪з┌й",
"subscriptionLogs": "┌п╪▓╪з╪▒╪┤тАМ┘З╪з█М ╪з╪┤╪к╪▒╪з┌й",
"subscriptionName": "┘Ж╪з┘Е ╪з╪┤╪к╪▒╪з┌й",
@@ -89,6 +97,8 @@
"tradeNotifications": "╪з╪╣┘Д╪з┘ЖтАМ┘З╪з█М ╪к╪м╪з╪▒╪к",
"trafficLimit": "┘Е╪н╪п┘И╪п█М╪к ╪к╪▒╪з┘Б█М┌й",
"trafficLogs": "┌п╪▓╪з╪▒╪┤тАМ┘З╪з█М ╪к╪▒╪з┘Б█М┌й",
"trafficUsage": "╪з╪│╪к┘Б╪з╪п┘З ╪з╪▓ ╪к╪▒╪з┘Б█М┌й",
"unknown": "┘Ж╪з┘Е╪┤╪о╪╡",
"unlimited": "┘Ж╪з┘Е╪н╪п┘И╪п",
"unverified": "╪к╪г█М█М╪п ┘Ж╪┤╪п┘З",
"update": "╪и┘ЗтАМ╪▒┘И╪▓╪▒╪│╪з┘Ж█М",
@@ -98,11 +108,15 @@
"userAgent": "╪╣╪з┘Е┘Д ┌й╪з╪▒╪и╪▒",
"userEmail": "╪з█М┘Е█М┘Д ┌й╪з╪▒╪и╪▒",
"userEmailPlaceholder": "╪з█М┘Е█М┘Д ┌й╪з╪▒╪и╪▒ ╪▒╪з ┘И╪з╪▒╪п ┌й┘Ж█М╪п",
"userId": "╪┤┘Ж╪з╪│┘З ┌й╪з╪▒╪и╪▒",
"userInfo": "╪з╪╖┘Д╪з╪╣╪з╪к ┌й╪з╪▒╪и╪▒",
"userList": "┘Б┘З╪▒╪│╪к ┌й╪з╪▒╪и╪▒╪з┘Ж",
"userLogs": "╪к╪з╪▒█М╪о┌Ж┘З ┘И╪▒┘И╪п",
"userName": "╪┤┘Ж╪з╪│┘З ┌й╪з╪▒╪и╪▒",
"userOrders": "╪│┘Б╪з╪▒╪┤тАМ┘З╪з",
"userProfile": "┘╛╪▒┘И┘Б╪з█М┘Д",
"userSubscriptions": "╪з╪┤╪к╪▒╪з┌йтАМ┘З╪з",
"verified": "╪к╪г█М█М╪п ╪┤╪п┘З"
"username": "┘Ж╪з┘Е ┌й╪з╪▒╪и╪▒█М",
"verified": "╪к╪г█М█М╪п ╪┤╪п┘З",
"viewDetails": "┘Е╪┤╪з┘З╪п┘З ╪м╪▓╪ж█М╪з╪к"
}
+1 -1
View File
@@ -28,7 +28,7 @@
"email": "Anna kelvollinen s├дhk├╢postiosoite.",
"existingAccount": "Onko sinulla jo tili?",
"get": "Hanki",
"invite": "Kutsukoodi",
"invite": "Kutsukoodi (valinnainen)",
"message": "#### Arvoisa k├дytt├дj├д,\n\nKiitos mielenkiinnostasi ja tuestasi. Sivuston toimintastrategian muutosten vuoksi olemme sulkeneet uusien k├дytt├дjien rekister├╢innin. T├дn├д aikana nykyisten k├дytt├дjien k├дytt├╢ ei vaikutu mill├д├дn tavalla.\n\nOlemme sitoutuneet tarjoamaan sinulle parempaa palvelua ja kokemusta, joten rekister├╢innin sulkemisen aikana suoritamme kattavan j├дrjestelm├дn optimoinnin ja toiminnallisuuden p├дivityksen. Tulevaisuudessa toivotamme sinut tervetulleeksi entist├д laadukkaamman sis├дll├╢n ja palvelun kera.\n\nSeuraa verkkosivustoamme ja sosiaalisen median alustoja saadaksesi uusimmat p├дivitykset ja ilmoitukset. Kiitos ymm├дrryksest├дsi ja tuestasi.\n\nJos sinulla on kysytt├дv├д├д tai tarvitset apua, ota yhteytt├д asiakaspalvelutiimiimme.\n\n**Kiitos viel├д kerran tuestasi ja ymm├дrryksest├дsi.**",
"passwordMismatch": "Salasanat eiv├дt t├дsm├д├д",
"success": "Rekister├╢inti onnistui, olet kirjautunut automaattisesti!",
+2
View File
@@ -39,6 +39,8 @@
"status": "Tila",
"subject": "Aihe",
"template": "Malline",
"traffic_exceed_email_template": "Liikenteen Ylitysilmoitusmalli",
"traffic_exceed_email_templateDescription": "{after}.variable{before} -paikat korvataan todellisilla tiedoilla. Varmista, ett├д s├дilyt├дt n├дm├д muuttujat.",
"verify_email_template": "S├дhk├╢postin Vahvistusmalli",
"verify_email_templateDescription": "Paikkamerkit {after}.variable{before} korvataan todellisilla tiedoilla. Varmista, ett├д pid├дt n├дm├д muuttujat.",
"whitelistSuffixes": "Sallittujen luetteloiden p├д├дtteet",
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "ADS-asetukset",
"Announcement Management": "Ilmoitusten hallinta",
"Apple": "Apple ID",
"Application Management": "Sovellushallinta",
"Auth Control": "Todennuksen hallinta",
"Coupon Management": "Kuponkien hallinta",
"Dashboard": "Kojelauta",
@@ -16,6 +17,7 @@
"Order Management": "Tilausten hallinta",
"Payment Config": "Maksukonfiguraatio",
"Phone Number": "Puhelinnumero",
"Rule Management": "S├д├дnt├╢hallinta",
"Server": "Palvelu",
"Server Management": "Palvelimen hallinta",
"Settings": "Asetukset",
-1
View File
@@ -22,7 +22,6 @@
"description": "Kuvaus",
"descriptionPlaceholder": "Sy├╢t├д maksutavan kuvaus",
"domain": "Verkkotunnus",
"domainPlaceholder": "valinnainen, esim. {esimerkki}",
"edit": "Muokkaa",
"editPayment": "Muokkaa maksutapaa",
"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"
}
+2
View File
@@ -13,6 +13,8 @@
"title": "Tietosuojak├дyt├дnt├╢"
},
"site": {
"customData": "Mukautettu tieto",
"customDataDescription": "Mukautettu tieto, jota k├дytet├д├дn sivuston mukautettuun tietoon",
"customHtml": "Mukautettu HTML",
"customHtmlDescription": "Mukautettu HTML-koodi, joka lis├дt├д├дn sivuston body -tagin loppuun.",
"keywords": "Avainsanat",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "Vahvista j├дrjestelm├дn p├дivitys",
"confirmUpgrade": "Vahvista p├дivitys",
"currentVersion": "Nykyinen j├дrjestelm├дversio:",
"developmentVersion": "Kehitysversio",
"errors": "Virheet",
"ip": "IP",
"ip": "IP-osoite",
"lastUpdated": "Viimeksi p├дivitetty:",
"newVersionAvailable": "Uusi versio",
"none": "Ei mit├д├дn",
"query": "Kysely",
"rebootDescription": "Oletko varma, ett├д haluat k├дynnist├д├д j├дrjestelm├дn uudelleen? T├дm├д toimenpide aiheuttaa lyhyen palvelukatkon.",
"rebooting": "J├дrjestelm├д k├дynnistyy uudelleen...",
"refreshLogs": "P├дivit├д lokit",
"request": "Pyynt├╢",
"serverVersion": "Palvelin",
"status": "Tila",
"systemLogs": "J├дrjestelm├дn lokit",
"systemReboot": "J├дrjestelm├дn uudelleenk├дynnistys",
@@ -22,5 +25,8 @@
"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.",
"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",
"actions": "toiminnot",
"active": "Aktiivinen",
"add": "Lis├д├д",
"administrator": "Yll├дpit├дj├д",
"areaCode": "Alueen koodi",
@@ -41,10 +42,12 @@
"email": "s├дhk├╢posti",
"enable": "Ota k├дytt├╢├╢n",
"expireTime": "Vanhentumisaika",
"expired": "Vanhentunut",
"expiredAt": "Vanhentunut",
"failed": "Ep├дonnistui",
"giftAmount": "Lahjan m├д├дr├д",
"giftAmountPlaceholder": "Sy├╢t├д lahjan m├д├дr├д",
"inactive": "Ep├дaktiivinen",
"invalidEmailFormat": "Virheellinen s├дhk├╢postimuoto",
"inviteCode": "Kutsukoodi",
"inviteCodePlaceholder": "Sy├╢t├д kutsukoodi (j├дt├д tyhj├дksi luodaksesi uuden)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "Sy├╢t├д uusi salasana (valinnainen)",
"permanent": "Pysyv├д",
"pleaseEnterEmail": "Ole hyv├д ja sy├╢t├д s├дhk├╢postiosoite",
"price": "Hinta",
"referer": "Suosittelija",
"refererId": "Viittaajan ID",
"refererIdPlaceholder": "Sy├╢t├д suosittelijan ID",
@@ -74,8 +78,12 @@
"searchIp": "Etsi IP-osoite",
"selectAuthType": "Valitse todennustyyppi",
"speedLimit": "Nopeusrajoitus",
"startTime": "Aloitusaika",
"status": "Tila",
"subscription": "Tilaus",
"subscriptionDetails": "Tilaustiedot",
"subscriptionId": "Tilauksen ID",
"subscriptionInfo": "Tilauksen tiedot",
"subscriptionList": "Tilauksen lista",
"subscriptionLogs": "Tilaushistoria",
"subscriptionName": "Tilauksen nimi",
@@ -89,6 +97,8 @@
"tradeNotifications": "Kauppailmoitukset",
"trafficLimit": "Liikenteen rajoitus",
"trafficLogs": "Liikennelokit",
"trafficUsage": "Liikenteen k├дytt├╢",
"unknown": "Tuntematon",
"unlimited": "Rajoittamaton",
"unverified": "Vahvistamaton",
"update": "P├дivit├д",
@@ -98,11 +108,15 @@
"userAgent": "K├дytt├дj├дagentti",
"userEmail": "K├дytt├дj├дn s├дhk├╢posti",
"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",
"userLogs": "Kirjautumishistoria",
"userName": "K├дytt├дj├дn tunniste",
"userOrders": "Tilaukset",
"userProfile": "Profiili",
"userSubscriptions": "Tilaukset",
"verified": "Vahvistettu"
"username": "K├дytt├дj├дnimi",
"verified": "Vahvistettu",
"viewDetails": "N├дyt├д tiedot"
}
+1 -1
View File
@@ -28,7 +28,7 @@
"email": "Veuillez entrer une adresse e-mail valide.",
"existingAccount": "Vous avez d├йj├а un compte ?",
"get": "Obtenir",
"invite": "Code d'invitation",
"invite": "Code d'invitation (facultatif)",
"message": "#### Cher utilisateur,\n\nMerci pour votre int├йr├кt et votre soutien. En raison d'un ajustement de notre strat├йgie op├йrationnelle, nous avons ferm├й la fonction d'inscription pour les nouveaux utilisateurs. Pendant cette p├йriode, l'utilisation par les utilisateurs existants ne sera pas affect├йe.\n\nNous nous engageons ├а vous offrir un meilleur service et une meilleure exp├йrience, c'est pourquoi nous proc├йderons ├а une optimisation compl├иte du syst├иme et ├а une mise ├а niveau des fonctionnalit├йs pendant la fermeture des inscriptions. ├А l'avenir, nous vous accueillerons avec un contenu et des services de meilleure qualit├й.\n\nVeuillez suivre notre site web et nos plateformes de m├йdias sociaux pour obtenir les derni├иres nouvelles et notifications. Merci pour votre compr├йhension et votre soutien.\n\nSi vous avez des questions ou avez besoin d'aide, n'h├йsitez pas ├а contacter notre ├йquipe de service client.\n\n**Merci encore pour votre soutien et votre compr├йhension.**",
"passwordMismatch": "Les mots de passe saisis ne correspondent pas",
"success": "Inscription r├йussie, vous ├кtes maintenant connect├й automatiquement !",
+2
View File
@@ -39,6 +39,8 @@
"status": "Statut",
"subject": "Sujet",
"template": "Mod├иle",
"traffic_exceed_email_template": "Mod├иle de notification de d├йpassement de trafic",
"traffic_exceed_email_templateDescription": "Les espaces r├йserv├йs {after}.variable{before} seront remplac├йs par des donn├йes r├йelles. Assurez-vous de conserver ces variables.",
"verify_email_template": "Mod├иle d'Email de V├йrification",
"verify_email_templateDescription": "Les espaces r├йserv├йs {after}.variable{before} seront remplac├йs par des donn├йes r├йelles. Assurez-vous de conserver ces variables.",
"whitelistSuffixes": "Suffixes de la liste blanche",
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "Configuration ADS",
"Announcement Management": "Gestion des annonces",
"Apple": "Identifiant Apple",
"Application Management": "Gestion des applications",
"Auth Control": "Contr├┤le d'authentification",
"Coupon Management": "Gestion des coupons",
"Dashboard": "Tableau de bord",
@@ -16,6 +17,7 @@
"Order Management": "Gestion des commandes",
"Payment Config": "Configuration de paiement",
"Phone Number": "Num├йro de t├йl├йphone",
"Rule Management": "Gestion des r├иgles",
"Server": "Serveur",
"Server Management": "Gestion des services",
"Settings": "Param├иtres",
-1
View File
@@ -22,7 +22,6 @@
"description": "Description",
"descriptionPlaceholder": "Entrez la description du mode de paiement",
"domain": "Domaine",
"domainPlaceholder": "facultatif, par exemple {exemple}",
"edit": "Modifier",
"editPayment": "Modifier le mode de paiement",
"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"
}
+2
View File
@@ -13,6 +13,8 @@
"title": "Politique de confidentialit├й"
},
"site": {
"customData": "Donn├йes personnalis├йes",
"customDataDescription": "Donn├йes personnalis├йes, utilis├йes pour les donn├йes personnalis├йes du site",
"customHtml": "HTML personnalis├й",
"customHtmlDescription": "Code HTML personnalis├й ├а injecter dans le bas de la balise body du site.",
"keywords": "Mots-cl├йs",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "Confirmer la mise ├а niveau du syst├иme",
"confirmUpgrade": "Confirmer la mise ├а niveau",
"currentVersion": "Version actuelle du syst├иme :",
"developmentVersion": "Version de d├йveloppement",
"errors": "Erreurs",
"ip": "IP",
"ip": "Adresse IP",
"lastUpdated": "Derni├иre mise ├а jour :",
"newVersionAvailable": "Nouvelle version",
"none": "Aucun",
"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.",
"rebooting": "Red├йmarrage du syst├иme...",
"refreshLogs": "Rafra├оchir les journaux",
"request": "Demande",
"serverVersion": "Serveur",
"status": "Statut",
"systemLogs": "Journaux syst├иme",
"systemReboot": "Red├йmarrage du syst├иme",
@@ -22,5 +25,8 @@
"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.",
"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",
"actions": "actions",
"active": "Actif",
"add": "Ajouter",
"administrator": "Administrateur",
"areaCode": "Indicatif r├йgional",
@@ -41,10 +42,12 @@
"email": "e-mail",
"enable": "Activer",
"expireTime": "Date d'expiration",
"expired": "Expir├й",
"expiredAt": "Expir├й le",
"failed": "├Йchou├й",
"giftAmount": "Montant du cadeau",
"giftAmountPlaceholder": "Entrez le montant du cadeau",
"inactive": "Inactif",
"invalidEmailFormat": "Format d'email invalide",
"inviteCode": "Code d'invitation",
"inviteCodePlaceholder": "Entrez le code d'invitation (laissez vide pour g├йn├йrer)",
@@ -63,6 +66,7 @@
"passwordPlaceholder": "Entrez un nouveau mot de passe (facultatif)",
"permanent": "Permanent",
"pleaseEnterEmail": "Veuillez entrer votre adresse e-mail",
"price": "Prix",
"referer": "R├йf├йrent",
"refererId": "ID du r├йf├йrent",
"refererIdPlaceholder": "Entrez l'ID du r├йf├йrent",
@@ -74,8 +78,12 @@
"searchIp": "Rechercher une adresse IP",
"selectAuthType": "S├йlectionner le type d'authentification",
"speedLimit": "Limite de vitesse",
"startTime": "Date de d├йbut",
"status": "Statut",
"subscription": "Abonnement",
"subscriptionDetails": "D├йtails de l'abonnement",
"subscriptionId": "ID d'abonnement",
"subscriptionInfo": "Informations sur l'abonnement",
"subscriptionList": "Liste des abonnements",
"subscriptionLogs": "Journaux d'abonnement",
"subscriptionName": "Nom de l'abonnement",
@@ -89,6 +97,8 @@
"tradeNotifications": "Notifications de commerce",
"trafficLimit": "Limite de trafic",
"trafficLogs": "Journaux de trafic",
"trafficUsage": "Utilisation du trafic",
"unknown": "Inconnu",
"unlimited": "Illimit├й",
"unverified": "Non v├йrifi├й",
"update": "Mettre ├а jour",
@@ -98,11 +108,15 @@
"userAgent": "Agent utilisateur",
"userEmail": "E-mail de l'utilisateur",
"userEmailPlaceholder": "Entrez l'email de l'utilisateur",
"userId": "ID utilisateur",
"userInfo": "Informations sur l'utilisateur",
"userList": "Liste des utilisateurs",
"userLogs": "Historique des connexions",
"userName": "Identifiant Utilisateur",
"userOrders": "Commandes",
"userProfile": "Profil",
"userSubscriptions": "Abonnements",
"verified": "V├йrifi├й"
"username": "Nom d'utilisateur",
"verified": "V├йrifi├й",
"viewDetails": "Voir les d├йtails"
}
+1 -1
View File
@@ -28,7 +28,7 @@
"email": "рдХреГрдкрдпрд╛ рдПрдХ рдорд╛рдиреНрдп рдИрдореЗрд▓ рдкрддрд╛ рджрд░реНрдЬ рдХрд░реЗрдВред",
"existingAccount": "рдкрд╣рд▓реЗ рд╕реЗ рдЦрд╛рддрд╛ рд╣реИ?",
"get": "рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ",
"invite": "рдЖрдордВрддреНрд░рдг рдХреЛрдб",
"invite": "рдЖрдордВрддреНрд░рдг рдХреЛрдб (рд╡реИрдХрд▓реНрдкрд┐рдХ)",
"message": "#### рдкреНрд░рд┐рдп рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛, рдирдорд╕реНрддреЗ!\n\nрд╣рдорд╛рд░реЗ рдкреНрд░рддрд┐ рдЖрдкрдХреА рд░реБрдЪрд┐ рдФрд░ рд╕рдорд░реНрдерди рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рд╕рд╛рдЗрдЯ рд╕рдВрдЪрд╛рд▓рди рд░рдгрдиреАрддрд┐ рдореЗрдВ рдмрджрд▓рд╛рд╡ рдХреЗ рдХрд╛рд░рдг, рд╣рдордиреЗ рдирдП рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкрдВрдЬреАрдХрд░рдг рдХреЛ рдмрдВрдж рдХрд░ рджрд┐рдпрд╛ рд╣реИред рдЗрд╕ рджреМрд░рд╛рди, рдореМрдЬреВрджрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рдЙрдкрдпреЛрдЧ рдкрд░ рдХреЛрдИ рдкреНрд░рднрд╛рд╡ рдирд╣реАрдВ рдкрдбрд╝реЗрдЧрд╛ред\n\nрд╣рдо рдЖрдкрдХреЛ рдмреЗрд╣рддрд░ рд╕реЗрд╡рд╛ рдФрд░ рдЕрдиреБрднрд╡ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рдмрджреНрдз рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдкрдВрдЬреАрдХрд░рдг рдмрдВрдж рд╣реЛрдиреЗ рдХреЗ рджреМрд░рд╛рди рд╣рдо рд╡реНрдпрд╛рдкрдХ рдкреНрд░рдгрд╛рд▓реА рдЕрдиреБрдХреВрд▓рди рдФрд░ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдЙрдиреНрдирдпрди рдХрд░реЗрдВрдЧреЗред рднрд╡рд┐рд╖реНрдп рдореЗрдВ, рд╣рдо рдЖрдкрдХреЛ рдмреЗрд╣рддрд░ рд╕рд╛рдордЧреНрд░реА рдФрд░ рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рд╕рд╛рде рд╕реНрд╡рд╛рдЧрдд рдХрд░реЗрдВрдЧреЗред\n\nрд╣рдорд╛рд░реА рд╡реЗрдмрд╕рд╛рдЗрдЯ рдФрд░ рд╕реЛрд╢рд▓ рдореАрдбрд┐рдпрд╛ рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рдкрд░ рдирд╡реАрдирддрдо рдЕрдкрдбреЗрдЯ рдФрд░ рд╕реВрдЪрдирд╛рдПрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдзреНрдпрд╛рди рджреЗрдВред рдЖрдкрдХреА рд╕рдордЭ рдФрд░ рд╕рдорд░реНрдерди рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред\n\nрдпрджрд┐ рдЖрдкрдХреЗ рдХреЛрдИ рдкреНрд░рд╢реНрди рд╣реИрдВ рдпрд╛ рд╕рд╣рд╛рдпрддрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдХреГрдкрдпрд╛ рд╣рдорд╛рд░реА рдЧреНрд░рд╛рд╣рдХ рд╕реЗрд╡рд╛ рдЯреАрдо рд╕реЗ рд╕рдВрдкрд░реНрдХ рдХрд░реЗрдВред\n\n**рдЖрдкрдХреЗ рд╕рдорд░реНрдерди рдФрд░ рд╕рдордЭ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд╛рд░ рдлрд┐рд░ рдзрдиреНрдпрд╡рд╛рджред**",
"passwordMismatch": "рджреЛрдиреЛрдВ рдмрд╛рд░ рджрд░реНрдЬ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдкрд╛рд╕рд╡рд░реНрдб рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛ рд░рд╣рд╛ рд╣реИ",
"success": "рдкрдВрдЬреАрдХрд░рдг рд╕рдлрд▓, рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд▓реЙрдЧ рдЗрди рд╣реЛ рдЧрдпрд╛!",
+2
View File
@@ -39,6 +39,8 @@
"status": "рд╕реНрдерд┐рддрд┐",
"subject": "рд╡рд┐рд╖рдп",
"template": "рдЯреЗрдореНрдкрд▓реЗрдЯ",
"traffic_exceed_email_template": "рдЯреНрд░реИрдлрд┐рдХ рдЕрдзрд┐рдХрддрд╛ рд╕реВрдЪрдирд╛ рдЯреЗрдореНрдкрд▓реЗрдЯ",
"traffic_exceed_email_templateDescription": "{after}.variable{before} рдкреНрд▓реЗрд╕рд╣реЛрд▓реНрдбрд░реНрд╕ рдХреЛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдЗрди рд╡реЗрд░рд┐рдПрдмрд▓реНрд╕ рдХреЛ рдмрдирд╛рдП рд░рдЦреЗрдВред",
"verify_email_template": "рд╕рддреНрдпрд╛рдкрди рдИрдореЗрд▓ рдЯреЗрдореНрдкрд▓реЗрдЯ",
"verify_email_templateDescription": "{after}.variable{before} рдкреНрд▓реЗрд╕рд╣реЛрд▓реНрдбрд░реНрд╕ рдХреЛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдбреЗрдЯрд╛ рд╕реЗ рдмрджрд▓рд╛ рдЬрд╛рдПрдЧрд╛ред рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдЗрди рд╡реЗрд░рд┐рдПрдмрд▓реНрд╕ рдХреЛ рдмрдирд╛рдП рд░рдЦреЗрдВред",
"whitelistSuffixes": "рд╢реНрд╡реЗрддрд╕реВрдЪреА рдкреНрд░рддреНрдпрдп",
+2
View File
@@ -2,6 +2,7 @@
"ADS Config": "рдПрдбреАрдПрд╕ рдХреЙрдиреНрдлрд╝рд┐рдЧ",
"Announcement Management": "рдШреЛрд╖рдгрд╛ рдкреНрд░рдмрдВрдзрди",
"Apple": "рдПрдкреНрдкрд▓ рдЖрдИрдбреА",
"Application Management": "рдРрдкреНрд▓рд┐рдХреЗрд╢рди рдкреНрд░рдмрдВрдзрди",
"Auth Control": "рдкреНрд░рдорд╛рдгрд┐рдХрд░рдг рдирд┐рдпрдВрддреНрд░рдг",
"Coupon Management": "рдХреВрдкрди рдкреНрд░рдмрдВрдзрди",
"Dashboard": "рдбреИрд╢рдмреЛрд░реНрдб",
@@ -16,6 +17,7 @@
"Order Management": "рдСрд░реНрдбрд░ рдкреНрд░рдмрдВрдзрди",
"Payment Config": "рднреБрдЧрддрд╛рди рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди",
"Phone Number": "рдлрд╝реЛрди рдирдВрдмрд░",
"Rule Management": "рдирд┐рдпрдо рдкреНрд░рдмрдВрдзрди",
"Server": "рд╕рд░реНрд╡рд░",
"Server Management": "рд╕рд░реНрд╡рд░ рдкреНрд░рдмрдВрдзрди",
"Settings": "рд╕реЗрдЯрд┐рдВрдЧреНрд╕",
-1
View File
@@ -22,7 +22,6 @@
"description": "рд╡рд┐рд╡рд░рдг",
"descriptionPlaceholder": "рднреБрдЧрддрд╛рди рд╡рд┐рдзрд┐ рдХрд╛ рд╡рд┐рд╡рд░рдг рджрд░реНрдЬ рдХрд░реЗрдВ",
"domain": "рдбреЛрдореЗрди",
"domainPlaceholder": "рд╡реИрдХрд▓реНрдкрд┐рдХ, рдЬреИрд╕реЗ рдХрд┐ {example}",
"edit": "рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ",
"editPayment": "рднреБрдЧрддрд╛рди рд╡рд┐рдзрд┐ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ",
"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": "рдирд┐рдпрдо рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛"
}
+2
View File
@@ -13,6 +13,8 @@
"title": "рдЧреЛрдкрдиреАрдпрддрд╛ рдиреАрддрд┐"
},
"site": {
"customData": "рдХрд╕реНрдЯрдо рдбреЗрдЯрд╛",
"customDataDescription": "рдХрд╕реНрдЯрдо рдбреЗрдЯрд╛, рд╕рд╛рдЗрдЯ рдХреЗ рдХрд╕реНрдЯрдо рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ",
"customHtml": "рдХрд╕реНрдЯрдо HTML",
"customHtmlDescription": "рд╕рд╛рдЗрдЯ рдХреЗ bodyреИрдЧ рдХреЗ рдиреАрдЪреЗ рдЗрдВрдЬреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╕реНрдЯрдо HTML рдХреЛрдбред",
"keywords": "рдХреАрд╡рд░реНрдб",
+8 -2
View File
@@ -6,15 +6,18 @@
"confirmSystemUpgrade": "рд╕рд┐рд╕реНрдЯрдо рдЙрдиреНрдирдпрди рдХреА рдкреБрд╖реНрдЯрд┐ рдХрд░реЗрдВ",
"confirmUpgrade": "рдЙрдиреНрдирдпрди рдХреА рдкреБрд╖реНрдЯрд┐ рдХрд░реЗрдВ",
"currentVersion": "рд╡рд░реНрддрдорд╛рди рд╕рд┐рд╕реНрдЯрдо рд╕рдВрд╕реНрдХрд░рдг:",
"developmentVersion": "рд╡рд┐рдХрд╛рд╕ рд╕рдВрд╕реНрдХрд░рдг",
"errors": "рддреНрд░реБрдЯрд┐рдпрд╛рдБ",
"ip": "рдЖрдИрдкреА",
"ip": "рдЖрдИрдкреА рдкрддрд╛",
"lastUpdated": "рдЕрдВрддрд┐рдо рдЕрдкрдбреЗрдЯ:",
"newVersionAvailable": "рдирдпрд╛ рд╕рдВрд╕реНрдХрд░рдг",
"none": "рдХреЛрдИ рдирд╣реАрдВ",
"query": "рдкреНрд░рд╢реНрди",
"rebootDescription": "рдХреНрдпрд╛ рдЖрдк рд╡рд╛рдХрдИ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдкреБрдирдГ рдЖрд░рдВрдн рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ? рдЗрд╕ рдХреНрд░рд┐рдпрд╛ рд╕реЗ рдереЛрдбрд╝реЗ рд╕рдордп рдХреЗ рд▓рд┐рдП рд╕реЗрд╡рд╛ рдореЗрдВ рдмрд╛рдзрд╛ рдЖ рд╕рдХрддреА рд╣реИред",
"rebooting": "рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдкреБрдирдГ рдЖрд░рдВрдн рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ...",
"refreshLogs": "рд▓реЙрдЧреНрд╕ рдХреЛ рддрд╛рдЬрд╝рд╛ рдХрд░реЗрдВ",
"request": "рдЕрдиреБрд░реЛрдз",
"serverVersion": "рд╕рд░реНрд╡рд░",
"status": "рд╕реНрдерд┐рддрд┐",
"systemLogs": "рд╕рд┐рд╕реНрдЯрдо рд▓реЙрдЧреНрд╕",
"systemReboot": "рд╕рд┐рд╕реНрдЯрдо рдкреБрдирд░рд╛рд░рдВрдн",
@@ -22,5 +25,8 @@
"systemUpgrade": "рд╕рд┐рд╕реНрдЯрдо рдЙрдиреНрдирдпрди",
"upgradeDescription": "рдХреНрдпрд╛ рдЖрдк рд╡рд╛рдХрдИ рд╕рд┐рд╕реНрдЯрдо рдЕрдкрдЧреНрд░реЗрдб рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ? рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдХреБрдЫ рдорд┐рдирдЯ рд▓рдЧ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕ рджреМрд░рд╛рди рд╕рд┐рд╕реНрдЯрдо рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдирд╣реАрдВ рджреЗ рд╕рдХрддрд╛ рд╣реИред",
"userAgent": "рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдПрдЬреЗрдВрдЯ",
"viewLogsAndManage": "рд╕рд┐рд╕реНрдЯрдо рд▓реЙрдЧ рджреЗрдЦреЗрдВ, рд╕рд┐рд╕реНрдЯрдо рдЕрдкрдЧреНрд░реЗрдб рдФрд░ рдкреБрдирд░рд╛рд░рдВрдн рд╕рдВрдЪрд╛рд▓рди рдХрд░реЗрдВ"
"versionInfo": "рд╕рдВрд╕реНрдХрд░рдг рдЬрд╛рдирдХрд╛рд░реА",
"viewLogsAndManage": "рд╕рд┐рд╕реНрдЯрдо рд▓реЙрдЧ рджреЗрдЦреЗрдВ, рд╕рд┐рд╕реНрдЯрдо рдЕрдкрдЧреНрд░реЗрдб рдФрд░ рдкреБрдирд░рд╛рд░рдВрдн рд╕рдВрдЪрд╛рд▓рди рдХрд░реЗрдВ",
"viewNewVersion": "рдирдпрд╛ рд╕рдВрд╕реНрдХрд░рдг рджреЗрдЦреЗрдВ",
"webVersion": "рд╡реЗрдм/рдПрдбрдорд┐рди"
}

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