@appthen/cli 1.2.10 → 1.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/.gitignore +1 -0
  2. package/bin/main.js +92 -0
  3. package/dist/index.js +7014 -14988
  4. package/package.json +8 -1
  5. package/tests/test-app/.appthen/shadow-space-100001-test-app-e99876b1.json +1862 -0
  6. package/tests/test-app/.appthen/space-config.json +8 -0
  7. package/tests/test-app/docs/AI-Workflow.flow +112 -0
  8. package/tests/test-app/docs/Logic-1.flow +16 -0
  9. package/tests/test-app/docs/Logic.flow +16 -0
  10. package/tests/test-app/docs/Project-Blueprint-1.flow +119 -0
  11. package/tests/test-app/docs/Project-Blueprint.flow +119 -0
  12. package/tests/test-app/docs/README.md +3 -0
  13. package/tests/test-app/docs/claude.md +194 -0
  14. package/tests/test-app/docs/page_requirement_analysis.md +149 -0
  15. package/tests/test-app/docs//345/267/245/345/215/225/347/256/241/347/220/206/347/263/273/347/273/237/350/257/246/347/273/206/350/256/276/350/256/241.md +377 -0
  16. package/tests/test-app/src/apis/AddTodoPost.api.ts +42 -0
  17. package/tests/test-app/src/apis/DeleteTodoPost.api.ts +32 -0
  18. package/tests/test-app/src/apis/GetListPost.api.ts +38 -0
  19. package/tests/test-app/src/apis/TicketAttachmentUploadPost.api.ts +42 -0
  20. package/tests/test-app/src/apis/UpdateTodoPost.api.ts +46 -0
  21. package/tests/test-app/src/app.css +15 -0
  22. package/tests/test-app/src/cloud_functions/ticket|attachment|upload.node.ts +86 -0
  23. package/tests/test-app/src/cloud_functions/ticket|comment|add.node.ts +65 -0
  24. package/tests/test-app/src/cloud_functions/types|entity|Ticket.node.ts +88 -0
  25. package/tests/test-app/src/cloud_functions/types|entity|TicketAttachment.node.ts +70 -0
  26. package/tests/test-app/src/cloud_functions/types|entity|TicketCategory.node.ts +56 -0
  27. package/tests/test-app/src/cloud_functions/types|entity|TicketComment.node.ts +62 -0
  28. package/tests/test-app/src/cloud_functions/types|entity|TicketHistory.node.ts +74 -0
  29. package/tests/test-app/src/cloud_functions/types|entity|TicketPriority.node.ts +68 -0
  30. package/tests/test-app/src/cloud_functions/types|entity|TicketStatus.node.ts +63 -0
  31. package/tests/test-app/src/cloud_functions/types|models|CreateTicketParams.node.ts +20 -0
  32. package/tests/test-app/src/cloud_functions/types|models|TicketListParams.node.ts +30 -0
  33. package/tests/test-app/src/cloud_functions/types|models|UpdateTicketParams.node.ts +22 -0
  34. package/tests/test-app/src/components/Button.js +11 -0
  35. package/tests/test-app/src/components/MessageCenter.tsx +506 -0
  36. package/tests/test-app/src/components/MouduleDemoNzp.tsx +40 -0
  37. package/tests/test-app/src/components/Timeline.tsx +145 -0
  38. package/tests/test-app/src/index.ts +2 -0
  39. package/tests/test-app/src/modules/work_order_module/apis/TicketCommentAddPost.api.ts +48 -0
  40. package/tests/test-app/src/modules/work_order_module/apis/TicketCreatePost.api.ts +52 -0
  41. package/tests/test-app/src/modules/work_order_module/apis/TicketDeleteDelete.api.ts +39 -0
  42. package/tests/test-app/src/modules/work_order_module/apis/TicketDetailGet.api.ts +39 -0
  43. package/tests/test-app/src/modules/work_order_module/apis/TicketListGet.api.ts +61 -0
  44. package/tests/test-app/src/modules/work_order_module/apis/TicketUpdatePut.api.ts +57 -0
  45. package/tests/test-app/src/modules/work_order_module/apis/TrainDoorFaultListGet.ts +76 -0
  46. package/tests/test-app/src/modules/work_order_module/apis/TrainDoorListGet.ts +76 -0
  47. package/tests/test-app/src/modules/work_order_module/apis/TrainDoorOperationRecordsGet.ts +284 -0
  48. package/tests/test-app/src/modules/work_order_module/apis/TrainDoorStatisticsGet.ts +96 -0
  49. package/tests/test-app/src/modules/work_order_module/cloud_function/category|list.node.ts +40 -0
  50. package/tests/test-app/src/modules/work_order_module/cloud_function/priority|list.node.ts +26 -0
  51. package/tests/test-app/src/modules/work_order_module/cloud_function/status|list.node.ts +26 -0
  52. package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|create.node.ts +54 -0
  53. package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|delete.node.ts +55 -0
  54. package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|detail.node.ts +65 -0
  55. package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|list.node.ts +85 -0
  56. package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|update.node.ts +73 -0
  57. package/tests/test-app/src/modules/work_order_module/data_model/Ticket.m.ts +85 -0
  58. package/tests/test-app/src/modules/work_order_module/data_model/TicketCategory.m.ts +53 -0
  59. package/tests/test-app/src/modules/work_order_module/data_model/TicketStatus.m.ts +60 -0
  60. package/tests/test-app/src/modules/work_order_module//345/267/245/345/215/225/347/263/273/347/273/237/344/272/247/345/223/201/350/256/276/350/256/241/346/226/207/346/241/243.md +301 -0
  61. package/tests/test-app/src/modules/work_order_module//345/267/245/345/215/225/347/263/273/347/273/237/345/274/200/345/217/221/344/273/273/345/212/241/345/210/206/345/267/245/346/226/207/346/241/243.md +345 -0
  62. package/tests/test-app/src/pages/CustomerManagement.tsx +535 -0
  63. package/tests/test-app/src/pages/CyberpunkDashboard.tsx +348 -0
  64. package/tests/test-app/src/pages/CyberpunkProductManagement.tsx +637 -0
  65. package/tests/test-app/src/pages/CyberpunkUserList.tsx +316 -0
  66. package/tests/test-app/src/pages/DashboardV2.tsx +334 -0
  67. package/tests/test-app/src/pages/DataReport.tsx +298 -0
  68. package/tests/test-app/src/pages/DataStatistics.tsx +317 -0
  69. package/tests/test-app/src/pages/DepartmentManagement.tsx +503 -0
  70. package/tests/test-app/src/pages/FileExplorer.tsx +441 -0
  71. package/tests/test-app/src/pages/OrderDetail.tsx +393 -0
  72. package/tests/test-app/src/pages/ProductManagement.tsx +521 -0
  73. package/tests/test-app/src/pages/ProjectTimeline.tsx +395 -0
  74. package/tests/test-app/src/pages/RoleManagement.tsx +523 -0
  75. package/tests/test-app/src/pages/SLAManagement.tsx +668 -0
  76. package/tests/test-app/src/pages/StaticCyberpunkDashboard.tsx +462 -0
  77. package/tests/test-app/src/pages/StaticCyberpunkUserList.tsx +567 -0
  78. package/tests/test-app/src/pages/StudentWeaknessList.tsx +547 -0
  79. package/tests/test-app/src/pages/SystemSettings.tsx +422 -0
  80. package/tests/test-app/src/pages/TaskManagement.tsx +467 -0
  81. package/tests/test-app/src/pages/TicketCreate.tsx +27 -0
  82. package/tests/test-app/src/pages/TicketDetail.tsx +27 -0
  83. package/tests/test-app/src/pages/TicketList.tsx +27 -0
  84. package/tests/test-app/src/pages/TicketManagement.tsx +402 -0
  85. package/tests/test-app/src/pages/TicketManagementPage.tsx +1238 -0
  86. package/tests/test-app/src/pages/UserProfile.tsx +404 -0
  87. package/tests/test-app/src/pages/VisualAIIDEUpgrade.tsx +245 -0
  88. package/tests/test-app/src/pages/WorkflowDesigner.tsx +434 -0
  89. package/tests/test-app/src/pages/admin/dashboard.tsx +591 -0
  90. package/tests/test-app/src/pages/appthen_guide/ComponentTreeUnderstanding.tsx +26 -0
  91. package/tests/test-app/src/pages/appthen_guide/DataBindingLearning.tsx +26 -0
  92. package/tests/test-app/src/pages/article-list.tsx +222 -0
  93. package/tests/test-app/src/pages/babyProductRecommendationPage.tsx +168 -0
  94. package/tests/test-app/src/pages/back-end/adminRootLayout.tsx +155 -0
  95. package/tests/test-app/src/pages/back-end/adminRootLayout10.tsx +157 -0
  96. package/tests/test-app/src/pages/back-end/adminRootLayout2.tsx +156 -0
  97. package/tests/test-app/src/pages/back-end/adminRootLayout3.tsx +156 -0
  98. package/tests/test-app/src/pages/back-end/adminRootLayout4.tsx +157 -0
  99. package/tests/test-app/src/pages/back-end/adminRootLayout5.tsx +157 -0
  100. package/tests/test-app/src/pages/back-end/adminRootLayout6.tsx +157 -0
  101. package/tests/test-app/src/pages/back-end/adminRootLayout7.tsx +157 -0
  102. package/tests/test-app/src/pages/back-end/adminRootLayout8.tsx +157 -0
  103. package/tests/test-app/src/pages/back-end/adminRootLayout9.tsx +157 -0
  104. package/tests/test-app/src/pages/back-end/backgroundManagementSystem.css +5 -0
  105. package/tests/test-app/src/pages/back-end/backgroundManagementSystem.tsx +1745 -0
  106. package/tests/test-app/src/pages/category-list.tsx +179 -0
  107. package/tests/test-app/src/pages/comment-list.tsx +194 -0
  108. package/tests/test-app/src/pages/component/WorkOrderCard.tsx +140 -0
  109. package/tests/test-app/src/pages/cover.tsx +42 -0
  110. package/tests/test-app/src/pages/cyberpunk/cyberpunkCRMPage.tsx +1299 -0
  111. package/tests/test-app/src/pages/data-analytics.tsx +1872 -0
  112. package/tests/test-app/src/pages/data-overview.tsx +600 -0
  113. package/tests/test-app/src/pages/data_dashboard/blueBrightGreenTechnologyWind.css +181 -0
  114. package/tests/test-app/src/pages/data_dashboard/blueBrightGreenTechnologyWind.tsx +225 -0
  115. package/tests/test-app/src/pages/data_dashboard/blueLargeScreen.css +181 -0
  116. package/tests/test-app/src/pages/data_dashboard/blueLargeScreen.tsx +138 -0
  117. package/tests/test-app/src/pages/data_dashboard/component_library/BlueBrightGreenBorder.tsx +47 -0
  118. package/tests/test-app/src/pages/data_dashboard/component_library/FullScreenContainer.tsx +133 -0
  119. package/tests/test-app/src/pages/demo-error-page.tsx +119 -0
  120. package/tests/test-app/src/pages/department-list.tsx +183 -0
  121. package/tests/test-app/src/pages/description_of_mock_interface.md +32 -0
  122. package/tests/test-app/src/pages/digitalLargeScreen.css +181 -0
  123. package/tests/test-app/src/pages/digitalLargeScreen.tsx +1417 -0
  124. package/tests/test-app/src/pages/goods-list.tsx +233 -0
  125. package/tests/test-app/src/pages/housekeeping/adminDashboardPage.tsx +880 -0
  126. package/tests/test-app/src/pages/mobile_terminal/PersonalCenter.css +3 -0
  127. package/tests/test-app/src/pages/mobile_terminal/PersonalCenter.tsx +362 -0
  128. package/tests/test-app/src/pages/mobile_terminal/WorkOrderHomepage.tsx +337 -0
  129. package/tests/test-app/src/pages/mobile_terminal/newWorkOrder.tsx +224 -0
  130. package/tests/test-app/src/pages/mobile_terminal/tabbar.tsx +67 -0
  131. package/tests/test-app/src/pages/mobile_terminal/uiHandsOnPractice.tsx +638 -0
  132. package/tests/test-app/src/pages/mobile_terminal/workOrderDetails.tsx +346 -0
  133. package/tests/test-app/src/pages/mobile_terminal/workOrderPage.tsx +345 -0
  134. package/tests/test-app/src/pages/notice-list.tsx +217 -0
  135. package/tests/test-app/src/pages/order-detail.tsx +330 -0
  136. package/tests/test-app/src/pages/order-list.tsx +195 -0
  137. package/tests/test-app/src/pages/order-management.tsx +563 -0
  138. package/tests/test-app/src/pages/page/OrderList.tsx +230 -0
  139. package/tests/test-app/src/pages/role-list.tsx +184 -0
  140. package/tests/test-app/src/pages/simple/simplePage.tsx +92 -0
  141. package/tests/test-app/src/pages/simple-page.tsx +43 -0
  142. package/tests/test-app/src/pages/test-destructure.tsx +44 -0
  143. package/tests/test-app/src/pages/test-error-page.tsx +75 -0
  144. package/tests/test-app/src/pages/test-page-with-errors.tsx +51 -0
  145. package/tests/test-app/src/pages/test-page.tsx +101 -0
  146. package/tests/test-app/src/pages/test-render.tsx +52 -0
  147. package/tests/test-app/src/pages/test-return-type.tsx +41 -0
  148. package/tests/test-app/src/pages/test-type-assertion.tsx +37 -0
  149. package/tests/test-app/src/pages/testPage.css +3 -0
  150. package/tests/test-app/src/pages/testPage.tsx +158 -0
  151. package/tests/test-app/src/pages/ui/styleSelectorPage.tsx +1554 -0
  152. package/tests/test-app/src/pages/user-list.tsx +212 -0
  153. package/tests/test-app/src/pages/web_version/website.css +205 -0
  154. package/tests/test-app/src/pages/web_version/website.tsx +1066 -0
  155. package/tests/test-app/src/pages/wrong-page.tsx +50 -0
  156. package/tests/test-app/src/pages//345/276/205/345/212/236.apidoc.json +336 -0
  157. package/tests/test-app/src/project.json +1120 -0
  158. package/tests/test-app/src/store/global.store.ts +10 -0
  159. package/tests/test-app/src/types/CreateTicketParams.m.ts +20 -0
  160. package/tests/test-app/src/types/SLAPolicy.ts +50 -0
  161. package/tests/test-app/src/types/Ticket.ts +68 -0
  162. package/tests/test-app/src/types/TicketAttachment.m.ts +67 -0
  163. package/tests/test-app/src/types/TicketComment.m.ts +59 -0
  164. package/tests/test-app/src/types/TicketEvaluation.ts +44 -0
  165. package/tests/test-app/src/types/TicketHistory.m.ts +71 -0
  166. package/tests/test-app/src/types/TicketListParams.m.ts +30 -0
  167. package/tests/test-app/src/types/TicketPriority.m.ts +65 -0
  168. package/tests/test-app/src/types/TicketRecord.ts +47 -0
  169. package/tests/test-app/src/types/TrainDoor.ts +284 -0
  170. package/tests/test-app/src/types/UpdateTicketParams.m.ts +22 -0
  171. package/tests/test-app/src/utils/__afterRequest.util.ts +3 -0
  172. package/tests/test-app/src/utils/__beforeRequest.util.ts +10 -0
  173. package/tests/test-app/src/utils/testGlobalAction.util.ts +7 -0
