feat(web): package menu
@@ -93,7 +93,8 @@
|
||||
"typescript-eslint": "^8.45.0",
|
||||
"unplugin-auto-import": "^20.2.0",
|
||||
"unplugin-vue-components": "^29.1.0",
|
||||
"vite": "npm:rolldown-vite@7.1.14"
|
||||
"vite": "npm:rolldown-vite@7.1.14",
|
||||
"vite-plugin-svgr": "^5.2.0"
|
||||
},
|
||||
"overrides": {
|
||||
"vite": "npm:rolldown-vite@7.1.14"
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
import { request } from '@/utils/request'
|
||||
|
||||
import type { Package } from '@/views/Package/types'
|
||||
|
||||
export const SYS_API_PREFIX = '/sys';
|
||||
// 套餐列表
|
||||
export const getPackageListUrl = `${SYS_API_PREFIX}/package-plans`
|
||||
export const getPackageList = (query: { category: Package['category']; status: boolean; }) => {
|
||||
export const getPackageListUrl = `/package-plans`
|
||||
export const getPackageList = (query?: { category?: Package['category']; status?: boolean; }) => {
|
||||
return request.get(getPackageListUrl, query)
|
||||
}
|
||||
// 获取套餐详情
|
||||
export const getPackageDetail = (package_plan_id: string) => {
|
||||
return request.get(`${SYS_API_PREFIX}/package-plans/${package_plan_id}`)
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 14:00:23
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-25 11:17:44
|
||||
* @Last Modified time: 2026-04-14 18:36:01
|
||||
*/
|
||||
import { request } from '@/utils/request'
|
||||
import type { CreateModalData, ChangeEmailModalForm } from '@/views/UserManagement/types'
|
||||
@@ -57,3 +57,8 @@ export const sendEmailCode = (data: { email: string }) => {
|
||||
export const changeEmail = (data: ChangeEmailModalForm) => {
|
||||
return request.put('/users/change-email', data)
|
||||
}
|
||||
|
||||
// 获取租户套餐信息
|
||||
export const getTenantSubscription = () => {
|
||||
return request.get('/tenant/subscription')
|
||||
}
|
||||
16
web/src/assets/images/index/arrow_right_dark.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编组 5</title>
|
||||
<g id="V1.1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="首页" transform="translate(-1229, -446)" stroke="#212332">
|
||||
<g id="编组-13" transform="translate(1120, 300)">
|
||||
<g id="编组-6" transform="translate(16, 138)">
|
||||
<g id="编组-5" transform="translate(93, 8)">
|
||||
<polyline id="路径" points="10 6 12 8 10 10"></polyline>
|
||||
<line x1="12" y1="8" x2="2" y2="8" id="路径-2"></line>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 820 B |
BIN
web/src/assets/images/menuNew/package_bg.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
17
web/src/assets/images/package/api_ops.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>频次</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-收费管理" transform="translate(-314, -750)" fill="currentColor" fill-rule="nonzero">
|
||||
<g id="编组-5" transform="translate(288, 64)">
|
||||
<g id="编组-13" transform="translate(0, 228)">
|
||||
<g transform="translate(20, 16)" id="频次">
|
||||
<g transform="translate(6, 442)">
|
||||
<path d="M8.32397431,14.7174176 L13.3908989,7.29436898 C13.5898421,7.00271091 13.5091666,6.60853935 13.2103296,6.41423815 C13.1037093,6.3447846 12.9784064,6.30774783 12.8502468,6.30780564 L8.86631603,6.30780564 L8.86631603,1.63467602 C8.86631603,1.28423255 8.57550429,1 8.21668864,1 C7.99937181,1 7.79662724,1.10601998 7.67603646,1.28258243 L2.60911183,8.70563102 C2.41016872,8.99728909 2.49084416,9.39125438 2.78947001,9.58576185 C2.89614942,9.65527988 3.02151846,9.69238624 3.149764,9.69240062 L7.13369475,9.69240062 L7.13369475,14.365324 C7.13369475,14.7157675 7.42450649,15 7.78332213,15 C8.00063896,15 8.20359472,14.89398 8.32397431,14.7174176 Z" id="路径"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
17
web/src/assets/images/package/app.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>应用</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-收费管理" transform="translate(-314, -414)" fill="currentColor" fill-rule="nonzero">
|
||||
<g id="编组-5" transform="translate(288, 64)">
|
||||
<g id="编组-13" transform="translate(0, 228)">
|
||||
<g transform="translate(20, 16)" id="应用">
|
||||
<g transform="translate(6, 106)">
|
||||
<path d="M5.73221919,1.5 L2.70920955,1.5 C2.04142437,1.5 1.5,2.0410081 1.5,2.70827986 L1.5,5.72897951 C1.5,6.39623705 2.04142437,6.93725937 2.70920955,6.93725937 L5.73223342,6.93725937 C6.40000437,6.93725937 6.94144297,6.39625128 6.94144297,5.72897951 L6.94144297,2.70826564 C6.94144297,2.0410081 6.40000437,1.5 5.73221919,1.5 L5.73221919,1.5 Z M12.7040542,1.5 L9.68104456,1.5 C9.01325938,1.5 8.47183501,2.0410081 8.47183501,2.70827986 L8.47183501,5.72897951 C8.47183501,6.39623705 9.01325938,6.93725937 9.68104456,6.93725937 L12.7040684,6.93725937 C13.3718536,6.93725937 13.913278,6.39625128 13.913278,5.72897951 L13.913278,2.70826564 C13.913278,2.0410081 13.3718394,1.5 12.7040542,1.5 L12.7040542,1.5 Z M5.73221919,8.4711823 L2.70920955,8.4711823 C2.04142437,8.4711823 1.5,9.01220462 1.5,9.67946216 L1.5,12.7001618 C1.5,13.3674336 2.04142437,13.9084417 2.70920955,13.9084417 L5.73223342,13.9084417 C6.40000437,13.9084417 6.94144297,13.3674336 6.94144297,12.7001618 L6.94144297,9.67946216 C6.94144297,9.01220462 6.40000437,8.4711823 5.73221919,8.4711823 L5.73221919,8.4711823 Z M14.1766032,10.5791939 L12.1883205,8.5402163 C11.7490465,8.08947578 11.0275174,8.07989009 10.5761312,8.51898273 L8.53500119,10.5057368 C8.08465397,10.944673 8.07520324,11.6656474 8.51434907,12.1163879 L10.5029307,14.1556499 C10.9422047,14.6063905 11.6640184,14.6158339 12.1148069,14.1768835 L14.1556522,12.1898308 C14.6067395,11.7505959 14.6155925,11.0296358 14.1766032,10.5791939 L14.1766032,10.5791939 Z" id="形状" transform="translate(8, 8) scale(1, -1) translate(-8, -8)"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
13
web/src/assets/images/package/arrow.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编组 49</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||
<g id="平台管理-套餐管理-个人版" transform="translate(-252, -435)" stroke="currentColor" stroke-width="2">
|
||||
<g id="编组-15" transform="translate(252, 398)">
|
||||
<g id="编组-49" transform="translate(0, 37)">
|
||||
<polyline id="路径" points="15 18 9 12 15 6"></polyline>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 759 B |
18
web/src/assets/images/package/disable.svg
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编组</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-套餐管理-个人版" transform="translate(-506, -748)" stroke="#171719" stroke-width="1.1">
|
||||
<g id="编组-5" transform="translate(288, 112)">
|
||||
<g id="编组-23" transform="translate(0, 616)">
|
||||
<g id="编组-19" transform="translate(186, 12)">
|
||||
<g id="编组" transform="translate(32, 8)">
|
||||
<circle id="椭圆形" cx="8" cy="8" r="6.45"></circle>
|
||||
<line x1="3.25956213" y1="3.2473795" x2="12.6934486" y2="12.6812659" id="路径-12"></line>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
18
web/src/assets/images/package/enable.svg
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编组</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-套餐管理-商业版-2" transform="translate(-1077, -748)" fill-rule="nonzero">
|
||||
<g id="编组-5备份-2" transform="translate(846, 112)">
|
||||
<g id="编组-23" transform="translate(0, 616)">
|
||||
<g id="编组-19" transform="translate(186, 12)">
|
||||
<g id="编组" transform="translate(45, 8)">
|
||||
<path d="M8,1.55 C9.78111832,1.55 11.3936183,2.27194084 12.5608387,3.43916126 C13.7280592,4.60638168 14.45,6.21888168 14.45,8 C14.45,9.78111832 13.7280592,11.3936183 12.5608387,12.5608387 C11.3936183,13.7280592 9.78111832,14.45 8,14.45 C6.21888168,14.45 4.60638168,13.7280592 3.43916126,12.5608387 C2.27194084,11.3936183 1.55,9.78111832 1.55,8 C1.55,6.21888168 2.27194084,4.60638168 3.43916126,3.43916126 C4.60638168,2.27194084 6.21888168,1.55 8,1.55 Z" id="路径" stroke="#171719" stroke-width="1.1"></path>
|
||||
<path d="M6.94857143,10.7314706 C6.78136231,10.7333786 6.62051945,10.6673918 6.50285714,10.5485714 L4.4,8.44571429 C4.1538388,8.19955308 4.15383881,7.80044692 4.40000001,7.55428572 C4.64616121,7.30812452 5.04526737,7.30812452 5.29142857,7.55428571 L6.94857143,9.21142857 L10.7085714,5.45142857 C10.9547326,5.20526739 11.3538388,5.20526739 11.6,5.45142859 C11.8461612,5.69758978 11.8461612,6.09669594 11.6,6.34285714 L7.39428571,10.5485714 C7.27662341,10.6673918 7.11578054,10.7333786 6.94857143,10.7314706 Z" id="路径" fill="#171719"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
19
web/src/assets/images/package/end_user.svg
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>终端</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-收费管理" transform="translate(-314, -558)" fill="currentColor">
|
||||
<g id="编组-5" transform="translate(288, 64)">
|
||||
<g id="编组-13" transform="translate(0, 228)">
|
||||
<g transform="translate(20, 16)" id="终端">
|
||||
<g transform="translate(6, 250)">
|
||||
<g id="编组-12" transform="translate(1, 1.5)">
|
||||
<path d="M13,0 C13.5522847,0 14,0.44771525 14,1 L14,3 C14,3.27614237 13.7761424,3.5 13.5,3.5 L0.5,3.5 C0.223857625,3.5 0,3.27614237 0,3 L0,1 C0,0.44771525 0.44771525,1.11022302e-16 1,0 L13,0 Z M2.1,1.2 C1.76862915,1.2 1.5,1.46862915 1.5,1.8 C1.5,2.13137085 1.76862915,2.4 2.1,2.4 C2.43137085,2.4 2.7,2.13137085 2.7,1.8 C2.7,1.46862915 2.43137085,1.2 2.1,1.2 Z M3.9,1.2 C3.56862915,1.2 3.3,1.46862915 3.3,1.8 C3.3,2.13137085 3.56862915,2.4 3.9,2.4 C4.23137085,2.4 4.5,2.13137085 4.5,1.8 C4.5,1.46862915 4.23137085,1.2 3.9,1.2 Z M5.7,1.2 C5.36862915,1.2 5.1,1.46862915 5.1,1.8 C5.1,2.13137085 5.36862915,2.4 5.7,2.4 C6.03137085,2.4 6.3,2.13137085 6.3,1.8 C6.3,1.46862915 6.03137085,1.2 5.7,1.2 Z M13.5,4.5 C13.7761424,4.5 14,4.72385763 14,5 L14,11.8 C14,12.4627417 13.4627417,13 12.8,13 L1.20000005,13 C0.537258322,13 0,12.4627417 0,11.8 L0,5 C0,4.72385763 0.223857625,4.5 0.5,4.5 Z M8,10 L6,10 C5.72385763,10 5.5,10.2238576 5.5,10.5 C5.5,10.7761424 5.72385763,11 6,11 L8,11 C8.27614237,11 8.5,10.7761424 8.5,10.5 C8.5,10.2238576 8.27614237,10 8,10 Z M2.85245368,7.14535031 C2.65658607,6.95069552 2.3400051,6.9516787 2.14535031,7.14754632 L2.0877102,7.21697355 C1.95331998,7.41226 1.97344177,7.68162321 2.14754632,7.85464969 L3.293,8.993 L2.14535707,10.1475395 C1.95069852,10.3434034 1.95167564,10.6599844 2.14753952,10.8546429 C2.3434034,11.0493015 2.65998438,11.0483244 2.85464293,10.8524605 L4.35464293,9.34317241 C4.54930412,9.14730587 4.54832395,8.83071967 4.35245368,8.63606224 Z" id="形状结合"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
17
web/src/assets/images/package/knowledge.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>知识库容量</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-收费管理" transform="translate(-314, -462)" fill="currentColor" fill-rule="nonzero">
|
||||
<g id="编组-5" transform="translate(288, 64)">
|
||||
<g id="编组-13" transform="translate(0, 228)">
|
||||
<g transform="translate(20, 16)" id="知识库容量">
|
||||
<g transform="translate(6, 154)">
|
||||
<path d="M2,13.2659458 L2,13.2763169 C2.02,14.2304616 2.751,15.0000005 3.672,15.0000005 L13,15.0000005 C13.552,15.0000005 14,14.5426328 14,13.9691089 L14,2.03607771 C14,1.7611133 13.8946114,1.49742586 13.7070462,1.30309395 C13.519481,1.10876204 13.2651245,0.999725798 13,1.00000052 L4,1.00000052 C2.895,1.00000052 2,1.92095808 2,3.06696881 L2,13.2669829 L2,13.2659458 Z M4.79999988,6.99763005 L4.79999988,3.0213358 C4.79999988,2.79317077 4.98,2.60649029 5.2,2.60649029 L7.6,2.60649029 C7.821,2.60649029 8.00000012,2.79317077 8.00000012,3.0213358 L8.00000012,6.99763005 C8.0001274,7.1655208 7.90266905,7.31693863 7.75311605,7.38120551 C7.60356305,7.4454724 7.43140463,7.40991604 7.317,7.29113325 L6.683,6.63360311 C6.6079727,6.55570465 6.5061637,6.51193446 6.4,6.51193446 C6.2938363,6.51193446 6.1920273,6.55570465 6.117,6.63360311 L5.483,7.29113325 C5.36859537,7.40991604 5.19643695,7.4454724 5.04688395,7.38120551 C4.89733095,7.31693863 4.7998726,7.1655208 4.79999988,6.99763005 L4.79999988,6.99763005 Z M3.576,13.5833026 C3.45866667,13.4629974 3.4,13.3164186 3.4,13.1435663 C3.4,12.9720968 3.45866667,12.8255181 3.576,12.7038301 C3.69266667,12.5821421 3.834,12.5212981 4,12.5212981 L12.3,12.5212981 C12.4656854,12.5212981 12.6,12.6556126 12.6,12.8212981 L12.6,13.4658346 C12.6,13.63152 12.4656854,13.7658346 12.3,13.7658346 L4,13.7658346 L4,13.7658346 C3.834,13.7658346 3.69266667,13.7049906 3.576,13.5833026 Z" id="形状"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
20
web/src/assets/images/package/memory_config.svg
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>记忆引擎</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-收费管理" transform="translate(-314, -510)" fill="currentColor">
|
||||
<g id="编组-5" transform="translate(288, 64)">
|
||||
<g id="编组-13" transform="translate(0, 228)">
|
||||
<g transform="translate(20, 16)" id="记忆引擎">
|
||||
<g transform="translate(6, 202)">
|
||||
<g id="编组-25" transform="translate(1, 1.5)">
|
||||
<path d="M4.33333333,0 C5.52995029,0 6.5,0.970564798 6.5,2.16781715 L6.499,2.193 L6.5,10.8390858 L6.47808338,10.8391196 C6.31578908,12.0589502 5.27189987,13 4.00833333,13 C2.63222383,13 1.51666667,11.8838505 1.51666667,10.5070103 C1.51666667,10.332196 1.53465035,10.1615842 1.56886767,9.99692601 C0.663423478,9.73754175 0,8.90246334 0,7.9123518 C0,7.36506373 0.202700377,6.86514401 0.537084253,6.48364722 C0.203054284,6.10374909 0,5.60343451 0,5.05566888 C0,3.85841652 0.970049709,2.88785173 2.16666667,2.88785173 C2.20862378,2.88785173 2.25030235,2.88904496 2.29167033,2.89139936 C2.210453,2.6663156 2.16666667,2.42218251 2.16666667,2.16781715 C2.16666667,0.970564798 3.13671638,0 4.33333333,0 Z" id="形状结合"></path>
|
||||
<path d="M11.8333333,0 C13.0299503,0 14,0.970564798 14,2.16781715 L13.999,2.193 L14,10.8390858 L13.9780834,10.8391196 C13.8157891,12.0589502 12.7718999,13 11.5083333,13 C10.1322238,13 9.01666667,11.8838505 9.01666667,10.5070103 C9.01666667,10.332196 9.03465035,10.1615842 9.06886767,9.99692601 C8.16342348,9.73754175 7.5,8.90246334 7.5,7.9123518 C7.5,7.36506373 7.70270038,6.86514401 8.03708425,6.48364722 C7.70305428,6.10374909 7.5,5.60343451 7.5,5.05566888 C7.5,3.85841652 8.47004971,2.88785173 9.66666667,2.88785173 C9.70862378,2.88785173 9.75030235,2.88904496 9.79167033,2.89139936 C9.710453,2.6663156 9.66666667,2.42218251 9.66666667,2.16781715 C9.66666667,0.970564798 10.6367164,0 11.8333333,0 Z" id="形状结合" transform="translate(10.75, 6.5) scale(-1, 1) translate(-10.75, -6.5)"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
17
web/src/assets/images/package/model.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>模型</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-收费管理" transform="translate(-314, -654)" fill="currentColor" fill-rule="nonzero">
|
||||
<g id="编组-5" transform="translate(288, 64)">
|
||||
<g id="编组-13" transform="translate(0, 228)">
|
||||
<g transform="translate(20, 16)" id="模型">
|
||||
<g transform="translate(6, 346)">
|
||||
<path d="M8.9375,2.45132371 C8.9375,2.73288225 8.816875,2.98590446 8.625,3.1602932 L8.625,4.35374628 L11.75,4.35374628 C12.7855339,4.35374628 13.625,5.20548988 13.625,6.25616886 L13.625,12.5975774 C13.625,13.6482564 12.7855339,14.5 11.75,14.5 L4.25,14.5 C3.21446609,14.5 2.375,13.6482564 2.375,12.5975774 L2.375,6.25616886 C2.375,5.20548988 3.21446609,4.35374628 4.25,4.35374628 L7.375,4.35374628 L7.375,3.1602932 C7.05390217,2.86889419 6.9698603,2.39296943 7.17127056,2.00658393 C7.37268081,1.62019842 7.80769695,1.42281399 8.22581154,1.52809601 C8.64392612,1.63337802 8.93750975,2.0142252 8.9375,2.45132371 Z M0.5,7.52445058 L1.75,7.52445058 L1.75,11.3292957 L0.5,11.3292957 L0.5,7.52445058 L0.5,7.52445058 Z M15.5,7.52445058 L14.25,7.52445058 L14.25,11.3292957 L15.5,11.3292957 L15.5,7.52445058 L15.5,7.52445058 Z M6.125,10.3780844 C6.64276695,10.3780844 7.0625,9.95221264 7.0625,9.42687315 C7.0625,8.90153366 6.64276695,8.47566186 6.125,8.47566186 C5.60723305,8.47566186 5.1875,8.90153366 5.1875,9.42687315 C5.1875,9.95221264 5.60723305,10.3780844 6.125,10.3780844 Z M10.8125,9.42687315 C10.8125,8.90153366 10.392767,8.47566186 9.875,8.47566186 C9.35723305,8.47566186 8.9375,8.90153366 8.9375,9.42687315 C8.9375,9.95221264 9.35723305,10.3780844 9.875,10.3780844 C10.392767,10.3780844 10.8125,9.95221264 10.8125,9.42687315 Z" id="形状"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
17
web/src/assets/images/package/ontology.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>本体工程</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-收费管理" transform="translate(-314, -606)" fill="currentColor" fill-rule="nonzero">
|
||||
<g id="编组-5" transform="translate(288, 64)">
|
||||
<g id="编组-13" transform="translate(0, 228)">
|
||||
<g transform="translate(20, 16)" id="本体工程">
|
||||
<g transform="translate(6, 298)">
|
||||
<path d="M8.00029166,11.9565844 C8.55099458,11.9458014 9.06454299,12.2334279 9.34305434,12.7086345 C9.62156569,13.1838411 9.62156569,13.7724504 9.34305434,14.247657 C9.06454299,14.7228637 8.55099458,15.0104901 8.00029166,14.9997071 C7.17156632,14.9834803 6.50823134,14.3070298 6.50823134,13.4781458 C6.50823134,12.6492617 7.17156632,11.9728113 8.00029166,11.9565844 L8.00029166,11.9565844 Z M10.6998458,3.52602054 C11.3812309,3.93684948 11.9607513,4.49662702 12.3949419,5.16336869 C12.4894327,5.30835024 12.5214141,5.48532999 12.4836406,5.65421257 C12.4458671,5.82309514 12.3415359,5.96958625 12.1942836,6.06049782 C11.5289324,6.46893919 11.1240922,7.19420398 11.1256614,7.97491772 C11.1256614,8.78688374 11.5578934,9.5224363 12.2456148,9.91966968 C12.5576851,10.0993288 12.6591809,10.5029786 12.4701887,10.8109657 C12.0643977,11.4723107 11.5176721,12.0359657 10.8690055,12.46173 C10.7204191,12.5590552 10.5377976,12.589527 10.3656617,12.5457166 C10.1935258,12.5019063 10.047691,12.387839 9.96370985,12.2313229 C9.57624512,11.5120945 8.82541474,11.0634332 8.00845798,11.0629552 C7.19433681,11.0636561 6.44575953,11.5094456 6.05728927,12.2249066 C5.8782134,12.5515596 5.46114745,12.6565552 5.15082705,12.4512304 C4.48752495,12.0126641 3.93197322,11.4297935 3.52572809,10.7462184 C3.35319815,10.4559047 3.43473788,10.0815865 3.71238698,9.88933762 C4.32253406,9.47072463 4.68664967,8.77785728 4.68534645,8.03791508 C4.686623,7.30050165 4.32496025,6.60967794 3.71822007,6.19057571 C3.4410501,5.99756611 3.36052505,5.62297181 3.53389441,5.3331116 C3.97422818,4.59704162 4.58752564,3.97953949 5.32056998,3.53418686 C5.60872463,3.35919418 5.98262572,3.44085743 6.17278447,3.72026241 C6.5863185,4.32982165 7.27545367,4.69435748 8.01204828,4.69318847 C8.74864289,4.69201945 9.43661752,4.32529808 9.84821467,3.71442932 C10.0377901,3.43444104 10.4111079,3.35219449 10.6998458,3.52602054 Z M2.52185326,6.47756371 C3.3623496,6.47756371 4.04370651,7.1589205 4.04370651,7.99941669 C4.04370651,8.83991289 3.3623496,9.52126968 2.52185326,9.52126968 C1.68135691,9.52126968 1,8.83991289 1,7.99941669 C1,7.1589205 1.68135691,6.47756371 2.52185326,6.47756371 L2.52185326,6.47756371 Z M13.4781467,6.47756371 C14.3186431,6.47756371 15,7.1589205 15,7.99941669 C15,8.83991289 14.3186431,9.52126968 13.4781467,9.52126968 C12.6376504,9.52126968 11.9562935,8.83991289 11.9562935,7.99941669 C11.9562935,7.1589205 12.6376504,6.47756371 13.4781467,6.47756371 L13.4781467,6.47756371 Z M8.00029166,1.0002929 C8.55099467,0.989509733 9.0645432,1.27713619 9.34305463,1.75234287 C9.62156606,2.22754954 9.62156606,2.81615891 9.34305463,3.29136558 C9.0645432,3.76657226 8.55099467,4.05419872 8.00029166,4.04341555 C7.17156646,4.02718851 6.50823169,3.35073813 6.50823169,2.52185423 C6.50823169,1.69297032 7.17156646,1.01651994 8.00029166,1.0002929 L8.00029166,1.0002929 Z" id="形状"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
17
web/src/assets/images/package/skill.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>技能</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-收费管理" transform="translate(-314, -366)" fill="currentColor" fill-rule="nonzero">
|
||||
<g id="编组-5" transform="translate(288, 64)">
|
||||
<g id="编组-13" transform="translate(0, 228)">
|
||||
<g transform="translate(20, 16)" id="技能">
|
||||
<g transform="translate(6, 58)">
|
||||
<path d="M13.1093988,2.59578193 L13.4555609,2.94978293 C13.8735923,3.3772807 13.8735923,4.06040714 13.4555609,4.48790491 L4.31301403,13.8374857 L4.2959692,13.8545385 C3.86181051,14.2794839 3.16536908,14.272015 2.74042373,13.8378563 L2.3940984,13.4840222 C1.97572454,13.0565775 1.97556347,12.3731715 2.3937358,11.9455296 L11.5364459,2.59578193 L11.5538614,2.57836647 C11.9882203,2.15362581 12.6846581,2.16142298 13.1093988,2.59578193 Z M12.0437778,8.13777778 C12.1548235,8.14157777 12.2459151,8.22925253 12.2553906,8.3422989 C12.3375526,9.32051934 13.0757988,10.1076496 14.0280997,10.2323906 C14.140251,10.2448863 14.2244871,10.3429276 14.2221758,10.458273 C14.2198645,10.5736184 14.1317717,10.6680483 14.019214,10.6758351 C13.0620685,10.7592707 12.2919283,11.5150446 12.1709758,12.4895962 C12.154941,12.6005116 12.0607522,12.6819263 11.9511371,12.6796198 C11.841522,12.6773133 11.7506877,12.5920053 11.7391279,12.4805092 C11.6579275,11.5026771 10.9208042,10.715182 9.96908446,10.5895088 C9.85693321,10.5770131 9.77269711,10.4789718 9.77500841,10.3636264 C9.7773197,10.248281 9.86541254,10.1538511 9.97797022,10.1460643 C10.9344274,10.0618167 11.7036291,9.30623726 11.8244312,8.33230322 C11.836223,8.24007169 11.9028425,8.16505835 11.9914835,8.14420276 L12.0437778,8.13777778 Z M4.04677778,1.77777778 C4.1576393,1.78069238 4.24873095,1.86836714 4.25820637,1.98141351 C4.34036837,2.95963395 5.07861462,3.74676424 6.03091554,3.87150517 C6.14306679,3.88400094 6.22730289,3.98204216 6.22499159,4.09738759 C6.2226803,4.21273302 6.13458746,4.30716294 6.02202978,4.31494975 C5.06488427,4.39838528 4.29474414,5.15415919 4.17379165,6.12871078 C4.15775682,6.23962624 4.06356797,6.32104094 3.95395289,6.31873441 C3.8443378,6.31642788 3.7535035,6.23111991 3.7419437,6.11962381 C3.66074329,5.14179167 2.92362,4.35429664 1.97190027,4.22862345 C1.85974901,4.21612767 1.77551292,4.11808646 1.77782421,4.00274103 C1.78013551,3.8873956 1.86822835,3.79296568 1.98078603,3.78517887 C2.93724323,3.70093132 3.70644486,2.94535187 3.827247,1.97141783 C3.83903882,1.8791863 3.90565827,1.80417296 3.99429929,1.78331737 L4.04677778,1.77777778 Z M7.97077778,1.77777778 C8.0434983,1.77530067 8.10642776,1.82945264 8.11640346,1.90326549 C8.16260941,2.23494023 8.42740507,2.48846695 8.75440104,2.51300179 C8.83292056,2.51049249 8.89856235,2.57355237 8.90101608,2.65384997 C8.90346982,2.73414756 8.84180632,2.80127582 8.7632868,2.80378512 C8.43951745,2.85069166 8.19138283,3.12184124 8.16705229,3.45532153 C8.16950603,3.53561913 8.10784253,3.60274738 8.02932301,3.60525668 C7.95080349,3.60776598 7.8851617,3.5447061 7.88270797,3.4644085 C7.83684011,3.13330736 7.57169477,2.87955371 7.24559896,2.85467221 C7.17114496,2.85152757 7.11169823,2.79012738 7.10936341,2.71395988 C7.10702859,2.63779237 7.16259799,2.57270502 7.2367132,2.56479757 C7.56078738,2.51781428 7.80901639,2.24618323 7.83294771,1.91235247 C7.83703762,1.85408063 7.87483694,1.80397192 7.92891392,1.78513476 L7.97077778,1.77777778 Z" id="形状结合"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
19
web/src/assets/images/package/sla.svg
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>SLA</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-套餐管理-个人版" transform="translate(-1058, -694)" fill="currentColor" fill-rule="nonzero">
|
||||
<g id="编组-5备份-4" transform="translate(1032, 112)">
|
||||
<g id="编组-13" transform="translate(0, 172)">
|
||||
<g transform="translate(20, 16)" id="SLA">
|
||||
<g transform="translate(6, 394)">
|
||||
<g id="形状" transform="translate(2, 1)">
|
||||
<path d="M10.8664675,0 L1.13077453,0 C0.507469547,0 0,0.500390625 0,1.12109375 L0,12.8789062 C0,13.496875 0.504711561,14 1.13077453,14 L10.8692255,14 C11.4925305,14 12,13.4996094 12,12.8789062 L12,1.12109375 C11.997242,0.500390625 11.4925305,0 10.8664675,0 Z M3.41714548,4.16171875 L4.69960929,3.97578125 C4.84302459,3.95390625 4.96713399,3.86640625 5.03056769,3.73789062 L5.60422891,2.58671875 C5.76419214,2.2640625 6.23029189,2.2640625 6.3930131,2.58671875 L6.96667433,3.73789062 C7.03010802,3.86640625 7.15421742,3.95664062 7.29763273,3.97578125 L8.58009653,4.16171875 C8.94139278,4.21367187 9.08480809,4.65390625 8.82279936,4.90546875 L7.89335785,5.80234375 C7.78855436,5.90351562 7.74166858,6.04570312 7.76649046,6.18789062 L7.98437141,7.45390625 C8.04504712,7.809375 7.66996093,8.08007812 7.34727649,7.91328125 L6.19995403,7.31445312 C6.07308665,7.24882812 5.91863939,7.24882812 5.79177201,7.31445312 L4.64720754,7.91328125 C4.3245231,8.08007812 3.94943691,7.809375 4.01011262,7.45390625 L4.22799356,6.18789062 C4.25281544,6.04570312 4.20592967,5.90351562 4.10112618,5.80234375 L3.17168467,4.90546875 C2.91519191,4.65390625 3.05584923,4.21367187 3.41714548,4.16171875 Z M9.00482648,11.4597656 L2.99241554,11.4597656 C2.65594116,11.4597656 2.38565847,11.1917969 2.38565847,10.8582031 C2.38565847,10.5246094 2.65594116,10.2566406 2.99241554,10.2566406 L9.00482648,10.2566406 C9.34130085,10.2566406 9.61158354,10.5273438 9.61158354,10.8582031 C9.61158354,11.1917969 9.34130085,11.4597656 9.00482648,11.4597656 Z"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
17
web/src/assets/images/package/space.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>空间</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-收费管理" transform="translate(-314, -318)" fill="currentColor" fill-rule="nonzero">
|
||||
<g id="编组-5" transform="translate(288, 64)">
|
||||
<g id="编组-13" transform="translate(0, 228)">
|
||||
<g transform="translate(20, 16)" id="空间">
|
||||
<g transform="translate(6, 10)">
|
||||
<path d="M13.6,5.75002346 L9.16,8.25495925 C8.75,8.48362559 8.5,8.94095826 8.5,9.45026056 L8.5,14.2938293 C8.5,14.8135256 8.99,15.1565251 9.4,14.9174648 L13.84,12.412529 C14.24,12.1838627 14.5,11.72653 14.5,11.2172277 L14.5,6.38405285 C14.5,5.85396271 14.01,5.52135713 13.6,5.75002346 Z M6.84,8.24456533 L2.4,5.75002346 C1.99,5.52135713 1.5,5.85396271 1.5,6.37365893 L1.5,11.2380156 C1.5,11.7473179 1.75,12.2046505 2.16,12.4333169 L6.6,14.9278587 C7.01,15.1565251 7.5,14.8135256 7.5,14.2938293 L7.5,9.43986663 C7.5,8.93056434 7.25,8.47323166 6.84,8.24456533 L6.84,8.24456533 Z M13.19,4.6170857 C13.4,4.50275253 13.5,4.30526797 13.48,4.11817733 C13.5,3.92069276 13.4,3.73360212 13.19,3.61926896 L8.67,1.16630279 C8.47,1.05196962 8.23,1 7.99,1 C7.75,1 7.51,1.05196962 7.31,1.16630279 L2.79,3.60887503 C2.58,3.7232082 2.49,3.92069276 2.5,4.1077834 C2.49,4.30526797 2.58,4.50275253 2.79,4.6170857 L7.31,7.05965794 C7.51,7.17399111 7.75,7.22596073 7.99,7.22596073 C8.23,7.22596073 8.47,7.17399111 8.67,7.05965794 L13.19,4.6170857 Z" id="形状"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
17
web/src/assets/images/package/technical_support.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>合规</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-收费管理" transform="translate(-314, -702)" fill="currentColor" fill-rule="nonzero">
|
||||
<g id="编组-5" transform="translate(288, 64)">
|
||||
<g id="编组-13" transform="translate(0, 228)">
|
||||
<g transform="translate(20, 16)" id="合规">
|
||||
<g transform="translate(6, 394)">
|
||||
<path d="M8,1 C10.1666667,2.37375001 12.3333333,3.47275 14.5,4.294375 C14.5,9.68437502 12.3333333,13.252625 8,15 L7.98618857,14.99475 L7.97410359,15 C3.65803454,13.252625 1.5,9.68437499 1.5,4.294375 C3.65803454,3.471875 5.81606905,2.37462499 7.97410359,1 L7.98705179,1.00874999 L8,1 Z M8,2.74999999 L8,13.25 C11.25,11.93925 12.8745684,9.262625 12.8745684,5.221 C11.25,4.604125 9.6245684,3.78074999 8,2.74999999 Z" id="形状"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
119
web/src/components/SiderMenu/SubscriptionDetailModal.tsx
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-04-14 12:28:23
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-04-16 17:34:02
|
||||
*/
|
||||
|
||||
import { useState, forwardRef, useImperativeHandle } from 'react';
|
||||
import { Flex, Tooltip, Divider } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import clsx from 'clsx';
|
||||
|
||||
import RbModal from '@/components/RbModal';
|
||||
import type { Subscription } from './index'
|
||||
import { billingUnits } from '@/views/Package/constant'
|
||||
import { useI18n } from '@/store/locale'
|
||||
import { UnitWrapper } from '@/views/Package'
|
||||
|
||||
export interface SubscriptionDetailModalRef {
|
||||
handleOpen: (subscription: Subscription | null) => void;
|
||||
}
|
||||
|
||||
const SubscriptionDetailModal = forwardRef<SubscriptionDetailModalRef>((_props, ref) => {
|
||||
const { t } = useTranslation();
|
||||
const [open, setOpen] = useState(false);
|
||||
const { language } = useI18n()
|
||||
const [detail, setDetail] = useState<Subscription | null>(null);
|
||||
|
||||
const handleOpen = (subscription: Subscription | null) => {
|
||||
setOpen(true)
|
||||
setDetail(subscription);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
handleOpen,
|
||||
}));
|
||||
|
||||
const getKeyWithLanguage = (key: string) => {
|
||||
return (language === 'en' ? `${key}_en` : key) as keyof Subscription['package_plan']
|
||||
}
|
||||
|
||||
return (
|
||||
<RbModal
|
||||
title={[t('package.packageDetail'), detail?.package_plan?.[getKeyWithLanguage('name')]].filter(item => item).join(' - ')}
|
||||
open={open}
|
||||
onCancel={handleCancel}
|
||||
footer={null}
|
||||
>
|
||||
{/* Header */}
|
||||
<h3 className="rb:text-[18px] rb:font-bold rb:text-[MiSans-Bold]" style={{ color: detail?.package_plan?.theme_color }}>
|
||||
{String(detail?.package_plan?.[getKeyWithLanguage('name')] ?? '')}
|
||||
</h3>
|
||||
|
||||
{/* Subtitle */}
|
||||
<p className="rb:text-[#5B6167] rb:mb-3">
|
||||
{String(detail?.package_plan?.[getKeyWithLanguage('core_value')] ?? '')}
|
||||
</p>
|
||||
|
||||
{/* Price */}
|
||||
<div className="rb:h-10">
|
||||
{detail?.package_plan?.billing_cycle !== 'permanent_free' && <>
|
||||
<span className="rb:text-[#5B6167] rb:inline-block rb:leading-5 rb:pt-3.25 rb:pb-1.75 rb:mr-1">¥</span>
|
||||
<span className="rb:text-[28px] rb:text-[MiSans-Bold] rb:font-bold rb:leading-10">{detail?.package_plan?.price}</span>
|
||||
</>}
|
||||
{detail?.package_plan?.billing_cycle && (
|
||||
<span className={clsx({
|
||||
'rb:text-[28px] rb:text-[MiSans-Bold] rb:font-bold rb:leading-10': detail?.package_plan?.billing_cycle === 'permanent_free',
|
||||
'rb:text-[#5B6167] rb:inline-block rb:leading-5 rb:pt-3.25 rb:pb-1.75 rb:ml-1': detail?.package_plan?.billing_cycle !== 'permanent_free'
|
||||
})}>
|
||||
{detail?.package_plan?.billing_cycle !== 'permanent_free' && ' /'}
|
||||
{t(`package.${detail?.package_plan?.billing_cycle}`)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Divider className="rb:my-4" />
|
||||
|
||||
{/* Features */}
|
||||
<Flex gap={12} vertical className="rb:space-y-3 rb:mb-4 rb:h-[calc(100vh-341px)]! rb:overflow-y-auto">
|
||||
{billingUnits.map(({ key, unit, icon }) => {
|
||||
const value = detail?.quota[key as keyof Subscription['quota']];
|
||||
if (value === undefined || value === null) return null;
|
||||
return (
|
||||
<UnitWrapper
|
||||
key={key}
|
||||
titleKey={key}
|
||||
value={value}
|
||||
unit={unit}
|
||||
icon={icon}
|
||||
theme_color={detail?.package_plan?.theme_color}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
{detail?.package_plan?.tech_support && (
|
||||
<UnitWrapper
|
||||
titleKey="tech_support"
|
||||
value={String(detail?.package_plan?.[getKeyWithLanguage('tech_support')] ?? '')}
|
||||
icon="technical_support"
|
||||
theme_color={detail?.package_plan?.theme_color}
|
||||
/>
|
||||
)}
|
||||
{detail?.package_plan?.sla_compliance && (
|
||||
<UnitWrapper
|
||||
titleKey="sla"
|
||||
value={String(detail?.package_plan?.[getKeyWithLanguage('sla_compliance')] ?? '')}
|
||||
icon="sla"
|
||||
theme_color={detail?.package_plan?.theme_color}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
</RbModal>
|
||||
);
|
||||
});
|
||||
|
||||
export default SubscriptionDetailModal;
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-02 15:25:31
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-27 19:11:43
|
||||
* @Last Modified time: 2026-04-16 17:35:38
|
||||
*/
|
||||
/**
|
||||
* SiderMenu Component
|
||||
@@ -18,7 +18,7 @@
|
||||
* @component
|
||||
*/
|
||||
|
||||
import { useState, useEffect, type FC } from 'react';
|
||||
import { useState, useEffect, useRef, type FC } from 'react';
|
||||
import { Menu as AntMenu, Layout, Flex } from 'antd';
|
||||
import { UserOutlined } from '@ant-design/icons';
|
||||
import type { MenuProps } from 'antd';
|
||||
@@ -30,6 +30,9 @@ import { useMenu, type MenuItem } from '@/store/menu';
|
||||
import styles from './index.module.css'
|
||||
import logo from '@/assets/images/logo.png'
|
||||
import { useUser } from '@/store/user';
|
||||
import { getTenantSubscription } from '@/api/user';
|
||||
import { useI18n } from '@/store/locale'
|
||||
import SubscriptionDetailModal, { type SubscriptionDetailModalRef } from './SubscriptionDetailModal'
|
||||
|
||||
// Import SVG files
|
||||
// space
|
||||
@@ -70,7 +73,51 @@ import pricingActiveIcon from '@/assets/images/menuNew/pricing_active.svg'
|
||||
import skillsIcon from '@/assets/images/menuNew/skills.svg'
|
||||
import skillsActiveIcon from '@/assets/images/menuNew/skills_active.svg'
|
||||
|
||||
export interface PackagePlan {
|
||||
id: string
|
||||
name: string
|
||||
name_en?: string
|
||||
version: string
|
||||
category: string
|
||||
tier_level: number
|
||||
price: number
|
||||
billing_cycle: string
|
||||
core_value?: string
|
||||
core_value_en?: string
|
||||
tech_support?: string
|
||||
tech_support_en?: string
|
||||
sla_compliance?: string
|
||||
sla_compliance_en?: string
|
||||
page_customization?: string
|
||||
page_customization_en?: string
|
||||
theme_color?: string
|
||||
}
|
||||
|
||||
export interface SubscriptionQuota {
|
||||
app_quota: number
|
||||
model_quota: number
|
||||
skill_quota: number
|
||||
end_user_quota: number
|
||||
workspace_quota: number
|
||||
api_ops_rate_limit: number
|
||||
memory_engine_quota: number
|
||||
ontology_project_quota: number
|
||||
knowledge_capacity_quota: number
|
||||
}
|
||||
|
||||
export interface Subscription {
|
||||
subscription_id: string | null
|
||||
tenant_id: string
|
||||
package_plan_id: string
|
||||
package_version: string
|
||||
package_plan: PackagePlan
|
||||
started_at: number | null
|
||||
expired_at: number | null
|
||||
status: string
|
||||
quota: SubscriptionQuota
|
||||
created_at: number
|
||||
updated_at: number
|
||||
}
|
||||
/** Icon path mapping table for menu items (normal and active states) */
|
||||
const iconPathMap: Record<string, string> = {
|
||||
'dashboard': dashboardIcon,
|
||||
@@ -121,10 +168,12 @@ const Menu: FC<{
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const { t } = useTranslation();
|
||||
const { language } = useI18n()
|
||||
const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
|
||||
const { allMenus, collapsed, loadMenus, toggleSider } = useMenu()
|
||||
const [menus, setMenus] = useState<MenuItem[]>([])
|
||||
const { user, storageType } = useUser()
|
||||
const subscriptionDetailRef = useRef<SubscriptionDetailModalRef>(null)
|
||||
|
||||
/** Filter menus based on user role and source */
|
||||
useEffect(() => {
|
||||
@@ -279,6 +328,25 @@ const Menu: FC<{
|
||||
localStorage.removeItem('user')
|
||||
}
|
||||
|
||||
const [subscription, setSubscription] = useState<Subscription | null>(null)
|
||||
useEffect(() => {
|
||||
if (source === 'manage') {
|
||||
getTenantSubscription()
|
||||
.then(res => {
|
||||
setSubscription(res as Subscription)
|
||||
})
|
||||
} else {
|
||||
setSubscription(null)
|
||||
}
|
||||
}, [source])
|
||||
|
||||
const getKeyWithLanguage = (key: string) => {
|
||||
return (language === 'en' ? `${key}_en` : key) as keyof Subscription['package_plan']
|
||||
}
|
||||
const handleViewDetail = () => {
|
||||
subscriptionDetailRef.current?.handleOpen(subscription)
|
||||
}
|
||||
|
||||
return (
|
||||
<Sider
|
||||
width={240}
|
||||
@@ -325,7 +393,8 @@ const Menu: FC<{
|
||||
inlineIndent={10}
|
||||
className={clsx("rb:overflow-y-auto", {
|
||||
'rb:max-h-[calc(100vh-136px)]': user?.is_superuser && source === 'space',
|
||||
'rb:max-h-[calc(100vh-76px)]': !(user?.is_superuser && source === 'space')
|
||||
'rb:max-h-[calc(100vh-76px)]': !(user?.is_superuser && source === 'space') && !(source === 'manage' && subscription && !collapsed),
|
||||
'rb:max-h-[calc(100vh-228px)]': source === 'manage' && subscription && !collapsed,
|
||||
})}
|
||||
/>
|
||||
{/* Return to space button for superusers */}
|
||||
@@ -341,6 +410,30 @@ const Menu: FC<{
|
||||
{collapsed ? null : t('common.returnToSpace')}
|
||||
</Flex>
|
||||
}
|
||||
{source === 'manage' && subscription && !collapsed &&
|
||||
<div className="rb:absolute rb:bottom-3 rb:left-3 rb:right-3 rb:py-3 rb:bg-cover rb:bg-[url('@/assets/images/menuNew/package_bg.png')] rb:overflow-hidden rb:rounded-xl">
|
||||
<div className="rb:h-4.5 rb:flex-1 rb:truncate rb:px-3 rb:text-[13px] rb:font-medium rb:leading-4.5">{subscription.package_plan?.[getKeyWithLanguage('name')]}</div>
|
||||
|
||||
<div className="rb:grid rb:grid-cols-4 rb:mt-4">
|
||||
{['workspace_quota', 'skill_quota', 'app_quota', 'model_quota'].map(key => (
|
||||
<div key={key} className="rb:text-center">
|
||||
<div className="rb:text-[13px] rb:font-[MiSans-Semibold] rb:font-semibold">{subscription.quota?.[key as keyof typeof subscription.quota]}</div>
|
||||
<div className="rb:mt-1 rb:text-[#5B6167] rb:text-[10px] rb:leading-3.5">{t(`index.${key}`)}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Flex align="center" justify="center" className="rb:mt-4! rb:border rb:p-2! rb:text-[12px] rb:leading-4 rb:mx-3! rb:rounded-lg rb:cursor-pointer"
|
||||
onClick={handleViewDetail}
|
||||
>
|
||||
{t('package.viewDetail')}
|
||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/index/arrow_right_dark.svg')]"></div>
|
||||
</Flex>
|
||||
</div>
|
||||
}
|
||||
|
||||
<SubscriptionDetailModal
|
||||
ref={subscriptionDetailRef}
|
||||
/>
|
||||
</Sider>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15,6 +15,10 @@ export const en = {
|
||||
startedDesc: 'Understand the core functions of the platform and quickly get started through graphic guidance and video tutorials. Includes a full process demonstration from creating a space to publishing an application.',
|
||||
spaceTitle:'Memory Bear Intelligent Space Management Platform',
|
||||
spaceSubTitle: 'Making it easier to implement intelligent models - a one-stop platform for model management, knowledge building, workflow orchestration, and spatial operations',
|
||||
workspace_quota: 'Spaces',
|
||||
skill_quota: 'Skills',
|
||||
app_quota: 'Apps',
|
||||
model_quota: 'Models',
|
||||
},
|
||||
version:{
|
||||
releaseDate: 'Release Date',
|
||||
@@ -2891,8 +2895,8 @@ Memory Bear: After the rebellion, regional warlordism intensified for several re
|
||||
context_details: 'Preference Details',
|
||||
supporting_evidence: 'Preference Source',
|
||||
specific_examples: 'Source',
|
||||
preferencesTip: 'Reminder: Click on the preferences above to view the corresponding Lenovo network',
|
||||
wordEmpty: 'There is currently no Lenovo network available',
|
||||
preferencesTip: 'Reminder: Click on the preferences above to view the corresponding association network',
|
||||
wordEmpty: 'There is currently no association network available',
|
||||
noData: 'Portrait data does not exist, please click the refresh button to initialize',
|
||||
},
|
||||
shortTermDetail: {
|
||||
@@ -3079,6 +3083,8 @@ Memory Bear: After the rebellion, regional warlordism intensified for several re
|
||||
ontology_project_quota: 'Ontology Project',
|
||||
model_quota: 'Model Quota',
|
||||
editPackage: 'Edit Package',
|
||||
|
||||
viewDetail: 'View full package details',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -15,6 +15,10 @@ export const zh = {
|
||||
startedDesc: '了解该平台的核心功能,并通过图形指引和视频教程快速上手。包含从创建空间到发布应用程序的整个操作流程演示。',
|
||||
spaceTitle:'记忆熊智能空间管理平台',
|
||||
spaceSubTitle: '使智能模型的实施变得更加容易——一个集模型管理、知识构建、工作流程编排以及空间操作于一体的综合性平台',
|
||||
workspace_quota: '空间',
|
||||
skill_quota: '技能',
|
||||
app_quota: '应用',
|
||||
model_quota: '模型',
|
||||
},
|
||||
version:{
|
||||
releaseDate: '发布日',
|
||||
@@ -3043,6 +3047,8 @@ export const zh = {
|
||||
ontology_project_quota: '本体工程',
|
||||
model_quota: '可负载模型数量',
|
||||
editPackage: '编辑套餐',
|
||||
|
||||
viewDetail: '查看完整套餐详情',
|
||||
},
|
||||
},
|
||||
}
|
||||
5
web/src/svg.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
declare module '*.svg?react' {
|
||||
import type { FC, SVGProps } from 'react'
|
||||
const ReactComponent: FC<SVGProps<SVGSVGElement>>
|
||||
export default ReactComponent
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import { clearAuthData } from './auth';
|
||||
import { message } from 'antd';
|
||||
import { refreshTokenUrl, refreshToken, loginUrl, logoutUrl } from '@/api/user'
|
||||
import i18n from '@/i18n'
|
||||
import { SYS_API_PREFIX } from '@/api/package'
|
||||
|
||||
/**
|
||||
* Standard API response structure
|
||||
@@ -75,10 +74,6 @@ let requests: RequestQueueItem[] = [];
|
||||
// Request interceptor
|
||||
service.interceptors.request.use(
|
||||
(config) => {
|
||||
console.log('config', config, config.url?.startsWith(SYS_API_PREFIX))
|
||||
if (config.url?.startsWith(SYS_API_PREFIX)) {
|
||||
config.baseURL = '';
|
||||
}
|
||||
if (!config.headers.Authorization) {
|
||||
const token = cookieUtils.get('authToken');
|
||||
if (token) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Space, Button, Row, Col, Flex } from 'antd';
|
||||
import { Space, Button, Flex } from 'antd';
|
||||
|
||||
import TopCardList from './components/TopCardList';
|
||||
import GuideCard from './components/GuideCard';
|
||||
|
||||
@@ -2,39 +2,52 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-04-14 11:43:57
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-04-14 14:55:20
|
||||
* @Last Modified time: 2026-04-14 11:44:40
|
||||
*/
|
||||
export const billingUnits = [
|
||||
{
|
||||
key: 'workspace_quota',
|
||||
unit: 'pcs', placeholder: 'numberPlaceholder',
|
||||
icon: 'space',
|
||||
},
|
||||
{
|
||||
key: 'skill_quota',
|
||||
unit: 'pcs', placeholder: 'numberPlaceholder',
|
||||
icon: 'skill',
|
||||
},
|
||||
{
|
||||
key: 'app_quota',
|
||||
unit: 'pcs', placeholder: 'numberPlaceholder',
|
||||
icon: 'app',
|
||||
},
|
||||
{
|
||||
key: 'knowledge_capacity_quota',
|
||||
unit: 'GB', placeholder: 'numberPlaceholder',
|
||||
icon: 'knowledge',
|
||||
},
|
||||
{
|
||||
key: 'memory_engine_quota',
|
||||
unit: 'pcs', placeholder: 'numberPlaceholder',
|
||||
icon: 'memory_config',
|
||||
},
|
||||
{
|
||||
key: 'end_user_quota',
|
||||
unit: 'pcs', placeholder: 'numberPlaceholder',
|
||||
icon: 'end_user',
|
||||
},
|
||||
{
|
||||
key: 'ontology_project_quota',
|
||||
unit: 'pcs', placeholder: 'numberPlaceholder',
|
||||
icon: 'ontology',
|
||||
},
|
||||
{
|
||||
key: 'model_quota',
|
||||
unit: 'ops', placeholder: 'numberPlaceholder',
|
||||
icon: 'model',
|
||||
},
|
||||
{
|
||||
key: 'api_ops_rate_limit',
|
||||
unit: 'ops', placeholder: 'numberPlaceholder',
|
||||
icon: 'api_ops',
|
||||
},
|
||||
]
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-25
|
||||
* @Date: 2026-04-14 11:34:42
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-04-14 14:59:11
|
||||
* @Last Modified time: 2026-04-16 17:23:49
|
||||
*/
|
||||
/**
|
||||
* Package Component
|
||||
@@ -15,11 +15,11 @@
|
||||
* @component
|
||||
*/
|
||||
|
||||
import { useMemo, useState, useEffect, type FC } from 'react';
|
||||
import { useRef, useMemo, useState, useEffect, type FC, type ComponentType, type SVGProps } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Flex, Row, Col, type SegmentedProps } from 'antd';
|
||||
import { Flex, Tooltip, Divider, Button, type SegmentedProps } from 'antd';
|
||||
import clsx from 'clsx';
|
||||
import Icon from '@ant-design/icons'
|
||||
|
||||
import type { Package } from './types'
|
||||
import { getPackageList } from '@/api/package';
|
||||
@@ -28,27 +28,95 @@ import { billingUnits } from './constant'
|
||||
import RbCard from '@/components/RbCard/Card'
|
||||
import BodyWrapper from '@/components/Empty/BodyWrapper'
|
||||
import { useI18n } from '@/store/locale'
|
||||
import RbButton from '@/components/RbButton'
|
||||
|
||||
import SpaceSvg from '@/assets/images/package/space.svg?react'
|
||||
import SkillSvg from '@/assets/images/package/skill.svg?react'
|
||||
import AppSvg from '@/assets/images/package/app.svg?react'
|
||||
import KnowledgeSvg from '@/assets/images/package/knowledge.svg?react'
|
||||
import MemoryConfigSvg from '@/assets/images/package/memory_config.svg?react'
|
||||
import EndUserSvg from '@/assets/images/package/end_user.svg?react'
|
||||
import OntologySvg from '@/assets/images/package/ontology.svg?react'
|
||||
import ModelSvg from '@/assets/images/package/model.svg?react'
|
||||
import TechnicalSupportSvg from '@/assets/images/package/technical_support.svg?react'
|
||||
import ApiOpsSvg from '@/assets/images/package/api_ops.svg?react'
|
||||
import arrowSvg from '@/assets/images/package/arrow.svg?react'
|
||||
import slaSvg from '@/assets/images/package/sla.svg?react';
|
||||
|
||||
const iconMap: Record<string, ComponentType<SVGProps<SVGSVGElement>>> = {
|
||||
space: SpaceSvg,
|
||||
skill: SkillSvg,
|
||||
app: AppSvg,
|
||||
knowledge: KnowledgeSvg,
|
||||
memory_config: MemoryConfigSvg,
|
||||
end_user: EndUserSvg,
|
||||
ontology: OntologySvg,
|
||||
model: ModelSvg,
|
||||
technical_support: TechnicalSupportSvg,
|
||||
api_ops: ApiOpsSvg,
|
||||
sla: slaSvg,
|
||||
}
|
||||
const btnClassNames = {
|
||||
permanent_free: 'rb:h-10! rb:rounded-[8px]!',
|
||||
default: 'rb:h-10! rb:rounded-[8px]! rb:bg-[#212332]! rb:text-white! rb:border-0! rb:hover:border-0! rb:hover:opacity-[0.8]',
|
||||
}
|
||||
|
||||
export const UnitWrapper = ({ titleKey, value, icon, unit, theme_color = '#171719' }: { titleKey: string; value: number | string; icon: string; unit?: string; theme_color?: string; }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const renderFeatureIcon = (iconKey: string, color: string) => {
|
||||
const SvgComponent = iconMap[iconKey]
|
||||
if (!SvgComponent) return null
|
||||
return <Icon component={SvgComponent} style={{ color, fontSize: 16 }} />
|
||||
}
|
||||
return (
|
||||
<Flex key={titleKey} align="start" gap={16}>
|
||||
<Flex
|
||||
align="center"
|
||||
justify="center"
|
||||
className="rb:mt-1! rb:shrink-0 rb:rounded-lg rb:size-7"
|
||||
style={{ backgroundColor: `${theme_color}14` }}
|
||||
>{renderFeatureIcon(icon, theme_color)}</Flex>
|
||||
<div className="rb:text-[13px] rb:leading-4.5">
|
||||
<div className="rb:text-[#5F6266]">{t(`package.${titleKey}`)}</div>
|
||||
<div>{value} {unit ? t(`package.${unit}`) : ''}</div>
|
||||
</div>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
const Package: FC = () => {
|
||||
const { t } = useTranslation();
|
||||
const { language } = useI18n()
|
||||
const navigate = useNavigate();
|
||||
const [data, setData] = useState<Package[]>([])
|
||||
const scrollRef = useRef<HTMLDivElement>(null)
|
||||
const CARD_WIDTH = 360
|
||||
const GAP = 12
|
||||
const [visibleCount, setVisibleCount] = useState(3)
|
||||
|
||||
useEffect(() => {
|
||||
const calcVisible = () => {
|
||||
if (!scrollRef.current) return
|
||||
const w = scrollRef.current.offsetWidth
|
||||
setVisibleCount(Math.floor((w + GAP) / (CARD_WIDTH + GAP)))
|
||||
}
|
||||
calcVisible()
|
||||
window.addEventListener('resize', calcVisible)
|
||||
return () => window.removeEventListener('resize', calcVisible)
|
||||
}, [])
|
||||
|
||||
const [activeTab, setActiveTab] = useState('saas_personal');
|
||||
const formatTabItems = useMemo(() => {
|
||||
return ['saas_personal', 'commercial_deployment'].map(value => ({
|
||||
value,
|
||||
label: t(`package.${value}`),
|
||||
label: `${t(`package.${value}`)}`,
|
||||
}))
|
||||
}, [t])
|
||||
/** Handle tab change */
|
||||
}, [t, activeTab])
|
||||
|
||||
const handleChangeTab = (value: SegmentedProps['value']) => {
|
||||
setActiveTab(value as string);
|
||||
}
|
||||
const getList = () => {
|
||||
getPackageList({ category: activeTab as Package['category'], status: true })
|
||||
getPackageList({ category: activeTab as Package['category'] })
|
||||
.then(res => {
|
||||
setData(res as Package[] || [])
|
||||
})
|
||||
@@ -61,10 +129,20 @@ const Package: FC = () => {
|
||||
const getKeyWithLanguage = (key: string) => {
|
||||
return (language === 'en' ? `${key}_en` : key) as keyof Package
|
||||
}
|
||||
/** Navigate to order history */
|
||||
const goToHistory = () => {
|
||||
navigate('/orders');
|
||||
}
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(0)
|
||||
const totalPages = visibleCount > 0 ? Math.ceil(data.length / visibleCount) : 1
|
||||
const showArrows = totalPages > 1
|
||||
const pageData = data.slice(currentPage * visibleCount, (currentPage + 1) * visibleCount)
|
||||
|
||||
useEffect(() => {
|
||||
setCurrentPage(0)
|
||||
}, [activeTab, visibleCount])
|
||||
|
||||
const handleChoosePlan = () => {
|
||||
window.open(`https://docs.redbearai.com/s/${language || 'en'}-memorybear`, '_blank')
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex justify="space-between" className="rb:mb-4!">
|
||||
@@ -73,70 +151,136 @@ const Package: FC = () => {
|
||||
options={formatTabItems}
|
||||
onChange={handleChangeTab}
|
||||
/>
|
||||
<RbButton className="rb:text-[#212332] rb:font-medium!" onClick={goToHistory}>
|
||||
<div
|
||||
className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/order/order.svg')]"
|
||||
></div>
|
||||
{t('pricing.orderHistory')}
|
||||
</RbButton>
|
||||
</Flex>
|
||||
<BodyWrapper empty={data.length < 1}>
|
||||
<Row gutter={[12, 12]} className="rb:max-h-[calc(100%-48px)]! rb:overflow-y-auto">
|
||||
{data.map((pkg) => (
|
||||
<Col key={pkg.id} span={8}>
|
||||
<RbCard
|
||||
className="rb:h-full! rb:shadow-md hover:rb:shadow-lg rb:transition-shadow"
|
||||
bodyClassName="rb:p-6! rb:h-full!"
|
||||
headerClassName="rb:min-h-0!"
|
||||
>
|
||||
<Flex vertical justify="space-between" className="rb:h-full!">
|
||||
<div>
|
||||
{/* Header */}
|
||||
<div className="rb:text-center rb:mb-6">
|
||||
<h3 className="rb:text-xl rb:font-bold rb:mb-2 rb:min-h-7" style={{ color: pkg.theme_color }}>
|
||||
{String(pkg[getKeyWithLanguage('name')] ?? '')}
|
||||
</h3>
|
||||
<p className="rb:text-sm rb:text-gray-500 rb:mb-4 rb:min-h-5">{String(pkg[getKeyWithLanguage('core_value')] ?? '')}</p>
|
||||
<div className="rb:text-4xl rb:font-bold rb:mb-2">
|
||||
{pkg.billing_cycle !== 'permanent_free' && <>¥{pkg.price}</>}
|
||||
{pkg.billing_cycle && <span className={clsx("", {
|
||||
'rb:text-base rb:font-normal rb:text-gray-500': pkg.billing_cycle !== 'permanent_free'
|
||||
})}>{pkg.billing_cycle !== 'permanent_free' && '/'}{t(`package.${pkg.billing_cycle}`)}</span>}
|
||||
</div>
|
||||
<div ref={scrollRef} className="rb:relative rb:mx-9">
|
||||
{showArrows && (
|
||||
<Flex
|
||||
align="center"
|
||||
justify="center"
|
||||
className={clsx("rb:absolute rb:-left-6 rb:top-1/2 rb:-translate-y-1/2 rb:-translate-x-3 rb:z-10 rb:h-25 rb:rounded-lg rb:w-6 rb:bg-[rgba(255,255,255,0.6)] rb:border rb:border-[rgba(255,255,255,0.6)]", {
|
||||
'rb:hover:border-[#171719] rb:cursor-pointer': currentPage > 0,
|
||||
'rb:cursor-not-allowed': currentPage === 0
|
||||
})}
|
||||
onClick={() => {
|
||||
if (currentPage === 0) return
|
||||
setCurrentPage(p => p - 1)
|
||||
}}
|
||||
>
|
||||
<Icon component={arrowSvg} style={{ color: currentPage === 0 ? '#E1E2E7' : '#171719', fontSize: 24 }} />
|
||||
</Flex>
|
||||
)}
|
||||
|
||||
<Flex gap={GAP} justify="center">
|
||||
{pageData.map((pkg) => (
|
||||
<div key={pkg.id} style={{ width: CARD_WIDTH, flexShrink: 0 }}>
|
||||
<RbCard
|
||||
className="rb:h-full! rb:hover:shadow-[0px_4px_10px_0px_rgba(0,0,0,0.12)]!"
|
||||
bodyClassName="rb:p-0! rb:pb-4! rb:h-full!"
|
||||
headerClassName="rb:min-h-0!"
|
||||
>
|
||||
<div className="rb:px-5 rb:pt-4">
|
||||
<div className="rb:h-25!">
|
||||
{/* Header */}
|
||||
<Flex justify="space-between" align="start" className="rb:mb-1!">
|
||||
<Tooltip title={String(pkg[getKeyWithLanguage('name')] ?? '')}>
|
||||
<h3 className="rb:text-[18px] rb:font-bold rb:text-[MiSans-Bold] rb:w-54.5 rb:line-clamp-2" style={{ color: pkg.theme_color }}>
|
||||
{String(pkg[getKeyWithLanguage('name')] ?? '')}
|
||||
</h3>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
|
||||
{/* Subtitle */}
|
||||
<Tooltip title={String(pkg[getKeyWithLanguage('core_value')] ?? '')}>
|
||||
<p className="rb:text-[#5B6167] rb:mb-4 rb:line-clamp-1">
|
||||
{String(pkg[getKeyWithLanguage('core_value')] ?? '')}
|
||||
</p>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
{/* Price */}
|
||||
<div className="rb:h-10 rb:mb-4">
|
||||
{pkg.billing_cycle !== 'permanent_free' && <>
|
||||
<span className="rb:text-[#5B6167] rb:inline-block rb:leading-5 rb:pt-3.25 rb:pb-1.75 rb:mr-1">¥</span>
|
||||
<span className="rb:text-[28px] rb:text-[MiSans-Bold] rb:font-bold rb:leading-10">{pkg.price}</span>
|
||||
</>}
|
||||
{pkg.billing_cycle && (
|
||||
<span className={clsx({
|
||||
'rb:text-[28px] rb:text-[MiSans-Bold] rb:font-bold rb:leading-10': pkg.billing_cycle === 'permanent_free',
|
||||
'rb:text-[#5B6167] rb:inline-block rb:leading-5 rb:pt-3.25 rb:pb-1.75 rb:ml-1': pkg.billing_cycle !== 'permanent_free'
|
||||
})}>
|
||||
{pkg.billing_cycle !== 'permanent_free' && ' /'}
|
||||
{t(`package.${pkg.billing_cycle}`)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Button
|
||||
type={pkg.billing_cycle !== 'permanent_free' ? 'primary' : 'default'}
|
||||
block
|
||||
className={btnClassNames[pkg.billing_cycle === 'permanent_free' ? 'permanent_free' : 'default']}
|
||||
onClick={handleChoosePlan}
|
||||
>
|
||||
{t('pricing.contactBtn')}
|
||||
</Button>
|
||||
|
||||
<Divider className="rb:my-4" />
|
||||
|
||||
{/* Features */}
|
||||
<div className="rb:space-y-3">
|
||||
{billingUnits.map(({ key, unit }) => {
|
||||
if (typeof pkg.quotas[key as keyof Package['quotas']] === 'number') {
|
||||
return (
|
||||
<div key={key} className="rb:flex rb:items-center rb:justify-between rb:text-sm">
|
||||
<span className="rb:text-gray-500">{t(`package.${key}`)}</span>
|
||||
<span>{pkg.quotas[key as keyof Package['quotas']]}{t(`package.${unit}`)}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<Flex gap={12} vertical className="rb:space-y-3 rb:mb-4 rb:h-[calc(100vh-401px)]! rb:overflow-y-auto">
|
||||
{billingUnits.map(({ key, unit, icon }) => {
|
||||
const value = pkg?.quotas?.[key as keyof Package['quotas']];
|
||||
if (value === undefined || value === null) return null;
|
||||
return (
|
||||
<UnitWrapper
|
||||
titleKey={key}
|
||||
value={value}
|
||||
unit={unit}
|
||||
icon={icon}
|
||||
theme_color={pkg.theme_color}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
{pkg.api_ops_rate_limit &&
|
||||
<div className="rb:flex rb:items-center rb:justify-between rb:text-sm">
|
||||
<span className="rb:text-gray-500">{t(`package.api_ops_rate_limit`)}</span>
|
||||
<span>{pkg.api_ops_rate_limit}{t('package.ops')}</span>
|
||||
</div>
|
||||
}
|
||||
{pkg.tech_support &&
|
||||
<div className="rb:flex rb:items-center rb:justify-between rb:text-sm">
|
||||
<span className="rb:text-gray-500">{t(`package.tech_support`)}</span>
|
||||
<span>{String(pkg[getKeyWithLanguage('tech_support')] ?? '')}</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
{pkg.tech_support && (
|
||||
<UnitWrapper
|
||||
titleKey="tech_support"
|
||||
value={String(pkg[getKeyWithLanguage('tech_support')] ?? '')}
|
||||
icon="technical_support"
|
||||
theme_color={pkg.theme_color}
|
||||
/>
|
||||
)}
|
||||
{pkg.sla_compliance && (
|
||||
<UnitWrapper
|
||||
titleKey="sla"
|
||||
value={String(pkg[getKeyWithLanguage('sla_compliance')] ?? '')}
|
||||
icon="sla"
|
||||
theme_color={pkg.theme_color}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
</div>
|
||||
</Flex>
|
||||
</RbCard>
|
||||
</div>
|
||||
))}
|
||||
</Flex>
|
||||
|
||||
</RbCard>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
{showArrows && (
|
||||
<Flex
|
||||
align="center"
|
||||
justify="center"
|
||||
className={clsx("rb:absolute rb:-right-12 rb:top-1/2 rb:-translate-y-1/2 rb:-translate-x-3 rb:z-10 rb:h-25 rb:rounded-lg rb:w-6 rb:bg-[rgba(255,255,255,0.6)] rb:border rb:border-[rgba(255,255,255,0.6)]", {
|
||||
'rb:hover:border-[#171719] rb:cursor-pointer': currentPage < totalPages - 1,
|
||||
'rb:cursor-not-allowed': currentPage >= totalPages - 1
|
||||
})}
|
||||
onClick={() => {
|
||||
if (currentPage >= totalPages - 1) return
|
||||
setCurrentPage(p => p + 1)
|
||||
}}
|
||||
>
|
||||
<Icon component={arrowSvg} className="rb:rotate-180" style={{ color: currentPage >= totalPages - 1 ? '#E1E2E7' : '#171719', fontSize: 24 }} />
|
||||
</Flex>
|
||||
)}
|
||||
</div>
|
||||
</BodyWrapper>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -2,60 +2,60 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-04-14 11:35:01
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-04-14 14:28:46
|
||||
* @Last Modified time: 2026-04-16 16:44:19
|
||||
*/
|
||||
export interface Package {
|
||||
id: string;
|
||||
// 名称
|
||||
name: string;
|
||||
name_en: string;
|
||||
// 类型
|
||||
category: "saas_personal" | "commercial_deployment";
|
||||
tier_level: number;
|
||||
// 版本
|
||||
version: string;
|
||||
// 状态
|
||||
status: boolean;
|
||||
// 价格
|
||||
price: string;
|
||||
// 计费周期
|
||||
billing_cycle: "monthly" | "yearly" | "permanent_free" | "local_deployment";
|
||||
// 核心价值
|
||||
core_value: string;
|
||||
core_value_en: string;
|
||||
// 技术支持
|
||||
tech_support: string;
|
||||
tech_support_en: string;
|
||||
// SLA与合规
|
||||
sla_compliance: string;
|
||||
sla_compliance_en: string;
|
||||
// 对话页面个性化配置
|
||||
page_customization: string;
|
||||
page_customization_en: string;
|
||||
// API OPS 频次(次/秒)
|
||||
api_ops_rate_limit: number;
|
||||
// 主题色
|
||||
theme_color: string;
|
||||
quotas: {
|
||||
// 空间数量
|
||||
workspace_quota: number;
|
||||
// 技能库数量
|
||||
skill_quota: number;
|
||||
// 应用数量
|
||||
app_quota: number;
|
||||
// 知识库容量
|
||||
knowledge_capacity_quota: string;
|
||||
// 记忆引擎数量
|
||||
memory_engine_quota: number;
|
||||
// 可记忆终端用户数
|
||||
end_user_quota: number;
|
||||
// 本体工程
|
||||
ontology_project_quota: number;
|
||||
// 可负载模型数量
|
||||
model_quota: number;
|
||||
},
|
||||
created_at: number;
|
||||
updated_at: number;
|
||||
created_by: string;
|
||||
updated_by: string | null;
|
||||
id: string;
|
||||
// 名称
|
||||
name: string | null;
|
||||
name_en: string | null;
|
||||
// 类型
|
||||
category: "saas_personal" | "commercial_deployment";
|
||||
tier_level: number;
|
||||
// 版本
|
||||
version: string;
|
||||
// 状态
|
||||
status: boolean;
|
||||
// 价格
|
||||
price: string | null;
|
||||
// 计费周期
|
||||
billing_cycle: "monthly" | "yearly" | "permanent_free" | "local_deployment";
|
||||
// 核心价值
|
||||
core_value: string | null;
|
||||
core_value_en: string | null;
|
||||
// 技术支持
|
||||
tech_support: string | null;
|
||||
tech_support_en: string | null;
|
||||
// SLA与合规
|
||||
sla_compliance: string | null;
|
||||
sla_compliance_en: string | null;
|
||||
// 对话页面个性化配置
|
||||
page_customization: string | null;
|
||||
page_customization_en: string | null;
|
||||
// 主题色
|
||||
theme_color: string;
|
||||
quotas: {
|
||||
// API OPS 频次(次/秒)
|
||||
api_ops_rate_limit: number | null;
|
||||
// 空间数量
|
||||
workspace_quota: number | null;
|
||||
// 技能库数量
|
||||
skill_quota: number | null;
|
||||
// 应用数量
|
||||
app_quota: number | null;
|
||||
// 知识库容量
|
||||
knowledge_capacity_quota: number | null;
|
||||
// 记忆引擎数量
|
||||
memory_engine_quota: number | null;
|
||||
// 可记忆终端用户数
|
||||
end_user_quota: number | null;
|
||||
// 本体工程
|
||||
ontology_project_quota: number | null;
|
||||
// 可负载模型数量
|
||||
model_quota: number | null;
|
||||
},
|
||||
created_at: number;
|
||||
updated_at: number;
|
||||
created_by: string | null;
|
||||
updated_by: string | null;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import react from '@vitejs/plugin-react'
|
||||
import { resolve } from 'path'
|
||||
import AutoImport from 'unplugin-auto-import/vite'
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
import svgr from 'vite-plugin-svgr';
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
@@ -32,6 +33,7 @@ export default defineConfig({
|
||||
imports: ['react', 'react-router-dom'],
|
||||
dts: 'public/auto-imports.d.ts',
|
||||
}),
|
||||
svgr({ svgrOptions: { icon: true } }),
|
||||
],
|
||||
css: {
|
||||
modules: {
|
||||
|
||||