Commit 37e3b3c8 authored by 李维's avatar 李维

dev commit

parent 3695f7ce
This diff is collapsed.
...@@ -3,9 +3,13 @@ ...@@ -3,9 +3,13 @@
"version": 1, "version": 1,
"newProjectRoot": "projects", "newProjectRoot": "projects",
"projects": { "projects": {
"ng-template-generator": { "ng-one": {
"projectType": "application", "projectType": "application",
"schematics": {}, "schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "", "root": "",
"sourceRoot": "src", "sourceRoot": "src",
"prefix": "app", "prefix": "app",
...@@ -13,26 +17,39 @@ ...@@ -13,26 +17,39 @@
"build": { "build": {
"builder": "@angular-devkit/build-angular:browser", "builder": "@angular-devkit/build-angular:browser",
"options": { "options": {
"outputPath": "dist/ng-template-generator", "outputPath": "dist",
"index": "src/index.html", "index": "src/index.html",
"main": "src/main.ts", "main": "src/main.ts",
"polyfills": "src/polyfills.ts", "polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json", "tsConfig": "tsconfig.app.json",
"aot": true, "aot": false,
"assets": [ "assets": [
"src/favicon.ico", "src/favicon.ico",
"src/assets", "src/assets",
{ "glob": "**/*", "input": "src/assets/libs/service-worker/", "output": "/" },
{ {
"glob": "**/*", "glob": "**/*",
"input": "./node_modules/@ant-design/icons-angular/src/inline-svg/", "input": "./node_modules/@ant-design/icons-angular/src/inline-svg/",
"output": "/assets/" "output": "/assets/"
},
{
"glob": "**/*",
"input": "./dist/game/",
"output": "/assets/cocos/"
} }
], ],
"styles": [ "styles": [
"src/styles.scss",
"./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"
], ],
"scripts": [] "scripts": [
"src/assets/libs/audio-recorder/lame.min.js",
"src/assets/libs/audio-recorder/worker.js",
"src/assets/libs/audio-recorder/recorder.js"
]
}, },
"configurations": { "configurations": {
"production": { "production": {
...@@ -47,39 +64,28 @@ ...@@ -47,39 +64,28 @@
"sourceMap": false, "sourceMap": false,
"extractCss": true, "extractCss": true,
"namedChunks": false, "namedChunks": false,
"aot": true,
"extractLicenses": true, "extractLicenses": true,
"vendorChunk": false, "vendorChunk": false,
"buildOptimizer": true, "buildOptimizer": true
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
} }
} }
}, },
"serve": { "serve": {
"builder": "@angular-devkit/build-angular:dev-server", "builder": "@angular-devkit/build-angular:dev-server",
"options": { "options": {
"browserTarget": "ng-template-generator:build" "browserTarget": "ng-one:build"
}, },
"configurations": { "configurations": {
"production": { "production": {
"browserTarget": "ng-template-generator:build:production" "browserTarget": "ng-one:build:production"
} }
} }
}, },
"extract-i18n": { "extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n", "builder": "@angular-devkit/build-angular:extract-i18n",
"options": { "options": {
"browserTarget": "ng-template-generator:build" "browserTarget": "ng-one:build"
} }
}, },
"test": { "test": {
...@@ -94,8 +100,7 @@ ...@@ -94,8 +100,7 @@
"src/assets" "src/assets"
], ],
"styles": [ "styles": [
"./node_modules/ng-zorro-antd/ng-zorro-antd.min.css", "src/styles.scss"
"src/styles.css"
], ],
"scripts": [] "scripts": []
} }
...@@ -117,16 +122,15 @@ ...@@ -117,16 +122,15 @@
"builder": "@angular-devkit/build-angular:protractor", "builder": "@angular-devkit/build-angular:protractor",
"options": { "options": {
"protractorConfig": "e2e/protractor.conf.js", "protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "ng-template-generator:serve" "devServerTarget": "ng-one:serve"
}, },
"configurations": { "configurations": {
"production": { "production": {
"devServerTarget": "ng-template-generator:serve:production" "devServerTarget": "ng-one:serve:production"
} }
} }
} }
} }
} }},
}, "defaultProject": "ng-one"
"defaultProject": "ng-template-generator"
} }
\ No newline at end of file
...@@ -66,7 +66,7 @@ const runSpawn = async function (){ ...@@ -66,7 +66,7 @@ const runSpawn = async function (){
ls.on('close', (code) => { ls.on('close', (code) => {
console.log(`child process exited with code ${code}`); console.log(`child process exited with code ${code}`);
//要压缩的目录 //要压缩的目录
let zippath = path.resolve(__dirname,"../dist", pkg.name); let zippath = path.resolve(__dirname,"../dist");
//压缩包的存放目录 //压缩包的存放目录
let date = new Date(); let date = new Date();
let zipname = pkg.name+"_"+date.Format("yyyyMMdd hh-mm-ss"); let zipname = pkg.name+"_"+date.Format("yyyyMMdd hh-mm-ss");
...@@ -112,3 +112,4 @@ exec(); ...@@ -112,3 +112,4 @@ exec();
\ No newline at end of file
This diff is collapsed.
...@@ -2,56 +2,77 @@ ...@@ -2,56 +2,77 @@
"name": "ng-template-generator", "name": "ng-template-generator",
"version": "0.0.1", "version": "0.0.1",
"scripts": { "scripts": {
"start": "ng serve", "start": "ng serve --host=0.0.0.0",
"build": "ng build --build--optimizer --aot --base-href /JGT/v3/", "build": "ng build --build--optimizer --aot --base-href /JGT/v3/",
"publish": "node ./bin/publish.js", "publish": "node ./bin/publish.js"
"ng": "ng",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "~9.0.2", "@angular/animations": "^7.2.10",
"@angular/common": "~9.0.2", "@angular/cdk": "^7.2.2",
"@angular/compiler": "~9.0.2", "@angular/common": "^7.2.10",
"@angular/core": "~9.0.2", "@angular/compiler": "^7.2.10",
"@angular/forms": "~9.0.2", "@angular/core": "^7.2.10",
"@angular/platform-browser": "~9.0.2", "@angular/flex-layout": "^7.0.0-beta.24",
"@angular/platform-browser-dynamic": "~9.0.2", "@angular/forms": "^7.2.10",
"@angular/router": "~9.0.2", "@angular/http": "^7.2.10",
"@fortawesome/angular-fontawesome": "^0.6.0", "@angular/material": "^7.2.2",
"@fortawesome/fontawesome-svg-core": "^1.2.27", "@angular/platform-browser": "^7.2.10",
"@fortawesome/free-regular-svg-icons": "^5.12.1", "@angular/platform-browser-dynamic": "^7.2.10",
"@fortawesome/free-solid-svg-icons": "^5.12.1", "@angular/platform-server": "^7.2.10",
"@tweenjs/tween.js": "^18.5.0", "@angular/router": "^7.2.10",
"ali-oss": "^6.5.1", "@tweenjs/tween.js": "^17.3.0",
"compressing": "^1.5.0", "ali-oss": "^6.0.0",
"ng-zorro-antd": "^8.5.2", "angular-bootstrap-colorpicker": "^3.0.32",
"rxjs": "~6.5.4", "angular-cropperjs": "^1.0.1",
"angular2-draggable": "^2.1.9",
"angular2-fontawesome": "^5.2.1",
"angularx-qrcode": "^1.5.3",
"animate.css": "^3.7.0",
"bootstrap": "^4.1.1",
"browser-image-compression": "^1.0.5",
"compressing": "^1.4.0",
"core-js": "^2.6.1",
"cropperjs": "1.4.1",
"css-element-queries": "^1.0.2",
"decimal.js": "^10.0.1",
"font-awesome": "^4.7.0",
"hammerjs": "^2.0.8",
"install": "^0.12.2",
"karma-cli": "^2.0.0",
"lodash": "^4.17.10",
"nedb": "^1.8.0",
"ng-lottie": "^0.3.1",
"ng-zorro-antd": "^7.2.0",
"ngx-color-picker": "^9.0.0",
"node-sass": "^4.14.0",
"npm": "^6.5.0",
"rxjs": "^6.3.3",
"rxjs-compat": "^6.3.3",
"rxjs-tslint": "^0.1.6",
"spark-md5": "^3.0.0", "spark-md5": "^3.0.0",
"tslib": "^1.10.0", "webpack": "^4.28.2",
"zone.js": "~0.10.2" "zone.js": "^0.8.26"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "~0.900.3", "@angular-devkit/build-angular": "^0.11.4",
"@angular/cli": "~9.0.3", "@angular/cli": "^7.2.10",
"@angular/compiler-cli": "~9.0.2", "@angular/compiler-cli": "^7.2.10",
"@angular/language-service": "~9.0.2", "@angular/language-service": "^7.2.10",
"@types/jasmine": "~3.5.0", "@types/jasmine": "^3.3.5",
"@types/jasminewd2": "~2.0.3", "@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1", "@types/node": "^10.12.18",
"codelyzer": "^5.1.2", "codelyzer": "^4.5.0",
"jasmine-core": "~3.5.0", "jasmine-core": "^3.3.0",
"jasmine-spec-reporter": "~4.2.1", "jasmine-spec-reporter": "^4.2.1",
"karma": "~4.3.0", "karma": "^3.1.4",
"karma-chrome-launcher": "~3.1.0", "karma-chrome-launcher": "^2.2.0",
"karma-coverage-istanbul-reporter": "~2.1.0", "karma-coverage-istanbul-reporter": "~2.0.0",
"karma-jasmine": "~2.0.1", "karma-jasmine": "^2.0.1",
"karma-jasmine-html-reporter": "^1.4.2", "karma-jasmine-html-reporter": "^1.4.0",
"protractor": "~5.4.3", "protractor": "^5.4.2",
"ts-node": "~8.3.0", "ts-node": "~5.0.1",
"tslint": "~5.18.0", "tslint": "^5.12.0",
"typescript": "~3.7.5" "typescript": "3.1.1"
} }
} }
import { ErrorHandler } from '@angular/core';
export class MyErrorHandler implements ErrorHandler {
handleError(error) {
console.log(error.stack);
(<any> window).courseware.sendErrorLog(error);
}
}
\ No newline at end of file
...@@ -5,12 +5,12 @@ import { Component , OnInit} from '@angular/core'; ...@@ -5,12 +5,12 @@ import { Component , OnInit} from '@angular/core';
templateUrl: './app.component.html', templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'] styleUrls: ['./app.component.scss']
}) })
export class AppComponent implements OnInit { export class AppComponent implements OnInit{
type = 'play'; type = 'play';
constructor() { constructor() {
const tp = this.getQueryString('type'); let tp = this.getQueryString("type");
if (tp) { if (tp){
this.type = tp; this.type = tp;
} }
} }
......
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, ErrorHandler } from '@angular/core';
import {MyErrorHandler} from './MyError';
import { AppComponent } from './app.component'; import { BrowserModule } from '@angular/platform-browser';
import { NgZorroAntdModule, NZ_I18N, zh_CN } from 'ng-zorro-antd'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule } from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { NgZorroAntdModule, NZ_I18N, zh_CN } from 'ng-zorro-antd';
import { NzButtonModule } from 'ng-zorro-antd/button';
import {Angular2FontawesomeModule} from 'angular2-fontawesome/angular2-fontawesome';
import { AppComponent } from './app.component';
import { FormComponent } from './form/form.component';
import { PlayComponent } from "./play/play.component";
// import { ColorPickerModule } from 'ngx-color-picker';
import { LessonTitleConfigComponent } from './common/lesson-title-config/lesson-title-config.component';
import { AudioRecorderComponent } from './common/audio-recorder/audio-recorder.component';
import { PlayerContentWrapperComponent } from './common/player-content-wrapper/player-content-wrapper.component';
/** 配置 angular i18n **/
import { registerLocaleData } from '@angular/common'; import { registerLocaleData } from '@angular/common';
import zh from '@angular/common/locales/zh'; import zh from '@angular/common/locales/zh';
import {FormComponent} from './form/form.component'; import {UploadImageWithPreviewComponent} from "./common/upload-image-with-preview/upload-image-with-preview.component";
import {PlayComponent} from './play/play.component'; import {BackgroundImagePipe} from "./pipes/background-image.pipe";
import {LessonTitleConfigComponent} from './common/lesson-title-config/lesson-title-config.component'; import {UploadVideoComponent} from "./common/upload-video/upload-video.component";
import {BackgroundImagePipe} from './pipes/background-image.pipe'; import {ResourcePipe} from "./pipes/resource.pipe";
import {UploadImageWithPreviewComponent} from './common/upload-image-with-preview/upload-image-with-preview.component'; import {TimePipe} from "./pipes/time.pipe";
import {PlayerContentWrapperComponent} from './common/player-content-wrapper/player-content-wrapper.component'; import {CustomHotZoneComponent} from "./common/custom-hot-zone/custom-hot-zone.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';
registerLocaleData(zh); registerLocaleData(zh);
@NgModule({ @NgModule({
...@@ -40,26 +41,22 @@ registerLocaleData(zh); ...@@ -40,26 +41,22 @@ registerLocaleData(zh);
TimePipe, TimePipe,
UploadVideoComponent, UploadVideoComponent,
CustomHotZoneComponent, CustomHotZoneComponent,
PlayerContentWrapperComponent PlayerContentWrapperComponent
], ],
imports: [ imports: [
BrowserModule,
NgZorroAntdModule,
FormsModule, FormsModule,
HttpClientModule, HttpClientModule,
BrowserAnimationsModule, BrowserAnimationsModule,
FontAwesomeModule BrowserModule,
Angular2FontawesomeModule,
NgZorroAntdModule,
//ColorPickerModule
], ],
providers: [ /** 配置 ng-zorro-antd 国际化(文案 及 日期) **/
{provide: ErrorHandler, useClass: MyErrorHandler}, providers : [
{ provide: NZ_I18N, useValue: zh_CN } { provide: NZ_I18N, useValue: zh_CN }
], ],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })
export class AppModule { export class AppModule { }
constructor(library: FaIconLibrary) {
library.addIconPacks(fas, far);
}
}
<div class="d-flex"> <div class="d-flex">
<div class="p-btn-record d-flex"> <div class="p-btn-record d-flex">
<div class="btn-clear" style="cursor: pointer" (click)="onBtnClearAudio()" *ngIf="withRmBtn && (audioUrl || audioBlob)"> <div
<fa-icon icon="times"></fa-icon> class="btn-clear"
(click)="onBtnClearAudio()"
*ngIf="withRmBtn && (audioUrl || audioBlob)"
>
<fa name="close"></fa>
</div> </div>
<div class="btn-record" *ngIf="type===Type.RECORD && !isUploading" <div
class="btn-record"
*ngIf="type === Type.RECORD && !isUploading"
[class.p-recording]="isRecording" [class.p-recording]="isRecording"
(click)="onBtnRecord()"> (click)="onBtnRecord()"
<fa-icon icon="microphone"></fa-icon> >
<i nz-icon nzType="audio" nzTheme="outline"></i>
Record Audio Record Audio
</div> </div>
<nz-upload <nz-upload
[nzAccept] = "'.mp3'" [nzAccept]="'.mp3'"
[nzShowUploadList]="false" [nzShowUploadList]="false"
[nzAction]="uploadUrl" [nzAction]="uploadUrl"
[nzData]="uploadData" [nzData]="uploadData"
(nzChange)="handleChange($event)"> (nzChange)="handleChange($event)"
>
<div class="btn-upload" [ngClass]="{'has-clear': withRmBtn && (audioUrl || audioBlob)}" *ngIf="type===Type.UPLOAD && !isUploading"> <div
<fa-icon icon="upload"></fa-icon> class="btn-upload ng-star-inserted"
[ngClass]="{ 'has-clear': withRmBtn && (audioUrl || audioBlob) }"
*ngIf="type === Type.UPLOAD && !isUploading"
>
<i nz-icon nzType="cloud-upload" nzTheme="outline"></i>
Upload Audio Upload Audio
</div> </div>
</nz-upload> </nz-upload>
<div class="p-upload-progress-bg" *ngIf="isUploading"> <div class="p-upload-progress-bg" *ngIf="isUploading">
<div class="i-bg" [style.width]="progress+'%'"></div> <div class="i-bg" [style.width]="progress + '%'"></div>
<div class="i-text"> <div class="i-text">
<fa-icon icon="cloud-upload-alt"></fa-icon> <i nz-icon nzType="loading" nzTheme="outline"></i>
Uploading... Uploading...
</div> </div>
</div> </div>
<div
*ngIf="audioUrl && needRemove; then truthyTemplate; else falsyTemplate"
></div>
<div *ngIf="audioUrl && needRemove; then truthyTemplate else falsyTemplate"></div> <ng-template #truthyTemplate>
<ng-template #truthyTemplate >
<div class="btn-delete" (click)="onBtnDeleteAudio()"> <div class="btn-delete" (click)="onBtnDeleteAudio()">
<fa-icon icon="close"></fa-icon> <i nz-icon nzType="close" nzTheme="outline"></i>
</div> </div>
</ng-template> </ng-template>
<ng-template #falsyTemplate> <ng-template #falsyTemplate>
<div class="btn-switch" (click)="onBtnSwitchType()"> <div class="btn-switch" (click)="onBtnSwitchType()">
<fa-icon icon="cog"></fa-icon> <i nz-icon nzType="setting" nzTheme="outline"></i>
</div> </div>
</ng-template> </ng-template>
</div> </div>
<div class="p-progress ml-2" (click)="onBtnPlay()" *ngIf="audioUrl || audioBlob"> <div
<nz-progress [nzPercent]="percent" [nzWidth]="30" [nzFormat]="progressText" class="p-progress ml-2"
nzType="circle"></nz-progress> (click)="onBtnPlay()"
<div class="p-btn-play" [style.left]="isPlaying?'8px':''"> *ngIf="audioUrl || audioBlob"
<fa-icon [icon]="playIcon"></fa-icon> >
<nz-progress
[nzPercent]="percent"
[nzWidth]="30"
[nzFormat]="progressText"
nzType="circle"
></nz-progress>
<div class="p-btn-play" [style.left]="isPlaying ? '8px' : ''">
<i nz-icon nzType="caret-right" nzTheme="outline"></i>
</div> </div>
</div> </div>
</div> </div>
.d-flex{
display: flex;
}
.p-btn-record { .p-btn-record {
font-size: 0.9rem; font-size: 0.9rem;
color: #555; color: #555;
...@@ -91,6 +88,7 @@ ...@@ -91,6 +88,7 @@
.p-progress { .p-progress {
margin-top: 2px; margin-top: 2px;
margin-left: 5px;
position: relative; position: relative;
line-height: 26px; line-height: 26px;
.p-btn-play { .p-btn-play {
...@@ -105,3 +103,6 @@ ...@@ -105,3 +103,6 @@
line-height: 33px; line-height: 33px;
} }
.d-flex{
display: flex;
}
\ No newline at end of file
...@@ -19,11 +19,10 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy { ...@@ -19,11 +19,10 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy {
isUploading = false; isUploading = false;
type = Type.UPLOAD; // record | upload type = Type.UPLOAD; // record | upload
Type = Type; Type = Type;
@Input()
withRmBtn = false; withRmBtn = false;
uploadUrl; uploadUrl = (<any>window).courseware.uploadUrl();
uploadData; uploadData = (<any>window).courseware.uploadData();
@Input() @Input()
needRemove = false; needRemove = false;
...@@ -33,7 +32,7 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy { ...@@ -33,7 +32,7 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy {
@Input() @Input()
set audioUrl(url) { set audioUrl(url) {
this._audioUrl = url; this._audioUrl = url
if (url) { if (url) {
this.audio.src = this._audioUrl; this.audio.src = this._audioUrl;
this.audio.load(); this.audio.load();
...@@ -55,13 +54,7 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy { ...@@ -55,13 +54,7 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy {
constructor( private nzMessageService: NzMessageService ) { constructor( 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;
};
} }
init() { init() {
...@@ -151,7 +144,6 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy { ...@@ -151,7 +144,6 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy {
onBtnSwitchType() { onBtnSwitchType() {
} }
onBtnClearAudio() { onBtnClearAudio() {
this.audioUrl = null;
this.audioRemoved.emit(); this.audioRemoved.emit();
} }
...@@ -194,7 +186,6 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy { ...@@ -194,7 +186,6 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy {
return true; return true;
} }
beforeUpload = (file: File) => { beforeUpload = (file: File) => {
this.audioUrl = null; this.audioUrl = null;
if (!this.checkSelectFile(file)) { if (!this.checkSelectFile(file)) {
return false; return false;
...@@ -205,7 +196,11 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy { ...@@ -205,7 +196,11 @@ export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy {
uploadSuccess = (url) => { uploadSuccess = (url) => {
this.nzMessageService.info('Upload Success'); this.nzMessageService.info('Upload Success');
this.isUploading = false; this.isUploading = false;
this.audioUrl = url; if(typeof url == "string"){
this.audioUrl = url
}else{
this.audioUrl = url.url
}
} }
uploadFailure = (err, file) => { uploadFailure = (err, file) => {
this.isUploading = false; this.isUploading = false;
......
...@@ -116,14 +116,12 @@ export class MySprite extends Sprite { ...@@ -116,14 +116,12 @@ export class MySprite extends Sprite {
load(url, anchorX = 0.5, anchorY = 0.5) { load(url, anchorX = 0.5, anchorY = 0.5) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const img = new Image(); const img = new Image();
img.onload = () => resolve(img); img.onload = () => resolve(img);
img.onerror = reject; img.onerror = reject;
img.src = url; img.src = url;
}).then(img => { }).then(img => {
this.init(img, anchorX, anchorY); this.init(img, anchorX, anchorY);
return img; return img;
}); });
...@@ -269,14 +267,12 @@ export class Item extends MySprite { ...@@ -269,14 +267,12 @@ export class Item extends MySprite {
const tween = new TWEEN.Tween(self); const tween = new TWEEN.Tween(self);
if (sequence.length > 0) { if (sequence.length > 0) {
// console.log('sequence.length: ', sequence.length);
const action = sequence.shift(); const action = sequence.shift();
tween.to(action['target'], action['time']); tween.to(action['target'], action['time']);
tween.onComplete( () => { tween.onComplete( () => {
runSequence(); runSequence();
}); });
tween.start(); tween.start();
self['shakeTween'] = tween; self['shakeTween'] = tween;
} }
} }
...@@ -341,9 +337,6 @@ export class ShapeRect extends MySprite { ...@@ -341,9 +337,6 @@ export class ShapeRect extends MySprite {
setSize(w, h) { setSize(w, h) {
this.width = w; this.width = w;
this.height = h; this.height = h;
console.log('w:', w);
console.log('h:', h);
} }
drawShape() { drawShape() {
...@@ -375,44 +368,34 @@ export class HotZoneItem extends MySprite { ...@@ -375,44 +368,34 @@ export class HotZoneItem extends MySprite {
this.width = w; this.width = w;
this.height = h; this.height = h;
const rect = new ShapeRect(this.ctx); const rect = new ShapeRect(this.ctx);
rect.x = -w / 2; rect.x = -w / 2;
rect.y = -h / 2; rect.y = -h / 2;
rect.setSize(w, h); rect.setSize(w, h);
rect.fillColor = '#ffffff'; rect.fillColor = '#FFFFFF';
rect.alpha = 0.2; rect.alpha = 0.2;
this.addChild(rect); this.addChild(rect);
} }
showLabel(text = null) { showLabel(text = null) {
if (!this.label) { if (!this.label) {
this.label = new Label(this.ctx); this.label = new Label(this.ctx);
this.label.anchorY = 0; this.label.anchorY = 0;
this.label.fontSize = '40px'; this.label.fontSize = '40px';
this.label.textAlign = 'center'; this.label.textAlign = 'center';
this.addChild(this.label); this.addChild(this.label);
// this.label.scaleX = 1 / this.scaleX;
// this.label.scaleY = 1 / this.scaleY;
this.refreshLabelScale(); this.refreshLabelScale();
} }
if (text) { if (text) {
this.label.text = text; this.label.text = text;
} else if (this.text) { } else if (this.text) {
this.label.text = this.text; this.label.text = this.text;
} }
this.label.visible = true; this.label.visible = true;
} }
hideLabel() { hideLabel() {
if (!this.label) { return; } if (!this.label) { return; }
this.label.visible = false; this.label.visible = false;
} }
...@@ -446,18 +429,14 @@ export class HotZoneItem extends MySprite { ...@@ -446,18 +429,14 @@ export class HotZoneItem extends MySprite {
this.arrowRight.load('assets/common/arrow_right.png', 1, 0.5); this.arrowRight.load('assets/common/arrow_right.png', 1, 0.5);
this.arrowRight.setScaleXY(0.06); this.arrowRight.setScaleXY(0.06);
} }
this.showLabel(); this.showLabel();
} }
hideLineDash() { hideLineDash() {
this.lineDashFlag = false; this.lineDashFlag = false;
if (this.arrow) { if (this.arrow) {
this.arrow.visible = false; this.arrow.visible = false;
} }
this.hideLabel(); this.hideLabel();
} }
...@@ -465,14 +444,11 @@ export class HotZoneItem extends MySprite { ...@@ -465,14 +444,11 @@ export class HotZoneItem extends MySprite {
drawArrow() { drawArrow() {
if (!this.arrow) { return; } if (!this.arrow) { return; }
const rect = this.getBoundingBox(); const rect = this.getBoundingBox();
this.arrow.x = rect.x + rect.width; this.arrow.x = rect.x + rect.width;
this.arrow.y = rect.y; this.arrow.y = rect.y;
this.arrow.update(); this.arrow.update();
this.arrowTop.x = rect.x + rect.width / 2; this.arrowTop.x = rect.x + rect.width / 2;
this.arrowTop.y = rect.y; this.arrowTop.y = rect.y;
this.arrowTop.update(); this.arrowTop.update();
...@@ -483,48 +459,201 @@ export class HotZoneItem extends MySprite { ...@@ -483,48 +459,201 @@ export class HotZoneItem extends MySprite {
} }
drawFrame() { drawFrame() {
this.ctx.save(); this.ctx.save();
const rect = this.getBoundingBox(); const rect = this.getBoundingBox();
const w = rect.width; const w = rect.width;
const h = rect.height; const h = rect.height;
const x = rect.x + w / 2; const x = rect.x + w / 2;
const y = rect.y + h / 2; const y = rect.y + h / 2;
this.ctx.setLineDash([5, 5]); this.ctx.setLineDash([5, 5]);
this.ctx.lineWidth = 2; this.ctx.lineWidth = 2;
this.ctx.strokeStyle = '#1bfff7'; this.ctx.strokeStyle = '#1bfff7';
// this.ctx.fillStyle = '#ffffff';
this.ctx.beginPath(); this.ctx.beginPath();
this.ctx.moveTo( x - w / 2, y - h / 2); this.ctx.moveTo( x - w / 2, y - h / 2);
this.ctx.lineTo(x + w / 2, y - h / 2); this.ctx.lineTo(x + w / 2, y - h / 2);
this.ctx.lineTo(x + w / 2, y + h / 2); this.ctx.lineTo(x + w / 2, y + h / 2);
this.ctx.lineTo(x - w / 2, y + h / 2); this.ctx.lineTo(x - w / 2, y + h / 2);
this.ctx.lineTo(x - w / 2, y - h / 2); this.ctx.lineTo(x - w / 2, y - h / 2);
// this.ctx.fill();
this.ctx.stroke(); this.ctx.stroke();
this.ctx.restore();
}
draw() {
super.draw();
if (this.lineDashFlag) {
this.drawFrame();
this.drawArrow();
}
}
}
export class HotZoneImageItem extends MySprite {
lineDashFlag = false;
arrow: MySprite;
label: Label;
image: MySprite;
image_url: String;
labelBox: MySprite;
audio_url: String;
card_audio_url: String
scale
text;
arrowTop;
arrowRight;
init(image_url = null, callback?, handleSave?){
this.showImage(image_url, (img)=>{
callback && callback(img.width, img.height)
this.setSize(img.width*this.image.scaleX, img.height*this.image.scaleY)
handleSave && handleSave()
this.lineDashFlag = true;
this.showLineDash()
this.showLabel();
this.drawArrow()
})
}
setSize(w, h) {
this.width = w;
this.height = h;
}
showLabel(text = null) {
if (!this.label) {
this.labelBox = new MySprite(this.ctx);
this.labelBox.load('assets/default/bg_50_50.png').then(()=>{
this.labelBox.x = this.labelBox.width/2;
this.labelBox.y = this.labelBox.height/2;
});
this.label = new Label(this.ctx);
// this.label.anchorY = 0;
this.label.fontSize = '30px';
this.label.textAlign = 'center';
this.label.color = "#FFFFFF"
this.labelBox.addChild(this.label);
this.addChild(this.labelBox);
this.refreshLabelScale();
}
if (text) {
this.label.text = text;
} else if (this.text) {
this.label.text = this.text;
}
this.label.visible = true;
}
hideLabel() {
if (!this.label) { return; }
this.label.visible = false;
}
showImage(image_url = null, callback) {
this.loadImage(image_url).then((img)=>{
if(this.image){
this.removeChild(this.image)
}
this.image = new MySprite(this.ctx);
this.image.init(img)
this.image.x = this.image.width/2
this.image.y = this.image.height/2
this.image.alpha = 0.7;
this.image_url = image_url;
this.addChild(this.image,-1);
callback && callback(this.image)
})
}
loadImage(image_url = null){
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = image_url;
})
}
hideImage() {
if (!this.image) { return; }
this.image.visible = false;
}
refreshLabelScale() {
this.labelBox.scaleX = 75 / (this.labelBox.width*this.image.scaleX)
}
showLineDash() {
if (this.arrow) {
this.arrow.visible = true;
} else {
this.arrow = new MySprite(this.ctx);
this.arrow.load('assets/common/arrow.png', 1, 0);
this.arrow.setScaleXY(0.06);
this.arrowTop = new MySprite(this.ctx);
this.arrowTop.load('assets/common/arrow_top.png', 0.5, 0);
this.arrowTop.setScaleXY(0.06);
this.arrowRight = new MySprite(this.ctx);
this.arrowRight.load('assets/common/arrow_right.png', 1, 0.5);
this.arrowRight.setScaleXY(0.06);
}
}
hideLineDash() {
this.lineDashFlag = false;
if (this.arrow) {
this.arrow.visible = false;
}
this.hideLabel();
}
drawArrow() {
if (!this.arrow) { return; }
const rect = this.getBoundingBox();
this.arrow.x = rect.x + rect.width;
this.arrow.y = rect.y;
this.arrow.update();
this.arrowTop.x = rect.x + rect.width / 2;
this.arrowTop.y = rect.y;
this.arrowTop.update();
this.arrowRight.x = rect.x + rect.width;
this.arrowRight.y = rect.y + rect.height / 2;
this.arrowRight.update();
}
drawFrame() {
this.ctx.save();
const rect = this.getBoundingBox();
const w = rect.width;
const h = rect.height;
const x = rect.x + w / 2;
const y = rect.y + h / 2;
this.ctx.setLineDash([5, 5]);
this.ctx.lineWidth = 2;
this.ctx.strokeStyle = '#1bfff7';
this.ctx.beginPath();
this.ctx.moveTo( x - w / 2, y - h / 2);
this.ctx.lineTo(x + w / 2, y - h / 2);
this.ctx.lineTo(x + w / 2, y + h / 2);
this.ctx.lineTo(x - w / 2, y + h / 2);
this.ctx.lineTo(x - w / 2, y - h / 2);
this.ctx.stroke();
this.ctx.restore(); this.ctx.restore();
} }
draw() { draw() {
super.draw(); super.draw();
if (this.lineDashFlag) { if (this.lineDashFlag) {
this.drawFrame(); this.drawFrame();
this.drawArrow(); this.drawArrow();
...@@ -569,14 +698,12 @@ export class EditorItem extends MySprite { ...@@ -569,14 +698,12 @@ export class EditorItem extends MySprite {
showLineDash() { showLineDash() {
this.lineDashFlag = true; this.lineDashFlag = true;
if (this.arrow) { if (this.arrow) {
this.arrow.visible = true; this.arrow.visible = true;
} else { } else {
this.arrow = new MySprite(this.ctx); this.arrow = new MySprite(this.ctx);
this.arrow.load('assets/common/arrow.png', 1, 0); this.arrow.load('assets/common/arrow.png', 1, 0);
this.arrow.setScaleXY(0.06); this.arrow.setScaleXY(0.06);
} }
this.showLabel(); this.showLabel();
...@@ -672,8 +799,6 @@ export class Label extends MySprite { ...@@ -672,8 +799,6 @@ export class Label extends MySprite {
drawText() { drawText() {
// console.log('in drawText', this.text);
if (!this.text) { return; } if (!this.text) { return; }
this.ctx.font = `${this.fontSize} ${this.fontName}`; this.ctx.font = `${this.fontSize} ${this.fontName}`;
...@@ -688,7 +813,6 @@ export class Label extends MySprite { ...@@ -688,7 +813,6 @@ export class Label extends MySprite {
this.ctx.fillStyle = '#000000'; this.ctx.fillStyle = '#000000';
this.ctx.fillText(this.text, 0, 0); this.ctx.fillText(this.text, 0, 0);
} }
...@@ -713,23 +837,8 @@ export function getPosByAngle(angle, len) { ...@@ -713,23 +837,8 @@ export function getPosByAngle(angle, len) {
export function getAngleByPos(px, py, mx, my) { export function getAngleByPos(px, py, mx, my) {
// const _x = p2x - p1x;
// const _y = p2y - p1y;
// const tan = _y / _x;
//
// const radina = Math.atan(tan); // 用反三角函数求弧度
// const angle = Math.floor(180 / (Math.PI / radina)); //
//
// console.log('r: ' , angle);
// return angle;
//
const x = Math.abs(px - mx); const x = Math.abs(px - mx);
const y = Math.abs(py - my); const y = Math.abs(py - my);
// const x = Math.abs(mx - px);
// const y = Math.abs(my - py);
const z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); const z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
const cos = y / z; const cos = y / z;
const radina = Math.acos(cos); // 用反三角函数求弧度 const radina = Math.acos(cos); // 用反三角函数求弧度
...@@ -759,7 +868,5 @@ export function getAngleByPos(px, py, mx, my) { ...@@ -759,7 +868,5 @@ export function getAngleByPos(px, py, mx, my) {
angle = 360 - angle; angle = 360 - angle;
} }
// console.log('angle: ', angle);
return angle; return angle;
} }
<div class="p-image-children-editor"> <div class="p-image-children-editor">
<div style="float: left; width: 25%;border-right: 2px solid #ddd; border-bottom: 2px solid #ddd;">
<h5 style="margin-left: 2.5%;"> preview: </h5> <h5 style="margin-left: 2.5%;">预览:</h5>
<div id="canvas-container" style="margin:5px;">
<div class="preview-box" #wrap> <div class="preview-box" #wrap style="margin-bottom: 20px">
<canvas id="canvas" #canvas></canvas> <canvas id="canvas" #canvas></canvas>
</div> </div>
</div>
<div style="text-align: center">
<button nz-button nzType="primary" [nzSize]="'small'" nzShape="round" (click)="saveClick()" [disabled]="!hotZoneChanged" >
<i nz-icon type="save"></i>
Save
</button>
</div>
<h5 style="border-top: 2px solid #ddd;">背景图:</h5>
<div nz-row nzType="flex" nzAlign="middle"> <div style="width: 200px;margin: auto;">
<div nz-col nzSpan="5" nzOffset="1">
<h5> add background: </h5>
<div class="bg-box"> <div class="bg-box">
<app-upload-image-with-preview <app-upload-image-with-preview
[picUrl]="bgItem?.url" [picUrl]="bgItem.url"
(imageUploaded)="onBackgroundUploadSuccess($event)"> (imageUploaded)="onBackgroundUploadSuccess($event)"
>
</app-upload-image-with-preview> </app-upload-image-with-preview>
</div> </div>
</div> </div>
<div nz-col nzSpan="5" nzOffset="1" class="img-box"
*ngFor="let it of hotZoneArr; let i = index" >
<div style=" height: 40px;">
<h5> item-{{i+1}}
<i style="margin-left: 20px; margin-top: 2px; float: right; cursor:pointer" (click)="deleteItem($event, i)"
nz-icon [nzTheme]="'twotone'" [nzType]="'close-circle'" [nzTwotoneColor]="'#ff0000'"></i>
</h5>
</div> </div>
<div style="float: left; width: 75%">
<!--<div class="img-box-upload">--> <div nzAlign="middle">
<!--<app-upload-image-with-preview--> <div class="img-box clearfix" *ngFor="let it of hotZoneArr; let i = index" style="border-bottom: 1px solid #DDD; padding-bottom: 10px;" >
<!--[picUrl]="it.pic_url"--> <div style="float: left; height: 115px; position: relative; width: 250px; ">
<!--(imageUploaded)="onImgUploadSuccessByImg($event, it)">--> <h3> 第-{{ i + 1 }}-题 </h3>
<!--</app-upload-image-with-preview>--> <div style="position: absolute; bottom: 0;">
<!--</div>--> <h5> 题目音频 </h5>
<app-audio-recorder [audioUrl]="it.audio_url ? it.audio_url : null" (audioUploaded)="onAudioUploadSuccess($event, it, false)" ></app-audio-recorder>
</div>
<!--<app-audio-recorder--> </div>
<!--[audioUrl]="it.audio_url ? it.audio_url : null "--> <div style="float: left; height: 115px; position: relative; width: 250px; ">
<!--(audioUploaded)="onAudioUploadSuccessByImg($event, it)"--> <div style="position: absolute; bottom: 0;">
<!--&gt;</app-audio-recorder>--> <h5> 卡片音频 </h5>
<app-audio-recorder [audioUrl]="it.card_audio_url ? it.card_audio_url : null" (audioUploaded)="onAudioUploadSuccess($event, it, true)" ></app-audio-recorder>
</div>
</div>
<div style="float: left;">
<div style="width:200px">
<app-upload-image-with-preview [picUrl]="it.image_url" (imageUploaded)="onImgUploadSuccessByImg($event, it)" ></app-upload-image-with-preview>
</div>
</div> </div>
<div style="float: left; display: flex; flex-direction: column; padding-left: 10px;">
<button style="flex:1; margin-bottom: 5px;" nz-button nzType="dashed" (click)="handleMoveItemUp($event, i)" [disabled]="i==0">
<i nz-icon nzType="up" nzTheme="outline"></i>
上移
</button>
<button style="flex:1; margin-bottom: 5px;" nz-button nzType="dashed" (click)="handleMoveItemDown($event, i)" [disabled]="i==hotZoneArr.length-1">
<i nz-icon nzType="down" nzTheme="outline"></i>
下移
</button>
<button style="flex:1; margin-bottom: 5px;" nz-button nzType="danger" (click)="deleteItem($event, i)">
<i nz-icon nzType="delete" nzTheme="outline"></i>
删除
</button>
</div>
</div>
<div nz-col nzSpan="5" nzOffset="1"> <div nz-col nzSpan="5" nzOffset="1">
<div class="bg-box"> <div class="bg-box">
<button nz-button nzType="dashed" (click)="addBtnClick()" <button
class="add-btn"> nz-button
nzType="dashed"
(click)="addBtnClick()"
class="add-btn"
>
<i nz-icon nzType="plus-circle" nzTheme="outline"></i> <i nz-icon nzType="plus-circle" nzTheme="outline"></i>
<!--Add Image--> <!--Add Image-->
Add hot zone Add hot zone
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</div>
<nz-divider></nz-divider> <nz-divider></nz-divider>
<div class="save-box"> <div class="save-box">
<button class="save-btn" nz-button nzType="primary" [nzSize]="'large'" nzShape="round"
(click)="saveClick()">
<i nz-icon nzType="save"></i>
Save
</button>
</div> </div>
</div> </div>
.p-image-children-editor { .p-image-children-editor {
width: 100%; width: 100%;
height: 100%; height: 100%;
border-radius: 0.5rem; border-radius: 0.5rem;
min-width: 1200px;
border: 2px solid #ddd; border: 2px solid #ddd;
.preview-box { .preview-box {
margin: auto; margin: auto;
width: 95%; width: 100%;
height: 35vw; // height: 35vw;
border: 2px dashed #ddd; border: 2px dashed #ddd;
border-radius: 0.5rem; border-radius: 0.5rem;
background-color: #fafafa; background-color: #fafafa;
text-align: center; text-align: center;
color: #aaa; color: #aaa;
.preview-img { .preview-img {
height: 100%; height: 100%;
width: auto; width: auto;
} }
} }
.bg-box {
.bg-box{
//width: 100%;
margin-bottom: 1rem; margin-bottom: 1rem;
}
.clearfix:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
} }
.img-box { .img-box {
margin-bottom: 1rem; margin: 1rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
} }
.img-box-upload{ .img-box-upload {
width: 80%; width: 120px;
height: 80px;
} }
.add-btn { .add-btn {
margin-top: 1rem; margin-top: 1rem;
width: 200px; width: 200px;
height: 90px; height: 90px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
} }
.save-box { .save-box {
width: 100%; width: 100%;
...@@ -85,21 +72,6 @@ h5 { ...@@ -85,21 +72,6 @@ h5 {
margin-top: 1rem; margin-top: 1rem;
} }
//@import '../../../style/common_mixin'; //@import '../../../style/common_mixin';
// //
//.p-image-uploader { //.p-image-uploader {
......
<div class="title-config"> <div class="title-config">
<div class="title-wrap"> <div class="title-wrap">
...@@ -8,10 +7,9 @@ ...@@ -8,10 +7,9 @@
<nz-select class="ml-1" style="width: 120px;" [(ngModel)]="__fontFamily" <nz-select class="ml-1" style="width: 120px;" [(ngModel)]="__fontFamily"
(ngModelChange)="onChangeFontFamily($event)" (ngModelChange)="onChangeFontFamily($event)"
nzPlaceHolder="Font Family" nzPlaceHolder="Font Family"
[nzDropdownMatchSelectWidth]="false"> [nzDropdownMatchSelectWidth]="false"
<nz-option [nzValue]="font" nzCustomContent [nzLabel]="font" *ngFor="let font of fontFamilyList"> >
<span [ngStyle]="{'font-family': font}" >{{font}}</span> <nz-option [nzValue]="font" [nzLabel]="font" *ngFor="let font of fontFamilyList"></nz-option>
</nz-option>
</nz-select> </nz-select>
<nz-select class="ml-1" style="width: 110px;" [(ngModel)]="__fontSize" <nz-select class="ml-1" style="width: 110px;" [(ngModel)]="__fontSize"
(ngModelChange)="onChangeFontSize()" (ngModelChange)="onChangeFontSize()"
...@@ -21,33 +19,28 @@ ...@@ -21,33 +19,28 @@
<div class="p-divider"></div> <div class="p-divider"></div>
<div class="i-tool-font-btn d-flex mr-2"> <div class="i-tool-font-btn d-flex mr-2">
<div class="position-relative fa-icon" (click)="onChangeBold()"> <div class="position-relative fa-icon" (click)="onChangeBold()">
<!-- <div class="fa fa-bold"></div>--> <div class="fa fa-bold"></div>
<fa-icon icon="bold"></fa-icon>
</div> </div>
</div> </div>
<div class="i-tool-font-btn d-flex mr-2"> <div class="i-tool-font-btn d-flex mr-2">
<div class="position-relative fa-icon" (click)="onChangeItalic()"> <div class="position-relative fa-icon" (click)="onChangeItalic()">
<!-- <div class="fa fa-italic"></div>--> <div class="fa fa-italic"></div>
<fa-icon icon="italic"></fa-icon>
</div> </div>
</div> </div>
<div class="i-tool-font-btn d-flex mr-2"> <div class="i-tool-font-btn d-flex mr-2">
<div class="position-relative fa-icon" (click)="onChangeUnderline()"> <div class="position-relative fa-icon" (click)="onChangeUnderline()">
<!-- <div class="fa fa-underline"></div>--> <div class="fa fa-underline"></div>
<fa-icon icon="underline"></fa-icon>
</div> </div>
</div> </div>
<div class="i-tool-font-btn d-flex"> <div class="i-tool-font-btn d-flex">
<div class="position-relative fa-icon" (click)="onChangeStrikethrough()"> <div class="position-relative fa-icon" (click)="onChangeStrikethrough()">
<!-- <div class="fa fa-strikethrough"></div>--> <div class="fa fa-strikethrough"></div>
<fa-icon icon="strikethrough"></fa-icon>
</div> </div>
</div> </div>
<div class="p-divider"></div> <div class="p-divider"></div>
<div class="i-tool-font-color d-flex"> <div class="i-tool-font-color d-flex">
<div class="position-relative i-left flex-fill" (click)="onChangeFontColor($event)"> <div class="position-relative i-left flex-fill" (click)="onChangeFontColor($event)">
<!-- <div class="fa fa-font"></div>--> <div class="fa fa-font"></div>
<fa-icon icon="palette"></fa-icon>
<div class="i-color" [style.background-color]="__fontColor"></div> <div class="i-color" [style.background-color]="__fontColor"></div>
</div> </div>
<div class="i-dropdown-menu" nzPlacement="bottom" <div class="i-dropdown-menu" nzPlacement="bottom"
...@@ -58,14 +51,14 @@ ...@@ -58,14 +51,14 @@
</div> </div>
<div class="p-divider"></div> <div class="p-divider"></div>
<div style="background: #fff;display: block;"> <div style="background: #fff;display: block;">
<div class="position-relative"> <div class="position-relative" (click)="onChangeStrikethrough()">
<app-audio-recorder [audioUrl]="titleObj && titleObj.audio_url" (audioUploaded)="titleAudioUploaded($event)"></app-audio-recorder> <app-audio-recorder [audioUrl]="titleObj && titleObj.audio_url" (audioUploaded)="titleAudioUploaded($event)"></app-audio-recorder>
</div> </div>
</div> </div>
</div> </div>
<div class="width-100 d-flex"> <div class="width-100 d-flex">
<iframe #titleEl id="titleContentEgret" frameborder="0" style="overflow: hidden;width: 100%; height:48px; margin: 0; padding: 0;"></iframe> <iframe #titleEl frameborder="0" style="overflow: hidden;width: 100%; height:48px; margin: 0; padding: 0;"></iframe>
</div> </div>
</div> </div>
...@@ -83,11 +76,37 @@ ...@@ -83,11 +76,37 @@
<ng-container *ngIf="withIcon">
<div class="row type-row">
课程类型:
<nz-radio-group [(ngModel)]="titleObj && titleObj.type" (ngModelChange)="typeChange($event)">
<label nz-radio nzValue="a">单数课</label>
<label nz-radio nzValue="b">双数课</label>
<label nz-radio nzValue="c">复习课</label>
</nz-radio-group>
</div>
</ng-container>
</div> </div>
<ng-container *ngIf="withIcon">
<div class="title-icons">
<div class="icons-list">
<nz-checkbox-wrapper style="width: 100%;clear:both" (nzOnChange)="iconsChanges($event)">
<div [class]="'icon-item icon-'+i" *ngFor="let i of groupIconsCount[titleObj.type];">
<div class="img-box">
<nz-badge class="icon-badge" [nzCount]="titleObj && titleObj.icons && titleObj.icons.indexOf(i) + 1">
<img [src]="'assets/title-icons/'+titleObj.type+'/icon-'+i+'.png'" alt="">
</nz-badge>
</div>
<label nz-checkbox [nzValue]="i" [ngModel]="titleObj && titleObj.icons && titleObj.icons.indexOf(i) > -1"></label>
</div>
</nz-checkbox-wrapper>
</div>
</div>
</ng-container>
</div> </div>
@import '../../style/common_mixin.css'; @import '../../style/common_mixin';
.title-config { .title-config {
.letter-wrap{ .letter-wrap{
...@@ -11,73 +11,39 @@ ...@@ -11,73 +11,39 @@
.type-row{ .type-row{
margin: 0;padding-top: 1rem; margin: 0;padding-top: 1rem;
} }
.icon-item{
} margin-right: 16px;
@font-face float: left;
{ width: 45px;
font-family: 'BRLNSDB'; height: 75px;
src: url("../../../assets/font/BRLNSDB.TTF") ; display: flex;
} justify-content: center;
align-items: center;
@font-face position: relative;
{ .icon-badge{
font-family: 'BRLNSB'; position: absolute;
src: url("../../../assets/font/BRLNSB.TTF") ; top: 0;
} right: 0;
}
@font-face .img-box{
{ top: 0;
font-family: 'BRLNSR'; position: absolute;
src: url("../../../assets/font/BRLNSR.TTF") ; width: 45px;
} height: 50px;
display: flex;
@font-face justify-content: center;
{ align-items: center;
font-family: 'GOTHIC'; img{
src: url("../../../assets/font/GOTHIC.TTF") ; max-width: 100%;
} }
}
@font-face label{
{ position: absolute;
font-family: 'GOTHICB'; bottom: 0;
src: url("../../../assets/font/GOTHICB.TTF") ; }
} }
@font-face
{
font-family: 'GOTHICBI';
src: url("../../../assets/font/GOTHICBI.TTF") ;
}
@font-face
{
font-family: 'GOTHICI';
src: url("../../../assets/font/GOTHICI.TTF") ;
}
@font-face
{
font-family: 'MMTextBook';
src: url("../../../assets/font/MMTextBook.otf") ;
}
@font-face
{
font-family: 'MMTextBook-Bold';
src: url("../../../assets/font/MMTextBook-Bold.otf") ;
}
@font-face
{
font-family: 'MMTextBook-BoldItalic';
src: url("../../../assets/font/MMTextBook-BoldItalic.otf") ;
} }
@font-face
{
font-family: 'MMTextBook-Italic';
src: url("../../../assets/font/MMTextBook-Italic.otf") ;
}
@mixin tool-btn { @mixin tool-btn {
border: 1px solid #ddd; border: 1px solid #ddd;
display: flex; display: flex;
...@@ -88,37 +54,16 @@ ...@@ -88,37 +54,16 @@
border-radius: 6px; border-radius: 6px;
color: #555; color: #555;
} }
.d-flex{
display: flex;
}
.position-relative { .p-title-box {
position: relative; .p-title {
}
.flex-fill {
-webkit-box-flex: 1;
flex: 1 1 auto;
justify-content: center;
display: flex;
}
.i-dropdown-menu{
width: 15px;
font-size: 10px;
border-left: 1px solid #ddd;
display: -webkit-box;
display: flex;
-webkit-box-align: center;
align-items: center;
flex: 0
}
.p-title-box .p-title {
font-size: 20px; font-size: 20px;
} }
.p-title-box input { input {
width: 300px; width: 300px;
margin-left: 10px; margin-left: 10px;
} }
}
.p-content { .p-content {
border: 1px solid #ddd; border: 1px solid #ddd;
...@@ -140,31 +85,33 @@ ...@@ -140,31 +85,33 @@
align-items: center; align-items: center;
border-bottom: 1px solid #ddd; border-bottom: 1px solid #ddd;
// save
.i-tool-save {
} @include tool-btn();
// save
.i-tool-save {
//@include tool-btn();
color: white; color: white;
} }
.i-tool-save:disabled { .i-tool-save:disabled {
color: #555; color: #555;
} }
// font-size // font-size
.i-tool-font-size { .i-tool-font-size {
//@include tool-btn(); @include tool-btn();
width: 37px; width: 37px;
} & > span {
.i-tool-font-size:hover { position: absolute;
top: -5px;
right: 5px;
}
}
.i-tool-font-size:hover {
color: black; color: black;
border-color: #bbb; border-color: #bbb;
} }
// font-color // font-color
.i-tool-font-color, .i-tool-font-btn { .i-tool-font-color, .i-tool-font-btn {
border: 1px solid #ddd; border: 1px solid #ddd;
//padding: 3px 7px; //padding: 3px 7px;
border-radius: 6px; border-radius: 6px;
...@@ -208,20 +155,20 @@ ...@@ -208,20 +155,20 @@
transform: scale(0.6); transform: scale(0.6);
} }
} }
} }
.i-tool-font-btn{ .i-tool-font-btn{
width: 31px; width: 31px;
} }
.fa-icon{ .fa-icon{
width: 100%; width: 100%;
height: 100%; height: 100%;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
} }
// bg-color // bg-color
.i-tool-bg-color { .i-tool-bg-color {
@include tool-btn(); @include tool-btn();
padding: 0 9px; padding: 0 9px;
::ng-deep > span { ::ng-deep > span {
...@@ -236,14 +183,17 @@ ...@@ -236,14 +183,17 @@
background-color: white; background-color: white;
margin-left: 10px; margin-left: 10px;
} }
} }
// horizontal-center // horizontal-center
.i-tool-horizontal-center { .i-tool-horizontal-center {
@include tool-btn(); @include tool-btn();
width: 37px; width: 37px;
}
} }
.p-box { .p-box {
width: 1280px; width: 1280px;
height: 720px; height: 720px;
...@@ -253,7 +203,9 @@ ...@@ -253,7 +203,9 @@
overflow: hidden; overflow: hidden;
} }
.p-sentence {
@include k-no-select();
}
.p-animation-index-box { .p-animation-index-box {
.i-animation-index { .i-animation-index {
...@@ -326,6 +278,7 @@ ...@@ -326,6 +278,7 @@
::ng-deep .ant-radio-button-wrapper { ::ng-deep .ant-radio-button-wrapper {
padding: 0 10px; padding: 0 10px;
@include k-no-select();
} }
.i-toolbox { .i-toolbox {
...@@ -356,6 +309,7 @@ ...@@ -356,6 +309,7 @@
cursor: pointer; cursor: pointer;
text-align: left; text-align: left;
display: flex; display: flex;
@include k-no-select();
} }
.i-active { .i-active {
background-color: antiquewhite; background-color: antiquewhite;
......
import { import {
Component, Component,
ElementRef, ElementRef,
...@@ -11,82 +10,6 @@ import { ...@@ -11,82 +10,6 @@ import {
ViewChild ViewChild
} from '@angular/core'; } from '@angular/core';
const editorTpl = `<html lang="en"><head><meta charset="utf-8">
<meta name="viewport"
content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"/>
<style>
@font-face{
font-family: 'BRLNSDB';
src: url("../../../assets/font/BRLNSDB.TTF") ;
}
@font-face{
font-family: 'BRLNSB';
src: url("../../../assets/font/BRLNSB.TTF") ;
}
@font-face{
font-family: 'BRLNSR';
src: url("../../../assets/font/BRLNSR.TTF") ;
}
@font-face{
font-family: 'GOTHIC';
src: url("../../../assets/font/GOTHIC.TTF") ;
}
@font-face{
font-family: 'GOTHICB';
src: url("../../../assets/font/GOTHICB.TTF") ;
}
@font-face{
font-family: 'GOTHICBI';
src: url("../../../assets/font/GOTHICBI.TTF") ;
}
@font-face{
font-family: 'GOTHICI';
src: url("../../../assets/font/GOTHICI.TTF") ;
}
@font-face{
font-family: 'MMTextBook';
src: url("../../../assets/font/MMTextBook.otf") ;
}
@font-face{
font-family: 'MMTextBook-Bold';
src: url("../../../assets/font/MMTextBook-Bold.otf") ;
}
@font-face{
font-family: 'MMTextBook-BoldItalic';
src: url("../../../assets/font/MMTextBook-BoldItalic.otf") ;
}
@font-face{
font-family: 'MMTextBook-Italic';
src: url("../../../assets/font/MMTextBook-Italic.otf") ;
}
html, body{
/*font-size: 30px;*/
}
body{
height:48px;
overflow: hidden;
margin: 0;
padding: 0 .5rem;
font-family: 'BRLNSB, BRLNSDB, BRLNSR, GOTHIC, GOTHICB, MMTextBook';
background: #FFF;
line-height: 48px;
}
</style>
</head>
<body>{{content}}</body>
</html>`;
@Component({ @Component({
selector: 'app-lesson-title-config', selector: 'app-lesson-title-config',
templateUrl: './lesson-title-config.component.html', templateUrl: './lesson-title-config.component.html',
...@@ -96,45 +19,22 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy, ...@@ -96,45 +19,22 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy,
fontFamilyList = [ fontFamilyList = [
'Arial', 'Arial',
'BRLNSB', 'ARBLI'
'BRLNSDB',
'BRLNSR',
'GOTHIC',
'GOTHICB',
// "GOTHICBI",
// "GOTHICI",
'MMTextBook',
// "MMTextBook-Bold",
// "MMTextBook-Italic",
// "MMTextBook-BoldItalic",
]; ];
colorList = [ colorList = [
'#000000', '#111111',
'#ffffff', '#ffffff',
'#595959', '#595959',
'#0075c2', '#0075c2',
'#c61c1e', '#c61c1e',
'#9cbc3a', '#9cbc3a'
'#008000',
'#FF0000',
'#D2691E',
]; ];
MIN_FONT_SIZE = 1; MIN_FONT_SIZE = 1;
MAX_FONT_SIZE = 7; MAX_FONT_SIZE = 7;
isShowFontColorPane = false; isShowFontColorPane = false;
isShowBGColorPane = false; isShowBGColorPane = false;
fontSizeRange = [ fontSizeRange: number[];
// {name: '1号', value: 9},
// {name: '2号', value: 13},
// {name: '3号', value: 16},
// {name: '4号', value: 18},
// {name: '5号', value: 24},
// {name: '6号', value: 32},
];
editorContent = ''; editorContent = '';
...@@ -145,17 +45,25 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy, ...@@ -145,17 +45,25 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy,
loopCnt = 0; loopCnt = 0;
maxLoops = 20; maxLoops = 20;
groupIconsCount = {
@ViewChild('titleEl', {static: true}) titleEl: ElementRef; a: Array.from(Array(11).keys()),
b: Array.from(Array(8).keys()),
c: Array.from(Array(8).keys()),
};
prevIcons = [];
prevType = '';
@ViewChild('titleEl') titleEl: ElementRef;
titleEW = null; titleEW = null;
@Input() @Input()
titleObj = { titleObj = {
type: 'a',
content: '', content: '',
icons: [],
audio_url: '' audio_url: ''
}; };
@Input()
withIcon = true;
@Output() @Output()
titleUpdated = new EventEmitter(); titleUpdated = new EventEmitter();
...@@ -176,12 +84,16 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy, ...@@ -176,12 +84,16 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy,
let defObj = this.titleObj; let defObj = this.titleObj;
if (!vars.titleObj.currentValue) { if (!vars.titleObj.currentValue) {
defObj = { defObj = {
type: 'a',
content: '', content: '',
icons: [],
audio_url: '' audio_url: ''
}; };
} else { } else {
defObj = vars.titleObj.currentValue; defObj = vars.titleObj.currentValue;
} }
this.titleObj.icons = defObj.icons || [];
this.titleObj.type = defObj.type || 'a';
this.titleObj.content = defObj.content || ''; this.titleObj.content = defObj.content || '';
this.titleObj.audio_url = defObj.audio_url || ''; this.titleObj.audio_url = defObj.audio_url || '';
this.titleEW.document.body.innerHTML = this.titleObj.content; this.titleEW.document.body.innerHTML = this.titleObj.content;
...@@ -190,23 +102,33 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy, ...@@ -190,23 +102,33 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy,
ngOnInit() { ngOnInit() {
if (!this.titleObj) { if (!this.titleObj) {
this.titleObj = { this.titleObj = {
type: 'a',
content: '', content: '',
icons: [],
audio_url: '' audio_url: ''
}; };
} }
this.titleObj.icons = this.titleObj.icons || [];
this.titleObj.type = this.titleObj.type || 'a';
this.titleObj.content = this.titleObj.content || ''; this.titleObj.content = this.titleObj.content || '';
this.titleObj.audio_url = this.titleObj.audio_url || ''; this.titleObj.audio_url = this.titleObj.audio_url || '';
this.editorContent = editorTpl.replace('{{content}}', this.titleObj.content) ; this.editorContent = `<html lang="en"><head><meta charset="utf-8">
<meta name="viewport"
content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"/>
</head>
<body style="height:48px;overflow: hidden;margin: 0;padding: 0 .5rem;background: #FFF;line-height: 48px;">
${this.titleObj.content}
</body>
</html>`;
this.titleEW = this.titleEl.nativeElement.contentWindow; this.titleEW = this.titleEl.nativeElement.contentWindow;
console.log('this.titleEW', this.titleEW);
const tdoc = this.titleEW.document; const tdoc = this.titleEW.document;
tdoc.designMode = 'on'; tdoc.designMode = "on";
tdoc.open('text/html', 'replace'); tdoc.open('text/html', 'replace');
tdoc.write(this.editorContent); tdoc.write(this.editorContent);
tdoc.close(); tdoc.close();
tdoc.addEventListener('keypress', this.keyPress, true); tdoc.addEventListener("keypress", this.keyPress, true);
tdoc.addEventListener('blur', () => { tdoc.addEventListener("blur", () => {
if (this.titleObj.content === this.titleEW.document.body.innerHTML.trim()) { if (this.titleObj.content === this.titleEW.document.body.innerHTML.trim()) {
return; return;
} }
...@@ -237,7 +159,30 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy, ...@@ -237,7 +159,30 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy,
ngOnDestroy(): void { ngOnDestroy(): void {
} }
iconsChanges(val) {
let a = this.titleObj.icons;
let b = val;
if (a.length > b.length) {
const diff = a.filter(x => !b.includes(x));
const ti = [...this.titleObj.icons];
for (let i = 0; i < diff.length; i++) {
const d = diff[i];
const idx = ti.indexOf(d);
ti.splice(idx, 1);
}
this.titleObj.icons = ti;
} else {
const diff = b.filter(x => !a.includes(x));
this.titleObj.icons = [...this.titleObj.icons, ...diff];
}
this.shouldSave();
}
typeChange(val) {
this.titleObj.icons = [];
this.shouldSave();
}
keyPress(evt) { keyPress(evt) {
try { try {
...@@ -250,9 +195,9 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy, ...@@ -250,9 +195,9 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy,
const key = String.fromCharCode(evt.charCode).toLowerCase(); const key = String.fromCharCode(evt.charCode).toLowerCase();
let cmd = ''; let cmd = '';
switch (key) { switch (key) {
case 'b': cmd = 'bold'; break; case 'b': cmd = "bold"; break;
case 'i': cmd = 'italic'; break; case 'i': cmd = "italic"; break;
case 'u': cmd = 'underline'; break; case 'u': cmd = "underline"; break;
} }
...@@ -269,13 +214,10 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy, ...@@ -269,13 +214,10 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy,
alert(e); alert(e);
} }
} }
execEditorCommand(command, option?: any) { execEditorCommand(command, option?: any) {
console.log('sssss');
try { try {
this.titleEW.focus(); this.titleEW.focus();
const result = this.titleEW.document.execCommand(command, false, option); this.titleEW.document.execCommand(command, false, option);
console.log(result);
this.loopCnt = 0; this.loopCnt = 0;
return false; return false;
...@@ -287,7 +229,7 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy, ...@@ -287,7 +229,7 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy,
}, 100); }, 100);
this.loopCnt += 1; this.loopCnt += 1;
} else { } else {
alert('Error executing command.'); alert("Error executing command.");
} }
} }
} }
...@@ -300,7 +242,7 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy, ...@@ -300,7 +242,7 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy,
this.execEditorCommand('forecolor', this.__fontColor); this.execEditorCommand('forecolor', this.__fontColor);
} }
onChangeFontFamily(font) { onChangeFontFamily(font) {
this.execEditorCommand('fontName', font); this.execEditorCommand('fontname', font);
} }
onChangeFontSize(size?: any) { onChangeFontSize(size?: any) {
...@@ -330,10 +272,9 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy, ...@@ -330,10 +272,9 @@ export class LessonTitleConfigComponent implements OnInit, OnChanges, OnDestroy,
this.titleUpdated.emit(this.titleObj); this.titleUpdated.emit(this.titleObj);
} }
shouldSave = () => { shouldSave = () => {
console.log('title shouldSave', this.titleObj); console.log('title shouldSave');
this.titleObj.content = this.titleEW.document.body.innerHTML.trim(); this.titleObj.content = this.titleEW.document.body.innerHTML.trim();
this.titleUpdated.emit(this.titleObj); this.titleUpdated.emit(this.titleObj);
} }
} }
@import '../../style/common_mixin.css'; @import '../../style/common_mixin';
.cmp-player-content-wrapper{ .cmp-player-content-wrapper{
max-height: 100%; max-height: 100%;
......
...@@ -18,7 +18,7 @@ import { ...@@ -18,7 +18,7 @@ import {
export class PlayerContentWrapperComponent implements OnInit, OnChanges, OnDestroy, AfterViewInit { export class PlayerContentWrapperComponent implements OnInit, OnChanges, OnDestroy, AfterViewInit {
@ViewChild('wrapperEl', {static: true }) wrapperEl: ElementRef; @ViewChild('wrapperEl') wrapperEl: ElementRef;
// // aspect ratio? // // aspect ratio?
@Input() ratio; @Input() ratio;
......
...@@ -5,21 +5,16 @@ ...@@ -5,21 +5,16 @@
[nzAction]="uploadUrl" [nzAction]="uploadUrl"
[nzData]="uploadData" [nzData]="uploadData"
(nzChange)="handleChange($event)"> (nzChange)="handleChange($event)">
<!--[nzBeforeUpload]="customUpload">-->
<div class="p-box d-flex align-items-center"> <div class="p-box d-flex align-items-center">
<div class="p-upload-icon" *ngIf="!picUrl && !uploading"> <div class="p-upload-icon" *ngIf="!picUrl && !uploading">
<i nz-icon nzType="cloud-upload" nzTheme="outline" [style.font-size]="iconSize + 'em'"></i> <i nz-icon type="cloud-upload" theme="outline" [style.font-size]="iconSize + 'em'"></i>
<div class="m-3"></div> <div class="m-3"></div>
<span>{{TIP}}</span> <span>{{TIP}}</span>
<!--<div class="mt-5 p-progress-bar" *ngIf="uploading">-->
<!--<div class="p-progress-bg" [style.width]="progress*0.2+'rem'"></div>-->
<!--<div class="p-progress-value">{{progress}}%</div>-->
<!--</div>-->
</div> </div>
<div class="p-upload-progress-bg" *ngIf="uploading"> <div class="p-upload-progress-bg" *ngIf="uploading">
<div class="i-bg" [style.width]="progress+'%'"></div> <div class="i-bg" [style.width]="progress+'%'"></div>
<div class="i-text"> <div class="i-text">
<fa-icon icon="cloud-upload-alt"></fa-icon> <fa name="cloud-upload"></fa>
Uploading... Uploading...
</div> </div>
</div> </div>
...@@ -32,6 +27,6 @@ ...@@ -32,6 +27,6 @@
nz-popconfirm nzTitle="Are you sure ?" nz-popconfirm nzTitle="Are you sure ?"
(nzOnConfirm)="onDelete()" (nzOnConfirm)="onDelete()"
> >
<i nz-icon nzType="close" nzTheme="outline"></i> <i nz-icon type="close" theme="outline"></i>
</div> </div>
</div> </div>
@import '../../style/common_mixin.css'; @import '../../style/common_mixin';
.p-image-uploader { .p-image-uploader {
position: relative; position: relative;
...@@ -52,15 +52,10 @@ ...@@ -52,15 +52,10 @@
.p-preview { .p-preview {
width: 100%; width: 100%;
height: 100%; height: 100%;
background-size: contain;
background-repeat: no-repeat;
background-position: 50% 50%;
//background-image: url("https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"); //background-image: url("https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png");
@include k-img-bg();
} }
} }
.d-flex{
display: flex;
}
} }
.p-btn-delete { .p-btn-delete {
......
...@@ -29,19 +29,10 @@ export class UploadImageWithPreviewComponent implements OnDestroy, OnChanges { ...@@ -29,19 +29,10 @@ export class UploadImageWithPreviewComponent implements OnDestroy, OnChanges {
@Input() @Input()
disableUpload = false; disableUpload = false;
uploadUrl; uploadUrl = (<any> window).courseware.uploadUrl();
uploadData; uploadData = (<any> window).courseware.uploadData();
constructor(private nzMessageService: NzMessageService) { constructor(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() { ngOnChanges() {
if (!this.picItem) { if (!this.picItem) {
...@@ -54,9 +45,6 @@ export class UploadImageWithPreviewComponent implements OnDestroy, OnChanges { ...@@ -54,9 +45,6 @@ export class UploadImageWithPreviewComponent implements OnDestroy, OnChanges {
handleChange(info: { type: string, file: UploadFile, event: any }): void { handleChange(info: { type: string, file: UploadFile, event: any }): void {
console.log('info:' , info);
switch (info.type) { switch (info.type) {
case 'start': case 'start':
// this.isUploading = true; // this.isUploading = true;
......
<div class="p-video-box">
<div class="up-video" style="display: flex;"> <div class="up-video" style="display: flex;">
<!--<nz-upload class="" [nzDisabled]="!showUploadBtn"--> <!--<nz-upload class="" [nzDisabled]="!showUploadBtn"-->
<!--[nzShowUploadList]="false"--> <!--[nzShowUploadList]="false"-->
...@@ -16,7 +16,8 @@ ...@@ -16,7 +16,8 @@
<button type="button" nz-button nzType="default" *ngIf="showUploadBtn" [disabled]="uploading" <button type="button" nz-button nzType="default" *ngIf="showUploadBtn" [disabled]="uploading"
[nzLoading]="uploading" > [nzLoading]="uploading" >
<i nz-icon nzType="plus" nzTheme="outline"></i> <i nz-icon type="plus" theme="outline"></i>
<span>{{ uploading ? 'Uploading' : 'Select Video' }}</span> <span>{{ uploading ? 'Uploading' : 'Select Video' }}</span>
<!--<span>Select Video</span>--> <!--<span>Select Video</span>-->
</button> </button>
...@@ -55,9 +56,9 @@ ...@@ -55,9 +56,9 @@
</div> </div>
<div class="p-box d-flex align-items-center p-video-uploader"> <div class="p-box d-flex align-items-center p-video-uploader" style="top: 20px;">
<div class="p-upload-icon" *ngIf="!showUploadBtn && !videoUrl && !uploading"> <div class="p-upload-icon" *ngIf="!showUploadBtn && !videoUrl && !uploading">
<i nz-icon nzType="upload" nzTheme="outline"></i> <i nz-icon type="upload" theme="outline"></i>
<div class="m-3"></div> <div class="m-3"></div>
<span>Click here to upload video</span> <span>Click here to upload video</span>
<div class="mt-5 p-progress-bar" *ngIf="uploading"> <div class="mt-5 p-progress-bar" *ngIf="uploading">
...@@ -69,26 +70,26 @@ ...@@ -69,26 +70,26 @@
[ngClass]="{'smart-bar': showUploadBtn}" > [ngClass]="{'smart-bar': showUploadBtn}" >
<div class="i-bg" [style.width]="progress+'%'"></div> <div class="i-bg" [style.width]="progress+'%'"></div>
<div class="i-text"> <div class="i-text">
<fa-icon icon="cloud-upload-alt"></fa-icon> <fa name="cloud-upload"></fa>
Uploading... Uploading...
</div> </div>
</div> </div>
<div class="p-upload-check-bg" *ngIf="checking"> <div class="p-upload-check-bg" *ngIf="checking">
<div class="i-bg" [style.width]="progress+'%'"></div> <div class="i-bg" [style.width]="progress+'%'"></div>
<div class="i-text"> <div class="i-text">
<fa-icon icon="cloud-upload-alt"></fa-icon> <fa name="cloud-upload"></fa>
<i nz-icon nzType="loading" nzTheme="outline"></i>Checking... <i nz-icon type="loading" theme="outline"></i>Checking...
</div> </div>
</div> </div>
<div class="p-preview" *ngIf="!uploading && videoUrl " > <div class="p-preview" *ngIf="!showUploadBtn && !uploading && videoUrl " >
<!--<video crossorigin="anonymous" [src]="videoUrl" controls #videoNode></video>--> <!--<video crossorigin="anonymous" [src]="videoUrl" controls #videoNode></video>-->
<video [src]="safeVideoUrl(videoUrl)" controls #videoNode></video> <video [src]="safeVideoUrl(videoUrl)" controls #videoNode (loadedmetadata)="videoLoadedMetaData()"></video>
</div> </div>
</div> </div>
<div [style.display]="!checkVideoExists?'none':''"> <div [style.display]="!checkVideoExists?'none':''">
<span><i nz-icon nzType="loading" nzTheme="outline"></i> checking file to upload</span> <span><i nz-icon type="loading" theme="outline"></i> checking file to upload</span>
</div>
</div> </div>
@import '../../style/common_mixin.css'; @import '../../style/common_mixin';
/*.p-video-box{
bottom: 0;
border: 2px dashed #ddd;
border-radius: 0.5rem;
background-color: #fafafa;
text-align: center;
color: #aaa;
padding-top: 56.25%;
//font-size: 4rem;
position: relative;
.p-upload-icon{
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50% ,-50%);
}
}*/
.p-video-uploader { .p-video-uploader {
position: relative; position: relative;
display: block; display: block;
...@@ -33,33 +17,25 @@ ...@@ -33,33 +17,25 @@
background-color: #fafafa; background-color: #fafafa;
text-align: center; text-align: center;
color: #aaa; color: #aaa;
.p-upload-icon {
}
}
.p-upload-icon {
text-align: center; text-align: center;
margin: auto; margin: auto;
.anticon-upload {
}
.p-upload-icon .anticon-upload {
color: #888; color: #888;
font-size: 5rem; font-size: 5rem;
} }
p-progress-bar { .p-progress-bar {
position: relative; position: relative;
width: 20rem; width: 20rem;
height: 1.5rem; height: 1.5rem;
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 1rem; border-radius: 1rem;
.p-progress-bg {
}
.p-progress-bar .p-progress-bg {
background-color: #1890ff; background-color: #1890ff;
border-radius: 1rem; border-radius: 1rem;
height: 100%; height: 100%;
} }
.p-progress-bar .p-progress-value { .p-progress-value {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
...@@ -70,19 +46,21 @@ p-progress-bar { ...@@ -70,19 +46,21 @@ p-progress-bar {
text-align: center; text-align: center;
font-size: 0.9rem; font-size: 0.9rem;
line-height: 1.5rem; line-height: 1.5rem;
} }
.p-preview { }
}
.p-preview {
width: 100%; width: 100%;
height: 100%; height: 100%;
//background-image: url("https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"); //background-image: url("https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png");
video{
}
.p-preview video{
max-height: 100%; max-height: 100%;
max-width: 100%; max-width: 100%;
position: absolute;
display: flex;
} }
}
}
}
.p-btn-delete { .p-btn-delete {
position: absolute; position: absolute;
right: -0.5rem; right: -0.5rem;
......
import {Component, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, Output, SecurityContext, ViewChild} from '@angular/core'; import {Component, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, Output, SecurityContext, ViewChild} from '@angular/core';
import {NzMessageService, UploadChangeParam, UploadFile, UploadFileStatus} from 'ng-zorro-antd'; import {NzMessageService, UploadFile} from 'ng-zorro-antd';
import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser'; import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser';
...@@ -24,7 +24,7 @@ export class UploadVideoComponent implements OnChanges, OnDestroy { ...@@ -24,7 +24,7 @@ export class UploadVideoComponent implements OnChanges, OnDestroy {
@Input() @Input()
videoUrl = ''; videoUrl = '';
@ViewChild('videoNode', {static: true }) @ViewChild('videoNode')
videoNode: ElementRef; videoNode: ElementRef;
...@@ -47,8 +47,8 @@ export class UploadVideoComponent implements OnChanges, OnDestroy { ...@@ -47,8 +47,8 @@ export class UploadVideoComponent implements OnChanges, OnDestroy {
item: any; item: any;
// videoItem = null; // videoItem = null;
uploadUrl; uploadUrl = (<any> window).courseware.uploadUrl();
uploadData; uploadData = (<any> window).courseware.uploadData();
constructor(private nzMessageService: NzMessageService, constructor(private nzMessageService: NzMessageService,
private sanitization: DomSanitizer private sanitization: DomSanitizer
...@@ -58,16 +58,6 @@ export class UploadVideoComponent implements OnChanges, OnDestroy { ...@@ -58,16 +58,6 @@ export class UploadVideoComponent implements OnChanges, OnDestroy {
this.uploading = false; this.uploading = false;
this.videoFile = null; this.videoFile = null;
this.uploadUrl = (<any> window).courseware.uploadUrl();
this.uploadData = (<any> window).courseware.uploadData();
window['air'].getUploadCallback = (url, data) => {
this.uploadUrl = url;
this.uploadData = data;
};
} }
ngOnChanges() { ngOnChanges() {
// if (!this.videoFile || this.showUploadBtn) { // if (!this.videoFile || this.showUploadBtn) {
...@@ -81,7 +71,7 @@ export class UploadVideoComponent implements OnChanges, OnDestroy { ...@@ -81,7 +71,7 @@ export class UploadVideoComponent implements OnChanges, OnDestroy {
} }
safeVideoUrl(url) { safeVideoUrl(url) {
console.log(url); console.log(url)
return this.sanitization.bypassSecurityTrustResourceUrl(url); // `${url}`; return this.sanitization.bypassSecurityTrustResourceUrl(url); // `${url}`;
} }
videoLoadedMetaData() { videoLoadedMetaData() {
...@@ -89,7 +79,7 @@ export class UploadVideoComponent implements OnChanges, OnDestroy { ...@@ -89,7 +79,7 @@ export class UploadVideoComponent implements OnChanges, OnDestroy {
} }
handleChange(info: UploadChangeParam/* { type: string, file: UploadFile, event: any }*/): void { handleChange(info: { type: string, file: UploadFile, event: any }): void {
console.log('info:' , info); console.log('info:' , info);
...@@ -119,7 +109,7 @@ export class UploadVideoComponent implements OnChanges, OnDestroy { ...@@ -119,7 +109,7 @@ export class UploadVideoComponent implements OnChanges, OnDestroy {
break; break;
case 'progress': case 'progress':
this.progress = info.event.percent; this.progress = parseInt(info.event.percent, 10);
this.doProgress(this.progress); this.doProgress(this.progress);
break; break;
} }
...@@ -162,9 +152,9 @@ export class UploadVideoComponent implements OnChanges, OnDestroy { ...@@ -162,9 +152,9 @@ export class UploadVideoComponent implements OnChanges, OnDestroy {
if (duration) { if (duration) {
duration = duration * 1000; duration = duration * 1000;
} }
file.height = height; file['height'] = height;
file.width = width; file['width'] = width;
file.duration = duration; file['duration'] = duration;
vid.preload = 'none'; vid.preload = 'none';
vid.src = ''; vid.src = '';
vid.remove(); vid.remove();
......
@import '../style/common_mixin.css';
.model-content {
width: 100%;
height: 100%;
}
<div class="model-content"> <div class="model-content">
<div class="card-config">
<div *ngFor="let item of contentObj.dataArray; let i = index" class="card-item" style="padding: 0.5vw;" >
<div class="card-item-content border">
<div class="card-item-content">
<div class="title" >
第-<strong>{{ i + 1 }}</strong>-题
</div>
<div class="section" >
<div class="section-title" >
题干
</div>
<div class="section-content">
<div style="flex:1">
<div style="display: flex; margin-bottom: 10px;">
<div style="flex:1">
<span>音频</span>
</div>
<div style="flex:11">
<app-audio-recorder [audioUrl]="item.audio_url" (audioUploaded)="onAudioUploadSuccessByItem($event, item)" ></app-audio-recorder>
</div>
</div>
</div>
</div>
</div>
<div style="position: absolute; left: 200px; top: 100px; width: 800px;">
<input type="text" nz-input [(ngModel)]="item.text" (blur)="save()"> <div class="section" >
<div class="section-title" >
正确选项
</div>
<div style="display: flex;">
<div *ngFor="let choiceItem of item.options; let choiceIndex = index" [ngClass]="{'hidden': !choiceItem.isCorrect}" style="width:400px; border:1px solid #CCC; padding:5px; border-radius: 5px; margin: 0 10px;">
<div *ngIf="choiceItem.isCorrect">
<app-upload-image-with-preview <div style="display: flex; margin-bottom: 10px;">
[picUrl]="item.pic_url" <div style="flex:1">
(imageUploaded)="onImageUploadSuccess($event, 'pic_url')" 文字
></app-upload-image-with-preview> </div>
<div style="flex:5">
<input type="text" nz-input placeholder="" [(ngModel)]="choiceItem.text" (blur)="saveItem()" />
</div>
</div>
<app-audio-recorder <div style="display: flex; margin-bottom: 10px;">
[audioUrl]="item.audio_url" <div style="flex:1">
(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>
<div style="flex:5">
<div style="width:300px">
<app-upload-image-with-preview style="width: 200px;" [picUrl]="choiceItem.image_url" (imageUploaded)="onImageUploadSuccessByItem($event, choiceItem)"></app-upload-image-with-preview>
</div>
</div>
</div>
</div> <div style="display: flex; ">
<div style="flex:2">
显示选项
</div>
<div style="flex:4">
<nz-radio-group [(ngModel)]="choiceItem.type" (ngModelChange)="saveItem()" >
<label nz-radio [nzValue]="'Text'">文字</label>
<label nz-radio [nzValue]="'Image'">图片</label>
</nz-radio-group>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="section" >
<div class="section-title" >
错误选项
</div>
<div class="section-content" >
<div *ngFor="let choiceItem of item.options; let choiceIndex = index" [ngClass]="{'hidden': choiceItem.isCorrect}" style="flex:1;border:1px solid #CCC; padding:5px; border-radius: 5px; margin: 0 10px;">
<div *ngIf="!choiceItem.isCorrect">
<div style="display: flex; margin-bottom: 10px;">
<div style="flex:1">
文字
</div>
<div style="flex:5">
<input type="text" nz-input placeholder="" [(ngModel)]="choiceItem.text" (blur)="saveItem()" />
</div>
</div>
<div style="display: flex; margin-bottom: 10px;">
<div style="flex:1">
图片
</div>
<div style="flex:5">
<div style="width: 400px;">
<app-upload-image-with-preview style="width: 100%;" [picUrl]="choiceItem.image_url" (imageUploaded)="onImageUploadSuccessByItem($event, choiceItem)"></app-upload-image-with-preview>
</div>
</div>
</div>
<div style="display: flex; ">
<div style="flex:2">
显示选项
</div>
<div style="flex:4">
<nz-radio-group [(ngModel)]="choiceItem.type" (ngModelChange)="saveItem()" >
<label nz-radio [nzValue]="'Text'">文字</label>
<label nz-radio [nzValue]="'Image'">图片</label>
</nz-radio-group>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="section" >
<div style="float:right; text-align: left; padding-left: 20px;">
<button style="flex:1;" nz-button nzType="default" (click)="handleMoveItemUp(i)" [disabled]="i==0">
<i nz-icon nzType="up" nzTheme="outline" style="float: left; margin-top: 4px;"></i>
<span style="float: right;">上移</span>
</button>
<button style="flex:1; margin-left: 10px; vertical-align:baseline;" nz-button nzType="default" (click)="handleMoveItemDown(i)" [disabled]="i==contentObj.dataArray.length-1">
<i nz-icon nzType="down" nzTheme="outline" style="float: left; margin-top: 4px;"></i>
<span style="float: right;">下移</span>
</button>
</div>
<div style="text-align: right; padding-right: 20px;">
<button style="margin-bottom: 10px;" nz-button nzType="danger" (click)="deleteItem(i)" >
<span>删除本题</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div *ngIf="contentObj.dataArray.length<26" class="card-item" style="padding: 0.5vw; width: 500px;" >
<button nz-button nzType="primary" class="add-btn" (click)="addItem()">
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>
新建卡片
</button>
</div>
</div>
@import "../style/common_mixin";
.model-content {
margin: 10px;
.card-config {
// width: 100%;
height: 100%;
// display: flex;
flex-wrap: wrap;
box-sizing: border-box;
// width: 500px;
.card-item{
margin-bottom: 40px;
.border {
border-radius: 20px;
border-style: dashed;
padding:20px;
width: 100%;
}
.card-item-content{
.title {
font-size: 24px;
width: 100%;
text-align: center;
}
.section{
border-top: 1px solid ;
padding: 10px 0;
.section-title{
font-size: 24px;
width: 100%;
}
.section-content{
display: flex;
flex-direction: row;
margin: 5px 0 10px 0;
}
}
.pic-sound-box {
width: 50%;
display: flex;
flex-direction: column;
}
.add-btn-box {
display: flex;
align-items: center;
justify-content: center;
height: 20vw;
padding: 10px;
padding-top: 5vw;
}
}
}
}
}
.hidden{
display: none;
}
import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, ApplicationRef, ChangeDetectorRef} from '@angular/core'; import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, ApplicationRef} from '@angular/core';
const defaultData = {
version: "1.1",
bgmusic: "",
dataArray:[
{
audio_url:"sm-choice-timeup-3",
options: [
{type:"Text", image_url:"default-image", text:"Demo_1", audio_url:"", isCorrect:true},
{type:"Image", image_url:"default-image", text:"", audio_url:"", isCorrect:false},
{type:"Text", image_url:"default-image", text:"Demo_1", audio_url:"", isCorrect:false},
{type:"Image", image_url:"default-image", text:"", audio_url:"", isCorrect:false}
]
},
{
audio_url:"sm-choice-timeup-3",
options: [
{type:"Text", image_url:"default-image", text:"Demo_2", audio_url:"", isCorrect:false},
{type:"Image", image_url:"default-image", text:"", audio_url:"", isCorrect:true},
{type:"Text", image_url:"default-image", text:"Demo_2", audio_url:"", isCorrect:false},
{type:"Image", image_url:"default-image", text:"", audio_url:"", isCorrect:false}
]
},
{
audio_url:"sm-choice-timeup-3",
options: [
{type:"Text", image_url:"default-image", text:"Demo_3", audio_url:"", isCorrect:false},
{type:"Image", image_url:"default-image", text:"", audio_url:"", isCorrect:false},
{type:"Text", image_url:"default-image", text:"Demo_3", audio_url:"", isCorrect:false},
{type:"Image", image_url:"default-image", text:"", audio_url:"", isCorrect:true}
]
},
]
}
@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";
// 储存对象
item;
_item: any;
contentObj = {
bgMusic:String,
dataArray:[
{
audio_url: String,
options: [
{type:String, image_url:String, text:String, audio_url:String, isCorrect:Boolean},
{type:String, image_url:String, text:String, audio_url:String, isCorrect:Boolean},
{type:String, image_url:String, text:String, audio_url:String, isCorrect:Boolean},
{type:String, image_url:String, text:String, audio_url:String, isCorrect:Boolean}
]
}
]
}
hotZoneItemArr: Array<Object> = [];
bgItem: Object;
constructor(private appRef: ApplicationRef,private changeDetectorRef: ChangeDetectorRef) { KEY = 'DataKey_East_L230';
set item(item) {
this._item = item;
}
get item() {
return this._item;
} }
@Output()
update = new EventEmitter();
constructor(private appRef: ApplicationRef) {
ngOnInit() { }
ngOnInit() {
this.item = {}; this.item = {};
this.item.contentObj = {};
// 获取存储的数据 const getData = (<any> window).courseware.getData;
(<any> window).courseware.getData((data) => { getData((data) => {
// console.log("读取数据", data)
if (data) { if (data) {
this.item = data; this.item = data;
} else {
this.item = {};
}
if ( !this.item.contentObj ) {
this.item.contentObj = {};
} }
this.init(); this.init();
this.changeDetectorRef.markForCheck();
this.changeDetectorRef.detectChanges();
this.refresh(); this.refresh();
this.save()
}, this.KEY);
}
ngOnChanges() {
}, this.saveKey); }
ngOnDestroy() {
} }
init() {
if (Object.keys(this.item.contentObj).length != 0 && this.item.contentObj.version && this.item.contentObj.version==defaultData.version) {
// console.log("读取数据", this.item.contentObj)
this.contentObj = this.item.contentObj;
} else {
this.contentObj = defaultData;
// console.log("使用默认数据", this.contentObj)
this.item.contentObj = this.contentObj;
}
}
ngOnChanges() { cardItemData(){
return {
audio_url: "",
options: [
{type:"Text", image_url:"", text:"", audio_url:"", isCorrect:true},
{type:"Text", image_url:"", text:"", audio_url:"", isCorrect:false},
{type:"Text", image_url:"", text:"", audio_url:"", isCorrect:false},
{type:"Text", image_url:"", text:"", audio_url:"", isCorrect:false}
]
}
} }
ngOnDestroy() { cardChoiceData(){
return { isText: true, text: "", image_url: "" }
}
getDefaultPicArr() {
let arr = defaultData;
return arr;
} }
initData() {
}
init() {
handleMoveItemUp(index){
if(index!=0){
this.item.contentObj.dataArray[index] = this.item.contentObj.dataArray.splice(index-1, 1, this.item.contentObj.dataArray[index])[0];
}else{
this.item.contentObj.dataArray.push(this.item.contentObj.dataArray.shift());
}
this.save()
}
handleMoveItemDown(index){
if(index!=this.item.contentObj.dataArray.length-1){
this.item.contentObj.dataArray[index] = this.item.contentObj.dataArray.splice(index+1, 1, this.item.contentObj.dataArray[index])[0];
}else{
this.item.contentObj.dataArray.unshift( this.item.contentObj.dataArray.splice(index,1)[0]);
}
this.save()
} }
deleteItem(index){
this.item.contentObj.dataArray.splice(index,1)
this.save()
}
addChoice(questionIndex) {
// let item = this.cardChoiceData();
// this.dataArray[questionIndex].choice.incorrect.push(item);
// this.saveItem();
}
/** onImageUploadSuccessByItem(e, item) {
* 储存图片数据 item.image_url = e.url
* @param e this.save();
*/ }
onImageUploadSuccess(e, key) {
this.item[key] = e.url; onImageUploadSuccess_Container(e) {
this.item.contentObj.cardContainerSetting.image_url = e.url
this.save(); this.save();
} }
/** onAudioUploadSuccessByItem(e, item) {
* 储存音频数据 item.audio_url = e.url;
* @param e this.save();
*/ }
onAudioUploadSuccess(e, key) {
this.item[key] = e.url; onTitleAudioUploadSuccess(e) {
// this.contentObj.bgMusic = e.url;
this.save(); this.save();
} }
addItem() {
let item = this.cardItemData();
this.contentObj.dataArray.push(item);
this.saveItem();
}
radioClick(it, radioValue) {
it.radioValue = radioValue;
this.saveItem();
}
clickCheckBox() {
this.saveItem();
}
saveItem() {
this.save();
}
/**
* 储存数据
*/
save() { save() {
(<any> window).courseware.setData(this.item, null, this.saveKey); (<any> window).courseware.setData(this.item, null, this.KEY);
this.refresh(); this.refresh();
// console.log("保存", this.item)
} }
/**
* 刷新 渲染页面
*/
refresh() { refresh() {
setTimeout(() => { setTimeout(() => {
this.appRef.tick(); this.appRef.tick();
}, 1); }, 1);
} }
} }
This diff is collapsed.
This diff is collapsed.
.game-container {
width: 100%;
height: 100%;
background: #ffffff;
background-size: cover;
}
#canvas {
}
@font-face
{
font-family: 'BRLNSDB';
src: url("../../assets/font/BRLNSDB.TTF") ;
}
.game-container {
width: 100%;
height: 100%;
//background-image: url("/assets/listen-read-circle/bg.jpg");
background: #ffffff;
background-repeat: no-repeat;
background-size: cover;
}
.read-and-point-copy {
width: 500px;
height: 85px;
object-fit: contain;
text-shadow: 0 6px 4px rgba(0, 0, 0, 0.5), 0 3px 0 #fffecc;
font-family: Questrian;
font-size: 72px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
color: #f8e424;
}
.read-and-point-copy .text-style-1 {
font-size: 48px;
}
.read-and-point-copy .text-style-2 {
font-size: 64px;
}
@font-face
{
font-family: 'BRLNSDB';
src: url("../../assets/font/BRLNSDB.TTF") ;
}
@font-face
{
font-family: 'RoundedBold';
src: url("../../assets/font/ArialRoundedBold.otf") ;
}
@font-face{
font-family: 'BRLNSB_1';
src: url("../../assets/font/BerlinSansFB/BRLNSB_1.TTF") ;
}
@font-face{
font-family: 'BerlinSansFBDemi-Bold';
src: url("../../assets/font/BerlinSansFB/BRLNSDB_1.TTF") ;
}
@font-face{
font-family: 'BRLNSR_1';
src: url("../../assets/font/BerlinSansFB/BRLNSR_1.TTF") ;
}
@font-face{
font-family: 'GOTHIC_1';
src: url("../../assets/font/CenturyGothic/GOTHIC_1.TTF") ;
}
@font-face{
font-family: 'GOTHICB_1';
src: url("../../assets/font/CenturyGothic/GOTHICB_1.TTF") ;
}
@font-face{
font-family: 'GOTHICBI_1';
src: url("../../assets/font/CenturyGothic/GOTHICBI_1.TTF") ;
}
@font-face{
font-family: 'GOTHICI_1';
src: url("../../assets/font/CenturyGothic/GOTHICI_1.TTF") ;
}
@font-face{
font-family: 'MMTextBook';
src: url("../../assets/font/MMTextBook/MMTextBook.otf") ;
}
@font-face{
font-family: 'MMTextBook-Bold';
src: url("../../assets/font/MMTextBook/MMTextBook-Bold.otf") ;
}
@font-face{
font-family: 'MMTextBook-BoldItalic';
src: url("../../assets/font/MMTextBook/MMTextBook-BoldItalic.otf") ;
}
@font-face{
font-family: 'MMTextBook-Italic';
src: url("../../assets/font/MMTextBook/MMTextBook-Italic.otf") ;
}
This diff is collapsed.
const res = [ const localImages = {
'_bg_1280_720_Ruler': 'assets/default/images/1280_720_Ruler.png',
'_mask_layer_1280_720': 'assets/default/images/mask_layer_1280_720.png',
'_bg_240_180': 'assets/default/images/bg_240_180.png',
'_bg_453_251': 'assets/default/images/bg_453_251.png',
'_bg_1280_222': 'assets/default/images/bg_1280_222.png',
'_bg_1280_720': 'assets/default/images/bg_1280_720.png',
'_bg_200_200': 'assets/default/images/bg_200_200.png',
'_bg_30_30': 'assets/default/images/bg_30_30.png',
'_bg_500_600': 'assets/default/images/bg_500_600.png',
'_bg_50_50': 'assets/default/images/bg_50_50.png',
'_bg_75_50': 'assets/default/images/bg_75_50.png',
'_bg_75_50_black': 'assets/default/images/bg_75_50_black.png',
'_flag': 'assets/default/images/flag.png',
'_go': 'assets/default/images/go.png',
'_header': 'assets/default/images/header.png',
'_ready': 'assets/default/images/ready.png',
'_replay': 'assets/default/images/replay.png',
'_scrap-pic-1': 'assets/default/images/scrap-pic-1.png',
'_scrap-pic-2': 'assets/default/images/scrap-pic-2.png',
'_scrap-pic-3': 'assets/default/images/scrap-pic-3.png',
'_sm-pic-1': 'assets/default/images/sm-pic-1.png',
'_sm-pic-2': 'assets/default/images/sm-pic-2.png',
'_sm-pic-3': 'assets/default/images/sm-pic-3.png',
'_sm-pic-4': 'assets/default/images/sm-pic-4.png',
'_star': 'assets/default/images/star.png',
'_bubble': 'assets/default/images/bubble.png',
'_image_none': 'assets/default/images/image_none.png',
// ['bg', "assets/play/bg.jpg"], 'arrow': 'assets/play/arrow.png',
['btn_left', "assets/play/btn_left.png"], 'background': 'assets/play/background.png',
['btn_right', "assets/play/btn_right.png"], 'base_line': 'assets/play/base_line.png',
// ['text_bg', "assets/play/text_bg.png"], 'default-image': 'assets/play/default-image.png',
'play_audio': 'assets/play/play_audio.png',
'play_audio_0': 'assets/play/play_audio_0.png',
'play_audio_1': 'assets/play/play_audio_1.png',
'play_audio_2': 'assets/play/play_audio_2.png',
'question_bg': 'assets/play/question_bg.png',
'restart': 'assets/play/restart.png',
'skier': 'assets/play/skier.png',
'snow- (1)': 'assets/play/snow-0.png',
'snow- (2)': 'assets/play/snow-1.png',
'snow- (3)': 'assets/play/snow-2.png',
'snow- (4)': 'assets/play/snow-3.png',
'snow- (5)': 'assets/play/snow-4.png',
'stage_number_bg': 'assets/play/stage_number_bg.png',
'start_btn': 'assets/play/start_btn.png',
'text_container': 'assets/play/text_container.png',
'score_bg': 'assets/play/score_bg.png',
]; 'card-frame- (1)': 'assets/play/frame/card-frame- (1).png',
'card-frame- (10)': 'assets/play/frame/card-frame- (10).png',
'card-frame- (11)': 'assets/play/frame/card-frame- (11).png',
'card-frame- (12)': 'assets/play/frame/card-frame- (12).png',
'card-frame- (13)': 'assets/play/frame/card-frame- (13).png',
'card-frame- (14)': 'assets/play/frame/card-frame- (14).png',
'card-frame- (15)': 'assets/play/frame/card-frame- (15).png',
'card-frame- (16)': 'assets/play/frame/card-frame- (16).png',
'card-frame- (17)': 'assets/play/frame/card-frame- (17).png',
'card-frame- (18)': 'assets/play/frame/card-frame- (18).png',
'card-frame- (19)': 'assets/play/frame/card-frame- (19).png',
'card-frame- (2)': 'assets/play/frame/card-frame- (2).png',
'card-frame- (20)': 'assets/play/frame/card-frame- (20).png',
'card-frame- (21)': 'assets/play/frame/card-frame- (21).png',
'card-frame- (22)': 'assets/play/frame/card-frame- (22).png',
'card-frame- (23)': 'assets/play/frame/card-frame- (23).png',
'card-frame- (24)': 'assets/play/frame/card-frame- (24).png',
'card-frame- (25)': 'assets/play/frame/card-frame- (25).png',
'card-frame- (26)': 'assets/play/frame/card-frame- (26).png',
'card-frame- (27)': 'assets/play/frame/card-frame- (27).png',
'card-frame- (28)': 'assets/play/frame/card-frame- (28).png',
'card-frame- (29)': 'assets/play/frame/card-frame- (29).png',
'card-frame- (3)': 'assets/play/frame/card-frame- (3).png',
'card-frame- (30)': 'assets/play/frame/card-frame- (30).png',
'card-frame- (31)': 'assets/play/frame/card-frame- (31).png',
'card-frame- (32)': 'assets/play/frame/card-frame- (32).png',
'card-frame- (33)': 'assets/play/frame/card-frame- (33).png',
'card-frame- (34)': 'assets/play/frame/card-frame- (34).png',
'card-frame- (4)': 'assets/play/frame/card-frame- (4).png',
'card-frame- (5)': 'assets/play/frame/card-frame- (5).png',
'card-frame- (6)': 'assets/play/frame/card-frame- (6).png',
'card-frame- (7)': 'assets/play/frame/card-frame- (7).png',
'card-frame- (8)': 'assets/play/frame/card-frame- (8).png',
'card-frame- (9)': 'assets/play/frame/card-frame- (9).png',
'card-frame- (35)': 'assets/play/frame/card-frame- (35).png',
'question-container': 'assets/play/question-container.png',
};
const localAudios = {
'sm-back': "assets/default/audio/sm-back.mp3",
'sm-display': "assets/default/audio/sm-display.mp3",
'sm-wrong': "assets/default/audio/sm-wrong.mp3",
'sm-win': "assets/default/audio/sm-win.mp3",
'sm-in': "assets/default/audio/sm-in.mp3",
'sm-out': "assets/default/audio/sm-out.mp3",
'sm-click': "assets/default/audio/sm-click.mp3",
'sm-start': "assets/default/audio/sm-start.mp3",
'sm-correct': 'assets/default/audio/sm-correct.mp3',
'sm-star': "assets/default/audio/sm-star.mp3",
'sm-choice-complete': 'assets/default/audio/sm-choice-complete.mp3',
'sm-choice-correct': 'assets/default/audio/sm-choice-correct.mp3',
'sm-choice-error': 'assets/default/audio/sm-choice-error.mp3',
'sm-choice-in': 'assets/default/audio/sm-choice-in.mp3',
'sm-choice-show-answer': 'assets/default/audio/sm-choice-show-answer.mp3',
'sm-choice-timeup-0': 'assets/default/audio/sm-choice-timeup-0.mp3',
'sm-choice-timeup-3': 'assets/default/audio/sm-choice-timeup-3.mp3',
'sm-go': 'assets/default/audio/sm-go.mp3',
'sm-ready': 'assets/default/audio/sm-ready.mp3',
const resAudio = [ 'skier': 'assets/audio/skier.mp3',
'win': 'assets/audio/win.mp3',
['click', "assets/play/music/click.mp3"], };
]; export {localImages, localAudios};
export {res, resAudio};
@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;
}
.anticon{
vertical-align: .1em!important;
}
import os
import json
def file_name(file_dir):
fileList =[]
for root, dirs, files in os.walk(file_dir):
fileList = files
return fileList
fileList = file_name(os.path.abspath('.'))
f = open('filename.txt', 'w')
for fn in fileList:
if fn.split(".")[0] != "creatJsonProfile":
f.write("'" + fn.split(".")[0] + "': 'assets/audio/" + fn + "',\n")
f.close()
\ No newline at end of file
'skier': 'assets/audio/skier.mp3',
'win': 'assets/audio/win.mp3',
import os
import json
def file_name(file_dir):
fileList =[]
for root, dirs, files in os.walk(file_dir):
fileList = files
return fileList
fileList = file_name(os.path.abspath('.'))
f = open('filename.txt', 'w')
for fn in fileList:
if fn.split(".")[0] != "creatJsonProfile":
f.write("'" + fn.split(".")[0] + "': 'assets/play/" + fn + "',\n")
f.close()
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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