@dssp/supervision 1.0.0-alpha.4 → 1.0.0-alpha.41

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 (217) hide show
  1. package/dist-client/graphql/building-inspection.d.ts +1 -0
  2. package/dist-client/graphql/building-inspection.js +100 -0
  3. package/dist-client/graphql/building-inspection.js.map +1 -0
  4. package/dist-client/pages/building-inspection/building-inspection-detail-checklist.d.ts +9 -0
  5. package/dist-client/pages/building-inspection/building-inspection-detail-checklist.js +130 -72
  6. package/dist-client/pages/building-inspection/building-inspection-detail-checklist.js.map +1 -1
  7. package/dist-client/pages/building-inspection/building-inspection-detail-drawing.d.ts +1 -0
  8. package/dist-client/pages/building-inspection/building-inspection-detail-drawing.js +77 -14
  9. package/dist-client/pages/building-inspection/building-inspection-detail-drawing.js.map +1 -1
  10. package/dist-client/pages/building-inspection/building-inspection-list.d.ts +18 -2
  11. package/dist-client/pages/building-inspection/building-inspection-list.js +360 -28
  12. package/dist-client/pages/building-inspection/building-inspection-list.js.map +1 -1
  13. package/dist-client/pages/building-inspection/component/building-inspection-detail-header.js +31 -9
  14. package/dist-client/pages/building-inspection/component/building-inspection-detail-header.js.map +1 -1
  15. package/dist-client/pages/building-inspection/component/daily-worklog-popup.d.ts +27 -0
  16. package/dist-client/pages/building-inspection/component/daily-worklog-popup.js +542 -0
  17. package/dist-client/pages/building-inspection/component/daily-worklog-popup.js.map +1 -0
  18. package/dist-client/pages/building-inspection/component/image-preview-popup.d.ts +15 -0
  19. package/dist-client/pages/building-inspection/component/image-preview-popup.js +351 -0
  20. package/dist-client/pages/building-inspection/component/image-preview-popup.js.map +1 -0
  21. package/dist-client/pages/building-inspection/component/inspection-document/inspection-request-document.d.ts +20 -0
  22. package/dist-client/pages/building-inspection/component/inspection-document/inspection-request-document.js +432 -0
  23. package/dist-client/pages/building-inspection/component/inspection-document/inspection-request-document.js.map +1 -0
  24. package/dist-client/pages/building-inspection/component/inspection-document/inspection-result-notification.d.ts +30 -0
  25. package/dist-client/pages/building-inspection/component/inspection-document/inspection-result-notification.js +479 -0
  26. package/dist-client/pages/building-inspection/component/inspection-document/inspection-result-notification.js.map +1 -0
  27. package/dist-client/pages/building-inspection/component/inspection-document/photo-album-popup.d.ts +27 -0
  28. package/dist-client/pages/building-inspection/component/inspection-document/photo-album-popup.js +401 -0
  29. package/dist-client/pages/building-inspection/component/inspection-document/photo-album-popup.js.map +1 -0
  30. package/dist-client/pages/building-inspection/component/inspection-event-provider.d.ts +2 -1
  31. package/dist-client/pages/building-inspection/component/inspection-event-provider.js +39 -17
  32. package/dist-client/pages/building-inspection/component/inspection-event-provider.js.map +1 -1
  33. package/dist-client/pages/building-inspection/inspection-create-popup.js +22 -9
  34. package/dist-client/pages/building-inspection/inspection-create-popup.js.map +1 -1
  35. package/dist-client/pages/building-inspection-grid/building-inspection-grid-detail.d.ts +60 -0
  36. package/dist-client/pages/building-inspection-grid/building-inspection-grid-detail.js +1132 -0
  37. package/dist-client/pages/building-inspection-grid/building-inspection-grid-detail.js.map +1 -0
  38. package/dist-client/pages/building-inspection-grid/component/grid-inspection-create-popup.d.ts +2 -0
  39. package/dist-client/pages/building-inspection-grid/component/grid-inspection-create-popup.js +740 -0
  40. package/dist-client/pages/building-inspection-grid/component/grid-inspection-create-popup.js.map +1 -0
  41. package/dist-client/pages/building-inspection-grid/component/grid-inspection-list-layer.d.ts +19 -0
  42. package/dist-client/pages/building-inspection-grid/component/grid-inspection-list-layer.js +205 -0
  43. package/dist-client/pages/building-inspection-grid/component/grid-inspection-list-layer.js.map +1 -0
  44. package/dist-client/pages/building-inspection-grid/component/notice-comment-popup.d.ts +1 -0
  45. package/dist-client/pages/building-inspection-grid/component/notice-comment-popup.js +304 -0
  46. package/dist-client/pages/building-inspection-grid/component/notice-comment-popup.js.map +1 -0
  47. package/dist-client/pages/building-inspection-grid/component/plan-preview-popup.d.ts +15 -0
  48. package/dist-client/pages/building-inspection-grid/component/plan-preview-popup.js +430 -0
  49. package/dist-client/pages/building-inspection-grid/component/plan-preview-popup.js.map +1 -0
  50. package/dist-client/pages/checklist/attachment-list-popup.d.ts +1 -0
  51. package/dist-client/pages/checklist/attachment-list-popup.js +250 -67
  52. package/dist-client/pages/checklist/attachment-list-popup.js.map +1 -1
  53. package/dist-client/pages/checklist/checklist-view.d.ts +7 -0
  54. package/dist-client/pages/checklist/checklist-view.js +363 -185
  55. package/dist-client/pages/checklist/checklist-view.js.map +1 -1
  56. package/dist-client/pages/checklist/comment-list-popup.js +14 -3
  57. package/dist-client/pages/checklist/comment-list-popup.js.map +1 -1
  58. package/dist-client/pages/checklist/file-preview-popup.js +0 -1
  59. package/dist-client/pages/checklist/file-preview-popup.js.map +1 -1
  60. package/dist-client/pages/checklist/inspection-info-popup.d.ts +50 -0
  61. package/dist-client/pages/checklist/inspection-info-popup.js +684 -0
  62. package/dist-client/pages/checklist/inspection-info-popup.js.map +1 -0
  63. package/dist-client/pages/checklist/inspection-tab-popup.d.ts +18 -0
  64. package/dist-client/pages/checklist/inspection-tab-popup.js +196 -0
  65. package/dist-client/pages/checklist/inspection-tab-popup.js.map +1 -0
  66. package/dist-client/pages/checklist-template/checklist-template-item.js +8 -3
  67. package/dist-client/pages/checklist-template/checklist-template-item.js.map +1 -1
  68. package/dist-client/pages/checklist-template/checklist-template-list.js +2 -2
  69. package/dist-client/pages/checklist-template/checklist-template-list.js.map +1 -1
  70. package/dist-client/route.d.ts +1 -1
  71. package/dist-client/route.js +3 -0
  72. package/dist-client/route.js.map +1 -1
  73. package/dist-client/stt/speech-to-text.d.ts +36 -0
  74. package/dist-client/stt/speech-to-text.js +89 -0
  75. package/dist-client/stt/speech-to-text.js.map +1 -0
  76. package/dist-client/stt/stt-utils.d.ts +28 -0
  77. package/dist-client/stt/stt-utils.js +146 -0
  78. package/dist-client/stt/stt-utils.js.map +1 -0
  79. package/dist-client/tsconfig.tsbuildinfo +1 -1
  80. package/dist-server/service/action-plan/index.d.ts +0 -1
  81. package/dist-server/service/action-plan/index.js +1 -2
  82. package/dist-server/service/action-plan/index.js.map +1 -1
  83. package/dist-server/service/building-inspection/building-inspection-mutation.d.ts +3 -3
  84. package/dist-server/service/building-inspection/building-inspection-mutation.js +145 -34
  85. package/dist-server/service/building-inspection/building-inspection-mutation.js.map +1 -1
  86. package/dist-server/service/building-inspection/building-inspection-query.d.ts +3 -4
  87. package/dist-server/service/building-inspection/building-inspection-query.js +46 -30
  88. package/dist-server/service/building-inspection/building-inspection-query.js.map +1 -1
  89. package/dist-server/service/building-inspection/building-inspection-type.d.ts +28 -9
  90. package/dist-server/service/building-inspection/building-inspection-type.js +96 -17
  91. package/dist-server/service/building-inspection/building-inspection-type.js.map +1 -1
  92. package/dist-server/service/building-inspection/building-inspection.d.ts +13 -0
  93. package/dist-server/service/building-inspection/building-inspection.js +55 -2
  94. package/dist-server/service/building-inspection/building-inspection.js.map +1 -1
  95. package/dist-server/service/building-inspection/index.d.ts +4 -7
  96. package/dist-server/service/building-inspection/index.js +11 -6
  97. package/dist-server/service/building-inspection/index.js.map +1 -1
  98. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-mutation.d.ts +6 -0
  99. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-mutation.js +56 -0
  100. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-mutation.js.map +1 -0
  101. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-query.d.ts +16 -0
  102. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-query.js +171 -0
  103. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-query.js.map +1 -0
  104. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-type.d.ts +23 -0
  105. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-type.js +90 -0
  106. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog-type.js.map +1 -0
  107. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog.d.ts +33 -0
  108. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog.js +132 -0
  109. package/dist-server/service/building-inspection-daily-worklog/building-inspection-daily-worklog.js.map +1 -0
  110. package/dist-server/service/building-inspection-daily-worklog/index.d.ts +5 -0
  111. package/dist-server/service/building-inspection-daily-worklog/index.js +9 -0
  112. package/dist-server/service/building-inspection-daily-worklog/index.js.map +1 -0
  113. package/dist-server/service/building-inspection-history/building-inspection-history-query.d.ts +16 -0
  114. package/dist-server/service/building-inspection-history/building-inspection-history-query.js +120 -0
  115. package/dist-server/service/building-inspection-history/building-inspection-history-query.js.map +1 -0
  116. package/dist-server/service/building-inspection-history/building-inspection-history-type.d.ts +5 -0
  117. package/dist-server/service/building-inspection-history/building-inspection-history-type.js +21 -0
  118. package/dist-server/service/building-inspection-history/building-inspection-history-type.js.map +1 -0
  119. package/dist-server/service/building-inspection-history/building-inspection-history.d.ts +34 -0
  120. package/dist-server/service/building-inspection-history/building-inspection-history.js +157 -0
  121. package/dist-server/service/building-inspection-history/building-inspection-history.js.map +1 -0
  122. package/dist-server/service/{building-inspection → building-inspection-history}/event-subscriber.d.ts +1 -1
  123. package/dist-server/service/{building-inspection → building-inspection-history}/event-subscriber.js +1 -1
  124. package/dist-server/service/building-inspection-history/event-subscriber.js.map +1 -0
  125. package/dist-server/service/building-inspection-history/index.d.ts +6 -0
  126. package/dist-server/service/building-inspection-history/index.js +10 -0
  127. package/dist-server/service/building-inspection-history/index.js.map +1 -0
  128. package/dist-server/service/checklist/checklist-mutation.d.ts +0 -5
  129. package/dist-server/service/checklist/checklist-mutation.js +1 -67
  130. package/dist-server/service/checklist/checklist-mutation.js.map +1 -1
  131. package/dist-server/service/checklist/checklist-query.d.ts +6 -0
  132. package/dist-server/service/checklist/checklist-query.js +63 -0
  133. package/dist-server/service/checklist/checklist-query.js.map +1 -1
  134. package/dist-server/service/checklist/checklist-type.d.ts +0 -13
  135. package/dist-server/service/checklist/checklist-type.js +1 -49
  136. package/dist-server/service/checklist/checklist-type.js.map +1 -1
  137. package/dist-server/service/checklist/checklist.d.ts +38 -3
  138. package/dist-server/service/checklist/checklist.js +131 -15
  139. package/dist-server/service/checklist/checklist.js.map +1 -1
  140. package/dist-server/service/checklist/event-subscriber.d.ts +2 -2
  141. package/dist-server/service/checklist/event-subscriber.js +2 -2
  142. package/dist-server/service/checklist/event-subscriber.js.map +1 -1
  143. package/dist-server/service/checklist/index.d.ts +1 -4
  144. package/dist-server/service/checklist/index.js +2 -5
  145. package/dist-server/service/checklist/index.js.map +1 -1
  146. package/dist-server/service/checklist-history/checklist-history-query.d.ts +11 -0
  147. package/dist-server/service/checklist-history/checklist-history-query.js +77 -0
  148. package/dist-server/service/checklist-history/checklist-history-query.js.map +1 -0
  149. package/dist-server/service/checklist-history/checklist-history-type.d.ts +5 -0
  150. package/dist-server/service/checklist-history/checklist-history-type.js +21 -0
  151. package/dist-server/service/checklist-history/checklist-history-type.js.map +1 -0
  152. package/dist-server/service/checklist-history/checklist-history.d.ts +50 -0
  153. package/dist-server/service/checklist-history/checklist-history.js +239 -0
  154. package/dist-server/service/checklist-history/checklist-history.js.map +1 -0
  155. package/dist-server/service/checklist-history/event-subscriber.d.ts +7 -0
  156. package/dist-server/service/checklist-history/event-subscriber.js +21 -0
  157. package/dist-server/service/checklist-history/event-subscriber.js.map +1 -0
  158. package/dist-server/service/checklist-history/index.d.ts +6 -0
  159. package/dist-server/service/checklist-history/index.js +10 -0
  160. package/dist-server/service/checklist-history/index.js.map +1 -0
  161. package/dist-server/service/checklist-item/checklist-item-query.d.ts +1 -1
  162. package/dist-server/service/checklist-item/checklist-item-query.js +5 -3
  163. package/dist-server/service/checklist-item/checklist-item-query.js.map +1 -1
  164. package/dist-server/service/checklist-item/index.d.ts +0 -1
  165. package/dist-server/service/checklist-item/index.js +1 -2
  166. package/dist-server/service/checklist-item/index.js.map +1 -1
  167. package/dist-server/service/checklist-item-comment/checklist-item-comment-mutation.d.ts +1 -0
  168. package/dist-server/service/checklist-item-comment/checklist-item-comment-mutation.js +33 -6
  169. package/dist-server/service/checklist-item-comment/checklist-item-comment-mutation.js.map +1 -1
  170. package/dist-server/service/checklist-item-comment/index.d.ts +0 -2
  171. package/dist-server/service/checklist-item-comment/index.js +1 -3
  172. package/dist-server/service/checklist-item-comment/index.js.map +1 -1
  173. package/dist-server/service/checklist-item-history/checklist-item-history-query.d.ts +16 -0
  174. package/dist-server/service/checklist-item-history/checklist-item-history-query.js +123 -0
  175. package/dist-server/service/checklist-item-history/checklist-item-history-query.js.map +1 -0
  176. package/dist-server/service/checklist-item-history/checklist-item-history-type.d.ts +5 -0
  177. package/dist-server/service/checklist-item-history/checklist-item-history-type.js +21 -0
  178. package/dist-server/service/checklist-item-history/checklist-item-history-type.js.map +1 -0
  179. package/dist-server/service/checklist-item-history/checklist-item-history.d.ts +25 -0
  180. package/dist-server/service/checklist-item-history/checklist-item-history.js +123 -0
  181. package/dist-server/service/checklist-item-history/checklist-item-history.js.map +1 -0
  182. package/dist-server/service/checklist-item-history/event-subscriber.d.ts +7 -0
  183. package/dist-server/service/checklist-item-history/event-subscriber.js +21 -0
  184. package/dist-server/service/checklist-item-history/event-subscriber.js.map +1 -0
  185. package/dist-server/service/checklist-item-history/index.d.ts +6 -0
  186. package/dist-server/service/checklist-item-history/index.js +10 -0
  187. package/dist-server/service/checklist-item-history/index.js.map +1 -0
  188. package/dist-server/service/checklist-template-item/checklist-template-item.js +2 -4
  189. package/dist-server/service/checklist-template-item/checklist-template-item.js.map +1 -1
  190. package/dist-server/service/index.d.ts +4 -2
  191. package/dist-server/service/index.js +22 -13
  192. package/dist-server/service/index.js.map +1 -1
  193. package/dist-server/service/issue/index.d.ts +0 -1
  194. package/dist-server/service/issue/index.js +1 -2
  195. package/dist-server/service/issue/index.js.map +1 -1
  196. package/dist-server/service/project-report/index.d.ts +0 -1
  197. package/dist-server/service/project-report/index.js +1 -2
  198. package/dist-server/service/project-report/index.js.map +1 -1
  199. package/dist-server/service/project-report/project-report.d.ts +0 -2
  200. package/dist-server/service/project-report/project-report.js +0 -6
  201. package/dist-server/service/project-report/project-report.js.map +1 -1
  202. package/dist-server/service/supervisor/index.d.ts +0 -1
  203. package/dist-server/service/supervisor/index.js +1 -2
  204. package/dist-server/service/supervisor/index.js.map +1 -1
  205. package/dist-server/tsconfig.tsbuildinfo +1 -1
  206. package/package.json +13 -13
  207. package/things-factory.config.js +3 -1
  208. package/dist-server/service/building-inspection/building-inspection-history.d.ts +0 -17
  209. package/dist-server/service/building-inspection/building-inspection-history.js +0 -86
  210. package/dist-server/service/building-inspection/building-inspection-history.js.map +0 -1
  211. package/dist-server/service/building-inspection/event-subscriber.js.map +0 -1
  212. package/dist-server/service/checklist/checklist-history.d.ts +0 -24
  213. package/dist-server/service/checklist/checklist-history.js +0 -120
  214. package/dist-server/service/checklist/checklist-history.js.map +0 -1
  215. package/dist-server/service/checklist-item-comment/event-subscriber.d.ts +0 -7
  216. package/dist-server/service/checklist-item-comment/event-subscriber.js +0 -21
  217. package/dist-server/service/checklist-item-comment/event-subscriber.js.map +0 -1
