Commit f6eba663 authored by liujiaxin's avatar liujiaxin

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="model-content">
<div style="position: absolute; left: 200px; top: 100px; width: 800px;">
<input type="text" nz-input [(ngModel)]="item.text" (blur)="save()">
<nz-form-item>
<nz-form-label [nzSpan]="4">Vocabulary</nz-form-label>
<nz-form-control [nzSpan]="8">
<app-upload-image-with-preview
[picUrl]="item.pic_url"
(imageUploaded)="onImageUploadSuccess($event, 'pic_url')"
[picUrl]="item.contentObj.pic_id"
(imageUploaded)="onHandleQuestionImage($event)"
></app-upload-image-with-preview>
<app-audio-recorder
[audioUrl]="item.audio_url"
(audioUploaded)="onAudioUploadSuccess($event, 'audio_url')"
></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>
</div>
\ No newline at end of file
<input type="text" nz-input placeholder="Please input title"
[(ngModel)]="item.contentObj.title" (blur)="updateQuestionTitle()">
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="4">Option</nz-form-label>
<nz-form-control [nzSpan]="20">
<button
nz-button
nzType="default"
(click)="addNewOptionItem()"
[disabled]="options.length >= 4"
>
<i class="anticon anticon-plus-circle-o"></i>
Add
</button>
<div class="opt-container">
<div
class="opt-wrap"
*ngFor="let item of options; let i = index"
>
<div class="tool-bar">
<label nz-checkbox [ngModel]="item.right" (click)="setRightAnswer(i)" class="right-answer">
Right
</label>
<div class="button-group">
<button
nz-button
nzType="primary"
nzSize="small"
nzShape="circle"
style="margin-right: 1rem;"
(click)="onHandleSwitchContent(item)"
>
<i class="anticon anticon-retweet"></i>
</button>
<nz-dropdown [nzTrigger]="'click'">
<button
nz-button
nzType="primary"
nzSize="small"
nzShape="circle"
nz-dropdown
>
<i class="anticon anticon-setting"></i>
</button>
<ul nz-menu>
<li nz-menu-item (click)="onMovePage(i, -1)" [class.disabled]="i < 1">
<i class="anticon anticon-arrow-up"></i>
Move Up
</li>
<li nz-menu-item (click)="onMovePage(i, 1)" [class.disabled]="i + 1 >= options.length">
<i class="anticon anticon-arrow-down"></i>
Move Down
</li>
<li nz-menu-item (click)="onDeleteCoursewareItem(i)">
<i class="anticon anticon-delete"></i>
Delete
</li>
</ul>
</nz-dropdown>
</div>
</div>
<div class="content-editor">
<input *ngIf="item.type === OPTION_TYPE.TEXT" type="text" nz-input [(ngModel)]="item.text"
placeholder="Please input title" (blur)="updateOptionItemText(i)">
<app-upload-image-with-preview
*ngIf="item.type === OPTION_TYPE.PIC"
[picUrl]="item.pic_id"
(imageUploaded)="onHandleOptionItemImage($event, i)"
></app-upload-image-with-preview>
<app-audio-recorder *ngIf="item.type === OPTION_TYPE.AUDIO"
[audioUrl]="item.audio_id"
(audioUploaded)="onHandleOptionItemAudio($event, i)">
</app-audio-recorder>
</div>
</div>
</div>
</nz-form-control>
</nz-form-item>
.opt-container {
width: 100%;
display: flex;
flex-wrap: wrap;
.opt-wrap {
margin: 0 1rem 1rem 0;
display: flex;
flex-direction: column;
height: 14rem;
width: 20rem;
border: 2px dashed #ddd;
border-radius: 0.5rem;
padding: 0.8rem;
.tool-bar {
display: flex;
justify-content: space-between;
align-items: center;
}
.content-editor {
height: 100%;
}
}
}
.disabled {
pointer-events: none;
opacity: 0.6;
}
import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, ApplicationRef, ChangeDetectorRef} from '@angular/core';
import * as _ from 'lodash';
import { NzModalService } from 'ng-zorro-antd';
@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_question';
// 储存对象
item;
originContent;
options = [];
OPTION_TYPE = {TEXT: 1, PIC: 2, AUDIO: 3};
constructor(private appRef: ApplicationRef,private changeDetectorRef: ChangeDetectorRef) {
constructor(private appRef: ApplicationRef,
private modalService: NzModalService,
private changeDetectorRef: ChangeDetectorRef) {
}
ngOnInit() {
this.item = {};
this.item = {
contentObj: {}
};
// 获取存储的数据
(<any> window).courseware.getData((data) => {
(window as any).courseware.getData((data) => {
if (data) {
this.item = data;
this.originContent = {...this.item.contentObj};
this.options = _.get(this.item.contentObj, 'options', []);
// Ken 2019-04-14 17:41 把showPic, showText的逻辑换为type
_.forEach(this.options, o => {
if (_.isUndefined(o.type)) {
o.type = o.showPic ? this.OPTION_TYPE.PIC : this.OPTION_TYPE.TEXT;
}
});
}
this.init();
this.changeDetectorRef.markForCheck();
this.changeDetectorRef.detectChanges();
......@@ -54,25 +71,18 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
}
/**
* 储存图片数据
* @param e
*/
onImageUploadSuccess(e, key) {
this.item[key] = e.url;
this.save();
}
// onImageUploadSuccess(e, key) {
//
// this.item[key] = e.url;
// this.save();
// }
/**
* 储存音频数据
* @param e
*/
onAudioUploadSuccess(e, key) {
this.item[key] = e.url;
this.save();
}
// onAudioUploadSuccess(e, key) {
//
// this.item[key] = e.url;
// this.save();
// }
......@@ -80,7 +90,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 +103,86 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
}, 1);
}
onHandleQuestionImage(e) {
this.item.contentObj.pic_id = e.url;
this.save();
}
updateQuestionTitle() {
this.save();
}
onHandleOptionItemImage(e, index) {
this.options[index].pic_id = e.url;
this.item.contentObj.options = this.options;
this.save();
}
onHandleOptionItemAudio(e, index) {
this.options[index].audio_id = e.url;
this.item.contentObj.options = this.options;
this.save();
}
updateOptionItemText(index) {
this.item.contentObj.options = this.options;
this.save();
}
setRightAnswer(index) {
this.options[index].right = !this.options[index].right;
this.item.contentObj.options = this.options;
this.save();
}
addNewOptionItem() {
const content = {
text: '',
pic_id: null,
right: false,
type: this.OPTION_TYPE.TEXT,
};
this.options.push(content);
}
onHandleSwitchContent(item) {
switch (item.type) {
case this.OPTION_TYPE.TEXT:
item.type = this.OPTION_TYPE.PIC;
break;
case this.OPTION_TYPE.PIC:
item.type = this.OPTION_TYPE.AUDIO;
break;
case this.OPTION_TYPE.AUDIO:
item.type = this.OPTION_TYPE.TEXT;
break;
}
this.item.contentObj.options = this.options;
this.save();
}
onMovePage(index, direction) {
const temp = this.options[index + direction];
this.options[index + direction] = this.options[index];
this.options[index] = temp;
this.options = [...this.options];
this.item.contentObj.options = this.options;
this.save();
}
onDeleteCoursewareItem(index) {
this.modalService.confirm({
nzTitle: 'Are you sure delete this?',
nzOkText: 'Yes',
nzOkType: 'danger',
nzCancelText: 'No',
nzOnOk: () => {
this.options.splice(index, 1);
this.item.contentObj.options = this.options;
this.save();
},
});
}
}
.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>
<canvas id="canvas" #canvas></canvas>
<div class="question-player">
<div class="top-part">
<img
*ngIf="data.contentObj.pic_id"
[src]="data.contentObj.pic_id "
alt="cover"
(dragstart)="false;$event.preventDefault();"
(click)="onHandleZoomIn()"
[@zoom]="zoomIn ? 'in' : 'none'"
/>
<div class="title">{{data.contentObj.title}}</div>
</div>
<div class="opt-container">
<div
class="opt-wrap"
*ngFor="let item of options; let i = index"
[@tip-border]="item.state || 'none'"
(click)="handleAnimation(item)"
>
<span class="opt-circle" [@tip-circle]="item.state || 'none'">{{transCharCode(i)}}</span>
<div class="text" *ngIf="item.type === OPTION_TYPE.TEXT">{{item.text}}</div>
<div class="audio" style="text-align: center" *ngIf="item.type === OPTION_TYPE.AUDIO" (click)="playAudio(item, $event)">
<i class="anticon anticon-sound"></i>
</div>
<img *ngIf="item.type === OPTION_TYPE.PIC" [src]="item.pic_id" alt=""
(dragstart)="false;$event.preventDefault();"/>
</div>
</div>
<!--<img src="/assets/question/left.png" alt="ufo" class="left-ufo" (dragstart)="false;$event.preventDefault();">-->
<!--<img src="/assets/question/right.png" alt="ufo" class="right-ufo" (dragstart)="false;$event.preventDefault();">-->
</div>
.question-player {
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
width: 100%;
background-image: url("../../assets/common_bg.jpg");
background-size: cover;
background-repeat: no-repeat;
.top-part {
height: 35%;
min-width: 60%;
max-width: 90%;
display: flex;
justify-content: center;
align-items: center;
img {
//width: 40%;
height: 60%;
margin-right: 1.5rem;
object-fit: contain;
}
.title {
font-size: 2.5rem;
color: #ffb00f;
background-color: white;
padding: 0.5rem 1rem;
border-radius: 1rem;
}
}
.opt-container {
height: 55%;
width: 80%;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
.opt-wrap {
width: 30%;
height: 45%;
position: relative;
background-color: #ffffff;
margin: 1rem;
border-radius: 0.8rem;
display: flex;
justify-content: center;
align-items: center;
border: 0.3rem solid #ffffff;
.opt-circle {
width: 2.5rem;
height: 2.5rem;
background-color: #ffffff;
position: absolute;
border-radius: 50%;
left: -1rem;
top: -1rem;
text-align: center;
line-height: 2.5rem;
font-size: 24px;
font-weight: 500;
}
img {
width: 100%;
height: 100%;
object-fit: contain;
}
.text {
font-size: 28px;
font-weight: 500;
}
.audio {
color: white;
background-color: #00BCD4;
border-radius: 5px;
font-size: 5vh;
font-weight: 500;
width: 13vh;
cursor: pointer;
}
}
}
.left-ufo {
width: 10%;
object-fit: contain;
position: absolute;
left: 15vh;
bottom: 20vh;
}
.right-ufo {
width: 10%;
object-fit: contain;
position: absolute;
right: 15vh;
bottom: 20vh;
}
}
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;
}
/* 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 */
/* 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