@movvjs/svelte-schedule-view 0.2.4 → 0.2.6-beta-1
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/.svelte-kit/__package__/i18n/locales/en.json +3 -1
- package/.svelte-kit/__package__/i18n/locales/ko.json +3 -1
- package/.svelte-kit/__package__/i18n/locales/vi.json +3 -1
- package/.svelte-kit/__package__/i18n/locales/zh-cn.json +3 -1
- package/.svelte-kit/__package__/i18n/locales/zh-tw.json +3 -1
- package/.svelte-kit/__package__/schedule-view/BookingInfo.svelte +49 -14
- package/.svelte-kit/__package__/schedule-view/PlaceSearch.svelte +21 -2
- package/.svelte-kit/__package__/schedule-view/api/common/index.d.ts +5 -1
- package/.svelte-kit/__package__/schedule-view/api/common/index.js +17 -3
- package/.svelte-kit/__package__/schedule-view/assets/scss/indie_booking.scss +58 -1
- package/.svelte-kit/__package__/schedule-view/components/flight-search/FlightSearch.svelte +193 -120
- package/.svelte-kit/__package__/schedule-view/components/flight-search/FlightSearch.svelte.d.ts +10 -2
- package/.svelte-kit/__package__/schedule-view/stores/booking.d.ts +2 -0
- package/.svelte-kit/__package__/schedule-view/stores/booking.js +2 -0
- package/.svelte-kit/__package__/schedule-view/types/flight.d.ts +1 -1
- package/.svelte-kit/ambient.d.ts +4 -0
- package/.svelte-kit/generated/server/internal.js +1 -1
- package/dist/i18n/locales/en.json +3 -1
- package/dist/i18n/locales/ko.json +3 -1
- package/dist/i18n/locales/vi.json +3 -1
- package/dist/i18n/locales/zh-cn.json +3 -1
- package/dist/i18n/locales/zh-tw.json +3 -1
- package/dist/schedule-view/BookingInfo.svelte +49 -14
- package/dist/schedule-view/PlaceSearch.svelte +21 -2
- package/dist/schedule-view/api/common/index.d.ts +5 -1
- package/dist/schedule-view/api/common/index.js +17 -3
- package/dist/schedule-view/assets/scss/indie_booking.scss +58 -1
- package/dist/schedule-view/components/flight-search/FlightSearch.svelte +193 -120
- package/dist/schedule-view/components/flight-search/FlightSearch.svelte.d.ts +10 -2
- package/dist/schedule-view/stores/booking.d.ts +2 -0
- package/dist/schedule-view/stores/booking.js +2 -0
- package/dist/schedule-view/types/flight.d.ts +1 -1
- package/package.json +3 -1
- package/src/lib/i18n/locales/en.json +3 -1
- package/src/lib/i18n/locales/ko.json +3 -1
- package/src/lib/i18n/locales/vi.json +3 -1
- package/src/lib/i18n/locales/zh-cn.json +3 -1
- package/src/lib/i18n/locales/zh-tw.json +3 -1
- package/src/lib/schedule-view/BookingInfo.svelte +51 -15
- package/src/lib/schedule-view/PlaceSearch.svelte +24 -1
- package/src/lib/schedule-view/api/common/index.ts +21 -3
- package/src/lib/schedule-view/assets/scss/indie_booking.scss +58 -1
- package/src/lib/schedule-view/components/flight-search/FlightSearch.svelte +208 -126
- package/src/lib/schedule-view/stores/booking.ts +6 -0
- package/src/lib/schedule-view/types/flight.ts +1 -1
- package/yarn.lock +334 -6
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"file": "File",
|
|
21
21
|
"fileUpload": "Upload file",
|
|
22
22
|
"firstName": "First name",
|
|
23
|
-
"flight": "Flight",
|
|
23
|
+
"flight": "Flight Info",
|
|
24
24
|
"guestName": "Guest Name",
|
|
25
25
|
"hours": "{hour} hour(s)",
|
|
26
26
|
"lastName": "Last name",
|
|
@@ -80,8 +80,10 @@
|
|
|
80
80
|
"noFlightsWereFound": "No flights were found.",
|
|
81
81
|
"pleaseEnterFlightNo": "Please enter flight No.",
|
|
82
82
|
"pleaseSelectAFlightNo": "Please select a flight No.",
|
|
83
|
+
"pleaseSelectAnAirport": "Please select an airport.",
|
|
83
84
|
"pleaseSelectDate": "Please select a date.",
|
|
84
85
|
"selectFlightNo": "Select Flight No.",
|
|
86
|
+
"selectTerminal": "Please select a terminal.",
|
|
85
87
|
"terminal": "Terminal {number}"
|
|
86
88
|
},
|
|
87
89
|
"placeholder": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"file": "파일",
|
|
21
21
|
"fileUpload": "파일 업로드",
|
|
22
22
|
"firstName": "이름",
|
|
23
|
-
"flight": "항공편",
|
|
23
|
+
"flight": "항공편 정보",
|
|
24
24
|
"guestName": "사용자명",
|
|
25
25
|
"hours": "{hour} 시간",
|
|
26
26
|
"lastName": "성",
|
|
@@ -67,8 +67,10 @@
|
|
|
67
67
|
"noFlightsWereFound": "항공편을 찾을 수 없습니다.",
|
|
68
68
|
"pleaseEnterFlightNo": "항공편명을 입력해주세요.",
|
|
69
69
|
"pleaseSelectAFlightNo": "항공편명을 선택해주세요.",
|
|
70
|
+
"pleaseSelectAnAirport": "공항을 선택해주세요.",
|
|
70
71
|
"pleaseSelectDate": "날짜를 선택해주세요.",
|
|
71
72
|
"selectFlightNo": "항공편명 선택",
|
|
73
|
+
"selectTerminal": "터미널을 선택해주세요.",
|
|
72
74
|
"terminal": "터미널 {number}"
|
|
73
75
|
},
|
|
74
76
|
"placeholder": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"file": "Tệp",
|
|
21
21
|
"fileUpload": "Cập nhật dử liệu",
|
|
22
22
|
"firstName": "Tên đầu tiên",
|
|
23
|
-
"flight": "
|
|
23
|
+
"flight": "Thông tin chuyến bay",
|
|
24
24
|
"guestName": "Tên khách",
|
|
25
25
|
"hours": "{hour} giờ",
|
|
26
26
|
"lastName": "Họ",
|
|
@@ -67,8 +67,10 @@
|
|
|
67
67
|
"noFlightsWereFound": "Không tìm thấy chuyến bay.",
|
|
68
68
|
"pleaseEnterFlightNo": "Vui lòng nhập số chuyến bay",
|
|
69
69
|
"pleaseSelectAFlightNo": "Vui lòng chọn số chuyến bay",
|
|
70
|
+
"pleaseSelectAnAirport": "Vui lòng chọn một sân bay.",
|
|
70
71
|
"pleaseSelectDate": "Vui lòng chọn một ngày.",
|
|
71
72
|
"selectFlightNo": "Chọn số chuyến bay",
|
|
73
|
+
"selectTerminal": "Vui lòng chọn một thiết bị đầu cuối.",
|
|
72
74
|
"terminal": "Nhà ga số 2"
|
|
73
75
|
},
|
|
74
76
|
"placeholder": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"file": "档案",
|
|
21
21
|
"fileUpload": "上传文件",
|
|
22
22
|
"firstName": "名",
|
|
23
|
-
"flight": "
|
|
23
|
+
"flight": "航班信息",
|
|
24
24
|
"guestName": "乘客姓名",
|
|
25
25
|
"hours": "{hour} 小时",
|
|
26
26
|
"lastName": "姓",
|
|
@@ -67,8 +67,10 @@
|
|
|
67
67
|
"noFlightsWereFound": "未找到航班。",
|
|
68
68
|
"pleaseEnterFlightNo": "请输入航班号",
|
|
69
69
|
"pleaseSelectAFlightNo": "请选择航班号",
|
|
70
|
+
"pleaseSelectAnAirport": "请选择一个机场。",
|
|
70
71
|
"pleaseSelectDate": "请选择日期。",
|
|
71
72
|
"selectFlightNo": "选择航班号",
|
|
73
|
+
"selectTerminal": "请选择一个终端。",
|
|
72
74
|
"terminal": "第{number}航站楼"
|
|
73
75
|
},
|
|
74
76
|
"placeholder": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"file": "檔案",
|
|
21
21
|
"fileUpload": "上傳文件",
|
|
22
22
|
"firstName": "名",
|
|
23
|
-
"flight": "
|
|
23
|
+
"flight": "航班資訊",
|
|
24
24
|
"guestName": "乘客姓名",
|
|
25
25
|
"hours": "{hour} 小時",
|
|
26
26
|
"lastName": "姓",
|
|
@@ -67,8 +67,10 @@
|
|
|
67
67
|
"noFlightsWereFound": "未找到航班。",
|
|
68
68
|
"pleaseEnterFlightNo": "請輸入航班號碼",
|
|
69
69
|
"pleaseSelectAFlightNo": "請選擇航班號碼",
|
|
70
|
+
"pleaseSelectAnAirport": "請選擇機場。",
|
|
70
71
|
"pleaseSelectDate": "請選擇日期。",
|
|
71
72
|
"selectFlightNo": "選擇航班號碼",
|
|
73
|
+
"selectTerminal": "請選擇一個終端。",
|
|
72
74
|
"terminal": "第{number}航廈"
|
|
73
75
|
},
|
|
74
76
|
"placeholder": {
|
|
@@ -15,7 +15,7 @@ import FlightSearch from "./components/flight-search/FlightSearch.svelte";
|
|
|
15
15
|
import PhoneNumberInput from "./PhoneNumberInput.svelte";
|
|
16
16
|
import FileUploader from "./FileUploader.svelte";
|
|
17
17
|
import CarSearch from "./CarSearch.svelte";
|
|
18
|
-
const { stdt, fullName, pax, extraServices, files, plans } = originalBooking;
|
|
18
|
+
const { stdt, fullName, pax, extraServices, files, plans, isFlightService } = originalBooking;
|
|
19
19
|
const {
|
|
20
20
|
withPreserveAndPreview,
|
|
21
21
|
hour,
|
|
@@ -44,9 +44,11 @@ async function copyContents() {
|
|
|
44
44
|
texts.push(`${$t("booking.startTime")} : ${dayjs($stdt).format("HH:mm")}`);
|
|
45
45
|
texts.push(`${$t("booking.carInfo")} : ${getCarName($originalBooking.carInfo, { seat: true, seatPostfix: $t("booking.seater") })}`);
|
|
46
46
|
texts.push(`${$t("booking.pax")} : ${$pax}`);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
if ($isFlightService) {
|
|
48
|
+
texts.push(
|
|
49
|
+
`${$t("booking.flight")} : ${$originalBooking.flight ? [$originalBooking.flight?.name, getTerminalName($originalBooking.flight)].filter(Boolean).join(" / ") || "- -" : "- -"}`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
50
52
|
texts.push(`${$t("booking.guestName")} : ${$fullName}`);
|
|
51
53
|
texts.push(`${$t("booking.telNo")} : ${PhoneNumberBiz.format($originalBooking.countryCode, $originalBooking.tel) || "- -"}`);
|
|
52
54
|
const extraServiceText = $originalBooking.extra?.length > 0 ? $originalBooking.extra.map((s) => $t(`extraServiceType.${s.type}`)).join(", ") : "- -";
|
|
@@ -103,13 +105,46 @@ async function toggleAutoPicket(e) {
|
|
|
103
105
|
function openFlightSearch() {
|
|
104
106
|
flightSearch$.open({
|
|
105
107
|
dateTime: $copiedBooking.ymd,
|
|
106
|
-
|
|
108
|
+
airport: (() => {
|
|
109
|
+
if ($copiedBooking.serviceType === BookingServiceType.pickup) {
|
|
110
|
+
return {
|
|
111
|
+
iata: $copiedBooking.origin?.iata || null,
|
|
112
|
+
code: $copiedBooking.origin?.code || null
|
|
113
|
+
};
|
|
114
|
+
} else if ($copiedBooking.serviceType === BookingServiceType.sending) {
|
|
115
|
+
return {
|
|
116
|
+
iata: $copiedBooking.dest?.iata || null,
|
|
117
|
+
code: $copiedBooking.dest?.code || null
|
|
118
|
+
};
|
|
119
|
+
} else {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
})(),
|
|
123
|
+
terminalOnly: $copiedBooking.serviceType === BookingServiceType.sending
|
|
107
124
|
}).then((flight) => {
|
|
108
125
|
$copiedBooking.flight = flight;
|
|
109
126
|
}).catch((e) => {
|
|
110
127
|
alert.open({ title: $t("alert.error"), text: e.message });
|
|
111
128
|
});
|
|
112
129
|
}
|
|
130
|
+
function getTerminalName(flight) {
|
|
131
|
+
if (!flight?.arrivalTerminal)
|
|
132
|
+
return null;
|
|
133
|
+
if (flight.selectType === "AUTO") {
|
|
134
|
+
switch (flight.arrivalTerminal) {
|
|
135
|
+
case "I":
|
|
136
|
+
return "International";
|
|
137
|
+
case "D":
|
|
138
|
+
return "Domestic";
|
|
139
|
+
default:
|
|
140
|
+
return `Terminal ${flight.arrivalTerminal}`;
|
|
141
|
+
}
|
|
142
|
+
} else if (flight.selectType === "MANUAL") {
|
|
143
|
+
return flight.arrivalTerminal;
|
|
144
|
+
} else {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
113
148
|
</script>
|
|
114
149
|
|
|
115
150
|
<Translation bind:this={translation$} />
|
|
@@ -167,17 +202,17 @@ function openFlightSearch() {
|
|
|
167
202
|
</td>
|
|
168
203
|
</tr>
|
|
169
204
|
|
|
170
|
-
{#if $
|
|
205
|
+
{#if $isFlightService}
|
|
171
206
|
<tr>
|
|
172
207
|
<th>{$t('booking.flight')}</th>
|
|
173
208
|
<td>
|
|
174
209
|
{#if !$isEdit}
|
|
175
210
|
{#if $originalBooking.flight}
|
|
176
211
|
<p class="indie_value-text flight">
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
212
|
+
{@html [$originalBooking.flight.name, getTerminalName($originalBooking.flight)]
|
|
213
|
+
.map((value, i) => (value ? (i === 0 ? `<b>${value}</b>` : value) : null))
|
|
214
|
+
.filter(Boolean)
|
|
215
|
+
.join(' / ')}
|
|
181
216
|
</p>
|
|
182
217
|
{#if $originalBooking.flight.selectType === 'MANUAL'}
|
|
183
218
|
<div class="indie_exclamation_mark_box sm black">
|
|
@@ -191,10 +226,10 @@ function openFlightSearch() {
|
|
|
191
226
|
<!-- -->
|
|
192
227
|
{#if $copiedBooking.flight}
|
|
193
228
|
<p class="indie_value-text flight">
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
229
|
+
{@html [$copiedBooking.flight.name, getTerminalName($copiedBooking.flight)]
|
|
230
|
+
.map((value, i) => (value ? (i === 0 ? `<b>${value}</b>` : value) : null))
|
|
231
|
+
.filter(Boolean)
|
|
232
|
+
.join(' / ')}
|
|
198
233
|
</p>
|
|
199
234
|
<button type="button" class="indie_btn_squre only refresh_black mgl10" on:click={() => openFlightSearch()}>다시선택</button>
|
|
200
235
|
{#if $copiedBooking.flight.selectType !== 'AUTO'}
|
|
@@ -1,16 +1,35 @@
|
|
|
1
|
-
<script>import
|
|
1
|
+
<script>import center from "@turf/center";
|
|
2
|
+
import { points } from "@turf/helpers";
|
|
3
|
+
import { CommonAPI } from "./api";
|
|
2
4
|
import { loader } from "./components/loader";
|
|
3
5
|
import BaseSearchInput, {} from "./BaseSearchInput.svelte";
|
|
6
|
+
import { copiedBooking } from "./stores/booking";
|
|
4
7
|
export let placeholder = "Title / Detailed address";
|
|
5
8
|
export let inputId;
|
|
6
9
|
export let title;
|
|
10
|
+
const { coordinates } = copiedBooking;
|
|
11
|
+
$:
|
|
12
|
+
centerCoordinate = (() => {
|
|
13
|
+
if ($coordinates.length === 0) {
|
|
14
|
+
return null;
|
|
15
|
+
} else {
|
|
16
|
+
try {
|
|
17
|
+
const features = points($coordinates.map(({ lng: lng2, lat: lat2 }) => [lng2, lat2]));
|
|
18
|
+
const centerFeature = center(features);
|
|
19
|
+
const [lng, lat] = centerFeature?.geometry?.coordinates;
|
|
20
|
+
return { lng, lat };
|
|
21
|
+
} catch (e) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
})();
|
|
7
26
|
let list = [];
|
|
8
27
|
async function search(keyword) {
|
|
9
28
|
if (!keyword?.trim())
|
|
10
29
|
return;
|
|
11
30
|
try {
|
|
12
31
|
loader.show();
|
|
13
|
-
const data = await CommonAPI.searchPlace(keyword);
|
|
32
|
+
const data = await CommonAPI.searchPlace(keyword, centerCoordinate);
|
|
14
33
|
list = data.map((item) => ({
|
|
15
34
|
title: item.title,
|
|
16
35
|
subTitle: item.address,
|
|
@@ -14,5 +14,9 @@ export declare class CommonAPI {
|
|
|
14
14
|
name: string;
|
|
15
15
|
url: string;
|
|
16
16
|
}>;
|
|
17
|
-
static searchPlace(keyword: string
|
|
17
|
+
static searchPlace(keyword: string, center: {
|
|
18
|
+
lat: number;
|
|
19
|
+
lng: number;
|
|
20
|
+
}): Promise<BookingLocation[]>;
|
|
21
|
+
static getPoiTerminals(code: string): Promise<string[]>;
|
|
18
22
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { axios } from '../../../axios';
|
|
2
2
|
import { get } from 'svelte/store';
|
|
3
3
|
import { env } from '../../../store/env';
|
|
4
|
+
import QS from 'qs';
|
|
4
5
|
export class CommonAPI {
|
|
5
6
|
static async getPickupPoint(ppno) {
|
|
6
7
|
const { target } = get(env);
|
|
@@ -90,10 +91,14 @@ export class CommonAPI {
|
|
|
90
91
|
throw Error('Invalid target');
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
|
-
static async searchPlace(keyword) {
|
|
94
|
+
static async searchPlace(keyword, center) {
|
|
94
95
|
const { target } = get(env);
|
|
96
|
+
const queryString = QS.stringify({
|
|
97
|
+
title: keyword,
|
|
98
|
+
...(center ? { lat: center.lat, lng: center.lng } : {})
|
|
99
|
+
}, { skipNulls: true });
|
|
95
100
|
if (target === 'B2B') {
|
|
96
|
-
const { data } = await axios.get(`/booking/scheduleView/place
|
|
101
|
+
const { data } = await axios.get(`/booking/scheduleView/place?${queryString}`);
|
|
97
102
|
if (data.mode === false) {
|
|
98
103
|
throw new Error(data.msg || data.message || JSON.stringify(data));
|
|
99
104
|
}
|
|
@@ -102,7 +107,7 @@ export class CommonAPI {
|
|
|
102
107
|
}
|
|
103
108
|
}
|
|
104
109
|
else if (target === 'FMS' || target === 'MOVV') {
|
|
105
|
-
const { data } = await axios.get(`/common/v2/place
|
|
110
|
+
const { data } = await axios.get(`/common/v2/place?${queryString}`);
|
|
106
111
|
if (data.mode === false) {
|
|
107
112
|
throw new Error(data.msg || data.message || JSON.stringify(data));
|
|
108
113
|
}
|
|
@@ -114,4 +119,13 @@ export class CommonAPI {
|
|
|
114
119
|
throw Error('Invalid target');
|
|
115
120
|
}
|
|
116
121
|
}
|
|
122
|
+
static async getPoiTerminals(code) {
|
|
123
|
+
const { data } = await axios.get(`/common/poiTerminal/list/${code}`);
|
|
124
|
+
if (data.mode === false) {
|
|
125
|
+
throw new Error(data.msg);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
return data.list;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
117
131
|
}
|
|
@@ -3038,8 +3038,9 @@
|
|
|
3038
3038
|
|
|
3039
3039
|
.map_box{
|
|
3040
3040
|
flex-grow: 1;
|
|
3041
|
-
background-color:
|
|
3041
|
+
background-color: royalblue;
|
|
3042
3042
|
position: relative;
|
|
3043
|
+
overflow: hidden;
|
|
3043
3044
|
|
|
3044
3045
|
.indie_ic_map_loca{
|
|
3045
3046
|
position: relative;
|
|
@@ -4611,5 +4612,61 @@
|
|
|
4611
4612
|
}
|
|
4612
4613
|
}
|
|
4613
4614
|
|
|
4615
|
+
|
|
4616
|
+
|
|
4617
|
+
|
|
4618
|
+
//마진 값
|
|
4619
|
+
.mg{
|
|
4620
|
+
@for $i from 0 through 40{
|
|
4621
|
+
@if(($i % 5) == 0){
|
|
4622
|
+
&t#{$i}{margin-top: #{$i}px;}
|
|
4623
|
+
&l#{$i}{margin-left: #{$i}px;}
|
|
4624
|
+
&r#{$i}{margin-right: #{$i}px;}
|
|
4625
|
+
&b#{$i}{margin-bottom: #{$i}px;}
|
|
4626
|
+
}
|
|
4627
|
+
}
|
|
4628
|
+
|
|
4629
|
+
&TMinus{
|
|
4630
|
+
margin-top: -1px;
|
|
4631
|
+
}
|
|
4632
|
+
|
|
4633
|
+
&-l-auto{
|
|
4634
|
+
margin-left: auto;
|
|
4635
|
+
}
|
|
4636
|
+
&-r-auto{
|
|
4637
|
+
margin-right: auto;
|
|
4638
|
+
}
|
|
4639
|
+
}
|
|
4640
|
+
|
|
4641
|
+
//패딩 값
|
|
4642
|
+
.pd{
|
|
4643
|
+
@for $i from 0 through 40{
|
|
4644
|
+
@if(($i % 5) == 0){
|
|
4645
|
+
&t#{$i}{padding-top: #{$i}px;}
|
|
4646
|
+
&l#{$i}{padding-left: #{$i}px;}
|
|
4647
|
+
&r#{$i}{padding-right: #{$i}px;}
|
|
4648
|
+
&b#{$i}{padding-bottom: #{$i}px;}
|
|
4649
|
+
}
|
|
4650
|
+
}
|
|
4651
|
+
}
|
|
4652
|
+
|
|
4653
|
+
// 넓이 값 - 퍼센트
|
|
4654
|
+
.w{
|
|
4655
|
+
@for $i from 0 through 100{
|
|
4656
|
+
@if(($i % 5) == 0){
|
|
4657
|
+
&#{$i}{width: #{$i + '%'};}
|
|
4658
|
+
}
|
|
4659
|
+
}
|
|
4660
|
+
}
|
|
4661
|
+
|
|
4662
|
+
// 넓이 값 - 픽셀
|
|
4663
|
+
.w{
|
|
4664
|
+
@for $i from 0 through 500{
|
|
4665
|
+
@if(($i % 10) == 0){
|
|
4666
|
+
&#{$i}px{width: #{$i + 'px'};}
|
|
4667
|
+
}
|
|
4668
|
+
}
|
|
4669
|
+
}
|
|
4670
|
+
|
|
4614
4671
|
}
|
|
4615
4672
|
|