@@ -0,0 +1,89 @@
1
+ import { __decorate } from "tslib";
2
+ import { LitElement } from 'lit';
3
+ import { customElement } from 'lit/decorators.js';
4
+ /**
5
+ * SpeechToText (음성 인식) 웹 컴포넌트
6
+ *
7
+ * - 음성 인식 시작/중지 메서드 제공
8
+ * - 인식 결과/에러/상태를 커스텀 이벤트(stt-result, stt-error, stt-status)로 외부에 전달
9
+ * - 버튼 등 UI는 포함하지 않음 (컨트롤은 외부에서)
10
+ *
11
+ * 사용 예시:
12
+ * <speech-to-text id="stt"></speech-to-text>
13
+ *
14
+ * // JS에서
15
+ * const stt = document.getElementById('stt') as SpeechToText;
16
+ * stt.startListening();
17
+ * stt.stopListening();
18
+ * stt.addEventListener('stt-result', e => { ... });
19
+ * stt.addEventListener('stt-error', e => { ... });
20
+ * stt.addEventListener('stt-status', e => { ... });
21
+ */
22
+ let SpeechToText = class SpeechToText extends LitElement {
23
+ constructor() {
24
+ super(...arguments);
25
+ this.recognition = null;
26
+ }
27
+ /**
28
+ * 음성 인식 시작
29
+ */
30
+ startListening() {
31
+ if (!('webkitSpeechRecognition' in window)) {
32
+ this.dispatchEvent(new CustomEvent('stt-error', { detail: { error: '지원되지 않는 브라우저입니다.' } }));
33
+ return;
34
+ }
35
+ this.recognition = new window.webkitSpeechRecognition();
36
+ this.recognition.lang = 'ko-KR';
37
+ this.recognition.continuous = false;
38
+ this.recognition.interimResults = true;
39
+ this.recognition.onresult = (event) => {
40
+ let finalTranscript = '';
41
+ let interimTranscript = '';
42
+ for (let i = event.resultIndex; i < event.results.length; i++) {
43
+ if (event.results[i].isFinal) {
44
+ finalTranscript += event.results[i][0].transcript;
45
+ }
46
+ else {
47
+ interimTranscript += event.results[i][0].transcript;
48
+ }
49
+ }
50
+ this.dispatchEvent(new CustomEvent('stt-result', {
51
+ detail: {
52
+ finalTranscript: finalTranscript.trim(),
53
+ interimTranscript: interimTranscript.trim()
54
+ }
55
+ }));
56
+ this.dispatchEvent(new CustomEvent('stt-status', {
57
+ detail: { status: `📝 Recognized: ${finalTranscript} ${interimTranscript}` }
58
+ }));
59
+ };
60
+ this.recognition.onerror = (event) => {
61
+ this.dispatchEvent(new CustomEvent('stt-error', { detail: { error: event.error } }));
62
+ };
63
+ this.recognition.onend = () => {
64
+ this.dispatchEvent(new CustomEvent('stt-status', { detail: { status: '음성 인식 종료' } }));
65
+ };
66
+ this.recognition.onstart = () => {
67
+ this.dispatchEvent(new CustomEvent('stt-status', { detail: { status: '🎙️ Listening...' } }));
68
+ };
69
+ this.recognition.start();
70
+ }
71
+ /**
72
+ * 음성 인식 중지
73
+ */
74
+ stopListening() {
75
+ if (this.recognition) {
76
+ this.recognition.stop();
77
+ this.dispatchEvent(new CustomEvent('stt-status', { detail: { status: '🛑 Stopped listening.' } }));
78
+ }
79
+ }
80
+ // UI 없음 (렌더링 X)
81
+ render() {
82
+ return null;
83
+ }
84
+ };
85
+ SpeechToText = __decorate([
86
+ customElement('speech-to-text')
87
+ ], SpeechToText);
88
+ export { SpeechToText };
89
+ //# sourceMappingURL=speech-to-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speech-to-text.js","sourceRoot":"","sources":["../../client/stt/speech-to-text.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement } from 'lit'\nimport { customElement } from 'lit/decorators.js'\n\n/**\n * SpeechToText (음성 인식) 웹 컴포넌트\n *\n * - 음성 인식 시작/중지 메서드 제공\n * - 인식 결과/에러/상태를 커스텀 이벤트(stt-result, stt-error, stt-status)로 외부에 전달\n * - 버튼 등 UI는 포함하지 않음 (컨트롤은 외부에서)\n *\n * 사용 예시:\n * <speech-to-text id=\"stt\"></speech-to-text>\n *\n * // JS에서\n * const stt = document.getElementById('stt') as SpeechToText;\n * stt.startListening();\n * stt.stopListening();\n * stt.addEventListener('stt-result', e => { ... });\n * stt.addEventListener('stt-error', e => { ... });\n * stt.addEventListener('stt-status', e => { ... });\n */\n@customElement('speech-to-text')\nexport class SpeechToText extends LitElement {\n private recognition: any = null\n\n /**\n * 음성 인식 시작\n */\n public startListening() {\n if (!('webkitSpeechRecognition' in window)) {\n this.dispatchEvent(new CustomEvent('stt-error', { detail: { error: '지원되지 않는 브라우저입니다.' } }))\n return\n }\n this.recognition = new window.webkitSpeechRecognition()\n this.recognition.lang = 'ko-KR'\n this.recognition.continuous = false\n this.recognition.interimResults = true\n\n this.recognition.onresult = (event: any) => {\n let finalTranscript = ''\n let interimTranscript = ''\n for (let i = event.resultIndex; i < event.results.length; i++) {\n if (event.results[i].isFinal) {\n finalTranscript += event.results[i][0].transcript\n } else {\n interimTranscript += event.results[i][0].transcript\n }\n }\n this.dispatchEvent(\n new CustomEvent('stt-result', {\n detail: {\n finalTranscript: finalTranscript.trim(),\n interimTranscript: interimTranscript.trim()\n }\n })\n )\n this.dispatchEvent(\n new CustomEvent('stt-status', {\n detail: { status: `📝 Recognized: ${finalTranscript} ${interimTranscript}` }\n })\n )\n }\n\n this.recognition.onerror = (event: any) => {\n this.dispatchEvent(new CustomEvent('stt-error', { detail: { error: event.error } }))\n }\n\n this.recognition.onend = () => {\n this.dispatchEvent(new CustomEvent('stt-status', { detail: { status: '음성 인식 종료' } }))\n }\n\n this.recognition.onstart = () => {\n this.dispatchEvent(new CustomEvent('stt-status', { detail: { status: '🎙️ Listening...' } }))\n }\n\n this.recognition.start()\n }\n\n /**\n * 음성 인식 중지\n */\n public stopListening() {\n if (this.recognition) {\n this.recognition.stop()\n this.dispatchEvent(new CustomEvent('stt-status', { detail: { status: '🛑 Stopped listening.' } }))\n }\n }\n\n // UI 없음 (렌더링 X)\n protected render() {\n return null\n }\n}\n\n// 타입 정의 (window에 webkitSpeechRecognition이 있는 경우)\ndeclare global {\n interface Window {\n webkitSpeechRecognition?: any\n }\n}\n"]}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 한글 숫자 → 아라비아 숫자 변환 맵
3
+ */
4
+ export declare const hangulDigits: Record<string, string>;
5
+ /**
6
+ * 음성 인식 오인식 보정 맵
7
+ */
8
+ export declare const misheardMap: Record<string, string>;
9
+ /**
10
+ * 합격/불합격 동의어
11
+ */
12
+ export declare const passSynonyms: string[];
13
+ export declare const failSynonyms: string[];
14
+ /**
15
+ * 체크리스트 명령 해석 결과 타입
16
+ */
17
+ export interface ParsedSpeechCommand {
18
+ rowIds: number[];
19
+ isPass: boolean | null;
20
+ actionText?: string;
21
+ raw: string;
22
+ }
23
+ /**
24
+ * 음성 인식 텍스트를 체크리스트 명령으로 해석
25
+ * @param command 음성 인식 결과 텍스트
26
+ * @param checklistLength 체크리스트 항목 개수(번호 범위 제한용)
27
+ */
28
+ export declare function parseSpeechCommand(command: string, checklistLength?: number): ParsedSpeechCommand;
@@ -0,0 +1,146 @@
1
+ // stt-utils.ts
2
+ // 음성 인식 텍스트를 체크리스트 명령으로 해석하는 유틸리티
3
+ /**
4
+ * 한글 숫자 → 아라비아 숫자 변환 맵
5
+ */
6
+ export const hangulDigits = {
7
+ 일: '1',
8
+ 이: '2',
9
+ 삼: '3',
10
+ 사: '4',
11
+ 오: '5',
12
+ 육: '6',
13
+ 륙: '6',
14
+ 칠: '7',
15
+ 팔: '8',
16
+ 구: '9',
17
+ 십: '10',
18
+ 십일: '11',
19
+ 열하나: '11',
20
+ 십이: '12',
21
+ 열둘: '12',
22
+ 십삼: '13',
23
+ 열셋: '13',
24
+ 십사: '14',
25
+ 열넷: '14',
26
+ 십오: '15',
27
+ 열다섯: '15',
28
+ 십육: '16',
29
+ 열여섯: '16',
30
+ 십칠: '17',
31
+ 열일곱: '17',
32
+ 십팔: '18',
33
+ 열여덟: '18',
34
+ 십구: '19',
35
+ 열아홉: '19',
36
+ 이십: '20',
37
+ 스물: '20'
38
+ };
39
+ /**
40
+ * 음성 인식 오인식 보정 맵
41
+ */
42
+ export const misheardMap = {
43
+ 일번: '1번',
44
+ 일본: '1번',
45
+ 이번: '2번',
46
+ 삼번: '3번',
47
+ 사번: '4번',
48
+ 오번: '5번',
49
+ 육번: '6번',
50
+ 륙번: '6번',
51
+ 칠번: '7번',
52
+ 팔번: '8번',
53
+ 구번: '9번',
54
+ 십번: '10번',
55
+ 십일번: '11번',
56
+ 열하나번: '11번',
57
+ 십이번: '12번',
58
+ 열둘번: '12번',
59
+ 십삼번: '13번',
60
+ 열셋번: '13번',
61
+ 십사번: '14번',
62
+ 열넷번: '14번',
63
+ 십오번: '15번',
64
+ 열다섯번: '15번',
65
+ 십육번: '16번',
66
+ 열여섯번: '16번',
67
+ 십칠번: '17번',
68
+ 열일곱번: '17번',
69
+ 십팔번: '18번',
70
+ 열여덟번: '18번',
71
+ 십구번: '19번',
72
+ 열아홉번: '19번',
73
+ 이십번: '20번',
74
+ 스물번: '20번',
75
+ // 추가 보정
76
+ '조치 사항': '조치사항',
77
+ 조치상: '조치사항',
78
+ 조치: '조치사항',
79
+ 자제: '자재'
80
+ };
81
+ /**
82
+ * 합격/불합격 동의어
83
+ */
84
+ export const passSynonyms = ['합격', 'pass', 'approved', 'okay'];
85
+ export const failSynonyms = ['불합격', 'fail', 'failed'];
86
+ /**
87
+ * 음성 인식 텍스트를 체크리스트 명령으로 해석
88
+ * @param command 음성 인식 결과 텍스트
89
+ * @param checklistLength 체크리스트 항목 개수(번호 범위 제한용)
90
+ */
91
+ export function parseSpeechCommand(command, checklistLength = 20) {
92
+ let original = command;
93
+ // (A) 하이픈 제거, 오인식 보정
94
+ command = command.replace(/-/g, '');
95
+ for (const [wrong, correct] of Object.entries(misheardMap)) {
96
+ command = command.replace(new RegExp(wrong, 'g'), correct);
97
+ }
98
+ // (B) 한글 숫자 변환
99
+ let tokens = command.split(/\s+/).map(token => {
100
+ if (hangulDigits[token])
101
+ return hangulDigits[token] + '번';
102
+ const m = token.match(/^([일이삼사오육륙칠팔구십])번$/);
103
+ if (m)
104
+ return hangulDigits[m[1]] + '번';
105
+ return token;
106
+ });
107
+ command = tokens.join(' ');
108
+ // (C) 번호 추출
109
+ const rowRegexGlobal = /(\d+)번/g;
110
+ let rowMatches = [...command.matchAll(rowRegexGlobal)];
111
+ let rowIds = [];
112
+ rowMatches.forEach(match => {
113
+ let numStr = match[1];
114
+ let numeric = parseInt(numStr, 10);
115
+ if (numeric >= 1 && numeric <= checklistLength) {
116
+ rowIds.push(numeric);
117
+ }
118
+ });
119
+ // (D) 합격/불합격 여부
120
+ let isPass = null;
121
+ for (let word of passSynonyms) {
122
+ if (command.includes(word)) {
123
+ isPass = true;
124
+ break;
125
+ }
126
+ }
127
+ for (let word of failSynonyms) {
128
+ if (command.includes(word)) {
129
+ isPass = false;
130
+ break;
131
+ }
132
+ }
133
+ // (E) 조치사항 텍스트 추출
134
+ let actionText;
135
+ let actionMatch = command.match(/조치사항\s*(.*)/);
136
+ if (actionMatch && actionMatch[1]) {
137
+ actionText = actionMatch[1].trim();
138
+ }
139
+ return {
140
+ rowIds,
141
+ isPass,
142
+ actionText,
143
+ raw: original
144
+ };
145
+ }
146
+ //# sourceMappingURL=stt-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stt-utils.js","sourceRoot":"","sources":["../../client/stt/stt-utils.ts"],"names":[],"mappings":"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","sourcesContent":["// stt-utils.ts\n// 음성 인식 텍스트를 체크리스트 명령으로 해석하는 유틸리티\n\n/**\n * 한글 숫자 → 아라비아 숫자 변환 맵\n */\nexport const hangulDigits: Record<string, string> = {\n 일: '1',\n 이: '2',\n 삼: '3',\n 사: '4',\n 오: '5',\n 육: '6',\n 륙: '6',\n 칠: '7',\n 팔: '8',\n 구: '9',\n 십: '10',\n 십일: '11',\n 열하나: '11',\n 십이: '12',\n 열둘: '12',\n 십삼: '13',\n 열셋: '13',\n 십사: '14',\n 열넷: '14',\n 십오: '15',\n 열다섯: '15',\n 십육: '16',\n 열여섯: '16',\n 십칠: '17',\n 열일곱: '17',\n 십팔: '18',\n 열여덟: '18',\n 십구: '19',\n 열아홉: '19',\n 이십: '20',\n 스물: '20'\n}\n\n/**\n * 음성 인식 오인식 보정 맵\n */\nexport const misheardMap: Record<string, string> = {\n 일번: '1번',\n 일본: '1번',\n 이번: '2번',\n 삼번: '3번',\n 사번: '4번',\n 오번: '5번',\n 육번: '6번',\n 륙번: '6번',\n 칠번: '7번',\n 팔번: '8번',\n 구번: '9번',\n 십번: '10번',\n 십일번: '11번',\n 열하나번: '11번',\n 십이번: '12번',\n 열둘번: '12번',\n 십삼번: '13번',\n 열셋번: '13번',\n 십사번: '14번',\n 열넷번: '14번',\n 십오번: '15번',\n 열다섯번: '15번',\n 십육번: '16번',\n 열여섯번: '16번',\n 십칠번: '17번',\n 열일곱번: '17번',\n 십팔번: '18번',\n 열여덟번: '18번',\n 십구번: '19번',\n 열아홉번: '19번',\n 이십번: '20번',\n 스물번: '20번',\n // 추가 보정\n '조치 사항': '조치사항',\n 조치상: '조치사항',\n 조치: '조치사항',\n 자제: '자재'\n}\n\n/**\n * 합격/불합격 동의어\n */\nexport const passSynonyms = ['합격', 'pass', 'approved', 'okay']\nexport const failSynonyms = ['불합격', 'fail', 'failed']\n\n/**\n * 체크리스트 명령 해석 결과 타입\n */\nexport interface ParsedSpeechCommand {\n rowIds: number[] // 체크리스트 항목 번호(1,2,3 등)\n isPass: boolean | null // 합격/불합격 여부 (없으면 null)\n actionText?: string // 조치사항 텍스트 (있을 때만)\n raw: string // 원본 텍스트\n}\n\n/**\n * 음성 인식 텍스트를 체크리스트 명령으로 해석\n * @param command 음성 인식 결과 텍스트\n * @param checklistLength 체크리스트 항목 개수(번호 범위 제한용)\n */\nexport function parseSpeechCommand(command: string, checklistLength = 20): ParsedSpeechCommand {\n let original = command\n\n // (A) 하이픈 제거, 오인식 보정\n command = command.replace(/-/g, '')\n for (const [wrong, correct] of Object.entries(misheardMap)) {\n command = command.replace(new RegExp(wrong, 'g'), correct)\n }\n\n // (B) 한글 숫자 변환\n let tokens = command.split(/\\s+/).map(token => {\n if (hangulDigits[token]) return hangulDigits[token] + '번'\n const m = token.match(/^([일이삼사오육륙칠팔구십])번$/)\n if (m) return hangulDigits[m[1]] + '번'\n return token\n })\n command = tokens.join(' ')\n\n // (C) 번호 추출\n const rowRegexGlobal = /(\\d+)번/g\n let rowMatches = [...command.matchAll(rowRegexGlobal)]\n let rowIds: number[] = []\n rowMatches.forEach(match => {\n let numStr = match[1]\n let numeric = parseInt(numStr, 10)\n if (numeric >= 1 && numeric <= checklistLength) {\n rowIds.push(numeric)\n }\n })\n\n // (D) 합격/불합격 여부\n let isPass: boolean | null = null\n for (let word of passSynonyms) {\n if (command.includes(word)) {\n isPass = true\n break\n }\n }\n for (let word of failSynonyms) {\n if (command.includes(word)) {\n isPass = false\n break\n }\n }\n\n // (E) 조치사항 텍스트 추출\n let actionText: string | undefined\n let actionMatch = command.match(/조치사항\\s*(.*)/)\n if (actionMatch && actionMatch[1]) {\n actionText = actionMatch[1].trim()\n }\n\n return {\n rowIds,\n isPass,\n actionText,\n raw: original\n }\n}\n"]}