Commit 7ed15fa4 authored by liujiangnan's avatar liujiangnan

feat: 迁移完成

parent 8a51c964
...@@ -30,7 +30,10 @@ ...@@ -30,7 +30,10 @@
], ],
"styles": [ "styles": [
"./node_modules/ng-zorro-antd/ng-zorro-antd.min.css", "./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": [] "scripts": []
}, },
...@@ -128,5 +131,8 @@ ...@@ -128,5 +131,8 @@
} }
} }
}, },
"defaultProject": "ng-template-generator" "defaultProject": "ng-template-generator",
} "cli": {
"analytics": "0d24335e-393e-4bb2-af07-a8a8ae7c4634"
}
}
\ No newline at end of file
...@@ -24,6 +24,7 @@ import {AudioRecorderComponent} from './common/audio-recorder/audio-recorder.com ...@@ -24,6 +24,7 @@ import {AudioRecorderComponent} from './common/audio-recorder/audio-recorder.com
import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontawesome'; import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontawesome';
import { fas } from '@fortawesome/free-solid-svg-icons'; import { fas } from '@fortawesome/free-solid-svg-icons';
import { far } from '@fortawesome/free-regular-svg-icons'; import { far } from '@fortawesome/free-regular-svg-icons';
import { BrLineBreakerPipe } from './pipes/br-line-breaker.pipe';
registerLocaleData(zh); registerLocaleData(zh);
...@@ -36,6 +37,7 @@ registerLocaleData(zh); ...@@ -36,6 +37,7 @@ registerLocaleData(zh);
AudioRecorderComponent, AudioRecorderComponent,
UploadImageWithPreviewComponent, UploadImageWithPreviewComponent,
BackgroundImagePipe, BackgroundImagePipe,
BrLineBreakerPipe,
ResourcePipe, ResourcePipe,
TimePipe, TimePipe,
UploadVideoComponent, UploadVideoComponent,
......
@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="1" tabindex="0"
[(ngModel)]="word.words[i].value"
(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>
<app-upload-image-with-preview <nz-divider></nz-divider>
[picUrl]="item.pic_url"
(imageUploaded)="onImageUploadSuccess($event, 'pic_url')"
></app-upload-image-with-preview>
<app-audio-recorder <div class="p-media-box d-flex">
[audioUrl]="item.audio_url" <div>
(audioUploaded)="onAudioUploadSuccess($event, 'audio_url')" <app-upload-image-with-preview [picUrl]="word.pic_id"
></app-audio-recorder> (imageUploaded)="onImageUploadSuccess($event, num)"
<app-custom-hot-zone></app-custom-hot-zone> ></app-upload-image-with-preview>
<app-upload-video></app-upload-video> </div>
<app-lesson-title-config></app-lesson-title-config> <nz-divider nzType="vertical"></nz-divider>
</div> <div>
<app-audio-recorder
[audioUrl]="word.spelling_audio"
(audioUploaded)="onVocabularyAudioUploadSuccess($event,num)"
></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>
\ 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: 2.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: 2.5rem;
height: 2.5rem;
border-radius: 20%;
vertical-align: bottom;
}
}
.p-box {
padding: 2rem;
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;
}
import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, ApplicationRef, ChangeDetectorRef} from '@angular/core'; import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, ApplicationRef, ChangeDetectorRef} from '@angular/core';
import * as _ from 'lodash';
@Component({ @Component({
selector: 'app-form', selector: 'app-form',
templateUrl: './form.component.html', templateUrl: './form.component.html',
styleUrls: ['./form.component.css'] styleUrls: ['./form.component.scss']
}) })
export class FormComponent implements OnInit, OnChanges, OnDestroy { export class FormComponent implements OnInit, OnChanges, OnDestroy {
// 储存数据用 // 储存数据用
saveKey = "test_0011"; saveKey = 'spelling';
// 储存对象 // 储存对象
item; item;
originContent;
defaultBoxes = new Array(15);
words = [];
bol: number;
inputs: any;
wordnum = [];
constructor(private appRef: ApplicationRef,private changeDetectorRef: ChangeDetectorRef) {
constructor(private appRef: ApplicationRef,
private changeDetectorRef: ChangeDetectorRef) {
this.bol = 0;
this.inputs = document.getElementsByName('Input');
} }
ngOnInit() { ngOnInit() {
this.item = {}; this.item = {
contentObj: {
}
};
// 获取存储的数据 // 获取存储的数据
(<any> window).courseware.getData((data) => { (window as any).courseware.getData((data) => {
if (data) { if (data) {
this.item = data; this.item = data;
} }
...@@ -50,32 +61,85 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -50,32 +61,85 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
init() { init() {
if (!this.item.contentObj.wordnum) {
this.item.contentObj.wordnum = [];
this.AddWord();
}
}
updateVocabulary() {
this.save();
} }
onVocabularyAudioUploadSuccess(e, num) {
this.item.contentObj.wordnum[num].spelling_audio = e.url;
this.updateVocabulary();
}
/** onImageUploadSuccess(e, num) {
* 储存图片数据 this.item.contentObj.wordnum[num].pic_id = e.url;
* @param e this.updateVocabulary();
*/
onImageUploadSuccess(e, key) {
this.item[key] = e.url;
this.save();
} }
/** keyup(event, value, num) {
* 储存音频数据 const word = _.get(this.item, `contentObj.wordnum[${num}]`);
* @param e if (event.keyCode === 13) {
*/ this.updateVocabulary();
onAudioUploadSuccess(e, key) { } 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 {
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();
}
}
}
}
}
}
}
}
this.item[key] = e.url; select(i, num) {
this.save(); const word = _.get(this.item, `contentObj.wordnum[${num}].words[${i}]`);
if (word.value !== '') {
word.selected = !word.selected;
this.updateVocabulary();
}
} }
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();
}
/** /**
* 储存数据 * 储存数据
*/ */
......
import {Pipe, PipeTransform} from '@angular/core'; import {Pipe, PipeTransform} from '@angular/core';
// import {ElectronUtil} from '../util/ElectronUtil';
declare const APP_PATH;
// const isInElectron = localStorage.getItem('electron');
@Pipe({ @Pipe({
name: 'backgroundImage' name: 'backgroundImage'
}) })
export class BackgroundImagePipe implements PipeTransform { export class BackgroundImagePipe implements PipeTransform {
transform(value: any, coursewareSid?: string) { transform(value: any) {
// const ret = value ? `url(${value})` : ''; return `url(${value})`;
const ret = value ? `url(${value})` : '';
return ret;
// let ret = value > 0 ? `url(/api/media-resource/${value}/file)` : '';
// if (isInElectron && ElectronUtil.hasCached(coursewareSid, value)) {
// ret = `url(file://${APP_PATH}/courseware_cache/${coursewareSid}/${value})`;
// }
// return ret;
} }
} }
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'brLineBreaker'
})
export class BrLineBreakerPipe implements PipeTransform {
transform(value: any, args?: any): any {
return value ? value.replace(/\n/g, '<br />') : '';
}
}
...@@ -2,25 +2,17 @@ import {Pipe, PipeTransform} from '@angular/core'; ...@@ -2,25 +2,17 @@ import {Pipe, PipeTransform} from '@angular/core';
// import {ElectronUtil} from '../util/ElectronUtil'; // import {ElectronUtil} from '../util/ElectronUtil';
declare const APP_PATH; declare const APP_PATH;
// const isInElectron = localStorage.getItem('electron'); const isInElectron = localStorage.getItem('electron');
@Pipe({ @Pipe({
name: 'resource' name: 'resource'
}) })
export class ResourcePipe implements PipeTransform { export class ResourcePipe implements PipeTransform {
transform(pic_url: any, coursewareSid?: string): string { transform(value: any, coursewareSid?: string): string {
// return pic_url; return value ? `/api/media-resource/${value}/file` : '';
if (pic_url && typeof pic_url === 'object') { // if (isInElectron && ElectronUtil.hasCached(coursewareSid, value)) {
return pic_url; // ret = `file://${APP_PATH}/courseware_cache/${coursewareSid}/${value}`;
}
// console.log('resource', pic_url)
return `${pic_url}?t=${Math.random()}`;
// let ret = value ? `/api/resource/${value}/file` : '';
// let ret = res_id ? `/resource/audio/${res_id}` : '';
// if (isInElectron && ElectronUtil.hasCached(coursewareSid, res_id)) {
// ret = `file://${APP_PATH}/courseware_cache/${coursewareSid}/${res_id}`;
// } // }
// return ret; // return ret;
} }
......
.game-container {
width: 100%;
height: 100%;
background: #ffffff;
background-size: cover;
}
#canvas {
}
@font-face
{
font-family: 'BRLNSDB';
src: url("../../assets/font/BRLNSDB.TTF") ;
}
<div class="game-container" #wrap> <div class="content">
<canvas id="canvas" #canvas></canvas> <div class="monkey-move">
<div class="tree">
<div>
<div class="trunk"></div>
</div>
<div class="leaves" #leavesNode>
<div class="leaf" *ngFor="let le of otherwordnum" >
<img [class]="le.rigof ? 'on':'off'" src="../../assets/spelling/leaves.png" alt="">
</div>
</div>
<div class="mo" #monkey>
<div class="monkey"><img src="../../assets/spelling/monkey.png" alt=""></div>
</div>
</div>
<div class="house">
<img src="../../assets/spelling/house.png" alt="">
</div>
</div>
<div class="spelling" *ngIf="words.length !== 0">
<div class="word">
<div *ngFor="let ss of wordnum;let b = index">
<div *ngFor="let it of words; let i = index"
[class]="b!==num? 'disappear':''">
<div *ngIf="it.selected"
[class]="!it.text ? 'blank' : (it.text === it.value ? 'blank proper' : 'blank mistake')"
(click)="onHandleChoose(i)">
<p>{{it.text}}</p>
</div>
<div *ngIf="!it.selected">
<p>{{it.value}}</p>
</div>
</div>
</div>
</div>
</div>
<div class="img-key" *ngIf="words.length !== 0">
<div class="img-audio k-16-9">
<div class="k-full-fill">
<img (click)="playSpellingAudio()" [src]="wordnum[num].pic_id" alt=""
(dragstart)="false;$event.preventDefault();">
</div>
</div>
<div class="word">
<div *ngFor="let item of letter;" (click)="add(item)">
<p>{{item}}</p>
</div>
</div>
</div>
</div> </div>
.content {
text-align: center;
width: 100%;
padding: 0 2em;
height: 100%;
justify-content: space-between;
background-color: #f3fdfe;
.spelling {
.word {
display: flex;
padding-bottom: 4vh;
font-family: "ChalkboardSE-Regular", "Helvetica Neue", Helvetica, Arial, sans-serif;
div {
display: inherit
}
p {
display: block;
line-height: 8.4vh;
border-radius: 15%;
margin: 0.2vh;
font-weight: 900;
font-size: 7vh;
//background-color: #85144b;
}
.blank {
border: 2px solid;
margin-right: 0.1vh;
margin-top: auto;
margin-bottom: auto;
//margin: 0 1vh;
display: inline-block;
width: 8.4vh;
height: 8.4vh;
border-radius: 20%;
vertical-align: top;
//background-color: #00C0FF;
}
.proper {
border: 2px solid #66cc33;
background-color: #c0f88b5c;
}
.mistake {
border: 2px solid #ff9999;
background-color: #ffd7d1;
}
.disappear {
display: none;
}
}
}
.img-key {
// padding-top: 5%;
display: flex;
.img-audio {
width: 100vh;
border: 1px solid #d6d6d6;
border-radius: 1rem;
background-color: #fefefe;
margin-right: 1rem;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.word {
display: flex;
flex-wrap: wrap;
div {
display: inline-block;
width: 6vh;
height: 6vh;
border-radius: 15%;
margin: 0.4vh;
vertical-align: top;
border: 2px solid;
:hover {
background-color: black;
color: white;
}
p {
display: block;
line-height: 5.5vh;
font-weight: 700;
font-size: 4vh;
}
}
}
}
.monkey-move {
padding-top: 10%;
display: flex;
.tree {
margin-left: 15%;
width: 85%;
position: relative;
.trunk {
width: 140%;
height: 1rem;
background-color: #ccffcc;
margin-left: -20%;
}
.monkey {
z-index: 2;
img {
width: 15vh;
height: 15vh;
margin-top: -1.9rem;
}
}
.mo {
margin-left: -15%;
transition: all 2s;
position: absolute;
}
.leaf {
margin-top: -4%;
// float: left;
width: 100%;
height: 100%;
border-radius: 100%;
margin-top: -0.5rem;
z-index: 1;
}
.leaves {
display: flex;
margin-top: -5%;
}
.on {
width: 6vh;
height: 6vh;
opacity: 1;
}
.off {
width: 6vh;
height: 6vh;
opacity: 0;
transition: all 2s;
}
}
}
.house {
// margin-right: -10%;
margin-top: -5%;
width: 50%;
height: 50%;
img {
width: 50%;
height: 100%;
}
}
}
This diff is collapsed.
@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;
}
@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;
}
...@@ -3,6 +3,8 @@ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; ...@@ -3,6 +3,8 @@ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module'; import { AppModule } from './app/app.module';
import { environment } from './environments/environment'; import { environment } from './environments/environment';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
if (environment.production) { if (environment.production) {
enableProdMode(); enableProdMode();
......
/* 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 */
@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;
}
This diff is collapsed.
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