@@ -0,0 +1,668 @@
1
+ /**
2
+ * SLA管理页面
3
+ * @type Page
4
+ * @route /sla-management
5
+ * @screen 1920x1080 #f5f5f5
6
+ * @frames web
7
+ */
8
+ import React from 'react';
9
+ import { Page, Text, View } from '@appthen/react';
10
+
11
+
12
+ class IProps {}
13
+
14
+ /*
15
+ * 数据与接口请求定义
16
+ */
17
+ class IState {}
18
+
19
+ class Document extends React.Component<IProps, IState> {
20
+ state = {
21
+ activeTab: '[object Object]',
22
+ slaPolicies: [],
23
+ slaMonitoring: {},
24
+ slaStatistics: {},
25
+ showPolicyModal: false,
26
+ ticketTypes: [],
27
+ departments: [],
28
+ workingHours: [
29
+ { day: 'monday', start: '09:00', end: '18:00', enabled: true },
30
+ { day: 'tuesday', start: '09:00', end: '18:00', enabled: true },
31
+ { day: 'wednesday', start: '09:00', end: '18:00', enabled: true },
32
+ { day: 'thursday', start: '09:00', end: '18:00', enabled: true },
33
+ { day: 'friday', start: '09:00', end: '18:00', enabled: true },
34
+ { day: 'saturday', start: '09:00', end: '12:00', enabled: false },
35
+ { day: 'sunday', start: '09:00', end: '12:00', enabled: false },
36
+ ],
37
+ holidays: [],
38
+ };
39
+
40
+ render() {
41
+ return (
42
+ <Page className="min-h-screen bg-[var(--gray-50)]">
43
+ <View className="ml-[auto] mr-[auto] p-[24px]">
44
+ <View className="flex justify-between items-center mb-[24px]">
45
+ <h1 className="text-2xl font-bold text-[#111827]">
46
+ SLA管理1234567891010777889
47
+ </h1>
48
+ <button
49
+ onClick={() => this.showCreatePolicyModal()}
50
+ className="bg-blue-600 hover:bg-blue-700 pl-[16px] pr-[16px] pt-[8px] pb-[8px] text-[#ffffff] rounded-lg"
51
+ >
52
+ 创建SLA策略
53
+ </button>
54
+ </View>
55
+ <View className="bg-[#ffffff] rounded-lg shadow-[0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)] mb-[24px]">
56
+ <View className="border-gray-200 border-b-[1px] border-b-solid">
57
+ <nav className="-mb-px space-x-8 flex pl-[24px] pr-[24px]">
58
+ <button
59
+ onClick={() => this.switchTab('policies')}
60
+ className={`py-4 px-1 border-b-2 font-medium text-sm ${
61
+ this.state.activeTab === 'policies'
62
+ ? 'border-blue-500 text-blue-600'
63
+ : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
64
+ }`}
65
+ >
66
+ SLA策略
67
+ </button>
68
+ <button
69
+ onClick={() => this.switchTab('monitoring')}
70
+ className={`py-4 px-1 border-b-2 font-medium text-sm ${
71
+ this.state.activeTab === 'monitoring'
72
+ ? 'border-blue-500 text-blue-600'
73
+ : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
74
+ }`}
75
+ >
76
+ SLA监控
77
+ </button>
78
+ <button
79
+ onClick={() => this.switchTab('statistics')}
80
+ className={`py-4 px-1 border-b-2 font-medium text-sm ${
81
+ this.state.activeTab === 'statistics'
82
+ ? 'border-blue-500 text-blue-600'
83
+ : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
84
+ }`}
85
+ >
86
+ SLA统计
87
+ </button>
88
+ <button
89
+ onClick={() => this.switchTab('settings')}
90
+ className={`py-4 px-1 border-b-2 font-medium text-sm ${
91
+ this.state.activeTab === 'settings'
92
+ ? 'border-blue-500 text-blue-600'
93
+ : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
94
+ }`}
95
+ >
96
+ 时间设置
97
+ </button>
98
+ </nav>
99
+ </View>
100
+ </View>
101
+ {!!(this.state.activeTab === 'policies') && (
102
+ <View className="bg-[#ffffff] rounded-lg shadow-[0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)]">
103
+ <View className="p-[24px]">
104
+ <View className="overflow-x-auto">
105
+ <table className="divide-y divide-gray-200 min-w-full">
106
+ <thead className="bg-[var(--gray-50)]">
107
+ <tr>
108
+ <th className="pl-[24px] pr-[24px] pt-[12px] pb-[12px] text-[#6b7280] text-xs font-medium [textTransform:uppercase] tracking-[0.05em]">
109
+ 策略名称
110
+ </th>
111
+ <th className="pl-[24px] pr-[24px] pt-[12px] pb-[12px] text-[#6b7280] text-xs font-medium [textTransform:uppercase] tracking-[0.05em]">
112
+ 工单类型
113
+ </th>
114
+ <th className="pl-[24px] pr-[24px] pt-[12px] pb-[12px] text-[#6b7280] text-xs font-medium [textTransform:uppercase] tracking-[0.05em]">
115
+ 优先级
116
+ </th>
117
+ <th className="pl-[24px] pr-[24px] pt-[12px] pb-[12px] text-[#6b7280] text-xs font-medium [textTransform:uppercase] tracking-[0.05em]">
118
+ 响应时间
119
+ </th>
120
+ <th className="pl-[24px] pr-[24px] pt-[12px] pb-[12px] text-[#6b7280] text-xs font-medium [textTransform:uppercase] tracking-[0.05em]">
121
+ 解决时间
122
+ </th>
123
+ <th className="pl-[24px] pr-[24px] pt-[12px] pb-[12px] text-[#6b7280] text-xs font-medium [textTransform:uppercase] tracking-[0.05em]">
124
+ 状态
125
+ </th>
126
+ <th className="pl-[24px] pr-[24px] pt-[12px] pb-[12px] text-[#6b7280] text-xs font-medium [textTransform:uppercase] tracking-[0.05em]">
127
+ 操作
128
+ </th>
129
+ </tr>
130
+ </thead>
131
+ <tbody className="divide-y divide-gray-200 bg-[#ffffff]">
132
+ {this.state.slaPolicies.map((policy, index) => (
133
+ <tr key={policy.id || index}>
134
+ <td className="pl-[24px] pr-[24px] pt-[16px] pb-[16px] text-sm text-[#111827]">
135
+ <Text>{policy.name}</Text>
136
+ </td>
137
+ <td className="pl-[24px] pr-[24px] pt-[16px] pb-[16px] text-sm text-[#111827]">
138
+ <Text>{policy.ticketType}</Text>
139
+ </td>
140
+ <td className="pl-[24px] pr-[24px] pt-[16px] pb-[16px]">
141
+ <Text
142
+ className="inline-flex px-2 py-1 text-xs font-semibold rounded-full"
143
+ style={{
144
+ backgroundColor:
145
+ this.getPriorityColor(policy.priority) + '20',
146
+ color: this.getPriorityColor(policy.priority),
147
+ }}
148
+ >
149
+ {policy.priority}
150
+ </Text>
151
+ </td>
152
+ <td className="pl-[24px] pr-[24px] pt-[16px] pb-[16px] text-sm text-[#111827]">
153
+ <Text>{this.formatTime(policy.responseTime)}</Text>
154
+ </td>
155
+ <td className="pl-[24px] pr-[24px] pt-[16px] pb-[16px] text-sm text-[#111827]">
156
+ <Text>{this.formatTime(policy.resolveTime)}</Text>
157
+ </td>
158
+ <td className="pl-[24px] pr-[24px] pt-[16px] pb-[16px]">
159
+ <Text
160
+ className={`inline-flex px-2 py-1 text-xs font-semibold rounded-full ${
161
+ policy.active
162
+ ? 'bg-green-100 text-green-800'
163
+ : 'bg-gray-100 text-gray-800'
164
+ }`}
165
+ >
166
+ {policy.active ? '启用' : '禁用'}
167
+ </Text>
168
+ </td>
169
+ <td className="pl-[24px] pr-[24px] pt-[16px] pb-[16px] text-sm">
170
+ <button
171
+ onClick={() => this.showEditPolicyModal(policy)}
172
+ className="text-blue-600 hover:text-blue-800 mr-[12px]"
173
+ >
174
+ 编辑
175
+ </button>
176
+ <button
177
+ onClick={() =>
178
+ this.togglePolicyStatus(
179
+ policy.id,
180
+ !policy.active
181
+ )
182
+ }
183
+ className="text-yellow-600 hover:text-yellow-800 mr-[12px]"
184
+ >
185
+ {policy.active ? '禁用' : '启用'}
186
+ </button>
187
+ <button
188
+ onClick={() => this.deletePolicy(policy.id)}
189
+ className="text-red-600 hover:text-red-800"
190
+ >
191
+ 删除
192
+ </button>
193
+ </td>
194
+ </tr>
195
+ ))}
196
+ </tbody>
197
+ </table>
198
+ </View>
199
+ </View>
200
+ </View>
201
+ )}
202
+ {!!(this.state.activeTab === 'monitoring') && (
203
+ <View className="space-y-6">
204
+ <View className="grid grid-cols-1 md:grid-cols-4 gap-4">
205
+ <View className="bg-[#ffffff] rounded-lg shadow-[0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)] p-[16px]">
206
+ <View className="text-2xl font-bold text-[var(--blue-600)]">
207
+ {0}
208
+ </View>
209
+ <View className="text-[#4b5563] text-sm">
210
+ <Text>监控工单总数</Text>
211
+ </View>
212
+ </View>
213
+ <View className="bg-[#ffffff] rounded-lg shadow-[0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)] p-[16px]">
214
+ <View className="text-2xl font-bold text-[var(--green-600)]">
215
+ {0}
216
+ </View>
217
+ <View className="text-[#4b5563] text-sm">
218
+ <Text>SLA正常</Text>
219
+ </View>
220
+ </View>
221
+ <View className="bg-[#ffffff] rounded-lg shadow-[0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)] p-[16px]">
222
+ <View className="text-2xl font-bold text-[var(--yellow-600)]">
223
+ {0}
224
+ </View>
225
+ <View className="text-[#4b5563] text-sm">
226
+ <Text>SLA预警</Text>
227
+ </View>
228
+ </View>
229
+ <View className="bg-[#ffffff] rounded-lg shadow-[0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)] p-[16px]">
230
+ <View className="text-2xl font-bold text-[var(--red-600)]">
231
+ {0}
232
+ </View>
233
+ <View className="text-[#4b5563] text-sm">
234
+ <Text>SLA超时</Text>
235
+ </View>
236
+ </View>
237
+ </View>
238
+ <View className="bg-[#ffffff] rounded-lg shadow-[0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)]">
239
+ <View className="p-[24px]">
240
+ <h2 className="text-lg font-semibold text-[#111827] mb-[16px]">
241
+ SLA监控详情
242
+ </h2>
243
+ <View className="space-y-4">
244
+ {(this.state.slaMonitoring?.details).map((item, index) => (
245
+ <View
246
+ key={index}
247
+ className="border-l-4 pl-4 py-2"
248
+ style={{
249
+ borderLeftColor: this.getSLAStatusColor(item.status),
250
+ }}
251
+ >
252
+ <View className="flex justify-between items-start">
253
+ <View>
254
+ <View className="font-medium text-[#111827]">
255
+ <Text>工单 #</Text>
256
+ <Text>{item.ticketId}</Text>
257
+ <Text>-</Text>
258
+ <Text>{item.title}</Text>
259
+ </View>
260
+ <View className="text-sm text-[#6b7280]">
261
+ <Text>类型:</Text>
262
+ <Text>{item.type}</Text>
263
+ <Text>| 优先级:</Text>
264
+ <Text>{item.priority}</Text>
265
+ <Text>| 处理人:</Text>
266
+ <Text>{item.assignee}</Text>
267
+ </View>
268
+ </View>
269
+ <View className="text-[var(--right)]">
270
+ <View
271
+ className={`text-sm font-medium`}
272
+ style={{
273
+ color: this.getSLAStatusColor(item.status),
274
+ }}
275
+ >
276
+ <Text>{item.statusText}</Text>
277
+ </View>
278
+ <View className="text-xs text-[#6b7280]">
279
+ <Text>剩余:</Text>
280
+ <Text>{item.remainingTime}</Text>
281
+ </View>
282
+ </View>
283
+ </View>
284
+ </View>
285
+ ))}
286
+ </View>
287
+ </View>
288
+ </View>
289
+ </View>
290
+ )}
291
+ {!!(this.state.activeTab === 'statistics') && (
292
+ <View className="space-y-6">
293
+ <View className="grid grid-cols-1 md:grid-cols-3 gap-4">
294
+ <View className="bg-[#ffffff] rounded-lg shadow-[0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)] p-[24px]">
295
+ <h3 className="text-lg font-medium text-[#111827] mb-[8px]">
296
+ SLA达成率
297
+ </h3>
298
+ <View className="text-3xl font-bold text-[var(--green-600)]">
299
+ <Text>
300
+ {(this.state.slaStatistics?.achievementRate || 0).toFixed(
301
+ 1
302
+ )}
303
+ </Text>
304
+ <Text>%</Text>
305
+ </View>
306
+ <View className="text-sm text-[#6b7280]">
307
+ <Text>本月</Text>
308
+ </View>
309
+ </View>
310
+ <View className="bg-[#ffffff] rounded-lg shadow-[0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)] p-[24px]">
311
+ <h3 className="text-lg font-medium text-[#111827] mb-[8px]">
312
+ 平均响应时间
313
+ </h3>
314
+ <View className="text-3xl font-bold text-[var(--blue-600)]">
315
+ <Text>
316
+ {this.formatTime(
317
+ this.state.slaStatistics?.avgResponseTime || 0
318
+ )}
319
+ </Text>
320
+ </View>
321
+ <View className="text-sm text-[#6b7280]">
322
+ <Text>本月</Text>
323
+ </View>
324
+ </View>
325
+ <View className="bg-[#ffffff] rounded-lg shadow-[0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)] p-[24px]">
326
+ <h3 className="text-lg font-medium text-[#111827] mb-[8px]">
327
+ 平均解决时间
328
+ </h3>
329
+ <View className="text-3xl font-bold text-[var(--purple-600)]">
330
+ <Text>
331
+ {this.formatTime(
332
+ this.state.slaStatistics?.avgResolveTime || 0
333
+ )}
334
+ </Text>
335
+ </View>
336
+ <View className="text-sm text-[#6b7280]">
337
+ <Text>本月</Text>
338
+ </View>
339
+ </View>
340
+ </View>
341
+ <View className="bg-[#ffffff] rounded-lg shadow-[0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)] p-[24px]">
342
+ <h3 className="text-lg font-medium text-[#111827] mb-[16px]">
343
+ SLA达成率趋势
344
+ </h3>
345
+ <View className="h-[256px] flex items-center justify-center bg-[var(--gray-50)] rounded">
346
+ <p className="text-[#6b7280]">趋势图表占位符</p>
347
+ </View>
348
+ </View>
349
+ <View className="bg-[#ffffff] rounded-lg shadow-[0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)] p-[24px]">
350
+ <h3 className="text-lg font-medium text-[#111827] mb-[16px]">
351
+ 分部门SLA统计
352
+ </h3>
353
+ <View className="overflow-x-auto">
354
+ <table className="divide-y divide-gray-200 min-w-full">
355
+ <thead className="bg-[var(--gray-50)]">
356
+ <tr>
357
+ <th className="pl-[24px] pr-[24px] pt-[12px] pb-[12px] text-[#6b7280] text-xs font-medium [textTransform:uppercase]">
358
+ 部门
359
+ </th>
360
+ <th className="pl-[24px] pr-[24px] pt-[12px] pb-[12px] text-[#6b7280] text-xs font-medium [textTransform:uppercase]">
361
+ 工单数量
362
+ </th>
363
+ <th className="pl-[24px] pr-[24px] pt-[12px] pb-[12px] text-[#6b7280] text-xs font-medium [textTransform:uppercase]">
364
+ SLA达成率
365
+ </th>
366
+ <th className="pl-[24px] pr-[24px] pt-[12px] pb-[12px] text-[#6b7280] text-xs font-medium [textTransform:uppercase]">
367
+ 平均响应时间
368
+ </th>
369
+ <th className="pl-[24px] pr-[24px] pt-[12px] pb-[12px] text-[#6b7280] text-xs font-medium [textTransform:uppercase]">
370
+ 平均解决时间
371
+ </th>
372
+ </tr>
373
+ </thead>
374
+ <tbody className="divide-y divide-gray-200 bg-[#ffffff]">
375
+ {(this.state.slaStatistics?.byDepartment).map(
376
+ (dept, index) => (
377
+ <tr key={index}>
378
+ <td className="pl-[24px] pr-[24px] pt-[16px] pb-[16px] text-sm text-[#111827]">
379
+ <Text>{dept.name}</Text>
380
+ </td>
381
+ <td className="pl-[24px] pr-[24px] pt-[16px] pb-[16px] text-sm text-[#111827]">
382
+ <Text>{dept.ticketCount}</Text>
383
+ </td>
384
+ <td className="pl-[24px] pr-[24px] pt-[16px] pb-[16px] text-sm text-[#111827]">{`${dept.achievementRate}%`}</td>
385
+ <td className="pl-[24px] pr-[24px] pt-[16px] pb-[16px] text-sm text-[#111827]">
386
+ <Text>
387
+ {this.formatTime(dept.avgResponseTime)}
388
+ </Text>
389
+ </td>
390
+ <td className="pl-[24px] pr-[24px] pt-[16px] pb-[16px] text-sm text-[#111827]">
391
+ <Text>
392
+ {this.formatTime(dept.avgResolveTime)}
393
+ </Text>
394
+ </td>
395
+ </tr>
396
+ )
397
+ )}
398
+ </tbody>
399
+ </table>
400
+ </View>
401
+ </View>
402
+ </View>
403
+ )}
404
+ {!!(this.state.activeTab === 'settings') && (
405
+ <View className="space-y-6">
406
+ <View className="bg-[#ffffff] rounded-lg shadow-[0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)]">
407
+ <View className="p-[24px]">
408
+ <h3 className="text-lg font-medium text-[#111827] mb-[16px]">
409
+ 工作时间设置
410
+ </h3>
411
+ <View className="space-y-3">
412
+ {this.state.workingHours.map((wh, index) => (
413
+ <View key={index} className="gap-4 flex items-center">
414
+ <View className="w-[96px]">
415
+ <Text className="text-sm font-medium text-[#374151]">
416
+ {wh.day === 'monday'
417
+ ? '周一'
418
+ : wh.day === 'tuesday'
419
+ ? '周二'
420
+ : wh.day === 'wednesday'
421
+ ? '周三'
422
+ : wh.day === 'thursday'
423
+ ? '周四'
424
+ : wh.day === 'friday'
425
+ ? '周五'
426
+ : wh.day === 'saturday'
427
+ ? '周六'
428
+ : '周日'}
429
+ </Text>
430
+ </View>
431
+ <input
432
+ type="checkbox"
433
+ checked={wh.enabled}
434
+ onChange={e =>
435
+ this.updateWorkingHours(
436
+ wh.day,
437
+ 'enabled',
438
+ e.target.checked
439
+ )
440
+ }
441
+ className="rounded"
442
+ />
443
+ <input
444
+ type="time"
445
+ value={wh.start}
446
+ onChange={e =>
447
+ this.updateWorkingHours(
448
+ wh.day,
449
+ 'start',
450
+ e.target.value
451
+ )
452
+ }
453
+ disabled={!wh.enabled}
454
+ className="pl-[8px] pr-[8px] pt-[4px] pb-[4px] border border-solid rounded"
455
+ />
456
+ <Text className="text-[#6b7280]">至</Text>
457
+ <input
458
+ type="time"
459
+ value={wh.end}
460
+ onChange={e =>
461
+ this.updateWorkingHours(
462
+ wh.day,
463
+ 'end',
464
+ e.target.value
465
+ )
466
+ }
467
+ disabled={!wh.enabled}
468
+ className="pl-[8px] pr-[8px] pt-[4px] pb-[4px] border border-solid rounded"
469
+ />
470
+ </View>
471
+ ))}
472
+ </View>
473
+ </View>
474
+ </View>
475
+ <View className="bg-[#ffffff] rounded-lg shadow-[0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)]">
476
+ <View className="p-[24px]">
477
+ <View className="flex justify-between items-center mb-[16px]">
478
+ <h3 className="text-lg font-medium text-[#111827]">
479
+ 节假日设置
480
+ </h3>
481
+ <button className="bg-blue-600 hover:bg-blue-700 pl-[16px] pr-[16px] pt-[8px] pb-[8px] text-[#ffffff] rounded-lg">
482
+ 添加节假日
483
+ </button>
484
+ </View>
485
+ <View className="space-y-2">
486
+ {this.state.holidays.map((holiday, index) => (
487
+ <View
488
+ key={index}
489
+ className="flex items-center justify-between p-[12px] bg-[var(--gray-50)] rounded"
490
+ >
491
+ <View>
492
+ <View className="font-medium text-[#111827]">
493
+ <Text>{holiday.name}</Text>
494
+ </View>
495
+ <View className="text-sm text-[#6b7280]">
496
+ <Text>{holiday.date}</Text>
497
+ </View>
498
+ </View>
499
+ <button
500
+ onClick={() => this.removeHoliday(holiday.id)}
501
+ className="text-red-600 hover:text-red-800"
502
+ >
503
+ 删除
504
+ </button>
505
+ </View>
506
+ ))}
507
+ </View>
508
+ </View>
509
+ </View>
510
+ </View>
511
+ )}
512
+ {!!this.state.showPolicyModal && (
513
+ <View className="inset-0 fixed bg-[var(--opacity-50)] overflow-y-auto h-full w-full z-50">
514
+ <View className="relative top-[40px] ml-[auto] mr-[auto] p-[20px] border border-solid w-[384px] shadow-[0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)] rounded-md bg-[#ffffff]">
515
+ <View className="mt-[12px]">
516
+ <h3 className="text-lg [lineHeight:6] font-medium text-[#111827] mb-[16px]">
517
+ {this.state.editingPolicy?.id
518
+ ? '编辑SLA策略'
519
+ : '创建SLA策略'}
520
+ </h3>
521
+ <View className="space-y-4">
522
+ <View>
523
+ <label className="block text-sm font-medium text-[#374151]">
524
+ 策略名称
525
+ </label>
526
+ <input
527
+ type="text"
528
+ className="block border-gray-300 focus:outline-none focus:ring-blue-500 focus:border-blue-500 mt-[4px] w-full pl-[12px] pr-[12px] pt-[8px] pb-[8px] border border-solid rounded-md shadow-[0 1px 2px 0 rgb(0 0 0 / 0.05)]"
529
+ value={this.state.editingPolicy?.name || ''}
530
+ onChange={e =>
531
+ this.setState({
532
+ editingPolicy: {
533
+ ...this.state.editingPolicy,
534
+ name: e.target.value,
535
+ },
536
+ })
537
+ }
538
+ />
539
+ </View>
540
+ <View>
541
+ <label className="block text-sm font-medium text-[#374151]">
542
+ 工单类型
543
+ </label>
544
+ <select
545
+ className="block border-gray-300 focus:outline-none focus:ring-blue-500 focus:border-blue-500 mt-[4px] w-full pl-[12px] pr-[12px] pt-[8px] pb-[8px] border border-solid rounded-md shadow-[0 1px 2px 0 rgb(0 0 0 / 0.05)]"
546
+ value={this.state.editingPolicy?.ticketType || ''}
547
+ onChange={e =>
548
+ this.setState({
549
+ editingPolicy: {
550
+ ...this.state.editingPolicy,
551
+ ticketType: e.target.value,
552
+ },
553
+ })
554
+ }
555
+ >
556
+ <option value="">请选择工单类型</option>
557
+ {this.state.ticketTypes.map((type, index) => (
558
+ <option key={index} value={type.value}>
559
+ <Text>{type.label}</Text>
560
+ </option>
561
+ ))}
562
+ </select>
563
+ </View>
564
+ <View>
565
+ <label className="block text-sm font-medium text-[#374151]">
566
+ 优先级
567
+ </label>
568
+ <select
569
+ className="block border-gray-300 focus:outline-none focus:ring-blue-500 focus:border-blue-500 mt-[4px] w-full pl-[12px] pr-[12px] pt-[8px] pb-[8px] border border-solid rounded-md shadow-[0 1px 2px 0 rgb(0 0 0 / 0.05)]"
570
+ value={this.state.editingPolicy?.priority || ''}
571
+ onChange={e =>
572
+ this.setState({
573
+ editingPolicy: {
574
+ ...this.state.editingPolicy,
575
+ priority: e.target.value,
576
+ },
577
+ })
578
+ }
579
+ >
580
+ <option value="">请选择优先级</option>
581
+ <option value="low">低</option>
582
+ <option value="medium">中</option>
583
+ <option value="high">高</option>
584
+ <option value="urgent">紧急</option>
585
+ </select>
586
+ </View>
587
+ <View>
588
+ <label className="block text-sm font-medium text-[#374151]">
589
+ 响应时间(分钟)
590
+ </label>
591
+ <input
592
+ type="number"
593
+ className="block border-gray-300 focus:outline-none focus:ring-blue-500 focus:border-blue-500 mt-[4px] w-full pl-[12px] pr-[12px] pt-[8px] pb-[8px] border border-solid rounded-md shadow-[0 1px 2px 0 rgb(0 0 0 / 0.05)]"
594
+ value={this.state.editingPolicy?.responseTime || 0}
595
+ onChange={e =>
596
+ this.setState({
597
+ editingPolicy: {
598
+ ...this.state.editingPolicy,
599
+ responseTime: parseInt(e.target.value) || 0,
600
+ },
601
+ })
602
+ }
603
+ />
604
+ </View>
605
+ <View>
606
+ <label className="block text-sm font-medium text-[#374151]">
607
+ 解决时间(分钟)
608
+ </label>
609
+ <input
610
+ type="number"
611
+ className="block border-gray-300 focus:outline-none focus:ring-blue-500 focus:border-blue-500 mt-[4px] w-full pl-[12px] pr-[12px] pt-[8px] pb-[8px] border border-solid rounded-md shadow-[0 1px 2px 0 rgb(0 0 0 / 0.05)]"
612
+ value={this.state.editingPolicy?.resolveTime || 0}
613
+ onChange={e =>
614
+ this.setState({
615
+ editingPolicy: {
616
+ ...this.state.editingPolicy,
617
+ resolveTime: parseInt(e.target.value) || 0,
618
+ },
619
+ })
620
+ }
621
+ />
622
+ </View>
623
+ <View>
624
+ <label className="flex items-center">
625
+ <input
626
+ type="checkbox"
627
+ checked={this.state.editingPolicy?.active || false}
628
+ onChange={e =>
629
+ this.setState({
630
+ editingPolicy: {
631
+ ...this.state.editingPolicy,
632
+ active: e.target.checked,
633
+ },
634
+ })
635
+ }
636
+ className="rounded"
637
+ />
638
+ <Text className="ml-[8px] text-sm text-[#374151]">
639
+ 启用策略
640
+ </Text>
641
+ </label>
642
+ </View>
643
+ </View>
644
+ <View className="gap-3 flex justify-end mt-[24px]">
645
+ <button
646
+ onClick={() => this.closePolicyModal()}
647
+ className="bg-gray-300 hover:bg-gray-400 pl-[16px] pr-[16px] pt-[8px] pb-[8px] text-[#374151] rounded-md"
648
+ >
649
+ 取消
650
+ </button>
651
+ <button
652
+ onClick={() => this.savePolicy()}
653
+ className="bg-blue-600 hover:bg-blue-700 pl-[16px] pr-[16px] pt-[8px] pb-[8px] text-[#ffffff] rounded-md"
654
+ >
655
+ 保存
656
+ </button>
657
+ </View>
658
+ </View>
659
+ </View>
660
+ </View>
661
+ )}
662
+ </View>
663
+ </Page>
664
+ );
665
+ }
666
+ }
667
+
668
+ export default Document;