Commit d0d3b1ac authored by 范雪寒's avatar 范雪寒

feat: 全部功能基本完成

parent a346681e
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, ErrorHandler } from '@angular/core';
import {MyErrorHandler} from './MyError';
import { MyErrorHandler } from './MyError';
import { AppComponent } from './app.component';
import { NgZorroAntdModule, NZ_I18N, zh_CN } from 'ng-zorro-antd';
......@@ -10,20 +10,21 @@ import { HttpClientModule } from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { registerLocaleData } from '@angular/common';
import zh from '@angular/common/locales/zh';
import {FormComponent} from './form/form.component';
import {PlayComponent} from './play/play.component';
import {LessonTitleConfigComponent} from './common/lesson-title-config/lesson-title-config.component';
import {BackgroundImagePipe} from './pipes/background-image.pipe';
import {UploadImageWithPreviewComponent} from './common/upload-image-with-preview/upload-image-with-preview.component';
import {PlayerContentWrapperComponent} from './common/player-content-wrapper/player-content-wrapper.component';
import {CustomHotZoneComponent} from './common/custom-hot-zone/custom-hot-zone.component';
import {UploadVideoComponent} from './common/upload-video/upload-video.component';
import {TimePipe} from './pipes/time.pipe';
import {ResourcePipe} from './pipes/resource.pipe';
import {AudioRecorderComponent} from './common/audio-recorder/audio-recorder.component';
import { FormComponent } from './form/form.component';
import { PlayComponent } from './play/play.component';
import { LessonTitleConfigComponent } from './common/lesson-title-config/lesson-title-config.component';
import { BackgroundImagePipe } from './pipes/background-image.pipe';
import { UploadImageWithPreviewComponent } from './common/upload-image-with-preview/upload-image-with-preview.component';
import { PlayerContentWrapperComponent } from './common/player-content-wrapper/player-content-wrapper.component';
import { CustomHotZoneComponent } from './common/custom-hot-zone/custom-hot-zone.component';
import { UploadVideoComponent } from './common/upload-video/upload-video.component';
import { TimePipe } from './pipes/time.pipe';
import { ResourcePipe } from './pipes/resource.pipe';
import { AudioRecorderComponent } from './common/audio-recorder/audio-recorder.component';
import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontawesome';
import { fas } from '@fortawesome/free-solid-svg-icons';
import { far } from '@fortawesome/free-regular-svg-icons';
import { UploadDragonBoneComponent } from './common/upload-dragon-bone/upload-dragon-bone.component';
registerLocaleData(zh);
......@@ -40,7 +41,7 @@ registerLocaleData(zh);
TimePipe,
UploadVideoComponent,
CustomHotZoneComponent,
UploadDragonBoneComponent,
PlayerContentWrapperComponent
],
......@@ -53,7 +54,7 @@ registerLocaleData(zh);
FontAwesomeModule
],
providers: [
{provide: ErrorHandler, useClass: MyErrorHandler},
{ provide: ErrorHandler, useClass: MyErrorHandler },
{ provide: NZ_I18N, useValue: zh_CN }
],
bootstrap: [AppComponent]
......
This diff is collapsed.
......@@ -32,33 +32,94 @@
<nz-divider style="margin-top: 10px;"></nz-divider>
<div style="margin-top: -20px; margin-bottom: 5px; width: 100%;">
<div style="margin-top: -20px; margin-bottom: 5px">
<nz-radio-group [ngModel]="it.itemType" (ngModelChange)="radioChange($event, it)">
<label *ngIf="isHasRect" nz-radio nzValue="rect">矩形</label>
<label *ngIf="isHasPic" nz-radio nzValue="pic">图片</label>
<label *ngIf="isHasText" nz-radio nzValue="text">文本</label>
</nz-radio-group>
</div>
<div *ngIf="customTypeGroupArr">
<nz-radio-group [ngModel]="it.gIdx" (ngModelChange)="customRadioChange($event, it)" style="display: flex; align-items: center; justify-content: center; flex-wrap: wrap;">
<div *ngFor="let group of customTypeGroupArr; let gIdx = index" style="display: flex; ">
<label nz-radio nzValue="{{gIdx}}">{{group.name}}</label>
</div>
</nz-radio-group>
<div *ngIf="it.itemType == 'pic'">
<app-upload-image-with-preview
[picUrl]="it?.pic_url"
(imageUploaded)="onItemImgUploadSuccess($event, it)">
</app-upload-image-with-preview>
</div>
</div>
<!-- <div *ngIf="!customTypeGroupArr">
<nz-radio-group [ngModel]="it.itemType" (ngModelChange)="radioChange($event, it)" style="display: flex; align-items: center; justify-content: center">
<label *ngIf="isHasRect" nz-radio nzValue="rect">矩形</label>
<label *ngIf="isHasPic" nz-radio nzValue="pic">图片</label>
<label *ngIf="isHasText" nz-radio nzValue="text">文本</label>
</nz-radio-group>
</div> -->
<div *ngIf="it.itemType == 'text'">
<input type="text" nz-input [(ngModel)]="it.text" (blur)="saveText(it)">
</div>
<div style="width: 100%; margin-top: 5px;">
<app-audio-recorder
[audioUrl]="it.audio_url"
(audioUploaded)="onItemAudioUploadSuccess($event, it)"
></app-audio-recorder>
<div *ngIf="customTypeGroupArr && customTypeGroupArr[it.gIdx]">
<div *ngIf="customTypeGroupArr[it.gIdx].pic">
<app-upload-image-with-preview
[picUrl]="it?.pic_url"
(imageUploaded)="onItemImgUploadSuccess($event, it)">
</app-upload-image-with-preview>
</div>
<div *ngIf="customTypeGroupArr[it.gIdx].text" style="margin-top: 5px">
<input type="text" nz-input [(ngModel)]="it.text" (blur)="saveText(it)">
</div>
<div *ngIf="customTypeGroupArr[it.gIdx].anima" align="center" style="margin-top: 5px">
<button nz-button (click)="setAnimaBtnClick(i)" >
<i nz-icon nzType="tool" nzTheme="outline"></i>
配置龙骨动画
</button>
</div>
<div *ngIf="customTypeGroupArr[it.gIdx].audio" style="display: flex;align-items: center; margin-top: 5px">
<app-audio-recorder
style="margin: auto"
[audioUrl]="it.audio_url"
(audioUploaded)="onItemAudioUploadSuccess($event, it)"
></app-audio-recorder>
</div>
</div>
<!-- <div *ngIf="!customTypeGroupArr">
<div *ngIf="it.itemType == 'pic'">
<app-upload-image-with-preview
[picUrl]="it?.pic_url"
(imageUploaded)="onItemImgUploadSuccess($event, it)">
</app-upload-image-with-preview>
</div>
<div *ngIf="it.itemType == 'text'">
<input type="text" nz-input [(ngModel)]="it.text" (blur)="saveText(it)">
</div>
<div *ngIf="isHasAudio"
style="width: 100%; margin-top: 5px; display: flex; align-items: center; justify-items: center;">
<app-audio-recorder
style="margin: auto"
[audioUrl]="it.audio_url"
(audioUploaded)="onItemAudioUploadSuccess($event, it)"
></app-audio-recorder>
</div>
<div *ngIf="it.itemType == 'rect' && isHasAnima" align="center" style="margin-bottom: 5px">
<button nz-button (click)="setAnimaBtnClick(i)" >
<i nz-icon nzType="tool" nzTheme="outline"></i>
配置龙骨动画
</button>
</div>
</div> -->
</div>
</div>
......@@ -83,12 +144,29 @@
<div class="save-box">
<button class="save-btn" nz-button nzType="primary" [nzSize]="'large'" nzShape="round"
<button style="margin-left: 200px" class="save-btn" nz-button nzType="primary" [nzSize]="'large'" nzShape="round"
(click)="saveClick()" >
<i nz-icon nzType="save"></i>
Save
</button>
<div *ngIf="isCopyData" style="height: 40px; display: flex; justify-items: center;" >
<label style="margin-left: 40px" nz-checkbox [(ngModel)]="bgItem.isShowDebugLine">显示辅助框</label>
<button style="margin-left: 20px; margin-top: -5px" nz-button (click)="copyHotZoneData()"> 复制基础数据 </button>
<div style="margin-left: 10px; margin-top: -5px" >
<span>粘贴数据: </span>
<input style="width: 100px;" type="text" nz-input [(ngModel)]="pasteData" >
<button style="margin-left: 5px;" nz-button [disabled]="pasteData==''" nzType="primary" (click)="importData()">导入</button>
</div>
</div>
</div>
......@@ -98,3 +176,52 @@
<label style="opacity: 0; position: absolute; top: 0px; font-family: 'BRLNSR_1'">1</label>
<!--龙骨面板-->
<nz-modal [(nzVisible)]="animaPanelVisible" nzTitle="配置资源文件" (nzAfterClose)="closeAfterPanel()" (nzOnCancel)="animaPanelCancel()" (nzOnOk)="animaPanelOk()" nzOkText="保存">
<div class="anima-upload-btn">
<span style="margin-right: 10px">上传 ske_json 文件: </span>
<nz-upload [nzShowUploadList]="false"
nzAccept="application/json"
[nzAction]="uploadUrl"
[nzData]="uploadData"
(nzChange)="skeJsonHandleChange($event)">
<button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
</nz-upload>
<i *ngIf="isSkeJsonLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i>
<span *ngIf="skeJsonData['name']" style="margin-left: 10px"><u> {{skeJsonData['name']}} </u></span>
</div>
<div class="anima-upload-btn">
<span style="margin-right: 10px">上传 tex_json 文件: </span>
<nz-upload [nzShowUploadList]="false"
nzAccept="application/json"
[nzAction]="uploadUrl"
[nzData]="uploadData"
(nzChange)="texJsonHandleChange($event)">
<button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
</nz-upload>
<i *ngIf="isTexJsonLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i>
<span *ngIf="texJsonData['name']" style="margin-left: 10px"><u> {{texJsonData['name']}} </u></span>
</div>
<div class="anima-upload-btn">
<span style="margin-right: 10px">上传 tex_png 文件: </span>
<nz-upload [nzShowUploadList]="false"
nzAccept = "image/*"
[nzAction]="uploadUrl"
[nzData]="uploadData"
(nzChange)="texPngHandleChange($event)">
<button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
</nz-upload>
<i *ngIf="isTexPngLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i>
<span *ngIf="texPngData['name']" style="margin-left: 10px"><u> {{texPngData['name']}} </u></span>
</div>
<div class="anima-upload-btn" *ngIf="customTypeGroupArr && customTypeGroupArr[curDragonBoneGIdx] && customTypeGroupArr[curDragonBoneGIdx].animaNames">
提示:需包含以下动画: {{customTypeGroupArr[curDragonBoneGIdx].animaNames.toString()}}
</div>
</nz-modal>
......@@ -81,19 +81,21 @@
}
}
h5 {
margin-top: 1rem;
.anima-upload-btn {
padding: 10px;
}
@font-face
{
font-family: 'BRLNSR_1';
src: url("/assets/font/BRLNSR_1.TTF") ;
h5 {
margin-top: 1rem;
}
//
//@font-face
//{
// font-family: 'BRLNSR_1';
// src: url("/assets/font/BRLNSR_1.TTF") ;
//}
......@@ -107,104 +109,3 @@ h5 {
//@import '../../../style/common_mixin';
//
//.p-image-uploader {
// position: relative;
// display: block;
// width: 100%;
// height: 0;
// padding-bottom: 56.25%;
// .p-box {
// position: absolute;
// left: 0;
// top: 0;
// right: 0;
// bottom: 0;
// border: 2px dashed #ddd;
// border-radius: 0.5rem;
// background-color: #fafafa;
// text-align: center;
// color: #aaa;
// .p-upload-icon {
// text-align: center;
// margin: auto;
// .anticon-upload {
// color: #888;
// font-size: 5rem;
// }
// .p-progress-bar {
// position: relative;
// width: 20rem;
// height: 1.5rem;
// border: 1px solid #ccc;
// border-radius: 1rem;
// .p-progress-bg {
// background-color: #1890ff;
// border-radius: 1rem;
// height: 100%;
// }
// .p-progress-value {
// position: absolute;
// top: 0;
// left: 0;
// width: 100%;
// height: 100%;
// text-shadow: 0 0 4px #000;
// color: white;
// text-align: center;
// font-size: 0.9rem;
// line-height: 1.5rem;
// }
// }
// }
// .p-preview {
// width: 100%;
// height: 100%;
// //background-image: url("https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png");
// @include k-img-bg();
// }
// }
//}
//
//.p-btn-delete {
// position: absolute;
// right: -0.5rem;
// top: -0.5rem;
// width: 2rem;
// height: 2rem;
// border: 0.2rem solid white;
// border-radius: 50%;
// font-size: 1.2rem;
// background-color: #fb781a;
// color: white;
// text-align: center;
//}
//
//.p-upload-progress-bg {
// position: absolute;
// width: 100%;
// height: 100%;
// display: flex;
// align-items: center;
// justify-content: center;
// & .i-text {
// position: absolute;
// text-align: center;
// color: white;
// text-shadow: 0 0 2px rgba(0, 0, 0, .85);
// }
// & .i-bg {
// position: absolute;
// left: 0;
// top: 0;
// height: 100%;
// background-color: #27b43f;
// border-radius: 0.5rem;
// }
//}
//
//
//:host ::ng-deep .ant-upload {
// display: block;
//}
<div class="position-relative">
<button nz-button (click)="setAnimaBtnClick()" style=" border-radius: 0.5rem; border: 1px solid #ddd;">
<i nz-icon nzType="tool" nzTheme="outline"></i>
{{btnName}}
</button>
<!--配置龙骨面板-->
<nz-modal [(nzVisible)]="animaPanelVisible" (nzAfterClose)="closePanel()" nzTitle="配置资源文件"
(nzOnCancel)="animaPanelCancel()" (nzOnOk)="animaPanelOk()" nzOkText="保存">
<div class="anima-upload-btn">
<span style="margin-right: 10px">上传 ske_json 文件: </span>
<nz-upload [nzShowUploadList]="false" nzAccept="application/json" [nzAction]="uploadUrl" [nzData]="uploadData"
(nzChange)="skeJsonHandleChange($event)">
<button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
</nz-upload>
<i *ngIf="isSkeJsonLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i>
<span *ngIf="skeJsonData && skeJsonData['name']" style="margin-left: 10px"><u> {{skeJsonData['name']}} </u></span>
</div>
<div class="anima-upload-btn">
<span style="margin-right: 10px">上传 tex_json 文件: </span>
<nz-upload [nzShowUploadList]="false" nzAccept="application/json" [nzAction]="uploadUrl" [nzData]="uploadData"
(nzChange)="texJsonHandleChange($event)">
<button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
</nz-upload>
<i *ngIf="isTexJsonLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i>
<span *ngIf="texJsonData && texJsonData['name']" style="margin-left: 10px"><u> {{texJsonData['name']}} </u></span>
</div>
<div class="anima-upload-btn">
<span style="margin-right: 10px">上传 tex_png 文件: </span>
<nz-upload [nzShowUploadList]="false" nzAccept="image/*" [nzAction]="uploadUrl" [nzData]="uploadData"
(nzChange)="texPngHandleChange($event)">
<button nz-button><i nz-icon nzType="upload"></i><span>Upload</span></button>
</nz-upload>
<i *ngIf="isTexPngLoading" style="margin-left: 10px;" nz-icon [nzType]="'loading'"></i>
<span *ngIf="texPngData && texPngData['name']" style="margin-left: 10px"><u> {{texPngData['name']}} </u></span>
</div>
<div class="anima-upload-btn" *ngIf="animaNames && animaNames.length > 0">
提示:需包含动画: {{animaNames.toString()}}.
</div>
</nz-modal>
</div>
\ No newline at end of file
@import '../../style/common_mixin.css';
.p-image-uploader {
position: relative;
display: block;
width: 100%;
height: 0;
padding-bottom: 56.25%;
.p-box {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
border: 2px dashed #ddd;
border-radius: 0.5rem;
background-color: #fafafa;
text-align: center;
color: #aaa;
.p-upload-icon {
text-align: center;
margin: auto;
.anticon-upload {
color: #888;
font-size: 5rem;
}
.p-progress-bar {
position: relative;
width: 20rem;
height: 1.5rem;
border: 1px solid #ccc;
border-radius: 1rem;
.p-progress-bg {
background-color: #1890ff;
border-radius: 1rem;
height: 100%;
}
.p-progress-value {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
text-shadow: 0 0 4px #000;
color: white;
text-align: center;
font-size: 0.9rem;
line-height: 1.5rem;
}
}
}
.p-preview {
width: 100%;
height: 100%;
background-size: contain;
background-repeat: no-repeat;
background-position: 50% 50%;
//background-image: url("https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png");
}
}
.d-flex{
display: flex;
}
}
.p-btn-delete {
position: absolute;
right: -0.5rem;
top: -0.5rem;
width: 2rem;
height: 2rem;
border: 0.2rem solid white;
border-radius: 50%;
font-size: 1.2rem;
background-color: #fb781a;
color: white;
text-align: center;
}
.p-upload-progress-bg {
position: absolute;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
& .i-text {
position: absolute;
text-align: center;
color: white;
text-shadow: 0 0 2px rgba(0, 0, 0, .85);
}
& .i-bg {
position: absolute;
left: 0;
top: 0;
height: 100%;
background-color: #27b43f;
border-radius: 0.5rem;
}
}
.anima-upload-btn {
padding: 10px;
}
:host ::ng-deep .ant-upload {
display: block;
}
import {ApplicationRef, Component, EventEmitter, Input, OnChanges, OnDestroy, Output} from '@angular/core';
import { NzMessageService, UploadXHRArgs, UploadFile } from 'ng-zorro-antd';
@Component({
selector: 'app-upload-dragon-bone',
templateUrl: './upload-dragon-bone.component.html',
styleUrls: ['./upload-dragon-bone.component.scss']
})
export class UploadDragonBoneComponent implements OnDestroy, OnChanges {
uploading = false;
progress = 0;
@Input()
btnName = '配置龙骨动画';
@Input()
animaNames = [];
@Input()
skeJsonData = {};
@Input()
texJsonData = {};
@Input()
texPngData = {};
@Output()
save = new EventEmitter();
@Output()
refreshEmitter = new EventEmitter();
// @Input()
// picUrl;
// @Input()
// canDelete = false;
// @Output()
// imageUploaded = new EventEmitter();
// @Output()
// imageUploadFailure = new EventEmitter();
// @Output()
// delete = new EventEmitter();
// @Input()
// picItem = null;
// @Input()
// iconSize = 2;
// @Input()
// TIP = 'Click here to upload image';
// @Input()
// disableUpload = false;
uploadUrl;
uploadData;
animaPanelVisible = false;
isSkeJsonLoading = false;
isTexJsonLoading = false;
isTexPngLoading = false;
constructor(private appRef: ApplicationRef, private nzMessageService: NzMessageService) {
this.uploadUrl = (<any> window).courseware.uploadUrl();
this.uploadData = (<any> window).courseware.uploadData();
window['air'].getUploadCallback = (url, data) => {
this.uploadUrl = url;
this.uploadData = data;
};
}
ngOnChanges() {
}
setAnimaBtnClick() {
this.animaPanelVisible = true;
this.refresh();
}
animaPanelCancel() {
this.animaPanelVisible = false;
this.refresh();
}
animaPanelOk() {
this.sendItemDragonBoneData();
this.animaPanelVisible = false;
this.refresh();
}
sendItemDragonBoneData() {
const data = {};
data['skeJsonData'] = this.skeJsonData;
data['texJsonData'] = this.texJsonData;
data['texPngData'] = this.texPngData;
this.save.emit(data);
}
skeJsonHandleChange(e) {
console.log('e: ', e);
switch (e.type) {
case 'start':
this.isSkeJsonLoading = true;
break;
case 'success':
this.skeJsonData['url'] = e.file.response.url;
this.skeJsonData['name'] = e.file.name;
this.nzMessageService.success('上传成功');
this.isSkeJsonLoading = false;
break;
case 'progress':
break;
}
}
texJsonHandleChange(e) {
console.log('e: ', e);
switch (e.type) {
case 'start':
this.isTexJsonLoading = true;
break;
case 'success':
this.texJsonData['url'] = e.file.response.url;
this.texJsonData['name'] = e.file.name;
this.nzMessageService.success('上传成功');
this.isTexJsonLoading = false;
break;
case 'progress':
break;
}
}
texPngHandleChange(e) {
console.log('e: ', e);
switch (e.type) {
case 'start':
this.isTexPngLoading = true;
break;
case 'success':
this.texPngData['url'] = e.file.response.url;
this.texPngData['name'] = e.file.name;
this.nzMessageService.success('上传成功');
this.isTexPngLoading = false;
break;
case 'progress':
break;
}
}
/**
* 刷新 渲染页面
*/
refresh() {
// this.refreshEmitter.emit();
setTimeout(() => {
this.appRef.tick();
}, 1);
}
closePanel() {
console.log(' in closePanel ');
this.refresh();
}
ngOnDestroy() {
}
}
<div class="model-content">
<div style="padding: 10px;">
<div style="width: 300px;" align='center'>
<span>图1: </span>
<app-upload-image-with-preview
[picUrl]="item.pic_url"
(imageUploaded)="onImageUploadSuccess($event, 'pic_url')">
</app-upload-image-with-preview>
</div>
<div style="width: 300px; margin-top: 5px;" align='center'>
<span>图2: </span>
<app-upload-image-with-preview
[picUrl]="item.pic_url_2"
(imageUploaded)="onImageUploadSuccess($event, 'pic_url_2')">
</app-upload-image-with-preview>
</div>
<div style="width: 300px; margin-top: 15px;">
<span>文本: </span>
<input type="text" nz-input [(ngModel)]="item.text" (blur)="save()">
</div>
<div style="margin-left: 5%; width:90%; margin-top: 100px; margin-bottom: 50px;">
<span style="height: 30px; font-size: 18px;">标题音频:</span>
<app-audio-recorder [audioUrl]="item.tittleAudio" (audioUploaded)="onAudioUploadSuccess($event)">
</app-audio-recorder>
<br>
<span style="height: 30px; font-size: 18px;">标题文本:</span>
<input style="width: 150px; " type="text" maxlength="15" nz-input [(ngModel)]="item.tittleTxt" (blur)="save()">
</div>
<div style="margin-top: 5px">
<span>音频: </span>
<app-audio-recorder
[audioUrl]="item.audio_url"
(audioUploaded)="onAudioUploadSuccess($event, 'audio_url')"
></app-audio-recorder>
</div>
<div *ngFor="let question of item.questionList; let i = index">
<div style="border-style: dotted; border-width: 1px;">
<div style="margin-left: 5%; margin-bottom: 50px; padding-top: 20px; ">
<span style="height: 30px; font-size: 18px;">问题{{i + 1}}音频:</span>
<app-audio-recorder [audioUrl]="question.questionAudio"
(audioUploaded)="onQuestionAudioUploadSuccess($event, i)">
</app-audio-recorder>
<br>
<span style="height: 30px; font-size: 18px;">问题{{i + 1}}文本:</span>
<br>
<input style="width: 150px; " type="text" maxlength="15" nz-input [(ngModel)]="question.questionTxt"
(blur)="save()">
<br>
<br>
<span style="height: 30px; font-size: 18px;">问题{{i + 1}}选项:</span>
<div *ngFor="let option of question.optionList; let j = index">
<div style="margin-top: 20px; float: left; border-width: 1px; border-style: dotted;
padding: 20px; margin-right: 20px; width: 230px;">
<span style="height: 30px; font-size: 18px;">选项{{j + 1}}音频:</span>
<app-audio-recorder [audioUrl]="option.optionAudio" (audioUploaded)="onOptionUploadSuccess($event, i, j)">
</app-audio-recorder>
<br>
<span style="height: 30px; font-size: 18px;">选项{{j + 1}}骨骼动画:</span>
<app-upload-dragon-bone [btnName]="[['配置骨骼动画']]" [animaNames]="[[['normal']]]"
[skeJsonData]=option.optionDragonBone.skeJsonData [texJsonData]=option.optionDragonBone.texJsonData
[texPngData]=option.optionDragonBone.texPngData (save)="saveAnima($event, option.optionDragonBone)"
(refreshEmitter)="refresh()">
</app-upload-dragon-bone>
<br>
<nz-radio-group [(ngModel)]="question.rightOptionIdx">
<div [nzValue]="j" nz-radio (click)="radioClick(i, j)">
<span style="height: 30px; font-size: 18px;">正确选项</span>
</div>
</nz-radio-group>
<div *ngIf="(question.optionList.length >= 4)">
<button style="margin-top: 20px; width: 100%; height: 32px; color: red;" nz-button nzType="dashed"
class="add-btn" (click)="removeOption(i, j)">
删除选项
</button>
</div>
</div>
</div>
<div *ngIf="(question.optionList.length < 4)">
<button style="margin-top: 20px; float: left; border-width: 1px;
border-style: dotted; padding: 20px; margin-right: 20px;
width: 230px; height: 231px;" nz-button nzType="dashed" class="add-btn" (click)="addOption(i)">
增加选项
</button>
</div>
</div>
<button style="margin-left: 5%; margin-top: 50px; width: 90%; height: 32px; color: red;" nz-button nzType="dashed"
class="add-btn" (click)="removeQuestion(i)">
删除问题{{i+1}}
</button>
<div style=" height: 50px; margin-top: 50px;">
</div>
</div>
</div>
<button style="margin-left: 5%; margin-top: 2px; margin-bottom: 100px; height: 50px; width: 90%;" nz-button
nzType="dashed" class="add-btn" (click)="addQuestion()">
添加问题
</button>
</div>
</div>
\ No newline at end of file
......@@ -18,24 +18,65 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
}
createShell() {
this.item.wordList.push({
word: '',
audio: '',
backWord: '',
backWordAudio: '',
addQuestion() {
this.item.questionList.push({
"questionAudio": "",
"questionTxt": "",
"rightOptionIdx": 0,
"optionList": [{
"optionDragonBone": {
"skeJsonData": { "url": "" },
"texJsonData": { "url": "" },
"texPngData": { "url": "" }
},
"optionAudio": ""
}, {
"optionDragonBone": {
"skeJsonData": { "url": "" },
"texJsonData": { "url": "" },
"texPngData": { "url": "" }
},
"optionAudio": ""
}, {
"optionDragonBone": {
"skeJsonData": { "url": "" },
"texJsonData": { "url": "" },
"texPngData": { "url": "" }
},
"optionAudio": ""
}]
});
this.save();
}
removeShell(idx) {
this.item.wordList.splice(idx, 1);
removeQuestion(idx) {
this.item.questionList.splice(idx, 1);
this.save();
}
ngOnInit() {
addOption(questionIdx) {
this.item.questionList[questionIdx].optionList.push({
"optionDragonBone": {
"skeJsonData": { "url": "" },
"texJsonData": { "url": "" },
"texPngData": { "url": "" }
},
"optionAudio": ""
});
this.save();
}
this.item = {};
removeOption(questionIdx, optionIdx) {
this.item.questionList[questionIdx].optionList.splice(optionIdx, 1);
this.save();
}
ngOnInit() {
this.item = {
tittleAudio: "",
tittleTxt: "",
questionList: []
};
// 获取存储的数据
(<any>window).courseware.getData((data) => {
......@@ -62,33 +103,35 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
}
/**
* 储存图片数据
* 储存音频数据
* @param e
*/
onImageUploadSuccess(e, key) {
onAudioUploadSuccess(e) {
this.item.tittleAudio = e.url;
this.save();
}
this.item[key] = e.url;
onOptionUploadSuccess(e, questionIdx, optionIdx) {
this.item.questionList[questionIdx].optionList[optionIdx].optionAudio = e.url;
this.save();
}
/**
* 储存音频数据
* @param e
*/
onAudioUploadSuccess(e, key) {
this.item[key] = e.url;
onQuestionAudioUploadSuccess(e, questionIdx) {
this.item.questionList[questionIdx].questionAudio = e.url;
this.save();
// questionTxt
}
onWordAudioUploadSuccess(e, idx) {
this.item.wordList[idx].audio = e.url;
radioClick(questionIdx, optionIdx) {
this.item.questionList[questionIdx].rightOptionIdx = optionIdx;
this.save();
}
onBackWordAudioUploadSuccess(e, idx) {
this.item.wordList[idx].backWordAudio = e.url;
saveAnima(event, group) {
group.skeJsonData = event.skeJsonData;
group.texJsonData = event.texJsonData;
group.texPngData = event.texPngData;
this.save();
}
......
This diff is collapsed.
......@@ -10,6 +10,8 @@ import {
playEffect,
stopEffect,
loadImgByUrl,
blinkNode,
stopBlinkNode,
asyncLoadImgByUrl,
asyncPlayEffectByUrl,
asyncLoadDragonBoneAnime,
......@@ -126,6 +128,14 @@ cc.Class({
addButtonListener(cc.find('Canvas/BtnNode/BtnRefresh'), () => {
this.showQuestion();
});
cc.find('Canvas/bgFrount/leef/TittleLabelNode').on('click', () => {
this.playIncomeAudio();
});
cc.find('Canvas/QuestionLabelBg/QuestionLabelNode').on('click', () => {
this.playQuestionAudio();
});
},
updateBgSize() {
......@@ -134,7 +144,18 @@ cc.Class({
async showQuestion() {
this.showOptions();
this.playIncomeAudio();
await this.questionBoardDown();
this.playQuestionAudio();
},
playIncomeAudio() {
asyncPlayEffectByUrl(this.data.tittleAudio);
},
playQuestionAudio() {
const audioUrl = this.data.questionList[this.status.currentQuestionIdx].questionAudio;
asyncPlayEffectByUrl(audioUrl);
},
showOptions() {
......@@ -149,16 +170,67 @@ cc.Class({
const optionNode = cc.instantiate(cc.find(`OptionNodeBase_${optionList.length}`));
optionNode.name = `optionNode_${idx}`;
optionNode.parent = cc.find('Canvas');
optionNode.addComponent(cc.Button);
optionNode.canClick = true;
optionNode.on('click', () => {
this.onOptionClicked(optionNode, idx);
});
const posNode = cc.find(`Canvas/OptionPosListBase/Option_${optionList.length}_${idx}`)
optionNode.x = posNode.x;
optionNode.y = posNode.y;
const animeNode = await asyncLoadDragonBoneAnime(cc.find('OptionDragonBoneBaseNode', optionNode), data.optionDragonBone);
// await asyncPlayDragonBoneAnimation(cc.find('OptionDragonBoneBaseNode', optionNode), 'normal', 1);
animeNode.scale = Math.min(260 / animeNode.width, 360 / animeNode.height, 1);
animeNode.name = 'animeNode';
animeNode.addComponent(cc.Button);
animeNode.on('click', () => {
this.onOptionClicked(optionNode, idx);
});
const btnFlower = cc.find('OptionSpeakerBtn/BtnFlower', optionNode);
const btnFlowerP = cc.find('OptionSpeakerBtn/BtnFlower_P', optionNode);
addButtonListener(cc.find('OptionSpeakerBtn', optionNode), async () => {
blinkNode(optionNode, btnFlowerP, btnFlower);
await asyncPlayEffectByUrl(data.optionAudio);
asyncPlayDragonBoneAnimation(animeNode, 'smoke', 1);
// asyncPlayDragonBoneAnimation(animeNode, 'normal', 1);
stopBlinkNode(optionNode, btnFlowerP, btnFlower);
});
});
},
async onOptionClicked(optionNode, idx) {
if (!optionNode.canClick) {
return;
}
optionNode.canClick = false;
if (this.data.questionList[this.status.currentQuestionIdx].rightOptionIdx == idx) {
this.onOptionRight(optionNode, idx);
return;
}
this.onOptionWrong(optionNode);
},
onOptionWrong(optionNode) {
const animeNode = cc.find('OptionDragonBoneBaseNode/animeNode', optionNode);
animeNode.color = cc.color(150, 150, 150, 255);
},
onOptionRight(optionNode, idx) {
const optionList = this.data.questionList[this.status.currentQuestionIdx].optionList;
const posNode = cc.find(`Canvas/OptionPosListBase/OptionTarget_${optionList.length}_${idx}`)
cc.tween(optionNode)
.to(1, { x: posNode.x }, { easing: 'quadIn' })
.start();
cc.tween(optionNode)
.to(1, { y: posNode.y, scale: 0.3 })
.to(0.5, { opacity: 0 })
.start();
},
async questionBoardDown() {
const questionLabel = cc.find('Canvas/QuestionLabelBg/QuestionLabelNode').getComponent(cc.Label);
questionLabel.string = this.data.questionList[this.status.currentQuestionIdx].questionTxt;
......
This diff is collapsed.
......@@ -239,8 +239,8 @@ export function addButtonListener(btnNode, func) {
}
btnNode.canNotClick = true;
playEffect('按钮');
await jelly(btnNode);
await func(btn);
await jelly(btnNode);
btnNode.canNotClick = false;
});
}
......@@ -332,4 +332,35 @@ export async function asyncLoadDragonBoneAnime(node, { skeJsonData: { url: skeJs
resolve(animaNode);
});
});
}
export function blinkNode(baseNode, activeNode, notActiveNode, delayTime = 0.2) {
cc.tween(baseNode)
.call(() => {
if (activeNode) {
activeNode.active = false;
}
if (notActiveNode) {
notActiveNode.active = true;
}
})
.delay(delayTime)
.call(() => {
if (activeNode) {
activeNode.active = true;
}
if (notActiveNode) {
notActiveNode.active = false;
}
})
.delay(delayTime)
.union()
.repeatForever()
.start();
}
export function stopBlinkNode(baseNode, activeNode, notActiveNode) {
baseNode.stopAllActions();
activeNode.active = true;
notActiveNode.active = false;
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment