|
@@ -0,0 +1,305 @@
|
|
|
+import { Component, Input } from '@angular/core';
|
|
|
+import {
|
|
|
+ IonHeader,
|
|
|
+ IonToolbar,
|
|
|
+ IonTitle,
|
|
|
+ IonContent,
|
|
|
+ IonList,
|
|
|
+ IonItem,
|
|
|
+ IonLabel,
|
|
|
+ IonInput,
|
|
|
+ IonTextarea,
|
|
|
+ IonButton,
|
|
|
+ IonButtons,
|
|
|
+ IonSelect,
|
|
|
+ IonSelectOption,
|
|
|
+ AlertController,
|
|
|
+ ModalController,
|
|
|
+ IonIcon
|
|
|
+} from '@ionic/angular/standalone';
|
|
|
+import { FormsModule } from '@angular/forms';
|
|
|
+import { NgIf } from '@angular/common';
|
|
|
+import { DatabaseService } from '../../services/database.service';
|
|
|
+import { Teacher } from '../../interfaces/teacher.interface';
|
|
|
+import { CloudUser } from '../../../lib/ncloud';
|
|
|
+import { addIcons } from 'ionicons';
|
|
|
+import {
|
|
|
+ createOutline,
|
|
|
+ saveOutline,
|
|
|
+ closeOutline,
|
|
|
+ trashOutline
|
|
|
+} from 'ionicons/icons';
|
|
|
+
|
|
|
+@Component({
|
|
|
+ selector: 'app-custom-teacher-detail',
|
|
|
+ template: `
|
|
|
+ <ion-header>
|
|
|
+ <ion-toolbar>
|
|
|
+ <ion-title>{{ isEditing ? '编辑教师' : '教师详情' }}</ion-title>
|
|
|
+ <ion-buttons slot="end">
|
|
|
+ <ion-button (click)="dismiss()">关闭</ion-button>
|
|
|
+ </ion-buttons>
|
|
|
+ </ion-toolbar>
|
|
|
+ </ion-header>
|
|
|
+
|
|
|
+ <ion-content>
|
|
|
+ <ion-list>
|
|
|
+ <ion-item>
|
|
|
+ <ion-label position="stacked">教师名称</ion-label>
|
|
|
+ <ion-input
|
|
|
+ [(ngModel)]="editedTeacher.name"
|
|
|
+ [readonly]="!isEditing"
|
|
|
+ ></ion-input>
|
|
|
+ </ion-item>
|
|
|
+
|
|
|
+ <ion-item>
|
|
|
+ <ion-label position="stacked">简短描述</ion-label>
|
|
|
+ <ion-input
|
|
|
+ [(ngModel)]="editedTeacher.description"
|
|
|
+ [readonly]="!isEditing"
|
|
|
+ ></ion-input>
|
|
|
+ </ion-item>
|
|
|
+
|
|
|
+ <ion-item>
|
|
|
+ <ion-label position="stacked">教学风格</ion-label>
|
|
|
+ <ion-select [(ngModel)]="teachingStyle" [disabled]="!isEditing">
|
|
|
+ <ion-select-option value="friendly">亲切友善</ion-select-option>
|
|
|
+ <ion-select-option value="strict">严谨认真</ion-select-option>
|
|
|
+ <ion-select-option value="humorous">幽默风趣</ion-select-option>
|
|
|
+ <ion-select-option value="inspiring">启发思考</ion-select-option>
|
|
|
+ </ion-select>
|
|
|
+ </ion-item>
|
|
|
+
|
|
|
+ <ion-item>
|
|
|
+ <ion-label position="stacked">专业领域</ion-label>
|
|
|
+ <ion-select [(ngModel)]="subject" multiple="true" [disabled]="!isEditing">
|
|
|
+ <ion-select-option value="math">数学</ion-select-option>
|
|
|
+ <ion-select-option value="physics">物理</ion-select-option>
|
|
|
+ <ion-select-option value="chemistry">化学</ion-select-option>
|
|
|
+ <ion-select-option value="biology">生物</ion-select-option>
|
|
|
+ <ion-select-option value="literature">语文</ion-select-option>
|
|
|
+ <ion-select-option value="english">英语</ion-select-option>
|
|
|
+ </ion-select>
|
|
|
+ </ion-item>
|
|
|
+
|
|
|
+ <ion-item>
|
|
|
+ <ion-label position="stacked">系统提示词</ion-label>
|
|
|
+ <ion-textarea
|
|
|
+ [(ngModel)]="editedTeacher.systemPrompt"
|
|
|
+ rows="6"
|
|
|
+ [readonly]="!isEditing"
|
|
|
+ ></ion-textarea>
|
|
|
+ </ion-item>
|
|
|
+ </ion-list>
|
|
|
+
|
|
|
+ <div class="action-buttons">
|
|
|
+ <ng-container *ngIf="!isEditing">
|
|
|
+ <ion-button expand="block" (click)="startEditing()">
|
|
|
+ <ion-icon name="create-outline" slot="start"></ion-icon>
|
|
|
+ 编辑
|
|
|
+ </ion-button>
|
|
|
+ <ion-button expand="block" color="danger" (click)="deleteTeacher()">
|
|
|
+ <ion-icon name="trash-outline" slot="start"></ion-icon>
|
|
|
+ 删除
|
|
|
+ </ion-button>
|
|
|
+ </ng-container>
|
|
|
+ <ng-container *ngIf="isEditing">
|
|
|
+ <ion-button expand="block" (click)="saveChanges()">
|
|
|
+ <ion-icon name="save-outline" slot="start"></ion-icon>
|
|
|
+ 保存
|
|
|
+ </ion-button>
|
|
|
+ <ion-button expand="block" fill="outline" color="medium" (click)="cancelEditing()">
|
|
|
+ <ion-icon name="close-outline" slot="start"></ion-icon>
|
|
|
+ 取消
|
|
|
+ </ion-button>
|
|
|
+ </ng-container>
|
|
|
+ </div>
|
|
|
+ </ion-content>
|
|
|
+ `,
|
|
|
+ styles: [`
|
|
|
+ .action-buttons {
|
|
|
+ padding: 16px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+ ion-button {
|
|
|
+ margin: 0;
|
|
|
+ }
|
|
|
+ `],
|
|
|
+ standalone: true,
|
|
|
+ imports: [
|
|
|
+ IonHeader,
|
|
|
+ IonToolbar,
|
|
|
+ IonTitle,
|
|
|
+ IonContent,
|
|
|
+ IonList,
|
|
|
+ IonItem,
|
|
|
+ IonLabel,
|
|
|
+ IonInput,
|
|
|
+ IonTextarea,
|
|
|
+ IonButton,
|
|
|
+ IonButtons,
|
|
|
+ IonSelect,
|
|
|
+ IonSelectOption,
|
|
|
+ IonIcon,
|
|
|
+ FormsModule,
|
|
|
+ NgIf
|
|
|
+ ]
|
|
|
+})
|
|
|
+export class CustomTeacherDetailComponent {
|
|
|
+ @Input() teacher!: Teacher;
|
|
|
+ editedTeacher: Teacher;
|
|
|
+ isEditing = false;
|
|
|
+ teachingStyle = '';
|
|
|
+ subject: string[] = [];
|
|
|
+
|
|
|
+ // 教学风格映射
|
|
|
+ private styleMap = {
|
|
|
+ friendly: '亲切友善',
|
|
|
+ strict: '严谨认真',
|
|
|
+ humorous: '幽默风趣',
|
|
|
+ inspiring: '启发思考'
|
|
|
+ };
|
|
|
+
|
|
|
+ // 反向映射,用于从提示词中解析教学风格
|
|
|
+ private reverseStyleMap: { [key: string]: string } = {
|
|
|
+ '亲切友善': 'friendly',
|
|
|
+ '严谨认真': 'strict',
|
|
|
+ '幽默风趣': 'humorous',
|
|
|
+ '启发思考': 'inspiring'
|
|
|
+ };
|
|
|
+
|
|
|
+ constructor(
|
|
|
+ private modalCtrl: ModalController,
|
|
|
+ private dbService: DatabaseService,
|
|
|
+ private alertController: AlertController
|
|
|
+ ) {
|
|
|
+ this.editedTeacher = { ...this.teacher };
|
|
|
+ // 注册图标
|
|
|
+ addIcons({
|
|
|
+ createOutline,
|
|
|
+ saveOutline,
|
|
|
+ closeOutline,
|
|
|
+ trashOutline
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ ngOnInit() {
|
|
|
+ this.editedTeacher = { ...this.teacher };
|
|
|
+
|
|
|
+ // 初始化专业领域
|
|
|
+ if (this.teacher.subject) {
|
|
|
+ this.subject = Array.isArray(this.teacher.subject) ?
|
|
|
+ this.teacher.subject :
|
|
|
+ [this.teacher.subject];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从系统提示词中解析教学风格
|
|
|
+ const promptLower = this.teacher.systemPrompt.toLowerCase();
|
|
|
+ for (const [style, value] of Object.entries(this.styleMap)) {
|
|
|
+ if (promptLower.includes(value)) {
|
|
|
+ this.teachingStyle = style;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ startEditing() {
|
|
|
+ this.isEditing = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ async saveChanges() {
|
|
|
+ try {
|
|
|
+ const currentUser = new CloudUser();
|
|
|
+ if (!currentUser.id) {
|
|
|
+ throw new Error('请先登录');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新系统提示词,保持与创建向导相同的格式
|
|
|
+ const style = this.styleMap[this.teachingStyle as keyof typeof this.styleMap];
|
|
|
+ const subjects = this.subject.map(s => {
|
|
|
+ switch(s) {
|
|
|
+ case 'math': return '数学';
|
|
|
+ case 'physics': return '物理';
|
|
|
+ case 'chemistry': return '化学';
|
|
|
+ case 'biology': return '生物';
|
|
|
+ case 'literature': return '语文';
|
|
|
+ case 'english': return '英语';
|
|
|
+ default: return s;
|
|
|
+ }
|
|
|
+ }).join('、');
|
|
|
+
|
|
|
+ const systemPrompt = `你是一位名叫"${this.editedTeacher.name}"的教师,教学风格${style}。
|
|
|
+你的专业领域是${subjects}。
|
|
|
+${this.editedTeacher.description}
|
|
|
+在教学过程中,你会根据学生的需求调整教学方式,确保知识传递的效果。`;
|
|
|
+
|
|
|
+ await this.dbService.updateCustomTeacher(
|
|
|
+ this.teacher.objectId!,
|
|
|
+ {
|
|
|
+ name: this.editedTeacher.name,
|
|
|
+ description: this.editedTeacher.description,
|
|
|
+ systemPrompt: systemPrompt,
|
|
|
+ subject: this.subject
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ // 更新本地教师对象
|
|
|
+ this.editedTeacher.systemPrompt = systemPrompt;
|
|
|
+ this.modalCtrl.dismiss(this.editedTeacher);
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Error updating teacher:', error);
|
|
|
+ const alert = await this.alertController.create({
|
|
|
+ header: '更新失败',
|
|
|
+ message: error instanceof Error ? error.message : '未知错误',
|
|
|
+ buttons: ['确定']
|
|
|
+ });
|
|
|
+ await alert.present();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ cancelEditing() {
|
|
|
+ this.editedTeacher = { ...this.teacher };
|
|
|
+ // 重置教学风格和专业领域
|
|
|
+ this.ngOnInit();
|
|
|
+ this.isEditing = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ dismiss() {
|
|
|
+ this.modalCtrl.dismiss();
|
|
|
+ }
|
|
|
+
|
|
|
+ async deleteTeacher() {
|
|
|
+ const alert = await this.alertController.create({
|
|
|
+ header: '确认删除',
|
|
|
+ message: `确定要删除教师"${this.teacher.name}"吗?`,
|
|
|
+ buttons: [
|
|
|
+ {
|
|
|
+ text: '取消',
|
|
|
+ role: 'cancel'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: '删除',
|
|
|
+ role: 'destructive',
|
|
|
+ handler: async () => {
|
|
|
+ try {
|
|
|
+ await this.dbService.deleteCustomTeacher(this.teacher.objectId!);
|
|
|
+ // 删除成功后关闭模态框,并传递删除成功的信号
|
|
|
+ this.modalCtrl.dismiss({ deleted: true });
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Error deleting teacher:', error);
|
|
|
+ const errorAlert = await this.alertController.create({
|
|
|
+ header: '删除失败',
|
|
|
+ message: error instanceof Error ? error.message : '未知错误',
|
|
|
+ buttons: ['确定']
|
|
|
+ });
|
|
|
+ await errorAlert.present();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ });
|
|
|
+ await alert.present();
|
|
|
+ }
|
|
|
+}
|