odant-work 1.0.1 → 1.0.2
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.
- package/$server/$folder/$class/$structure/$server/handlers/pages/form/license/$handler/license.js +9 -6
- package/$server/$folder/$class/handlers/pages/form/object/$handler/class.js +27 -0
- package/$server/$folder/$class/handlers/pages/form/object/$handler/object.js +352 -0
- package/$server/$folder/$class/handlers/pages/form/objects/$handler/objects.js +39 -2
- package/$server/$folder/handlers/pages/form/$handler/form.js +427 -68
- package/$server/$folder/lib/tools/tools.js +9 -2
- package/MODULES/Register/REGISTER/$register/$folder/$class/$account/handlers/pages/form/postings/$handler/postings.js +388 -103
- package/MODULES/Register/REGISTER/$register/$folder/$class/$register/handlers/pages/form/journal/$handler/journal.js +84 -5
- package/MODULES/Register/REGISTER/$register/$folder/$class/$register/handlers/pages/form/sheet/$handler/sheet.js +84 -5
- package/data/store.json +3 -3
- package/oda/components/packets/packets.js +6 -0
- package/package.json +1 -1
- package/sources/data/api.js +180 -1
- package/sources/data/progress.md +37 -0
- package/sources/modules/license/index.js +7 -5
package/$server/$folder/$class/$structure/$server/handlers/pages/form/license/$handler/license.js
CHANGED
|
@@ -204,19 +204,19 @@ export default {
|
|
|
204
204
|
<oda-icon icon="carbon:user-multiple" :icon-size="20"></oda-icon>
|
|
205
205
|
<span>Одновременные сессии (рабочие места)</span>
|
|
206
206
|
</div>
|
|
207
|
-
<span class="badge">Вечная база: {{status?.baseSeats ||
|
|
207
|
+
<span class="badge">Вечная база: {{status?.baseSeats || 10}} мест</span>
|
|
208
208
|
</div>
|
|
209
209
|
<div class="seats-meter">
|
|
210
|
-
<span class="seats-big">{{status?.activeSeatsCount || 0}} / {{status?.totalSeats ||
|
|
211
|
-
<span>активных сессий ({{status?.baseSeats ||
|
|
210
|
+
<span class="seats-big">{{status?.activeSeatsCount || 0}} / {{status?.totalSeats || 10}}</span>
|
|
211
|
+
<span>активных сессий ({{status?.baseSeats || 10}} вечных + {{status?.addonSeats || 0}} срочных годовых)</span>
|
|
212
212
|
</div>
|
|
213
213
|
<div class="kv-list">
|
|
214
214
|
<div class="kv-row">
|
|
215
215
|
<span class="kv-label">Уровень поддержки (SLA)</span>
|
|
216
|
-
<span class="kv-val">{{status?.support?.tierName || '
|
|
216
|
+
<span class="kv-val">{{status?.support?.tierName || 'Enterprise'}} ({{status?.support?.reactionText || 'до 15 минут'}})</span>
|
|
217
217
|
</div>
|
|
218
218
|
<div class="kv-row">
|
|
219
|
-
<span class="kv-label">Включённый 1-й год поддержки
|
|
219
|
+
<span class="kv-label">Включённый 1-й год поддержки ПАК (Enterprise, далее — по желанию)</span>
|
|
220
220
|
<span class="kv-val">{{baseSupportText}}</span>
|
|
221
221
|
</div>
|
|
222
222
|
<div class="kv-row">
|
|
@@ -240,7 +240,10 @@ export default {
|
|
|
240
240
|
<oda-icon icon="carbon:machine-learning-model" :icon-size="20"></oda-icon>
|
|
241
241
|
<span>Предустановленный локальный стек ИИ ODANT-WORK</span>
|
|
242
242
|
</div>
|
|
243
|
-
<span class="badge"
|
|
243
|
+
<span class="badge">Базовые операции локально · мощные ИИ — через API из любого источника</span>
|
|
244
|
+
</div>
|
|
245
|
+
<div style="font-size:12.5px; color:var(--text-muted, #64748b); margin-bottom:10px;">
|
|
246
|
+
Интегрированные модели предназначены для базовых ежедневных операций. Если требуются более мощные модели ИИ, их можно подключить через API из любого внешнего или корпоративного источника в разделе <code>/MODELS</code>.
|
|
244
247
|
</div>
|
|
245
248
|
<div class="models-grid">
|
|
246
249
|
<div class="model-box" ~for="status?.preinstalledModels || []">
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Мета хендлера form/object — стандартное представление редактора объекта/документа на форме.
|
|
3
|
+
* allowTools: false отключает верхний тулбар с кнопками хендлеров (Скрин 6).
|
|
4
|
+
*/
|
|
5
|
+
export default {
|
|
6
|
+
icon: 'icons:description',
|
|
7
|
+
label: 'Объект',
|
|
8
|
+
allowTools: false,
|
|
9
|
+
allowSave: true,
|
|
10
|
+
hiddenInViewList: true,
|
|
11
|
+
roles: ['BOSS', 'USER'],
|
|
12
|
+
async allowUse($context, params) {
|
|
13
|
+
const t = $context?.type;
|
|
14
|
+
if (t && t !== '$catalog' && t !== '$operation' && t !== '$class' && !($context?.DATA?.METADATA?.FIELDS?.length))
|
|
15
|
+
return false;
|
|
16
|
+
try {
|
|
17
|
+
const s = (await $context?.db_schema?.({ session: params?.session }))?.schema;
|
|
18
|
+
if (s)
|
|
19
|
+
return (s.family === 'operation' || s.family === 'catalog') && s.type !== '$virtual' && (s.fields.length > 0 || !s.leaf);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const md = await $context?.METADATA;
|
|
25
|
+
return Array.isArray(md?.FIELDS) && md.FIELDS.length > 0;
|
|
26
|
+
},
|
|
27
|
+
}
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* form/object — стандартная вьюха редактора объекта/документа на стандартной форме work-form (Скрин 6).
|
|
3
|
+
* Верхний тулбар хендлеров отключён через allowTools: false у хендлера.
|
|
4
|
+
* Сервисные действия (Провести / Проведен / Отменить, Печать, Удалить / Восстановить) выводятся
|
|
5
|
+
* в левой части подвала формы (#focusedTools), а кнопки OK / Сохранить / Закрыть и вкладки — в правой.
|
|
6
|
+
*/
|
|
7
|
+
import objectsProto from '../../objects/$handler/objects.js';
|
|
8
|
+
|
|
9
|
+
function _day(d) {
|
|
10
|
+
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
|
|
11
|
+
}
|
|
12
|
+
const _today = () => _day(new Date());
|
|
13
|
+
|
|
14
|
+
const proto = Object.defineProperties({}, Object.getOwnPropertyDescriptors(objectsProto));
|
|
15
|
+
|
|
16
|
+
Object.assign(proto, {
|
|
17
|
+
imports: 'oda//button, oda//icon, ~/lib//editor-form',
|
|
18
|
+
isObjectView: true,
|
|
19
|
+
template: /*html*/`
|
|
20
|
+
<style>
|
|
21
|
+
:host {
|
|
22
|
+
@apply --vertical;
|
|
23
|
+
@apply --flex;
|
|
24
|
+
background: var(--content-background, #fff);
|
|
25
|
+
color: var(--content-color, #222);
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
font-size: 13px;
|
|
28
|
+
}
|
|
29
|
+
.obj-header {
|
|
30
|
+
@apply --horizontal;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: space-between;
|
|
33
|
+
gap: 12px;
|
|
34
|
+
padding: 8px 16px 4px;
|
|
35
|
+
flex-shrink: 0;
|
|
36
|
+
}
|
|
37
|
+
.obj-title {
|
|
38
|
+
font-size: 16px;
|
|
39
|
+
font-weight: 700;
|
|
40
|
+
color: light-dark(#3b28a8, #93c5fd);
|
|
41
|
+
overflow: hidden;
|
|
42
|
+
text-overflow: ellipsis;
|
|
43
|
+
white-space: nowrap;
|
|
44
|
+
}
|
|
45
|
+
.context {
|
|
46
|
+
@apply --horizontal;
|
|
47
|
+
align-items: center;
|
|
48
|
+
gap: 6px;
|
|
49
|
+
font-size: 12px;
|
|
50
|
+
flex-shrink: 0;
|
|
51
|
+
}
|
|
52
|
+
.context select {
|
|
53
|
+
padding: 2px 6px;
|
|
54
|
+
font-size: 12px;
|
|
55
|
+
border: 1px solid var(--border-color);
|
|
56
|
+
border-radius: 3px;
|
|
57
|
+
background: var(--content-background);
|
|
58
|
+
color: var(--content-color);
|
|
59
|
+
}
|
|
60
|
+
.obj-scroll {
|
|
61
|
+
@apply --vertical;
|
|
62
|
+
flex: 1;
|
|
63
|
+
min-height: 0;
|
|
64
|
+
overflow-y: auto;
|
|
65
|
+
padding-bottom: 8px;
|
|
66
|
+
}
|
|
67
|
+
oda-editor-form {
|
|
68
|
+
flex-shrink: 0;
|
|
69
|
+
}
|
|
70
|
+
.error {
|
|
71
|
+
padding: 6px 16px;
|
|
72
|
+
color: var(--error-color, #c53030);
|
|
73
|
+
background: light-dark(#fff5f5, rgba(229, 62, 62, 0.15));
|
|
74
|
+
border-top: 1px solid var(--error-color, #feb2b2);
|
|
75
|
+
border-bottom: 1px solid var(--error-color, #feb2b2);
|
|
76
|
+
white-space: break-spaces;
|
|
77
|
+
font-size: 12.5px;
|
|
78
|
+
}
|
|
79
|
+
.entries {
|
|
80
|
+
@apply --vertical;
|
|
81
|
+
gap: 3px;
|
|
82
|
+
margin: 6px 16px 0;
|
|
83
|
+
padding: 8px 10px;
|
|
84
|
+
font-size: 12px;
|
|
85
|
+
background: light-dark(#f8f7f2, #22232a);
|
|
86
|
+
border: 1px solid light-dark(#d8d7ce, #3e4049);
|
|
87
|
+
border-radius: 4px;
|
|
88
|
+
}
|
|
89
|
+
.entries-title {
|
|
90
|
+
font-weight: 700;
|
|
91
|
+
color: light-dark(#444, #cbd5e1);
|
|
92
|
+
margin-bottom: 2px;
|
|
93
|
+
}
|
|
94
|
+
.trajectory {
|
|
95
|
+
@apply --vertical;
|
|
96
|
+
gap: 4px;
|
|
97
|
+
margin: 6px 16px 0;
|
|
98
|
+
padding: 8px 10px;
|
|
99
|
+
font-size: 12px;
|
|
100
|
+
background: light-dark(#f8f7f2, #22232a);
|
|
101
|
+
border: 1px solid light-dark(#d8d7ce, #3e4049);
|
|
102
|
+
border-radius: 4px;
|
|
103
|
+
}
|
|
104
|
+
.trajectory-title {
|
|
105
|
+
font-weight: 700;
|
|
106
|
+
color: light-dark(#444, #cbd5e1);
|
|
107
|
+
}
|
|
108
|
+
.traj-row {
|
|
109
|
+
@apply --horizontal;
|
|
110
|
+
gap: 8px;
|
|
111
|
+
align-items: center;
|
|
112
|
+
}
|
|
113
|
+
.traj-link {
|
|
114
|
+
cursor: pointer;
|
|
115
|
+
text-decoration: underline;
|
|
116
|
+
color: light-dark(#1d4ed8, #93c5fd);
|
|
117
|
+
}
|
|
118
|
+
.traj-num {
|
|
119
|
+
margin-left: auto;
|
|
120
|
+
text-align: right;
|
|
121
|
+
font-variant-numeric: tabular-nums;
|
|
122
|
+
}
|
|
123
|
+
</style>
|
|
124
|
+
<div class="obj-header">
|
|
125
|
+
<div class="obj-title" :title="editorTitle">{{editorTitle}}</div>
|
|
126
|
+
<label class="context" ~if="showContext && !editing?.id">От места:
|
|
127
|
+
<select @change="contextKey = $this.value">
|
|
128
|
+
<option ~for="contexts" :value="contextKeyOf($for.item)"
|
|
129
|
+
:selected="contextKeyOf($for.item) === contextKeyOf(context)">{{contextTitle($for.item)}}</option>
|
|
130
|
+
</select>
|
|
131
|
+
</label>
|
|
132
|
+
</div>
|
|
133
|
+
<div class="error" ~if="error">{{error}}</div>
|
|
134
|
+
<div class="obj-scroll">
|
|
135
|
+
<oda-editor-form ~if="editing" :metadata="activeSchema" :data="editing" :field-errors="fieldErrors"
|
|
136
|
+
@input="onFormInput" @change="onFormInput" @cell-changed="onFormInput"></oda-editor-form>
|
|
137
|
+
<div class="entries" ~if="entries?.length">
|
|
138
|
+
<div class="entries-title">Проводки:</div>
|
|
139
|
+
<div class="entry" ~for="entries">{{entryText($for.item)}}</div>
|
|
140
|
+
</div>
|
|
141
|
+
<div class="trajectory" ~if="objectBalances?.length || trajectory?.length">
|
|
142
|
+
<div class="trajectory-title" ~if="objectBalances?.length">Остатки по счетам</div>
|
|
143
|
+
<div class="traj-row" ~for="objectBalances">
|
|
144
|
+
<span class="traj-link" @tap="openBalanceAccount($for.item)">{{$for.item.label}}</span>
|
|
145
|
+
<span class="traj-num">{{$for.item.balance}}{{$for.item.qty ? ' (' + $for.item.qty + ')' : ''}}</span>
|
|
146
|
+
</div>
|
|
147
|
+
<div class="trajectory-title" ~if="trajectory?.length">Движения ({{trajectory.length}})</div>
|
|
148
|
+
<div class="traj-row" ~for="trajectory">
|
|
149
|
+
<span>{{$for.item.date}}</span>
|
|
150
|
+
<span class="traj-link" @tap="openTrajectoryOp($for.item)">{{$for.item.op}}</span>
|
|
151
|
+
<span>{{$for.item.account}}</span>
|
|
152
|
+
<span class="traj-num">{{$for.item.debit ? '+' + $for.item.debit : ($for.item.credit ? '−' + $for.item.credit : $for.item.qty)}} → {{$for.item.balance}}</span>
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
`,
|
|
157
|
+
mountToolbarSlots() {
|
|
158
|
+
// У формы объекта верхнего тулбара нет (allowTools: false)
|
|
159
|
+
},
|
|
160
|
+
getItemButtons() {
|
|
161
|
+
return [];
|
|
162
|
+
},
|
|
163
|
+
getFocusedButtons() {
|
|
164
|
+
return [];
|
|
165
|
+
},
|
|
166
|
+
getFocusedServices() {
|
|
167
|
+
const list = [];
|
|
168
|
+
if (this.isOperation) {
|
|
169
|
+
if (this.canRegister) {
|
|
170
|
+
list.push({
|
|
171
|
+
id: 'post',
|
|
172
|
+
label: 'Провести',
|
|
173
|
+
icon: 'icons:settings',
|
|
174
|
+
isService: true,
|
|
175
|
+
service: true,
|
|
176
|
+
order: 1,
|
|
177
|
+
disabled: this.busy,
|
|
178
|
+
execute: async () => {
|
|
179
|
+
await this.post();
|
|
180
|
+
this._notifyForm();
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
else if (this.canCancel) {
|
|
185
|
+
list.push({
|
|
186
|
+
id: 'cancel',
|
|
187
|
+
label: 'Проведен (Отменить)',
|
|
188
|
+
icon: 'icons:settings',
|
|
189
|
+
isService: true,
|
|
190
|
+
service: true,
|
|
191
|
+
order: 1,
|
|
192
|
+
disabled: this.busy,
|
|
193
|
+
execute: async () => {
|
|
194
|
+
await this.cancelOperation();
|
|
195
|
+
this._notifyForm();
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
for (let i = 0; i < (this.printForms || []).length; i++) {
|
|
200
|
+
const pf = this.printForms[i];
|
|
201
|
+
list.push({
|
|
202
|
+
id: `print_${pf.name}`,
|
|
203
|
+
label: pf.label || pf.name || 'Печать',
|
|
204
|
+
icon: 'icons:print',
|
|
205
|
+
isService: true,
|
|
206
|
+
service: true,
|
|
207
|
+
order: 2 + i,
|
|
208
|
+
disabled: this.busy,
|
|
209
|
+
execute: () => this.printForm(pf.name),
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (this.canRemove) {
|
|
214
|
+
list.push({
|
|
215
|
+
id: 'remove',
|
|
216
|
+
label: 'Удалить',
|
|
217
|
+
icon: 'icons:delete',
|
|
218
|
+
isService: true,
|
|
219
|
+
service: true,
|
|
220
|
+
order: 10,
|
|
221
|
+
disabled: this.busy,
|
|
222
|
+
execute: async () => {
|
|
223
|
+
if (await this.removeObject()) {
|
|
224
|
+
this._findFormHost()?.closeActiveTab?.(true);
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
if (this.canRestore) {
|
|
230
|
+
list.push({
|
|
231
|
+
id: 'restore',
|
|
232
|
+
label: 'Восстановить',
|
|
233
|
+
icon: 'icons:restore',
|
|
234
|
+
isService: true,
|
|
235
|
+
service: true,
|
|
236
|
+
order: 11,
|
|
237
|
+
disabled: this.busy,
|
|
238
|
+
execute: async () => {
|
|
239
|
+
await this.restoreObject();
|
|
240
|
+
this._notifyForm();
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
return list;
|
|
245
|
+
},
|
|
246
|
+
onFormInput() {
|
|
247
|
+
if (this.fieldErrors && Object.keys(this.fieldErrors).length)
|
|
248
|
+
this.fieldErrors = {};
|
|
249
|
+
this.schedulePreview?.();
|
|
250
|
+
const host = this._findFormHost();
|
|
251
|
+
host?.updateActiveTabLabel?.(this.editorTitle);
|
|
252
|
+
},
|
|
253
|
+
async attached() {
|
|
254
|
+
try {
|
|
255
|
+
await Promise.all([this.loadSchema(), this.loadScope()]);
|
|
256
|
+
}
|
|
257
|
+
catch (e) {
|
|
258
|
+
this.error = String(e?.message || e);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (this._pendingNav) {
|
|
262
|
+
const nav = this._pendingNav;
|
|
263
|
+
this._pendingNav = null;
|
|
264
|
+
await this.applyNav(nav);
|
|
265
|
+
}
|
|
266
|
+
else if (!this.editing) {
|
|
267
|
+
await this.initFromNav({});
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
async applyNav(nav = {}) {
|
|
271
|
+
if (!this.schema) {
|
|
272
|
+
this._pendingNav = nav;
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
await this.initFromNav(nav);
|
|
276
|
+
},
|
|
277
|
+
async initFromNav(nav = {}) {
|
|
278
|
+
this.clearError();
|
|
279
|
+
if (nav.leafCid) {
|
|
280
|
+
await this.loadLeafSchema(nav.leafCid);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
this.leafCid = '';
|
|
284
|
+
this.leafSchema = null;
|
|
285
|
+
}
|
|
286
|
+
if (nav.id) {
|
|
287
|
+
await this.select({ id: String(nav.id), cid: nav.leafCid || '' });
|
|
288
|
+
}
|
|
289
|
+
else if (nav.copyFrom) {
|
|
290
|
+
const found = await this.$item.fetch('db_read', { id: String(nav.copyFrom) });
|
|
291
|
+
if (found?.names && typeof found.names === 'object')
|
|
292
|
+
this.names = { ...(this.names || {}), ...found.names };
|
|
293
|
+
await this.loadLeafSchema(found?.cid || nav.leafCid || '');
|
|
294
|
+
const baseBody = { ...(found?.body || {}) };
|
|
295
|
+
delete baseBody.id;
|
|
296
|
+
delete baseBody.version;
|
|
297
|
+
delete baseBody.status;
|
|
298
|
+
this.editing = this.isOperation ? { ...baseBody, time: _today() } : baseBody;
|
|
299
|
+
this.entries = [];
|
|
300
|
+
this.entryNames = { objects: {}, classes: {} };
|
|
301
|
+
this.objectBalances = [];
|
|
302
|
+
this.trajectory = [];
|
|
303
|
+
this.printForms = [];
|
|
304
|
+
if (this.isOperation)
|
|
305
|
+
this.schedulePreview();
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
this.editing = this.isOperation ? { time: _today(), ...(nav.initialData || {}) } : { ...(nav.initialData || {}) };
|
|
309
|
+
this.entries = [];
|
|
310
|
+
this.entryNames = { objects: {}, classes: {} };
|
|
311
|
+
this.objectBalances = [];
|
|
312
|
+
this.trajectory = [];
|
|
313
|
+
this.printForms = [];
|
|
314
|
+
if (this.isOperation)
|
|
315
|
+
this.schedulePreview();
|
|
316
|
+
}
|
|
317
|
+
this.focusedItem = this.editing || { id: nav.id || 'new' };
|
|
318
|
+
this.snapshot();
|
|
319
|
+
this.async(() => {
|
|
320
|
+
if (this.isConnected)
|
|
321
|
+
this.snapshot();
|
|
322
|
+
});
|
|
323
|
+
const host = this._findFormHost();
|
|
324
|
+
host?.updateActiveTabLabel?.(this.editorTitle);
|
|
325
|
+
this._notifyForm();
|
|
326
|
+
},
|
|
327
|
+
async saveAndStay() {
|
|
328
|
+
const ok = await this.save();
|
|
329
|
+
if (ok) {
|
|
330
|
+
if (this.editing?.id) {
|
|
331
|
+
await this.loadEntries();
|
|
332
|
+
await this.loadPrints();
|
|
333
|
+
await this.loadTrajectory();
|
|
334
|
+
}
|
|
335
|
+
const host = this._findFormHost();
|
|
336
|
+
host?.updateActiveTabLabel?.(this.editorTitle);
|
|
337
|
+
this._notifyForm();
|
|
338
|
+
}
|
|
339
|
+
return ok;
|
|
340
|
+
},
|
|
341
|
+
async saveAndClose() {
|
|
342
|
+
if (this.canSave) {
|
|
343
|
+
const ok = await this.save();
|
|
344
|
+
if (!ok)
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
347
|
+
this._findFormHost()?.closeActiveTab?.(true);
|
|
348
|
+
return true;
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
export default proto;
|
|
@@ -1117,10 +1117,21 @@ export default {
|
|
|
1117
1117
|
const qty = e.qty ? ` (${e.doc_qty ?? e.qty}${e.doc_unit ? ' ' + e.doc_unit : ''})` : '';
|
|
1118
1118
|
return `Дт ${side(e.debit, e.debit_analytics)} — Кт ${side(e.credit, e.credit_analytics)}: ${Number(e.amount || 0).toLocaleString('ru-RU', { minimumFractionDigits: 2 })}${qty}`;
|
|
1119
1119
|
},
|
|
1120
|
-
/** Загрузить объект и открыть
|
|
1120
|
+
/** Загрузить объект и открыть вьюху редактора (внутри work-form — на вкладке form/object, автономно — модально). */
|
|
1121
1121
|
async openEditor(row) {
|
|
1122
1122
|
if (!row?.id || this.editorOpen)
|
|
1123
1123
|
return;
|
|
1124
|
+
const formHost = this._findFormHost();
|
|
1125
|
+
if (formHost && typeof formHost.openInForm === 'function') {
|
|
1126
|
+
const target = await this.targetItem(row.cid || '');
|
|
1127
|
+
await formHost.openInForm(target || this.$item, {
|
|
1128
|
+
view: 'object',
|
|
1129
|
+
id: row.id,
|
|
1130
|
+
leafCid: row.cid || '',
|
|
1131
|
+
label: row.name || row.title || row.id,
|
|
1132
|
+
});
|
|
1133
|
+
return;
|
|
1134
|
+
}
|
|
1124
1135
|
this.editorOpen = true;
|
|
1125
1136
|
this.editing = null;
|
|
1126
1137
|
try {
|
|
@@ -1287,10 +1298,10 @@ export default {
|
|
|
1287
1298
|
return;
|
|
1288
1299
|
if (!this.schema)
|
|
1289
1300
|
await this.loadSchema().catch(() => {});
|
|
1301
|
+
let chosenCid = '';
|
|
1290
1302
|
if (!this.schema?.leaf) {
|
|
1291
1303
|
if (!this.leaves?.length)
|
|
1292
1304
|
return;
|
|
1293
|
-
let chosenCid = '';
|
|
1294
1305
|
if (typeof WORK?.showModal === 'function' && typeof document !== 'undefined') {
|
|
1295
1306
|
chosenCid = await this.pickTargetLeafClass();
|
|
1296
1307
|
if (!chosenCid)
|
|
@@ -1299,6 +1310,21 @@ export default {
|
|
|
1299
1310
|
else {
|
|
1300
1311
|
chosenCid = this.leafCid || this.leaves[0].cid;
|
|
1301
1312
|
}
|
|
1313
|
+
}
|
|
1314
|
+
const formHost = this._findFormHost();
|
|
1315
|
+
if (formHost && typeof formHost.openInForm === 'function') {
|
|
1316
|
+
const target = chosenCid ? await this.targetItem(chosenCid) : this.$item;
|
|
1317
|
+
const leafLabel = chosenCid ? (this.classes?.[chosenCid]?.label || this.leaves?.find(l => l.cid === chosenCid)?.label || '') : '';
|
|
1318
|
+
const title = leafLabel || this.schema?.title || 'Объект';
|
|
1319
|
+
await formHost.openInForm(target || this.$item, {
|
|
1320
|
+
view: 'object',
|
|
1321
|
+
create: true,
|
|
1322
|
+
leafCid: chosenCid || '',
|
|
1323
|
+
label: `${title} · новый объект`,
|
|
1324
|
+
});
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
if (chosenCid) {
|
|
1302
1328
|
this.editorOpen = true;
|
|
1303
1329
|
await this.loadLeafSchema(chosenCid);
|
|
1304
1330
|
}
|
|
@@ -1326,6 +1352,17 @@ export default {
|
|
|
1326
1352
|
async copyRow(row = this.focusedRow) {
|
|
1327
1353
|
if (!row?.id || this.editorOpen || !this.canCreate)
|
|
1328
1354
|
return;
|
|
1355
|
+
const formHost = this._findFormHost();
|
|
1356
|
+
if (formHost && typeof formHost.openInForm === 'function') {
|
|
1357
|
+
const target = await this.targetItem(row.cid || '');
|
|
1358
|
+
await formHost.openInForm(target || this.$item, {
|
|
1359
|
+
view: 'object',
|
|
1360
|
+
copyFrom: row.id,
|
|
1361
|
+
leafCid: row.cid || '',
|
|
1362
|
+
label: `${row.name || 'Объект'} (копия)`,
|
|
1363
|
+
});
|
|
1364
|
+
return;
|
|
1365
|
+
}
|
|
1329
1366
|
this.editorOpen = true;
|
|
1330
1367
|
this.clearError();
|
|
1331
1368
|
try {
|