i18n.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /**
  2. * I18n Mock Handlers
  3. * 国际化相关的 mock 处理器
  4. */
  5. /**
  6. * 获取多语言列表 - 成功场景
  7. *
  8. * @description 获取系统支持的语言列表
  9. * @method GET
  10. * @url /dr/api/v1/pub/language
  11. * @access 公开接口
  12. *
  13. * @returns {Object[]} data - 语言列表
  14. * @returns {string} data[].language - 语言代码(en/zh)
  15. * @returns {string} data[].display - 语言显示名称
  16. *
  17. * @example
  18. * mockGetLanguageListSuccess();
  19. * cy.wait('@getLanguageListSuccess').its('response.body.data').should('have.length', 2);
  20. *
  21. * @see docs/DR.md - 章节4
  22. */
  23. export function mockGetLanguageListSuccess() {
  24. cy.intercept('GET', '/dr/api/v1/pub/language', {
  25. statusCode: 200,
  26. body: {
  27. code: "0x000000",
  28. data: [
  29. {
  30. language: "en",
  31. display: "English"
  32. },
  33. {
  34. language: "zh",
  35. display: "简体中文"
  36. }
  37. ],
  38. description: "Success",
  39. solution: ""
  40. }
  41. }).as('getLanguageListSuccess');
  42. }
  43. /**
  44. * 获取多语言列表 - 空列表场景
  45. *
  46. * @description 获取多语言列表,返回空列表
  47. * @method GET
  48. * @url /dr/api/v1/pub/language
  49. * @access 公开接口
  50. *
  51. * @returns {Object[]} data - 空语言列表
  52. *
  53. * @example
  54. * mockGetLanguageListEmpty();
  55. * cy.wait('@getLanguageListEmpty');
  56. *
  57. * @see docs/DR.md - 章节4
  58. */
  59. export function mockGetLanguageListEmpty() {
  60. cy.intercept('GET', '/dr/api/v1/pub/language', {
  61. statusCode: 200,
  62. body: {
  63. code: "0x000000",
  64. data: [],
  65. description: "Success",
  66. solution: ""
  67. }
  68. }).as('getLanguageListEmpty');
  69. }
  70. /**
  71. * 获取翻译文件 - 成功场景
  72. *
  73. * @description 获取指定语言的翻译文件
  74. * @method GET
  75. * @url /dr/api/v1/pub/trans/{locale}/{locale}.js
  76. * @access 公开接口
  77. *
  78. * @param {string} locale - 语言代码(zh_CN/en_US)
  79. *
  80. * @returns {Object} 翻译键值对
  81. *
  82. * @example
  83. * mockI18nSuccess('en_US');
  84. * cy.wait('@getI18nZHSuccess');
  85. *
  86. * @see docs/DR.md - 章节3
  87. */
  88. export function mockI18nSuccess(locale: 'zh_CN' | 'en_US') {
  89. const mockData = locale === 'zh_CN' ? {
  90. greeting: '你好,世界!',
  91. name: '张三',
  92. patient: '患者管理',
  93. register: '注册',
  94. tasklist: '任务清单',
  95. historylist: '历史清单',
  96. archivelist: '归档清单',
  97. bin: '回收站',
  98. outputlist: '传输清单',
  99. exam: '检查',
  100. examlist: '检查清单',
  101. process: '处理',
  102. print: '打印',
  103. printlist: '打印清单',
  104. worklist: '任务清单',
  105. 'worklist.operationPanel': '操作面板',
  106. 'register.basicInfoPanel': '基本信息表单区域',
  107. 'register.protocolListPanel': '待选择协议列表区域',
  108. 'register.selectedProtocolListPanel': '已选择协议列表区域',
  109. 'worklistTable.patientId': '患者编号',
  110. 'worklistTable.name': '患者姓名',
  111. 'register.patientId': '患者编号',
  112. 'register.patientName': '患者姓名',
  113. 'register.gender': '性别',
  114. 'register.gender.male': '男',
  115. 'register.gender.female': '女',
  116. // Login page
  117. 'login.username': '用户名',
  118. 'login.username.placeholder': '请输入用户名',
  119. 'login.username.required': '请输入用户名',
  120. 'login.password': '密码',
  121. 'login.password.placeholder': '请输入密码',
  122. 'login.password.required': '请输入密码',
  123. 'login.submit': '登录',
  124. 'login.emergency': '急诊',
  125. 'login.success': '登录成功',
  126. 'login.failed': '登录失败',
  127. 'login.failedDetail': ',详情:',
  128. 'login.networkError': ',网络错误:',
  129. 'login.unknownError': '未知错误',
  130. 'login.emergency.success': '急诊模式启动成功',
  131. 'login.emergency.failed': '急诊操作失败:'
  132. } : {
  133. greeting: 'Hello, world!',
  134. name: 'John Doe',
  135. patient: 'Patient Management',
  136. register: 'Register',
  137. tasklist: 'Task List',
  138. historylist: 'History List',
  139. archivelist: 'Archive List',
  140. bin: 'Recycle Bin',
  141. outputlist: 'Transfer List',
  142. exam: 'Examination',
  143. examlist: 'Examination List',
  144. process: 'Process',
  145. print: 'Print',
  146. printlist: 'Print List',
  147. worklist: 'Task List',
  148. 'worklist.operationPanel': 'Operation Panel',
  149. 'register.basicInfoPanel': 'Basic Information Form Area',
  150. 'register.protocolListPanel': 'Protocol Selection List Area',
  151. 'register.selectedProtocolListPanel': 'Selected Protocol List Area',
  152. 'worklistTable.patientId': 'Patient ID',
  153. 'worklistTable.name': 'Patient Name',
  154. 'register.patientId': 'Patient ID',
  155. 'register.patientName': 'Patient Name',
  156. 'register.gender': 'Gender',
  157. 'register.gender.male': 'Male',
  158. 'register.gender.female': 'Female',
  159. // Login page
  160. 'login.username': 'Username',
  161. 'login.username.placeholder': 'Enter username',
  162. 'login.username.required': 'Please enter username',
  163. 'login.password': 'Password',
  164. 'login.password.placeholder': 'Enter password',
  165. 'login.password.required': 'Please enter password',
  166. 'login.submit': 'Login',
  167. 'login.emergency': 'Emergency',
  168. 'login.success': 'Login successful',
  169. 'login.failed': 'Login failed',
  170. 'login.failedDetail': ', details: ',
  171. 'login.networkError': ', network error: ',
  172. 'login.unknownError': 'Unknown error',
  173. 'login.emergency.success': 'Emergency mode activated successfully',
  174. 'login.emergency.failed': 'Emergency operation failed: '
  175. };
  176. cy.intercept('GET', `/dr/api/v1/pub/trans/${locale}/${locale.split('_')[0]}.js`, (req) => {
  177. req.reply({
  178. statusCode: 200,
  179. body: mockData
  180. });
  181. }).as(`getI18n${locale.toUpperCase()}Success`);
  182. }
  183. // 封装获取多语言资源失败的 mock (404错误)
  184. export function mockI18nError(locale: 'zh_CN' | 'en_US') {
  185. cy.intercept('GET', `/dr/api/v1/pub/trans/${locale}/${locale.split('_')[0]}.js`, (req) => {
  186. req.reply({
  187. statusCode: 404,
  188. body: {
  189. message: 'Not Found',
  190. error: 'Translation file not found'
  191. }
  192. });
  193. }).as(`getI18n${locale.toUpperCase()}Error`);
  194. }
  195. // 封装获取多语言资源服务器错误的 mock (500错误)
  196. export function mockI18nServerError(locale: 'zh_CN' | 'en_US') {
  197. cy.intercept('GET', `/dr/api/v1/pub/trans/${locale}/${locale.split('_')[0]}.js`, (req) => {
  198. req.reply({
  199. statusCode: 500,
  200. body: {
  201. message: 'Internal Server Error',
  202. error: 'Server error occurred'
  203. }
  204. });
  205. }).as(`getI18n${locale.toUpperCase()}ServerError`);
  206. }
  207. // 封装获取多语言资源超时的 mock
  208. export function mockI18nTimeout(locale: 'zh_CN' | 'en_US') {
  209. cy.intercept('GET', `/dr/api/v1/pub/trans/${locale}/${locale.split('_')[0]}.js`, (req) => {
  210. req.reply({
  211. delay: 30000, // 30秒延迟,模拟超时
  212. statusCode: 200,
  213. body: {}
  214. });
  215. }).as(`getI18n${locale.toUpperCase()}Timeout`);
  216. }
  217. // 封装获取多语言资源格式错误的 mock
  218. export function mockI18nInvalidFormat(locale: 'zh_CN' | 'en_US') {
  219. cy.intercept('GET', `/dr/api/v1/pub/trans/${locale}/${locale.split('_')[0]}.js`, (req) => {
  220. req.reply({
  221. statusCode: 200,
  222. body: "invalid json format" // 返回非JSON格式数据
  223. });
  224. }).as(`getI18n${locale.toUpperCase()}InvalidFormat`);
  225. }
  226. // 封装获取多语言资源空数据的 mock
  227. export function mockI18nEmptyData(locale: 'zh_CN' | 'en_US') {
  228. cy.intercept('GET', `/dr/api/v1/pub/trans/${locale}/${locale.split('_')[0]}.js`, (req) => {
  229. req.reply({
  230. statusCode: 200,
  231. body: {} // 返回空对象
  232. });
  233. }).as(`getI18n${locale.toUpperCase()}EmptyData`);
  234. }
  235. // 封装获取多语言资源网络错误的 mock
  236. export function mockI18nNetworkError(locale: 'zh_CN' | 'en_US') {
  237. cy.intercept('GET', `/dr/api/v1/pub/trans/${locale}/${locale.split('_')[0]}.js`, (req) => {
  238. req.reply({
  239. forceNetworkError: true
  240. });
  241. }).as(`getI18n${locale.toUpperCase()}NetworkError`);
  242. }
  243. // 封装软件信息API的 mock,避免影响页面加载
  244. export function mockSoftwareInfo(locale: 'zh_CN' | 'en_US' = 'zh_CN') {
  245. cy.intercept('GET', '/dr/api/v1/pub/software_info', (req) => {
  246. req.reply({
  247. statusCode: 200,
  248. body: {
  249. code: "0x000000",
  250. data: {
  251. FPD: "Physics",
  252. GEN: "Physics",
  253. current_locale: locale,
  254. default_locale: "zh_CN",
  255. guest: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NjA0OTc2NDksImlkIjoyLCJuYW1lIjoiZ3Vlc3QifQ.hUV5_GOzlWKDeFioJCsHMG2IXa0oJPfNNlPsr69ypqc",
  256. language: ["en", "zh"],
  257. product: "VETDROS",
  258. server: {
  259. auth: {
  260. build: "2025-10-08 11:06:08",
  261. desc: "Authentication Server repo",
  262. submodule: ["0baa8db0[rpc_idl]"],
  263. version: "0.4.0-21-g4a37cc7"
  264. },
  265. dcmtk: {
  266. build: "2025-09-29 16:35:39",
  267. desc: "Dcmtk Server repo",
  268. submodule: ["c2039235[rpc_idl]"],
  269. version: "0.4.0-2-g36bc18f"
  270. },
  271. imgProc: {
  272. build: "2025-09-29 16:36:36",
  273. desc: "Img Proc Server repo",
  274. submodule: [
  275. "d00bfca5[auto_wwwl]",
  276. "89fd9218[collimator_circle]",
  277. "c9582bbe[collimator_rect]",
  278. "98c510bd[enhance]",
  279. "6f9bf7de[enhance_v3]",
  280. "5905e001[rpc_idl]"
  281. ],
  282. version: "0.4.0-7-gca1c8a4"
  283. },
  284. protocol: {
  285. build: "2025-10-08 11:06:13",
  286. desc: "Protocol Server repo",
  287. submodule: ["0baa8db0[rpc_idl]"],
  288. version: "0.4.0-8-g47990eb"
  289. },
  290. resource: {
  291. build: "2025-10-08 11:06:17",
  292. desc: "Resource Server repo",
  293. submodule: ["9725e654[rpc_idl]"],
  294. version: "0.4.0-9-g10766e8"
  295. },
  296. study: {
  297. build: "2025-10-08 11:06:15",
  298. desc: "Study Server repo",
  299. submodule: ["8595ea2d[rpc_idl]"],
  300. version: "0.5.0-1-g7620712"
  301. },
  302. task: {
  303. build: "2025-10-08 11:06:19",
  304. desc: "Task Server repo",
  305. submodule: ["8595ea2d[rpc_idl]"],
  306. version: "0.4.0-11-g494849d"
  307. }
  308. },
  309. sn: "19d5d2eb-8b720370-7d617b19-670dd1ae"
  310. },
  311. description: "Success",
  312. solution: ""
  313. }
  314. });
  315. }).as('getSoftwareInfo');
  316. }
  317. // 封装logger API的 mock,避免影响页面加载
  318. export function mockLogger() {
  319. cy.intercept('POST', '/log', (req) => {
  320. req.reply({
  321. statusCode: 204, // No Content - 更适合日志请求,不会被误认为页面导航
  322. body: null, // 明确返回 null,避免任何可能的页面影响
  323. headers: {
  324. 'content-type': 'application/json',
  325. 'cache-control': 'no-cache'
  326. }
  327. });
  328. }).as('postLog');
  329. }
  330. // 封装所有必要的API mock,避免影响页面加载
  331. export function mockAllRequiredAPIs(locale: 'zh_CN' | 'en_US' = 'zh_CN') {
  332. mockSoftwareInfo(locale);
  333. mockLogger();
  334. }