Commit 3c618f37 authored by Tt's avatar Tt

表单完成

parent f2bf7b06
export const defaultData = {
"pic_url": "http://staging-teach.cdn.ireadabc.com/ed94332a503c31e0908bd4c6923a2665.png",
"pic_url_2": "http://staging-teach.cdn.ireadabc.com/5fb60317ade0195d35ad8034d5370a7f.png",
"text": "This is a test label.",
"audio_url": "http://staging-teach.cdn.ireadabc.com/f47f1d7b5c160fe1c59500d180346240.mp3"
}
\ No newline at end of file
export const defaultData = { "questions": [{ "parts": [{ "id": "166668702213640281", "answer": "freedow", "options": [{ "blocks": [{ "type": "img", "txt": "", "line": "", "img": "", "tag": "", "image": "http://staging-teach.cdn.ireadabc.com/19ac75d2de5455d268eaef8184bf805b.png" }] }, { "blocks": [{ "type": "line", "txt": "", "line": 5, "img": "", "tag": "" }, { "type": "txt", "txt": "", "line": "", "img": "", "tag": "", "text": "do you go to the park?" }] }, { "blocks": [{ "type": "txt", "txt": "", "line": "", "img": "", "tag": "", "text": "On saturdays freedow" }] }] }, { "id": "1666687612725869271", "answer": "fish", "options": [{ "blocks": [{ "type": "img", "txt": "", "line": "", "img": "", "tag": "", "image": "http://staging-teach.cdn.ireadabc.com/3f0f2572da257eedbec51f8d05e2a7d8.png" }] }] }, { "id": "1666687632465177361", "answer": "want", "options": [{ "blocks": [{ "type": "txt", "txt": "", "line": "", "img": "", "tag": "", "text": "Dave" }, { "type": "line", "txt": "", "line": 5, "img": "", "tag": "" }, { "type": "txt", "txt": "", "line": "", "img": "", "tag": "", "text": "want" }] }] }, { "id": "1666687646496548891", "answer": "red", "options": [{ "blocks": [{ "type": "txt", "txt": "", "line": "", "img": "", "tag": "", "text": "The fish color is " }] }, { "blocks": [{ "type": "line", "txt": "", "line": 5, "img": "", "tag": "" }, { "type": "txt", "txt": "", "line": "", "img": "", "tag": "", "text": "answer red." }] }] }] }], "title": "单词填空", "imgAni": { "ske": { "url": "http://staging-teach.cdn.ireadabc.com/4ec3da85d888ad3c5c57e10fca728499.json", "name": "鱼1_ske.json" }, "tex": { "url": "http://staging-teach.cdn.ireadabc.com/2c52380a3f3cdd3f5d38870bee2c9ffd.json", "name": "鱼1_tex.json" }, "png": { "url": "http://staging-teach.cdn.ireadabc.com/3ca112e3bb312d5e9b7182bbb97c616d.png", "name": "鱼1_tex.png" } }, "startAudio": "http://staging-teach.cdn.ireadabc.com/e587cf79c91d1cc4339540bb04b2aad0_l.mp3", "blockStruct": [{ "pId": "166668702213640281", "point": { "x": 3, "y": 6 }, "answer": "freedow" }, { "pId": "1666687612725869271", "point": { "x": 0, "y": 0 }, "answer": "fish" }, { "pId": "1666687632465177361", "point": { "x": 2, "y": 2 }, "answer": "want" }, { "pId": "1666687646496548891", "point": { "x": 3, "y": 4 }, "answer": "red" }, { "pId": "1666690945919654191", "point": { "x": 6, "y": 0 }, "answer": "" }, { "pId": "1666690947164283561", "point": { "x": 7, "y": 0 }, "answer": "" }, { "pId": "1666690948198775141", "point": { "x": 8, "y": 0 }, "answer": "" }, { "pId": "1666690949365322761", "point": { "x": 9, "y": 0 }, "answer": "" }, { "pId": "1666690950490929471", "point": { "x": 10, "y": 0 }, "answer": "" }, { "pId": "1666690951587641301", "point": { "x": 11, "y": 0 }, "answer": "" }, { "pId": "1666691011251823481", "point": { "x": 1, "y": 2 }, "answer": "" }, { "pId": "1666691012456843041", "point": { "x": 0, "y": 2 }, "answer": "" }, { "pId": "1666691014542512891", "point": { "x": 4, "y": 0 }, "answer": "" }, { "pId": "1666691015690655041", "point": { "x": 5, "y": 0 }, "answer": "" }, { "pId": "1666691022128352361", "point": { "x": 6, "y": 4 }, "answer": "" }, { "pId": "1666691023272815341", "point": { "x": 7, "y": 4 }, "answer": "" }, { "pId": "1666691024581239481", "point": { "x": 6, "y": 5 }, "answer": "" }, { "pId": "1666691025624146431", "point": { "x": 5, "y": 5 }, "answer": "" }, { "pId": "1666691027374885051", "point": { "x": 5, "y": 7 }, "answer": "" }, { "pId": "1666691030049556651", "point": { "x": 6, "y": 7 }, "answer": "" }, { "pId": "1666691031985800491", "point": { "x": 4, "y": 8 }, "answer": "" }, { "pId": "1666691033412905401", "point": { "x": 0, "y": 8 }, "answer": "" }], "blocks": [[{ "val": "f" }, { "val": "i" }, { "val": "s" }, { "val": "h" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }], [{ "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }], [{ "val": "" }, { "val": "" }, { "val": "w" }, { "val": "a" }, { "val": "n" }, { "val": "t" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }], [{ "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }], [{ "val": "" }, { "val": "" }, { "val": "" }, { "val": "r" }, { "val": "e" }, { "val": "d" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }], [{ "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }], [{ "val": "" }, { "val": "" }, { "val": "" }, { "val": "f" }, { "val": "r" }, { "val": "e" }, { "val": "e" }, { "val": "d" }, { "val": "o" }, { "val": "w" }, { "val": "" }, { "val": "" }], [{ "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }], [{ "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }, { "val": "" }]], "audioName": "" }
\ No newline at end of file
......@@ -65,10 +65,11 @@ export class ComponentBase {
* 储存音频数据
* @param e
*/
onAudioUploadSuccess(e, key, it = this.item,audioName) {
onAudioUploadSuccess(e, key, it = this.item, audioName) {
let url = e.url;
it[key] = url;
it[audioName] = e.name || "";
it[audioName] = e.audioName || "";
console.log(JSON.stringify(e));
this.save();
}
......
......@@ -78,7 +78,10 @@
<div class="border-dashed" style="margin: 20px;width: 1000px;">
<span style="font-size: 20px;">标题文字: </span>
<input type="text" nz-input [(ngModel)]="item.title" (blur)="save()">
<span style="font-size: 20px;">提示动画: </span>
<app-upload-dragon-bone style="width: 100%" (save)="onDragonBoneSave($event,item)" [skeJsonData]="item.imgAni.ske"
[texJsonData]="item.imgAni.tex" [texPngData]="item.imgAni.png">
</app-upload-dragon-bone>
<span style="font-size: 20px;">开始音频: </span>
<div style="display:flex ;">
<div>
......@@ -89,89 +92,117 @@
<span>{{ item.audioName}}</span>
</div>
</div>
<div *ngIf="item.tipSwitch == 1">
<span style="font-size: 20px;">提示动画: </span>
<app-upload-dragon-bone style="width: 100%" (save)="onDragonBoneSave($event,item)"
[skeJsonData]="item.imgAni.ske" [texJsonData]="item.imgAni.tex" [texPngData]="item.imgAni.png">
</app-upload-dragon-bone>
<div>
</div>
</div>
</div>
</div>
<!-- 题目区 -->
<div style="margin: 20px;width: 1000px;">
<div style=" margin: 20px;width: 1000px;">
<div *ngFor="let question of item.questions; let i = index">
<div style="display: flex;margin-top: 20px;">
<div class="border-solid" style="min-width: 1000px;">
<div class="word-type-title">
题目{{i+1}}
</div>
<div class="option-text">
<div class="word-input-title">
<span style="color:red;margin-left:-15px">* </span>
<span>题目文字: </span>
</div>
<input type="text" class="input-place-red" nz-input [(ngModel)]="question.text" placeholder="必填,根据文本内容去判断对错"
(blur)="save()">
</div>
<div class="option-text">
<div class="word-input-title">
<span style="color:red;margin-left:-15px">* </span>
<span>关键字: </span>
<div *ngFor="let part of question.parts; let p = index">
<div style="display: flex;">
<div class="word-type-title">
题{{p+1}}
</div>
<button style="margin-left:10px;margin-top:-5px" class="btn-red" nz-button nzType="default" nzDanger
(click)="removePart(i,p)">删除题</button>
</div>
<input type="text" class="input-place-red" nz-input [(ngModel)]="question.word" placeholder="必填,根据文本内容去判断对错"
(blur)="save()">
</div>
<div class="option-audio">
<div class="word-input-title">
题目音频:
</div>
<div style="display: flex">
<div>
<app-audio-recorder [audioUrl]="question.audio"
(audioUploaded)="onAudioUploadSuccess($event, 'audio',question,'audioName')"></app-audio-recorder>
</div>
<div style="margin: 5px">
<span>
{{ question.audioName}}
</span>
<input type="text" class="input-place-red" style="width: 580px;margin-top: 20px;" nz-input
[(ngModel)]="part.answer" placeholder="输入答案" (blur)="save()">
<div *ngFor="let option of part.options; let j = index">
<div style="margin-top: 20px;" class="border-dashed">
<div style="display: flex;">
<div class="word-type-title">
条: {{j+1}}
</div>
<button style="margin-left:10px;margin-top:-5px" class="btn-red" nz-button nzType="default" nzDanger
(click)="removeOption(i,p,j)">删除条</button>
</div>
<div style="display: flex;width:900px;margin-top: 10px;">
<div style="display: flex;flex-wrap: wrap;">
<div *ngFor="let block of option.blocks; let k = index" style="display: flex;">
<div *ngIf="block.type == 'txt'">
<input type="text" class="input-place-red" style="width: 80px;" nz-input
[(ngModel)]="block.text" placeholder="输入文字" (blur)="save()">
</div>
<div *ngIf="block.type == 'tag'">
<input type="text" class="input-place-red" style="width: 80px;" nz-input [(ngModel)]="block.tag"
placeholder="输入标签" (blur)="save()">
</div>
<div *ngIf="block.type=='img'" style="display: flex;">
<div style="width:60px">
<app-upload-image-with-preview [picUrl]="block.image" [TIP]="''"
(imageUploaded)="onImageUploadSuccess($event,'image',block)">
</app-upload-image-with-preview>
</div>
</div>
<div *ngIf="block.type=='line'" style="display: flex;">
<input type="number" placeholder="线长" class="input-place-red" style="width: 80px;" nz-input
[(ngModel)]="block.line" (blur)="save()">
<!-- <input type="text" placeholder="输入答案" class="input-place-red" style="width: 80px;" nz-input
[(ngModel)]="block.text" (blur)="save()"> -->
</div>
</div>
<div style="display: block;">
<div *ngIf="option.blocks.length >0"
style="margin-top: 5px;margin-left: 5px;width: 20px;height:20px;border-radius: 20px;border: 1px solid #f00;color: #f00;text-align: center;line-height: 15px;cursor: pointer;"
(click)="removeBlock(i,p,j)">
-
</div>
</div>
</div>
</div>
<div style="display: flex;">
<div>
<button style="margin: 10px 10px 10px 0" class="btn-blue" nz-button nzType="default" nzDanger
(click)="addBlock(i,p,j,'txt')">增加文字</button>
<button style="margin: 10px 10px 10px 0" class="btn-blue" nz-button nzType="default" nzDanger
(click)="addBlock(i,p,j,'line')">增加填空</button>
<button style="margin: 10px 10px 10px 0" class="btn-blue" nz-button nzType="default" nzDanger
(click)="addBlock(i,p,j,'img')">增加图片</button>
<button style="margin: 10px 10px 10px 0" class="btn-blue" nz-button nzType="default" nzDanger
(click)="addBlock(i,p,j,'tag')">增加标签</button>
</div>
</div>
<div style="margin-left: 15px;">
</div>
</div>
</div>
</div>
<!-- <div>
<span style="font-size: 20px;">标题图片: </span>
<div style="width:300px">
<app-upload-image-with-preview [picUrl]="question.image"
(imageUploaded)="onImageUploadSuccess($event,'image',question)"></app-upload-image-with-preview>
</div>
</div> -->
<div class="option-time">
<div class="word-input-title">
<span>录音时间: </span>
<div>
<button class="btn-blue" style="margin-top: 10px;" nz-button nzType="default" nzDanger
(click)="addOption(i,p)">增加条</button>
</div>
<input type="number" placeholder="录音超过时间将自动提交成绩" nz-input [(ngModel)]="question.time" (blur)="save()">
<nz-divider></nz-divider>
</div>
</div>
<div style="margin:0 20px">
<button class="btn-red" nz-button nzType="default" nzDanger (click)="removeQuestion(i)">删除题目</button>
<button *ngIf="item.questions.length < 4" class="btn-blue" style="margin-top: 10px;" nz-button
nzType="default" nzDanger (click)="copyQuestion(i)">复制题目</button>
<button class="btn-blue" style="margin-top: 10px;" nz-button nzType="default" nzDanger
(click)="addPart(i)">增加题</button>
</div>
</div>
</div>
<div style="margin-top: 20px;">
<button *ngIf="item.questions.length < 4" class="btn-blue" style="width: 1000px; height: 50px;" nz-button
nzType="default" nzDanger (click)="addQuestion()">+增加题目</button>
</div>
<!-- 块区 -->
<div class="border-dashed" style=" margin: 20px;width: 1000px;">
<span style="font-size: 20px;">配置题目方块: </span>
<div *ngFor="let line of item.blocks; let y = index" style="display: flex;">
<div *ngFor="let block of line; let x = index">
<div style="border: 1px solid #000;width:52px;height:52px;">
<button nz-button nz-dropdown [nzDropdownMenu]="menu" [nzPlacement]="'bottomLeft'"
style="border: none;width:50px;height:50px;font-size:20px">{{ block.val }}</button>
<nz-dropdown-menu #menu="nzDropdownMenu">
<ul nz-menu>
<li *ngIf="!!block.val" nz-menu-item (click)="onSelectBlockClear($event,x,y,block)">清除</li>
<li *ngIf="!block.val" nz-menu-item (click)="onSelectBlockHide($event,x,y,block)">关闭块</li>
<div *ngFor="let part of item.questions[0].parts; let p = index">
<li *ngIf="!block.val" nz-menu-item (click)="onSelectBlock($event,x,y,part,block)">{{part.answer}}</li>
</div>
</ul>
</nz-dropdown-menu>
</div>
</div>
</div>
</div>
<nz-modal [(nzVisible)]="isVisible" [nzTitle]="null" [nzContent]="modalContent" [nzFooter]="modalFooter"
(nzOnCancel)="handleCancel()">
......
......@@ -11,27 +11,39 @@ import { ComponentBase } from './ComponentBase';
export class FormComponent extends ComponentBase implements OnInit, OnChanges, OnDestroy {
// 储存数据用
saveKey = "ngt10_tydh";
saveKey = "ngt14_czm";
// 储存对象
item: any = {
questions: [{
parts: [],
}],
title: '单词填空',
imgAni: {
ske: {},
tex: {},
png: {}
},
tipSwitch: 1,//提示功能开关
startAudio: "",
audioName: "",
title: "听音对话",
//1 ~ 6 个
questions: [],
blockStruct: [
// {
// pId: null,
// point: { x: 0, y: 0 }
// }
],
blocks: [
[{ val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }],
[{ val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }],
[{ val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }],
[{ val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }],
[{ val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }],
[{ val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }],
[{ val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }],
[{ val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }],
[{ val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }, { val: '' }]]
};
// item: any = {
// title: '幸运大转盘',
// questionText: "亲爱的小玩家,游戏马上就要开始啦!请动动手指转动转盘,当转盘停止,注意观察指针指向的魔法图片,并大声说出魔法咒语,魔法咒语正确,你就可以获得一张魔法卡牌。 游戏结束后,根据获得的魔法卡牌数量,你将获得相应的能量石奖励!开始挑战吧!",
// questionTextAudio: "http://staging-teach.cdn.ireadabc.com/18ebee93b3eabcd55649a01366431af7.mp3",
// questions: [],
// };
init() {
this.autoBlocks();
}
isVisible = false;
deleteTitle = "是否删除题目";
......@@ -49,19 +61,18 @@ export class FormComponent extends ComponentBase implements OnInit, OnChanges, O
this.handleCancel();
}
deleteBgAudio() {
this.item.bgAudio = "";
this.item.audioBgName = "";
this.save();
}
//题---question 块--part 条---option 节点---block
addQuestion() {
if (this.item.questions.length == 6) return;
this.item.questions.push({
type: 'img',
audio: '',
text: '',
image: '',
time: null,
audioName: "",
parts: [],
});
this.save();
}
removeQuestion(idx) {
this.openDelete("确定删除题目?", () => {
this.item.questions.splice(idx, 1);
......@@ -74,25 +85,144 @@ export class FormComponent extends ComponentBase implements OnInit, OnChanges, O
this.save();
}
addOption(idx) {
if (this.item.questions[idx].options.length == 4) return;
this.item.questions[idx].options.push({
text: '',
audio: '',
image: '',
word: '',
time: '',
addPart(idx) {
let count = 0;
function randId() {
count++;
let time = new Date().getTime();
let rand = Math.floor(Math.random() * 100000);
return `${time}${rand}${count}`
}
this.item.questions[idx].parts.push({
id: randId(),
answer: '',
options: [],
});
this.save();
}
removePart(idx, pdx) {
this.openDelete("确定删除块?", () => {
this.item.questions[idx].parts.splice(pdx, 1);
this.save();
})
}
copyPart(idx, pdx) {
let data = this.item.questions[idx].parts[pdx]
this.item.questions[idx].parts.push(JSON.parse(JSON.stringify(data)));
this.save();
}
removeOption(idx, n) {
addOption(idx, pdx) {
this.item.questions[idx].parts[pdx].options.push({
blocks: []
})
this.save();
}
removeOption(idx, pdx, n) {
this.openDelete("确定删除选项?", () => {
this.item.questions[idx].options.splice(n, 1);
this.item.questions[idx].parts[pdx].options.splice(n, 1);
this.save();
})
}
addBlock(idx, pdx, odx, type) {
this.item.questions[idx].parts[pdx].options[odx].blocks.push({
type: type,
txt: '',//文本内容 line中的正确答案
line: '',
img: '',
tag: ''
})
}
removeBlock(idx, pdx, odx) {
this.openDelete("确定删除块?", () => {
this.item.questions[idx].parts[pdx].options[odx].blocks.pop();
this.save();
})
}
autoBlocks() {
let self = this;
function searchWord(x, y) {
let word = '';
self.item.blockStruct.forEach(struct => {
if (struct.point.y != y) return;//不是一行
if (struct.point.x <= x && struct.point.x + struct.answer.length - 1 >= x) {
word = struct.answer[x - struct.point.x];
}
})
return word;
}
let blocks = [];
for (let y = 0; y < 9; y++) {
const line = [];
for (let x = 0; x < 12; x++) {
let val = searchWord(x, y);
line.push({ val: val })
}
blocks.push(line);
}
this.item.blocks = blocks;
}
onSelectBlock(e, x, y, val, block) {
if (this.item.blockStruct.some(bs => bs.pId == val.id)) {
alert("此题已设置");
return
}
if (x + val.answer.length > 12) {
alert("长度不足,应向前移动" + Math.abs((12 - x - val.answer.length)) + "");
return;
}
this.item.blockStruct.push({
pId: val.id,
point: { x, y },
answer: val.answer
})
this.autoBlocks();
this.save();
}
onSelectBlockHide(e, x, y, block) {
if (block.val) return;
let count = 0;
function randId() {
count++;
let time = new Date().getTime();
let rand = Math.floor(Math.random() * 100000);
return `${time}${rand}${count}`
}
this.item.blockStruct.push({
pId: randId(),
point: { x, y },
answer: ''
})
this.autoBlocks();
this.save();
}
onSelectBlockClear(e, x, y, block) {
if (!block.val) return;
const self = this;
function searchBlock(x, y) {
let rblock = null;
self.item.blockStruct.forEach(struct => {
if (struct.point.y != y) return;//不是一行
if (struct.point.x <= x && struct.point.x + struct.answer.length - 1 >= x) {
rblock = struct
}
})
return rblock;
}
let val = searchBlock(x, y)
if (!val) return;
this.item.blockStruct = this.item.blockStruct.filter(bs => bs.pId != val.pId)
this.autoBlocks();
this.save();
}
ngChange() {
this.save();
}
onDragonBoneSave(e, item) {
console.log(e);
this.save();
......
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