Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

курсач / 1302_3_Курсовая

.pdf
Скачиваний:
0
Добавлен:
27.12.2025
Размер:
848.31 Кб
Скачать

31

stmt.finalize();

db.run('COMMIT', (err) => { if (err) reject(err);

else resolve(); });

});

});

}

}

export const studentRepository = new StudentRepository();

Листинг программного кода серверной части. student.soap.ts import { studentService } from '@/student/student.service';

export const soapService = { StudentService: {

StudentPort: {

getStudent: async function (args: { id: string }) {

const student = await studentService.getStudentById(Number(args.id)); return { student };

},

// НОВЫЙ МЕТОД getStudents: async function () {

const students = await studentService.getAllStudents(); return { students };

},

createStudent: async function (args: { name: string;

specialization: string; course: string;

}) {

32

const newStudent = await studentService.createStudent({ name: args.name,

specialization: args.specialization, course: Number(args.course),

});

return { student: newStudent }; },

},

},

};

Листинг программного кода серверной части. rest.service.ts

import type { Student, CreateStudentDto, RequestMetrics,

} from "@/types/student";

const API_URL = "http://localhost:8000/api/students";

//==========================================

//1. ХЕЛПЕР ДЛЯ ЗАМЕРОВ (Специфика курсовой)

//==========================================

async function measure<T>( label: string,

requestAction: () => Promise<Response>,

): Promise<{ data: T; metrics: RequestMetrics }> { const startTotal = performance.now();

//1. СЕТЬ (Скачиваем текст, но не парсим в объект) const response = await requestAction();

const textData = await response.text();

//2. ЗАМЕР ПАРСИНГА

const startParse = performance.now();

33

const jsonData = JSON.parse(textData); const endParse = performance.now();

const endTotal = performance.now();

const rawString = JSON.stringify(jsonData, null, 2);

return {

data: jsonData, metrics: {

method: label, protocol: "REST",

duration: endTotal - startTotal, parsingTime: endParse - startParse, dataSize: rawString.length, rawResponse: rawString,

},

};

}

//==========================================

//2. ЭКСПОРТ ДЛЯ UI (Адаптер)

//==========================================

/*

App.vue импортирует именно это.

ServicePanel получит то, что ждет (данные + метрики),

а внутри мы вызываем чистый pureRestService. */

export const restService = { async getAll() {

return measure("Get List", () => fetch(API_URL)); },

async create(student: CreateStudentDto) { return measure("Create", () =>

34

fetch(API_URL, { method: "POST",

headers: { "Content-Type": "application/json" }, body: JSON.stringify(student),

}),

);

},

};

Листинг программного кода серверной части. soap.service.ts import type {

Student,

CreateStudentDto,

RequestMetrics,

} from "@/types/student";

const SOAP_URL = "http://localhost:8000/soap";

async function measure<T>( label: string,

xmlBody: string,

parseLogic: (rawXml: string) => T,

): Promise<{ data: T; metrics: RequestMetrics }> { const startTotal = performance.now();

const response = await fetch(SOAP_URL, { method: "POST",

headers: { "Content-Type": "text/xml" }, body: xmlBody,

});

const textResponse = await response.text();

const startParse = performance.now();

const parsedData = parseLogic(textResponse); const endParse = performance.now();

35

const endTotal = performance.now();

return {

data: parsedData, metrics: {

method: label, protocol: "SOAP",

duration: endTotal - startTotal, parsingTime: endParse - startParse, dataSize: textResponse.length, rawResponse: textResponse,

},

};

}

export const soapService = { async getAll() {

const xml = `

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="http://www.examples.com/wsdl/StudentService.wsdl">

<soapenv:Header/>

<soapenv:Body><tns:getStudentsRequest/></soapenv:Body>

</soapenv:Envelope>`;

return measure<Student[]>("Get List", xml, (rawXml) => { const parser = new DOMParser();

const doc = parser.parseFromString(rawXml, "text/xml"); const nodes = doc.getElementsByTagName("students"); const students: Student[] = [];

for (let i = 0; i < nodes.length; i++) { const node = nodes[i];

if (!node) continue;

36

const getId = (tag: string) => node.getElementsByTagName(tag)[0]?.textContent;

students.push({

id: Number(getId("id") || 0), name: getId("name") || "",

specialization: getId("specialization") || "", course: Number(getId("course") || 0),

});

}

return students; });

},

async create(student: CreateStudentDto) { const xml = `

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="http://www.examples.com/wsdl/StudentService.wsdl">

<soapenv:Header/>

<soapenv:Body>

<tns:createStudentRequest> <tns:name>${student.name}</tns:name> <tns:specialization>${student.specialization}</tns:specialization> <tns:course>${student.course}</tns:course>

</tns:createStudentRequest>

</soapenv:Body>

</soapenv:Envelope>`;

return measure<any>("Create", xml, (rawXml) => { return rawXml;

});

},

};

Листинг программного кода серверной части. ServicePanel.vue

37

<template> <v-card

class="h-100" elevation="4" border

>

<!-- Шапка --> <v-toolbar

density="comfortable"

:color="color"

>

<template v-slot:prepend> <v-icon

:icon="icon || 'mdi-api'" class="ml-2"

/>

</template>

<v-toolbar-title class="font-weight-bold">{{ title }}</v-toolbar-title> <template v-slot:append>

<v-chip class="font-weight-bold mr-2" color="white" variant="elevated"

label

>

{{ protocol }} </v-chip>

</template> </v-toolbar>

<v-card-text class="pa-4"> <!-- Блок управления --> <v-sheet

class="pa-4 mb-4 bg-grey-lighten-5" rounded

38

border

>

<div

class="text-subtitle-2 mb-2 text-medium-emphasis text-uppercase font-weight-bold"

>

Действия

</div>

<v-btn class="mb-4" block size="large" variant="flat"

prepend-icon="mdi-download" :loading="loading" :color="color" @click="loadData"

>

Загрузить список </v-btn>

<v-row dense> <v-col cols="6">

<v-text-field v-model="newStudent.name" label="Имя" density="compact" variant="outlined" hide-details bg-color="white"

/> </v-col>

<v-col cols="4"> <v-text-field

v-model="newStudent.specialization"

39

label="Спец-ть" density="compact" variant="outlined" hide-details bg-color="white"

/> </v-col>

<v-col cols="2"> <v-btn

block class="rounded" variant="elevated" color="success" height="40" :loading="loading" @click="createData"

>

<v-icon icon="mdi-plus" /> </v-btn>

</v-col> </v-row> </v-sheet>

<div class="d-flex justify-space-between align-center mb-2"> <h3 class="text-h6">Данные</h3>

<v-badge color="grey-darken-1" inline :content="students.length"

/>

</div>

<v-sheet border rounded

40

class="student-list-container mb-4 pa-2 bg-grey-lighten-5"

>

<div

v-if="students.length === 0" class="text-center pa-4 text-grey"

>

Нет данных. Нажмите "Загрузить". </div>

<v-list v-else

bg-color="transparent" density="compact"

>

<!-- Карточка с рамкой для "студент" --> <v-list-item

v-for="s in students" :key="s.id"

class="mb-2 bg-white rounded border" elevation="1"

>

<template v-slot:prepend> <v-avatar

color="grey-lighten-3" size="small"

>

<span class="text-subtitle-2 text-black">{{ s.course }}</span> </v-avatar>

</template>

<v-list-item-title class="font-weight-bold text-body-1 ml-2"> {{ s.name }}

</v-list-item-title>

<v-list-item-subtitle class="ml-2 text-caption">

Соседние файлы в папке курсач