Commit d446143c authored by liujiaxin's avatar liujiaxin

finish 1

parent 8a51c964
......@@ -30,7 +30,10 @@
],
"styles": [
"./node_modules/ng-zorro-antd/ng-zorro-antd.min.css",
"src/styles.css"
"./node_modules/font-awesome/css/font-awesome.css",
"./node_modules/bootstrap/dist/css/bootstrap.min.css",
"./node_modules/animate.css/animate.min.css",
"src/styles.scss"
],
"scripts": []
},
......
@import '../style/common_mixin.css';
.model-content {
width: 100%;
height: 100%;
}
<div class="p-box" *ngFor="let word of item.contentObj.wordnum;index as num;">
<nz-card nzTitle="Word Spelling [{{num + 1}} / {{item.contentObj?.wordnum?.length}}]" [nzExtra]="extraTemplate">
<div>
<div class="spelling-box" *ngFor="let box of defaultBoxes; index as i">
<div class="model-content">
<div *ngIf="word.words[i]">
<div class="w-radio"
(click)="select(i,num)">
<div class="r-radio"
[class.green]="word.words[i].selected"></div>
</div>
<input class="p-letter-input" name="Input" type="text" maxlength="4" tabindex="0"
[(ngModel)]="word.words[i].value"
(blur)="inputSave($event)"
(keyup)="keyup($event,word.words[i].value,num);">
<div style="position: absolute; left: 200px; top: 100px; width: 800px;">
</div>
<input type="text" nz-input [(ngModel)]="item.text" (blur)="save()">
</div>
<span class="p-hint">
1. Type letters of word in left <br>
2. Press Enter to confirm <br>
3. Click round point to set 'Missing Letter'
</span>
</div>
<div class="mt-3">
<div class="show" *ngFor="let it of word.words">
<div *ngIf="it.selected" class="blank"><p></p></div>
<div *ngIf="!it.selected"><p>{{it.value}}</p></div>
</div>
</div>
<nz-divider></nz-divider>
<app-upload-image-with-preview
[picUrl]="item.pic_url"
(imageUploaded)="onImageUploadSuccess($event, 'pic_url')"
></app-upload-image-with-preview>
<app-audio-recorder
[audioUrl]="item.audio_url"
(audioUploaded)="onAudioUploadSuccess($event, 'audio_url')"
[audioUrl]="item.contentObj['audio_word']"
(audioUploaded)="onVocabularyAudioUploadSuccess($event, 'audio_word')"
></app-audio-recorder>
<app-custom-hot-zone></app-custom-hot-zone>
<app-upload-video></app-upload-video>
<app-lesson-title-config></app-lesson-title-config>
<!--<div class="p-media-box d-flex">-->
<!--<div>-->
<!--<app-upload-image-with-preview [picId]="word.pic_id"-->
<!--(imageUploaded)="onImageUploadSuccess($event, num)"-->
<!--&gt;</app-upload-image-with-preview>-->
<!--</div>-->
<!--<nz-divider nzType="vertical"></nz-divider>-->
<!--<div>-->
<!--<app-audio-recorder-->
<!--[audioId]="word.spelling_audio"-->
<!--(audioUploaded)="onVocabularyAudioUploadSuccess($event,num)"-->
<!--&gt;</app-audio-recorder>-->
<!--</div>-->
<!--</div>-->
</nz-card>
<ng-template #extraTemplate>
<!--<button nz-button nzType="danger" nz-popconfirm nzTitle="Are you sure ?" (nzOnConfirm)="DeletWord(num)">Delete-->
<!--</button>-->
</ng-template>
</div>
<div nz-row nzType="flex" nzJustify="start" nzAlign="top" >
<div nz-col nzSpan="12">
<div class="show" style="display: flex; flex-direction: column;"
*ngFor="let it of selectedArr; let i = index">
<div style="display: flex; align-items: center">
<p style="margin-left: 0.8rem; margin-right: 50px;">{{it.value}}: </p>
<app-audio-recorder
[audioUrl]="it.audio"
(audioUploaded)="onAudioUploadSuccessSelected($event, i)"
></app-audio-recorder>
</div>
</div>
<div style="display: flex; align-items: center" *ngFor="let it of options; let i = index">
<input class="p-letter-options" type="text" maxlength="4"
[(ngModel)]="options[i].value"
(keyup)="setWrongOptions($event, i)">
<app-audio-recorder
[audioUrl]="it.audio"
(audioUploaded)="onAudioUploadSuccessOptions($event, i)"
></app-audio-recorder>
</div>
</div>
<div nz-col nzSpan="10">
<app-upload-image-with-preview
[picUrl]="item.contentObj.pic_res_id"
(imageUploaded)="onHandleOptionItemImage($event)"
>
</app-upload-image-with-preview>
</div>
</div>
\ No newline at end of file
<!--<button nz-button nzType="primary" (click)="AddWord()">-->
<!--+ Add Word-->
<!--</button>-->
p {
margin: 0;
}
.spelling-box {
// width: 2.5rem;
// height: 2.5rem;
display: inline-block;
margin: 0.2rem;
input {
width: 7rem;
height: 2.7rem;
text-align: center;
display: inline-block;
border: 0.1rem solid #888;
line-height: 2.7rem;
font-weight: 900;
font-size: 1.8rem;
}
.r-radio {
width: 0.5rem;
height: 0.5rem;
border: 1px solid #888;
border-radius: 50%;
}
.green {
background-color: #8dd897;
}
.w-radio {
width: 1rem;
height: 1rem;
margin: 20% auto;
border: 1px solid;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
}
button {
margin-top: 2%;
margin-left: 5%;
}
.show {
display: inline-block;
div {
display: inline;
}
p {
display: block;
line-height: 2.5rem;
border-radius: 15%;
margin: 0 1px;
font-weight: 900;
font-size: 1.8rem;
}
.blank {
border: 2px solid;
margin: 0 3px;
display: inline-block;
width: 5rem;
height: 2.5rem;
border-radius: 10px;
vertical-align: bottom;
}
}
.p-box {
margin-bottom: 1.5rem;
nz-card {
border-radius: 0.5rem;
}
}
.p-letter-input:focus {
border-color: #1eb461 !important;
}
.p-media-box {
& > div:nth-child(1) {
width: 18rem;
}
nz-divider {
height: 10rem;
margin: 0 2rem;
}
}
.p-hint {
margin-left: 1rem;
color: #888;
font-size: 10px;
display: inline-block;
}
.p-letter-options {
display: inline-block;
margin: 0.2rem;
margin-right: 40px;
width: 7rem;
height: 2.7rem;
text-align: center;
border: 0.1rem solid #888;
line-height: 2.7rem;
font-weight: 900;
font-size: 1.8rem;
}
import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, ApplicationRef, ChangeDetectorRef} from '@angular/core';
import * as _ from 'lodash';
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.css']
styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit, OnChanges, OnDestroy {
// 储存数据用
saveKey = "test_0011";
saveKey = 'ww_diamond';
// 储存对象
item;
// originContent;
defaultBoxes = new Array(8);
words = [];
bol: number;
inputs: any;
options = [];
selectedArr = [];
constructor(private appRef: ApplicationRef,private changeDetectorRef: ChangeDetectorRef) {
constructor(private appRef: ApplicationRef,
private changeDetectorRef: ChangeDetectorRef) {
this.bol = 0;
this.inputs = document.getElementsByName('Input');
}
ngOnInit() {
this.item = {};
this.item = {
contentObj: {
}
};
// this.originContent = {...this.item.contentObj};
// 获取存储的数据
(<any> window).courseware.getData((data) => {
(window as any).courseware.getData((data) => {
// this.originContent = {...data.contentObj};
if (data) {
this.item = data;
}
if (!this.item.contentObj.wordnum || !this.item.contentObj.wordnum.length) {
this.item.contentObj.wordnum = [];
this.AddWord();
}
this.init();
this.changeDetectorRef.markForCheck();
this.changeDetectorRef.detectChanges();
......@@ -42,6 +58,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
ngOnChanges() {
}
ngOnDestroy() {
......@@ -50,29 +67,30 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
init() {
this.options = this.item.contentObj.options || [{value: '', audio: ''}, {value: '', audio: ''}];
this.selectedArr = this.item.contentObj.selectedArr || this.initSelectedArr();
}
/**
* 储存图片数据
* @param e
*/
onImageUploadSuccess(e, key) {
this.item[key] = e.url;
this.save();
}
// /**
// * 储存图片数据
// * @param e
// */
// onImageUploadSuccess(e, key) {
//
// this.item[key] = e.url;
// this.save();
// }
/**
* 储存音频数据
* @param e
*/
onAudioUploadSuccess(e, key) {
this.item[key] = e.url;
this.save();
}
// /**
// * 储存音频数据
// * @param e
// */
// onAudioUploadSuccess(e, key) {
//
// this.item[key] = e.url;
// this.save();
// }
......@@ -80,7 +98,7 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
* 储存数据
*/
save() {
(<any> window).courseware.setData(this.item, null, this.saveKey);
(window as any).courseware.setData(this.item, null, this.saveKey);
this.refresh();
}
......@@ -93,5 +111,163 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
}, 1);
}
updateVocabulary() {
this.save();
}
onVocabularyAudioUploadSuccess(e, key) {
this.item.contentObj[key] = e.url;
this.updateVocabulary();
}
onAudioUploadSuccessSelected(e, i) {
this.selectedArr[i].audio = e.url;
this.item.contentObj.selectedArr = this.selectedArr;
this.updateVocabulary();
}
onAudioUploadSuccessOptions(e, i) {
this.options[i].audio = e.url;
this.updateVocabulary();
}
onImageUploadSuccess(e, num) {
this.item.contentObj.wordnum[num].pic_id = e.url;
this.updateVocabulary();
}
keyup(event, value, num) {
const word = _.get(this.item, `contentObj.wordnum[${num}]`);
console.log('event:', event);
if (event.keyCode === 13) {
this.updateVocabulary();
} else {
for (let i = 0; i < this.inputs.length; i++) {
if (event.path[0] === this.inputs[i]) {
if (value !== '' && event.keyCode <= 90 && event.keyCode >= 65) {
if (i === this.inputs.length - 1) {
} else {
if (this.inputs[i].value.length >= this.inputs[i].maxLength) {
this.inputs[i + 1].focus();
}
}
} else {
if (event.key === 'Backspace') {
if (i === 0) {
} else {
if (this.bol !== 1) {
this.bol++;
} else {
word.words[i].selected = false;
this.bol = 0;
this.inputs[i - 1].focus();
}
}
}
}
}
}
}
}
select(i, num) {
const word = _.get(this.item, `contentObj.wordnum[${num}].words[${i}]`);
if (word.value !== '') {
word.selected = !word.selected;
if (!word.selected) {
this.deleteSelectOne(i);
} else {
this.addSelectOne(word.value, i);
}
// this.initSelectedArr();
this.item.contentObj.selectedArr = this.selectedArr;
this.updateVocabulary();
}
}
deleteSelectOne(targetIndex) {
for (let i = 0; i < this.selectedArr.length; i++) {
if (this.selectedArr[i].index === targetIndex) {
this.selectedArr.splice(i, 1);
break;
}
}
}
addSelectOne(value, targetIndex) {
const data = {value, audio: '', index: targetIndex};
this.selectedArr.push(data);
this.selectedArr.sort((a, b) => {
return a.index - b.index;
});
}
initSelectedArr() {
this.selectedArr = [];
if (!this.item.contentObj.wordnum) {
return this.selectedArr;
}
const words = this.item.contentObj.wordnum[0].words;
for (let i = 0; i < words.length; i++) {
if (words[i].selected) {
this.selectedArr.push( {value: words[i].value, audio: '', index: i} );
}
}
this.item.contentObj.selectedArr = this.selectedArr;
return this.selectedArr;
}
AddWord() {
this.words = [];
for (let i = 0; i < 15; i++) {
this.words.push({
value: '',
selected: false
});
}
this.item.contentObj.wordnum.push({
words: this.words,
spelling_audio: '',
pic_id: ''
});
}
DeletWord(num) {
this.item.contentObj.wordnum.splice(num, 1);
this.updateVocabulary();
}
setWrongOptions(e, i) {
this.item.contentObj.options = this.options;
this.updateVocabulary();
}
onHandleOptionItemImage(e) {
this.item.contentObj.pic_res_id = e.url;
this.updateVocabulary();
}
inputSave(e) {
}
}
......@@ -7,7 +7,7 @@ interface AirWindow extends Window {
}
declare let window: AirWindow;
class Sprite {
export class Sprite {
x = 0;
y = 0;
color = '';
......
export function tAngle(target, base) {
const radians = Math.atan2(base.y - target.y, target.x - base.x);
return radians * 180 / Math.PI; // degrees
}
export function circleCollide(c1, c2) {
const dx = Math.abs(c1.x - c2.x);
const dy = Math.abs(c1.y - c2.y);
const dist = Math.sqrt(dx * dx + dy * dy);
return dist < c1.radius + c2.radius;
}
export function shuffle(arr){
if (!arr) {
return [];
}
const temp = [...arr];
const result = [];
let random;
while(temp.length > 0){
random = Math.floor(Math.random() * temp.length);
result.push(temp[random]);
temp.splice(random, 1)
}
return result;
}
// export default {
// tAngle,
// circleCollide,
// shuffle
// }
.game-container {
width: 100%;
height: 100%;
background: #ffffff;
background-image: url("../../assets/diamond/bg.jpg");
//background: #00C0FF;
background-repeat: no-repeat;
background-size: cover;
}
#canvas {
////background: #222222;
//width: 800px;
//height: 600px;
}
@font-face
{
font-family: 'BRLNSDB';
src: url("../../assets/font/BRLNSDB.TTF") ;
font-family: 'RoundedBold';
src: url("../../assets/font/Arial Rounded Bold.otf") format("opentype");
}
This diff is collapsed.
const res = [
// ['bg', "assets/play/bg.jpg"],
['btn_left', "assets/play/btn_left.png"],
['btn_right', "assets/play/btn_right.png"],
// ['text_bg', "assets/play/text_bg.png"],
['bg', "assets/diamond/bg.jpg"],
['paper', "assets/diamond/paper.png"],
['slate', "assets/diamond/slate.png"],
['question', "assets/diamond/question.png"],
['d-red', "assets/diamond/red.png"],
['d-yellow', "assets/diamond/yellow.png"],
['d-purple', "assets/diamond/purple.png"],
['end', "assets/diamond/end.png"],
['light', "assets/diamond/light.png"],
['question_light', "assets/diamond/question_light.png"],
];
const resAudio = [
['click', "assets/play/music/click.mp3"],
];
export {res, resAudio};
export default res;
@mixin hide-overflow-text {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
@mixin k-no-select {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
@mixin k-img-bg {
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
/* You can add global styles to this file, and also import other style files */
/* You can add global styles to this file, and also import other style files */
/* You can add global styles to this file, and also import other style files */
html, body {
width: 100%;
height: 100%;
font-size: 16px;
}
body {
background-color: #f0f2f5 !important;
}
* {
outline: none;
}
@font-face {
font-family: ChalkboardSE-Regular;
src: url('/assets/font/ChalkboardSE-Regular.woff') format('WOFF');
}
.k-16-9 {
position: relative;
width: 100%;
height: fit-content;
&:before {
content: "";
display: block;
position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%;
}
}
.k-full-fill {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.k-flex-center {
display: flex;
align-items: center;
justify-content: center;
}
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