shared-ritm 1.2.122 → 1.2.124

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 (108) hide show
  1. package/README.md +103 -103
  2. package/dist/index.css +1 -1
  3. package/dist/shared-ritm.es.js +281 -275
  4. package/dist/shared-ritm.umd.js +4 -4
  5. package/dist/types/api/services/ControlsService.d.ts +1 -0
  6. package/dist/types/api/types/Api_Controls.d.ts +10 -0
  7. package/package.json +1 -1
  8. package/src/App.vue +2461 -2461
  9. package/src/api/services/AuthService.ts +53 -53
  10. package/src/api/services/CommentsService.ts +24 -24
  11. package/src/api/services/ControlsService.ts +69 -65
  12. package/src/api/services/FileService.ts +17 -17
  13. package/src/api/services/GanttService.ts +17 -17
  14. package/src/api/services/MetricsService.ts +110 -110
  15. package/src/api/services/ProjectsService.ts +79 -79
  16. package/src/api/services/RepairsService.ts +119 -119
  17. package/src/api/services/TasksService.ts +145 -145
  18. package/src/api/types/Api_Auth.ts +86 -86
  19. package/src/api/types/Api_Comment.ts +40 -40
  20. package/src/api/types/Api_Controls.ts +82 -72
  21. package/src/api/types/Api_Files.ts +7 -7
  22. package/src/api/types/Api_Projects.ts +60 -60
  23. package/src/api/types/Api_Service.ts +9 -9
  24. package/src/api/types/Api_Tasks.ts +319 -319
  25. package/src/common/app-button/AppButton.vue +173 -173
  26. package/src/common/app-checkbox/AppCheckbox.vue +26 -26
  27. package/src/common/app-date-picker/AppDatePicker.vue +81 -81
  28. package/src/common/app-datepicker/AppDatepicker.vue +165 -165
  29. package/src/common/app-dialogs/AppConfirmDialog.vue +99 -99
  30. package/src/common/app-dropdown/AppDropdown.vue +31 -31
  31. package/src/common/app-icon/AppIcon.vue +108 -108
  32. package/src/common/app-input/AppInput.vue +148 -148
  33. package/src/common/app-input-search/AppInputSearch.vue +174 -174
  34. package/src/common/app-layout/AppLayout.vue +84 -84
  35. package/src/common/app-layout/components/AppLayoutHeader.vue +273 -273
  36. package/src/common/app-layout/components/AppLayoutPage.vue +16 -16
  37. package/src/common/app-loader/index.vue +43 -43
  38. package/src/common/app-page-layout/AppPageLayout.vue +122 -122
  39. package/src/common/app-select/AppSelect.vue +157 -157
  40. package/src/common/app-sheet/AppSheet.vue +120 -120
  41. package/src/common/app-sidebar/AppSidebar.vue +168 -168
  42. package/src/common/app-sidebar/components/SidebarMenu.vue +37 -37
  43. package/src/common/app-sidebar/components/SidebarMenuItem.vue +148 -148
  44. package/src/common/app-table/components/TablePagination.vue +152 -152
  45. package/src/common/app-table/controllers/useColumnSelector.ts +38 -38
  46. package/src/common/app-table/controllers/useTableModel.ts +102 -93
  47. package/src/common/app-toggle/AppToggle.vue +24 -24
  48. package/src/common/app-wrapper/AppWrapper.vue +28 -28
  49. package/src/global.d.ts +1 -1
  50. package/src/icons/components/arrow-down-icon.vue +25 -25
  51. package/src/icons/components/arrow-frame-icon.vue +19 -19
  52. package/src/icons/components/arrow-square.vue +22 -22
  53. package/src/icons/components/table-filter-icon.vue +30 -30
  54. package/src/icons/dialogs/RemoveIcon.vue +12 -12
  55. package/src/icons/dialogs/SafetyIcon.vue +12 -12
  56. package/src/icons/header/NotificationIcon.vue +18 -18
  57. package/src/icons/header/PersonIcon.vue +11 -11
  58. package/src/icons/header/SettingIcon.vue +14 -14
  59. package/src/icons/header/flashIcon.vue +24 -24
  60. package/src/icons/header/searchStatusIcon.vue +24 -24
  61. package/src/icons/header/smallCapsIcon.vue +34 -34
  62. package/src/icons/sidebar/assign-module-icon.vue +36 -36
  63. package/src/icons/sidebar/instrument-history-icon.vue +32 -32
  64. package/src/icons/sidebar/instrument-order-icon.vue +38 -38
  65. package/src/icons/sidebar/instrument-work-zone-icon.vue +18 -18
  66. package/src/icons/sidebar/instruments-icon.vue +45 -45
  67. package/src/icons/sidebar/logo-icon.vue +15 -15
  68. package/src/icons/sidebar/logout-icon.vue +13 -13
  69. package/src/icons/sidebar/modules-icon.vue +16 -16
  70. package/src/icons/sidebar/notifications-icon.vue +24 -24
  71. package/src/icons/sidebar/order-icon.vue +44 -44
  72. package/src/icons/sidebar/pass-icon.vue +38 -38
  73. package/src/icons/sidebar/positions-icon.vue +42 -42
  74. package/src/icons/sidebar/preorder-icon.vue +19 -19
  75. package/src/icons/sidebar/projects-icon.vue +31 -31
  76. package/src/icons/sidebar/repair-object-icon.vue +18 -18
  77. package/src/icons/sidebar/repairs-icon.vue +20 -20
  78. package/src/icons/sidebar/roles-icon.vue +26 -26
  79. package/src/icons/sidebar/status-history-icon.vue +24 -24
  80. package/src/icons/sidebar/tasks-icon.vue +28 -28
  81. package/src/icons/sidebar/tasks_tasks-icon.vue +39 -39
  82. package/src/icons/sidebar/tasks_today-icon.vue +27 -27
  83. package/src/icons/sidebar/teams-icon.vue +32 -32
  84. package/src/icons/sidebar/user-icon.vue +18 -18
  85. package/src/icons/sidebar/users-icon.vue +46 -46
  86. package/src/icons/sidebar/videosources-icon.vue +19 -19
  87. package/src/icons/sidebar/videowall-icon.vue +13 -13
  88. package/src/icons/sidebar/videozones-icon.vue +21 -21
  89. package/src/icons/sidebar/warehouses-icon.vue +43 -43
  90. package/src/icons/sidebar/workshop-icon.vue +100 -100
  91. package/src/icons/sidebar/workzones-icon.vue +22 -22
  92. package/src/icons/task/attention-icon.vue +13 -13
  93. package/src/icons/task/clock-icon.vue +10 -10
  94. package/src/icons/task/delete-icon.vue +10 -10
  95. package/src/icons/task/fire-icon.vue +16 -16
  96. package/src/index.ts +123 -123
  97. package/src/main.ts +28 -28
  98. package/src/quasar-user-options.ts +17 -17
  99. package/src/router/index.ts +10 -10
  100. package/src/shared/styles/general.css +124 -124
  101. package/src/shims-vue.d.ts +5 -5
  102. package/src/utils/confirm.ts +12 -12
  103. package/src/utils/faceApiHelper.ts +132 -132
  104. package/src/utils/helpers.ts +59 -59
  105. package/src/utils/notification.ts +9 -9
  106. package/dist/types/api/services/ComentsServise.d.ts +0 -10
  107. package/dist/types/api/services/PhotoService.d.ts +0 -53
  108. package/dist/types/api/types/Api_Users.d.ts +0 -43
package/src/main.ts CHANGED
@@ -1,28 +1,28 @@
1
- import { createApp } from 'vue'
2
- import { Quasar, quasarUserOptions } from './quasar-user-options'
3
- import router from './router/index'
4
-
5
- import '@quasar/extras/material-icons/material-icons.css'
6
- import 'quasar/src/css/index.sass'
7
-
8
- import '@/shared/styles/general.css'
9
-
10
- import App from './App.vue'
11
-
12
- const app = createApp(App)
13
-
14
- //@ts-ignore
15
- app.use(Quasar, quasarUserOptions)
16
-
17
- app.use(router)
18
- app.mount('#app')
19
-
20
- const observerErrRe = /^ResizeObserver loop completed/
21
-
22
- const originalConsoleError = console.error
23
- console.error = (...args) => {
24
- if (typeof args[0] === 'string' && observerErrRe.test(args[0])) {
25
- return
26
- }
27
- originalConsoleError(...args)
28
- }
1
+ import { createApp } from 'vue'
2
+ import { Quasar, quasarUserOptions } from './quasar-user-options'
3
+ import router from './router/index'
4
+
5
+ import '@quasar/extras/material-icons/material-icons.css'
6
+ import 'quasar/src/css/index.sass'
7
+
8
+ import '@/shared/styles/general.css'
9
+
10
+ import App from './App.vue'
11
+
12
+ const app = createApp(App)
13
+
14
+ //@ts-ignore
15
+ app.use(Quasar, quasarUserOptions)
16
+
17
+ app.use(router)
18
+ app.mount('#app')
19
+
20
+ const observerErrRe = /^ResizeObserver loop completed/
21
+
22
+ const originalConsoleError = console.error
23
+ console.error = (...args) => {
24
+ if (typeof args[0] === 'string' && observerErrRe.test(args[0])) {
25
+ return
26
+ }
27
+ originalConsoleError(...args)
28
+ }
@@ -1,17 +1,17 @@
1
- import { Quasar, Notify, Loading, Dialog } from 'quasar'
2
-
3
- import 'quasar/src/css/index.sass'
4
- import '@quasar/extras/roboto-font/roboto-font.css'
5
- import '@quasar/extras/material-icons/material-icons.css'
6
- import '@quasar/extras/material-icons-outlined/material-icons-outlined.css'
7
- import '@quasar/extras/mdi-v7/mdi-v7.css'
8
-
9
- const quasarUserOptions = {
10
- plugins: {
11
- Notify,
12
- Loading,
13
- Dialog,
14
- },
15
- }
16
-
17
- export { Quasar, quasarUserOptions }
1
+ import { Quasar, Notify, Loading, Dialog } from 'quasar'
2
+
3
+ import 'quasar/src/css/index.sass'
4
+ import '@quasar/extras/roboto-font/roboto-font.css'
5
+ import '@quasar/extras/material-icons/material-icons.css'
6
+ import '@quasar/extras/material-icons-outlined/material-icons-outlined.css'
7
+ import '@quasar/extras/mdi-v7/mdi-v7.css'
8
+
9
+ const quasarUserOptions = {
10
+ plugins: {
11
+ Notify,
12
+ Loading,
13
+ Dialog,
14
+ },
15
+ }
16
+
17
+ export { Quasar, quasarUserOptions }
@@ -1,10 +1,10 @@
1
- import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
2
-
3
- const routes: RouteRecordRaw[] = []
4
-
5
- const router = createRouter({
6
- history: createWebHistory(),
7
- routes,
8
- })
9
-
10
- export default router
1
+ import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
2
+
3
+ const routes: RouteRecordRaw[] = []
4
+
5
+ const router = createRouter({
6
+ history: createWebHistory(),
7
+ routes,
8
+ })
9
+
10
+ export default router
@@ -1,124 +1,124 @@
1
- :root {
2
- --main-header-height: 73px;
3
- --main-footer-height: 66px;
4
- --sidebar-width-max: 250px;
5
- --sidebar-width-min: 66px;
6
- }
7
-
8
- /*border-radius*/
9
- :root {
10
- --border-radius-xxs: 4px;
11
- --border-radius-xs: 8px;
12
- --border-radius-s: 12px;
13
- --border-radius-m: 16px;
14
- }
15
-
16
- /*color*/
17
- :root {
18
- --g-blue: #3f8cff;
19
- --g-blue-light: #e4efff;
20
- --g-blue-dark: #1c75ff;
21
- --g-green: #00d097;
22
- --g-green-light: #e0f9f2;
23
- --g-green-dark: #b8f8e7;
24
- --g-red: #ff192d;
25
- --g-red-light: #fdecee;
26
- --g-red-dark: #ffdcde;
27
- --g-grey-100: #d8e0f0;
28
-
29
- --g-font-color: #0a1629;
30
- --g-font-grey-color: #b9c0c7;
31
- --g-font-secondary-color: #7d8592;
32
-
33
- --g-grey-background: #ced5e0;
34
- --g-grey-hover-background: #9fa5af;
35
- --g-secondary-background: #f4f9fd;
36
- --g-thirty-background: #c8cbcf;
37
-
38
- --g-fire-color-1: #fee7e7;
39
- --g-fire-color-2: #fed4d5;
40
- --g-fire-color-3: #fcc0c0;
41
- --g-fire-color-4: #f9a2a2;
42
- --g-fire-color-5: #f97d7e;
43
- --g-fire-color-6: #f65160;
44
- --g-fire-color-7: #ff192d;
45
- --g-fire-color-8: #ab0514;
46
- --g-fire-color-9: #6e000a;
47
- }
48
-
49
- * {
50
- margin: 0;
51
- padding: 0;
52
- }
53
-
54
- button:active,
55
- button:focus {
56
- outline: none !important;
57
- }
58
-
59
- html {
60
- font-family: 'NunitoSansFont', sans-serif !important;
61
- }
62
-
63
- .ant-dropdown {
64
- z-index: 10000;
65
- .content {
66
- z-index: 10000;
67
- }
68
- }
69
-
70
- @font-face {
71
- font-family: 'NunitoSansFont';
72
- src: local('NunitoSansFont-Regular'), url('../fonts/NunitoSansFont.ttf') format('truetype');
73
- font-weight: 400;
74
- font-style: normal;
75
- }
76
-
77
- @font-face {
78
- font-family: 'NunitoSansFont';
79
- src: local('NunitoSansFont-Bold'), url('../fonts/NunitoSans_7pt-Bold.ttf') format('truetype');
80
- font-weight: 700;
81
- font-style: normal;
82
- }
83
-
84
- @font-face {
85
- font-family: 'Montserrat';
86
- src: local('Montserrat-Regular'), url('../fonts/Montserrat.ttf') format('truetype');
87
- font-weight: 400;
88
- font-style: normal;
89
- }
90
-
91
- @font-face {
92
- font-family: 'Montserrat';
93
- src: local('Montserrat-Bold'), url('../fonts/Montserrat-Bold.ttf') format('truetype');
94
- font-weight: 700;
95
- font-style: normal;
96
- }
97
-
98
- @font-face {
99
- font-family: 'Inter';
100
- src: local('Inter-Regular'), url('../fonts/Inter_18pt-Regular.ttf') format('truetype');
101
- font-weight: 400;
102
- font-style: normal;
103
- }
104
-
105
- @font-face {
106
- font-family: 'Inter';
107
- src: local('Inter-SemiBold'), url('../fonts/Inter_18pt-SemiBold.ttf') format('truetype');
108
- font-weight: 600;
109
- font-style: normal;
110
- }
111
-
112
- @font-face {
113
- font-family: 'Inter';
114
- src: local('Inter-Bold'), url('../fonts/Inter_18pt-Bold.ttf') format('truetype');
115
- font-weight: 700;
116
- font-style: normal;
117
- }
118
-
119
- @font-face {
120
- font-family: 'Inter';
121
- src: local('Inter-Black'), url('../fonts/Inter_18pt-Black.ttf') format('truetype');
122
- font-weight: 900;
123
- font-style: normal;
124
- }
1
+ :root {
2
+ --main-header-height: 73px;
3
+ --main-footer-height: 66px;
4
+ --sidebar-width-max: 250px;
5
+ --sidebar-width-min: 66px;
6
+ }
7
+
8
+ /*border-radius*/
9
+ :root {
10
+ --border-radius-xxs: 4px;
11
+ --border-radius-xs: 8px;
12
+ --border-radius-s: 12px;
13
+ --border-radius-m: 16px;
14
+ }
15
+
16
+ /*color*/
17
+ :root {
18
+ --g-blue: #3f8cff;
19
+ --g-blue-light: #e4efff;
20
+ --g-blue-dark: #1c75ff;
21
+ --g-green: #00d097;
22
+ --g-green-light: #e0f9f2;
23
+ --g-green-dark: #b8f8e7;
24
+ --g-red: #ff192d;
25
+ --g-red-light: #fdecee;
26
+ --g-red-dark: #ffdcde;
27
+ --g-grey-100: #d8e0f0;
28
+
29
+ --g-font-color: #0a1629;
30
+ --g-font-grey-color: #b9c0c7;
31
+ --g-font-secondary-color: #7d8592;
32
+
33
+ --g-grey-background: #ced5e0;
34
+ --g-grey-hover-background: #9fa5af;
35
+ --g-secondary-background: #f4f9fd;
36
+ --g-thirty-background: #c8cbcf;
37
+
38
+ --g-fire-color-1: #fee7e7;
39
+ --g-fire-color-2: #fed4d5;
40
+ --g-fire-color-3: #fcc0c0;
41
+ --g-fire-color-4: #f9a2a2;
42
+ --g-fire-color-5: #f97d7e;
43
+ --g-fire-color-6: #f65160;
44
+ --g-fire-color-7: #ff192d;
45
+ --g-fire-color-8: #ab0514;
46
+ --g-fire-color-9: #6e000a;
47
+ }
48
+
49
+ * {
50
+ margin: 0;
51
+ padding: 0;
52
+ }
53
+
54
+ button:active,
55
+ button:focus {
56
+ outline: none !important;
57
+ }
58
+
59
+ html {
60
+ font-family: 'NunitoSansFont', sans-serif !important;
61
+ }
62
+
63
+ .ant-dropdown {
64
+ z-index: 10000;
65
+ .content {
66
+ z-index: 10000;
67
+ }
68
+ }
69
+
70
+ @font-face {
71
+ font-family: 'NunitoSansFont';
72
+ src: local('NunitoSansFont-Regular'), url('../fonts/NunitoSansFont.ttf') format('truetype');
73
+ font-weight: 400;
74
+ font-style: normal;
75
+ }
76
+
77
+ @font-face {
78
+ font-family: 'NunitoSansFont';
79
+ src: local('NunitoSansFont-Bold'), url('../fonts/NunitoSans_7pt-Bold.ttf') format('truetype');
80
+ font-weight: 700;
81
+ font-style: normal;
82
+ }
83
+
84
+ @font-face {
85
+ font-family: 'Montserrat';
86
+ src: local('Montserrat-Regular'), url('../fonts/Montserrat.ttf') format('truetype');
87
+ font-weight: 400;
88
+ font-style: normal;
89
+ }
90
+
91
+ @font-face {
92
+ font-family: 'Montserrat';
93
+ src: local('Montserrat-Bold'), url('../fonts/Montserrat-Bold.ttf') format('truetype');
94
+ font-weight: 700;
95
+ font-style: normal;
96
+ }
97
+
98
+ @font-face {
99
+ font-family: 'Inter';
100
+ src: local('Inter-Regular'), url('../fonts/Inter_18pt-Regular.ttf') format('truetype');
101
+ font-weight: 400;
102
+ font-style: normal;
103
+ }
104
+
105
+ @font-face {
106
+ font-family: 'Inter';
107
+ src: local('Inter-SemiBold'), url('../fonts/Inter_18pt-SemiBold.ttf') format('truetype');
108
+ font-weight: 600;
109
+ font-style: normal;
110
+ }
111
+
112
+ @font-face {
113
+ font-family: 'Inter';
114
+ src: local('Inter-Bold'), url('../fonts/Inter_18pt-Bold.ttf') format('truetype');
115
+ font-weight: 700;
116
+ font-style: normal;
117
+ }
118
+
119
+ @font-face {
120
+ font-family: 'Inter';
121
+ src: local('Inter-Black'), url('../fonts/Inter_18pt-Black.ttf') format('truetype');
122
+ font-weight: 900;
123
+ font-style: normal;
124
+ }
@@ -1,5 +1,5 @@
1
- declare module '*.vue' {
2
- import { DefineComponent } from 'vue'
3
- const component: DefineComponent<{}, {}, any>
4
- export default component
5
- }
1
+ declare module '*.vue' {
2
+ import { DefineComponent } from 'vue'
3
+ const component: DefineComponent<{}, {}, any>
4
+ export default component
5
+ }
@@ -1,12 +1,12 @@
1
- import { defineAsyncComponent } from 'vue'
2
- import { useQuasar } from 'quasar'
3
- const $q = useQuasar()
4
-
5
- const AppConfirmDialog = defineAsyncComponent(() => import('@/common/app-dialogs/AppConfirmDialog.vue'))
6
-
7
- export const appConfirm = (content: string, type: 'delete' | 'edit') => {
8
- return $q.dialog({
9
- component: AppConfirmDialog,
10
- componentProps: { content, type },
11
- })
12
- }
1
+ import { defineAsyncComponent } from 'vue'
2
+ import { useQuasar } from 'quasar'
3
+ const $q = useQuasar()
4
+
5
+ const AppConfirmDialog = defineAsyncComponent(() => import('@/common/app-dialogs/AppConfirmDialog.vue'))
6
+
7
+ export const appConfirm = (content: string, type: 'delete' | 'edit') => {
8
+ return $q.dialog({
9
+ component: AppConfirmDialog,
10
+ componentProps: { content, type },
11
+ })
12
+ }
@@ -1,132 +1,132 @@
1
- import * as faceapi from 'face-api.js'
2
-
3
- class FaceApiHelper {
4
- // async getFaceSnapshot(inputImage: any, box: any) {
5
- // const regionsToExtract = [new faceapi.Rect(box.x, box.y, box.width, box.height)]
6
- // const faceImages = await faceapi.extractFaces(inputImage, regionsToExtract)
7
- // if (faceImages.length) {
8
- // const dataUrl = faceImages[0].toDataURL('image/jpeg')
9
- // photo.value = dataUrl.replace(/^data:image\/\w+;base64,/, '')
10
- // }
11
- // }
12
-
13
- // Метод настройки конфига для стрима
14
- getVideoStreamConfig(width: number, height: number) {
15
- return {
16
- audio: false,
17
- video: {
18
- width: { min: width, ideal: width },
19
- height: { min: height, ideal: height },
20
- facingMode: 'environment', // или 'user' для фронтальной камеры
21
- },
22
- }
23
- }
24
-
25
- // Метод для настройки рамки, где должно помещаться лицо
26
- getContourCoordinate(width: number, height: number) {
27
- return {
28
- x: width * 0.25,
29
- y: height * 0.05,
30
- width: width * 0.5,
31
- height: height * 0.9,
32
- }
33
- }
34
-
35
- getBoxData(box: any) {
36
- if (!box) return null
37
- return {
38
- x: box.x,
39
- y: box.y,
40
- width: box.width,
41
- height: box.height,
42
- }
43
- }
44
-
45
- setStylesForCanvas(canvasContainer: any) {
46
- canvasContainer.width = '100%'
47
- canvasContainer.height = '100%'
48
- canvasContainer.style.position = 'absolute'
49
- canvasContainer.style.top = '0'
50
- canvasContainer.style.left = '0'
51
- }
52
-
53
- // Метод для рассчёта того, что лицо полностью помещается в рамке
54
- checkFaceInclusion(frame: any, face: any) {
55
- if (!frame || !face) return false
56
-
57
- if (face.width > frame.width || face.height > frame.height) {
58
- return false
59
- }
60
-
61
- const faceXmin = face.x
62
- const faceXmax = face.x + face.width
63
- const faceYmin = face.y
64
- const faceYmax = face.y + face.height
65
-
66
- const frameXmin = frame.x
67
- const frameXmax = frame.x + frame.width
68
- const frameYmin = frame.y
69
- const frameYmax = frame.y + frame.height
70
-
71
- return faceXmin >= frameXmin && faceXmax <= frameXmax && faceYmin >= frameYmin && faceYmax <= frameYmax
72
- }
73
-
74
- async getFaceDetections(videoRef: any, inputSize: number) {
75
- if (!videoRef) return []
76
- const options = new faceapi.TinyFaceDetectorOptions({ inputSize })
77
- return faceapi.detectSingleFace(videoRef, options).withFaceLandmarks(true)
78
- }
79
-
80
- getCanvas(videoRef: any) {
81
- return faceapi.createCanvasFromMedia(videoRef)
82
- }
83
-
84
- getResizedAndDetection(canvas: any, detections: any, ctx: any, videoWidth: number, videoHeight: number) {
85
- faceapi.matchDimensions(canvas, { width: videoWidth, height: videoHeight })
86
-
87
- const resized = faceapi.resizeResults(detections, {
88
- width: videoWidth,
89
- height: videoHeight,
90
- })
91
-
92
- ctx.clearRect(0, 0, videoWidth, videoHeight)
93
-
94
- faceapi.draw.drawDetections(canvas, resized)
95
- faceapi.draw.drawFaceLandmarks(canvas, resized)
96
- //faceapi.draw.drawFaceExpressions(canvas, resized)
97
- }
98
-
99
- async getFaceSnapshot(inputImage: any, box: any) {
100
- const regionsToExtract = [new faceapi.Rect(box.x, box.y, box.width, box.height)]
101
- const faceImages = await faceapi.extractFaces(inputImage, regionsToExtract)
102
-
103
- if (faceImages.length) {
104
- const dataUrl = faceImages[0].toDataURL('image/jpeg')
105
- return dataUrl.replace(/^data:image\/\w+;base64,/, '')
106
- }
107
-
108
- return null
109
- }
110
-
111
- async initModels() {
112
- let date = new Date()
113
- console.log(date)
114
- try {
115
- await Promise.all([
116
- faceapi.nets.tinyFaceDetector.loadFromUri('/models'),
117
- faceapi.nets.faceLandmark68TinyNet.loadFromUri('/models'),
118
- ])
119
- } catch (error) {
120
- console.error(error)
121
- }
122
- date = new Date()
123
- console.log(date)
124
- }
125
- }
126
-
127
- let helper: FaceApiHelper
128
-
129
- export default function useFaceApiHelper() {
130
- if (!helper) helper = new FaceApiHelper()
131
- return helper
132
- }
1
+ import * as faceapi from 'face-api.js'
2
+
3
+ class FaceApiHelper {
4
+ // async getFaceSnapshot(inputImage: any, box: any) {
5
+ // const regionsToExtract = [new faceapi.Rect(box.x, box.y, box.width, box.height)]
6
+ // const faceImages = await faceapi.extractFaces(inputImage, regionsToExtract)
7
+ // if (faceImages.length) {
8
+ // const dataUrl = faceImages[0].toDataURL('image/jpeg')
9
+ // photo.value = dataUrl.replace(/^data:image\/\w+;base64,/, '')
10
+ // }
11
+ // }
12
+
13
+ // Метод настройки конфига для стрима
14
+ getVideoStreamConfig(width: number, height: number) {
15
+ return {
16
+ audio: false,
17
+ video: {
18
+ width: { min: width, ideal: width },
19
+ height: { min: height, ideal: height },
20
+ facingMode: 'environment', // или 'user' для фронтальной камеры
21
+ },
22
+ }
23
+ }
24
+
25
+ // Метод для настройки рамки, где должно помещаться лицо
26
+ getContourCoordinate(width: number, height: number) {
27
+ return {
28
+ x: width * 0.25,
29
+ y: height * 0.05,
30
+ width: width * 0.5,
31
+ height: height * 0.9,
32
+ }
33
+ }
34
+
35
+ getBoxData(box: any) {
36
+ if (!box) return null
37
+ return {
38
+ x: box.x,
39
+ y: box.y,
40
+ width: box.width,
41
+ height: box.height,
42
+ }
43
+ }
44
+
45
+ setStylesForCanvas(canvasContainer: any) {
46
+ canvasContainer.width = '100%'
47
+ canvasContainer.height = '100%'
48
+ canvasContainer.style.position = 'absolute'
49
+ canvasContainer.style.top = '0'
50
+ canvasContainer.style.left = '0'
51
+ }
52
+
53
+ // Метод для рассчёта того, что лицо полностью помещается в рамке
54
+ checkFaceInclusion(frame: any, face: any) {
55
+ if (!frame || !face) return false
56
+
57
+ if (face.width > frame.width || face.height > frame.height) {
58
+ return false
59
+ }
60
+
61
+ const faceXmin = face.x
62
+ const faceXmax = face.x + face.width
63
+ const faceYmin = face.y
64
+ const faceYmax = face.y + face.height
65
+
66
+ const frameXmin = frame.x
67
+ const frameXmax = frame.x + frame.width
68
+ const frameYmin = frame.y
69
+ const frameYmax = frame.y + frame.height
70
+
71
+ return faceXmin >= frameXmin && faceXmax <= frameXmax && faceYmin >= frameYmin && faceYmax <= frameYmax
72
+ }
73
+
74
+ async getFaceDetections(videoRef: any, inputSize: number) {
75
+ if (!videoRef) return []
76
+ const options = new faceapi.TinyFaceDetectorOptions({ inputSize })
77
+ return faceapi.detectSingleFace(videoRef, options).withFaceLandmarks(true)
78
+ }
79
+
80
+ getCanvas(videoRef: any) {
81
+ return faceapi.createCanvasFromMedia(videoRef)
82
+ }
83
+
84
+ getResizedAndDetection(canvas: any, detections: any, ctx: any, videoWidth: number, videoHeight: number) {
85
+ faceapi.matchDimensions(canvas, { width: videoWidth, height: videoHeight })
86
+
87
+ const resized = faceapi.resizeResults(detections, {
88
+ width: videoWidth,
89
+ height: videoHeight,
90
+ })
91
+
92
+ ctx.clearRect(0, 0, videoWidth, videoHeight)
93
+
94
+ faceapi.draw.drawDetections(canvas, resized)
95
+ faceapi.draw.drawFaceLandmarks(canvas, resized)
96
+ //faceapi.draw.drawFaceExpressions(canvas, resized)
97
+ }
98
+
99
+ async getFaceSnapshot(inputImage: any, box: any) {
100
+ const regionsToExtract = [new faceapi.Rect(box.x, box.y, box.width, box.height)]
101
+ const faceImages = await faceapi.extractFaces(inputImage, regionsToExtract)
102
+
103
+ if (faceImages.length) {
104
+ const dataUrl = faceImages[0].toDataURL('image/jpeg')
105
+ return dataUrl.replace(/^data:image\/\w+;base64,/, '')
106
+ }
107
+
108
+ return null
109
+ }
110
+
111
+ async initModels() {
112
+ let date = new Date()
113
+ console.log(date)
114
+ try {
115
+ await Promise.all([
116
+ faceapi.nets.tinyFaceDetector.loadFromUri('/models'),
117
+ faceapi.nets.faceLandmark68TinyNet.loadFromUri('/models'),
118
+ ])
119
+ } catch (error) {
120
+ console.error(error)
121
+ }
122
+ date = new Date()
123
+ console.log(date)
124
+ }
125
+ }
126
+
127
+ let helper: FaceApiHelper
128
+
129
+ export default function useFaceApiHelper() {
130
+ if (!helper) helper = new FaceApiHelper()
131
+ return helper
132
+ }