Commit 65938874 authored by 范雪寒's avatar 范雪寒

feat: 初始form项目

parent 676b0d3c
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
/out-tsc
# Only exists if Bazel was run
/bazel-out
# dependencies
/node_modules
/publish
# profiling files
chrome-profiler-events*.json
speed-measure-plugin*.json
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings
# System Files
.DS_Store
Thumbs.db
This diff is collapsed.
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"ng-template-generator": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/ng-template-generator",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/favicon.ico",
"src/assets",
{
"glob": "**/*",
"input": "./node_modules/@ant-design/icons-angular/src/inline-svg/",
"output": "/assets/"
}
],
"styles": [
"./node_modules/ng-zorro-antd/ng-zorro-antd.min.css",
"src/styles.css"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "ng-template-generator:build"
},
"configurations": {
"production": {
"browserTarget": "ng-template-generator:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "ng-template-generator:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"./node_modules/ng-zorro-antd/ng-zorro-antd.min.css",
"src/styles.css"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "ng-template-generator:serve"
},
"configurations": {
"production": {
"devServerTarget": "ng-template-generator:serve:production"
}
}
}
}
}
},
"defaultProject": "ng-template-generator"
}
/****
* 批量编译打包模板工具
* 运行 npm run publish T_01 命令来打包T_01模板
* 运行 npm run publish T_01,T_02,T_03,T_04 命令来分别打包 T_01,T_02,T_03,T_04 这四个模板,注意逗号要用英文的
* 运行 npm run publish all 命令来打包所有模板
*/
const spawn = require('child_process').spawn;
const path = require("path");
const fs = require("fs");
const os = require('os');
const compressing = require("compressing");
//Linux系统上'Linux'
//macOS 系统上'Darwin'
//Windows系统上'Windows_NT'
let sysType = os.type();
Date.prototype.Format = function(fmt) {
var o = {
"M+" : this.getMonth() + 1,
"d+" : this.getDate(),
"h+" : this.getHours(),
"m+" : this.getMinutes(),
"s+" : this.getSeconds(),
"q+" : Math.floor((this.getMonth() + 3) / 3),
"S" : this.getMilliseconds()
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt))
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
}
function clean(zipPath){
if(fs.existsSync(zipPath)){
fs.unlinkSync(zipPath);
}
}
const runSpawn = async function (){
await new Promise(function(resolve,reject){
let pkg = require("../package.json");
let ls;
if(sysType==="Windows_NT"){
//ng build --prod --build--optimizer --base-href /ng-one/
ls = spawn("cmd.exe", ['/c', 'ng', 'build', '--prod', '--build--optimizer', '--base-href', '/template-base-href/'] );
}else{
ls = spawn("ng", ['build', '--prod', '--build--optimizer', '--base-href', '/template-base-href/'] );
}
ls.stdout.on('data', (data) => {
console.log(` ${data}`);
});
ls.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
reject();
});
ls.on('close', (code) => {
console.log(`child process exited with code ${code}`);
//要压缩的目录
let zippath = path.resolve(__dirname,"../dist", pkg.name);
//压缩包的存放目录
let date = new Date();
let zipname = pkg.name+"_"+date.Format("yyyyMMdd hh-mm-ss");
let zipdir = path.resolve(__dirname,"../publish/"+zipname+".zip");
clean(zipdir); //删除原有的包
const tarStream = new compressing.zip.Stream();
fs.readdir(zippath,function(err,files){
if(err){
console.log("======文件打开异常======");
console.log(err);
reject();
}
for(let i=0;i<files.length;i++){
tarStream.addEntry(zippath+"/"+files[i]);
}
let writeStream = fs.createWriteStream(zipdir);
tarStream.pipe(writeStream);
writeStream.on('close', () => {
console.log(`模板 ${pkg.name} 打包已完成!`);
resolve();
})
});
});
});
}
// let projects = "";
// if(process.argv.length<3){
// console.log("缺少参数");
// return;
// }
// projects = process.argv[2];
let exec = async function(){
//压缩模板
await runSpawn();
}
exec();
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# You can see what browsers were selected by your queries by running:
# npx browserslist
> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.
\ No newline at end of file
// @ts-check
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
/**
* @type { import("protractor").Config }
*/
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./src/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.json')
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};
\ No newline at end of file
import { AppPage } from './app.po';
import { browser, logging } from 'protractor';
describe('workspace-project App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getTitleText()).toEqual('Welcome to ng-one!');
});
afterEach(async () => {
// Assert that there are no errors emitted from the browser
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
expect(logs).not.toContain(jasmine.objectContaining({
level: logging.Level.SEVERE,
} as logging.Entry));
});
});
import { browser, by, element } from 'protractor';
export class AppPage {
navigateTo() {
return browser.get(browser.baseUrl) as Promise<any>;
}
getTitleText() {
return element(by.css('app-root h1')).getText() as Promise<string>;
}
}
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"jasminewd2",
"node"
]
}
}
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, './coverage/ng-one'),
reports: ['html', 'lcovonly', 'text-summary'],
fixWebpackSourcePaths: true
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true
});
};
This diff is collapsed.
{
"name": "ng-template-generator",
"version": "0.0.1",
"scripts": {
"start": "ng serve",
"build": "ng build --build--optimizer --aot --base-href /JGT/v3/",
"publish": "node ./bin/publish.js",
"ng": "ng",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "~9.0.2",
"@angular/common": "~9.0.2",
"@angular/compiler": "~9.0.2",
"@angular/core": "~9.0.2",
"@angular/forms": "~9.0.2",
"@angular/platform-browser": "~9.0.2",
"@angular/platform-browser-dynamic": "~9.0.2",
"@angular/router": "~9.0.2",
"@fortawesome/angular-fontawesome": "^0.6.0",
"@fortawesome/fontawesome-svg-core": "^1.2.27",
"@fortawesome/free-regular-svg-icons": "^5.12.1",
"@fortawesome/free-solid-svg-icons": "^5.12.1",
"@tweenjs/tween.js": "~18.5.0",
"ali-oss": "^6.5.1",
"compressing": "^1.5.0",
"ng-zorro-antd": "^8.5.2",
"rxjs": "~6.5.4",
"spark-md5": "^3.0.0",
"tslib": "^1.10.0",
"zone.js": "~0.10.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.900.3",
"@angular/cli": "~9.0.3",
"@angular/compiler-cli": "~9.0.2",
"@angular/language-service": "~9.0.2",
"@types/jasmine": "~3.5.0",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1",
"codelyzer": "^5.1.2",
"jasmine-core": "~3.5.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~4.3.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~2.1.0",
"karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.4.2",
"protractor": "~5.4.3",
"ts-node": "~8.3.0",
"tslint": "~5.18.0",
"typescript": "~3.7.5"
}
}
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
<app-form *ngIf="type==='form'"></app-form>
<app-play *ngIf="type==='play'"></app-play>
\ No newline at end of file
import { Component , OnInit} from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
type = 'play';
constructor() {
const tp = this.getQueryString('type');
if (tp) {
this.type = tp;
}
}
ngOnInit() {
}
getQueryString(name) {
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
const r = window.location.search.substr(1).match(reg);
if (r != null) {
return unescape(r[2]);
}
return null;
}
}
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, ErrorHandler } from '@angular/core';
import {MyErrorHandler} from './MyError';
import { AppComponent } from './app.component';
import { NgZorroAntdModule, NZ_I18N, zh_CN } from 'ng-zorro-antd';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { registerLocaleData } from '@angular/common';
import zh from '@angular/common/locales/zh';
import {FormComponent} from './form/form.component';
import {PlayComponent} from './play/play.component';
import {LessonTitleConfigComponent} from './common/lesson-title-config/lesson-title-config.component';
import {BackgroundImagePipe} from './pipes/background-image.pipe';
import {UploadImageWithPreviewComponent} from './common/upload-image-with-preview/upload-image-with-preview.component';
import {PlayerContentWrapperComponent} from './common/player-content-wrapper/player-content-wrapper.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);
@NgModule({
declarations: [
AppComponent,
FormComponent,
PlayComponent,
LessonTitleConfigComponent,
AudioRecorderComponent,
UploadImageWithPreviewComponent,
BackgroundImagePipe,
ResourcePipe,
TimePipe,
UploadVideoComponent,
CustomHotZoneComponent,
PlayerContentWrapperComponent
],
imports: [
BrowserModule,
NgZorroAntdModule,
FormsModule,
HttpClientModule,
BrowserAnimationsModule,
FontAwesomeModule
],
providers: [
{provide: ErrorHandler, useClass: MyErrorHandler},
{ provide: NZ_I18N, useValue: zh_CN }
],
bootstrap: [AppComponent]
})
export class AppModule {
constructor(library: FaIconLibrary) {
library.addIconPacks(fas, far);
}
}
<div class="d-flex">
<div class="p-btn-record d-flex">
<div class="btn-clear" style="cursor: pointer" (click)="onBtnClearAudio()" *ngIf="withRmBtn && (audioUrl || audioBlob)">
<fa-icon icon="times"></fa-icon>
</div>
<div class="btn-record" *ngIf="type===Type.RECORD && !isUploading"
[class.p-recording]="isRecording"
(click)="onBtnRecord()">
<fa-icon icon="microphone"></fa-icon>
Record Audio
</div>
<nz-upload
[nzAccept] = "'.mp3'"
[nzShowUploadList]="false"
[nzAction]="uploadUrl"
[nzData]="uploadData"
(nzChange)="handleChange($event)">
<div class="btn-upload" [ngClass]="{'has-clear': withRmBtn && (audioUrl || audioBlob)}" *ngIf="type===Type.UPLOAD && !isUploading">
<fa-icon icon="upload"></fa-icon>
Upload Audio
</div>
</nz-upload>
<div class="p-upload-progress-bg" *ngIf="isUploading">
<div class="i-bg" [style.width]="progress+'%'"></div>
<div class="i-text">
<fa-icon icon="cloud-upload-alt"></fa-icon>
Uploading...
</div>
</div>
<div *ngIf="audioUrl && needRemove; then truthyTemplate else falsyTemplate"></div>
<ng-template #truthyTemplate >
<div class="btn-delete" (click)="onBtnDeleteAudio()">
<fa-icon icon="close"></fa-icon>
</div>
</ng-template>
<ng-template #falsyTemplate>
<div class="btn-switch" (click)="onBtnSwitchType()">
<fa-icon icon="cog"></fa-icon>
</div>
</ng-template>
</div>
<div class="p-progress ml-2" (click)="onBtnPlay()" *ngIf="audioUrl || audioBlob">
<nz-progress [nzPercent]="percent" [nzWidth]="30" [nzFormat]="progressText"
nzType="circle"></nz-progress>
<div class="p-btn-play" [style.left]="isPlaying?'8px':''">
<fa-icon [icon]="playIcon"></fa-icon>
</div>
</div>
</div>
.d-flex{
display: flex;
}
.p-btn-record {
font-size: 0.9rem;
color: #555;
font-family: "Monospaced Number", "Chinese Quote", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
.btn-record, .btn-upload {
cursor: pointer;
text-align: center;
width: 130px;
height: 33px;
line-height: 33px;
border-radius: 0.5rem 0 0 0.5rem;
border: 1px solid #ddd;
border-right: 0.5px;
&:hover {
color: rgb(64, 169, 255);
}
}
.btn-record.has-clear, .btn-upload.has-clear{
border-radius:0;
border-left: 0;
}
.btn-clear{
text-align: center;
color: #aaa;
padding: 0 0.5rem;
border: 1px solid #ddd;
border-radius: 0.5rem 0 0 0.5rem;
height: 33px;
line-height: 33px;
}
.btn-switch {
text-align: center;
color: #aaa;
padding: 0 0.5rem;
border: 1px solid #ddd;
border-radius: 0 0.5rem 0.5rem 0;
height: 33px;
line-height: 33px;
&:hover {
color: rgb(64, 169, 255);
}
}
.btn-delete {
text-align: center;
color: #aaa;
padding: 0 0.5rem;
border: 1px solid #ddd;
border-radius: 0 0.5rem 0.5rem 0;
height: 33px;
line-height: 33px;
&:hover {
color: #ec5b56;
}
}
}
.p-recording {
background: orangered;
color: white !important;
}
.p-upload-progress-bg {
position: relative;
width: 130px;
height: 33px;
line-height: 33px;
& .i-text {
position: absolute;
width: 100%;
height: 100%;
text-align: center;
border-radius: 0.5rem 0 0 0.5rem;
border: 1px solid #ddd;
border-right: 0.5px;
color: white;
text-shadow: 0 0 2px rgba(0, 0, 0, .85);
}
& .i-bg {
position: absolute;
left: 0;
top: 0;
height: 100%;
background-color: #27b43f;
border-radius: 0.5rem 0 0 0.5rem;
}
}
.p-progress {
margin-top: 2px;
position: relative;
line-height: 26px;
.p-btn-play {
position: absolute;
left: 10px;
top: 3px;
color: #555;
}
}
:host ::ng-deep nz-upload {
line-height: 33px;
}
import {Component, EventEmitter, Input, OnDestroy, OnInit, Output, NgZone, OnChanges} from '@angular/core';
import {NzMessageService, NzNotificationService, UploadFile} from 'ng-zorro-antd';
import {HttpClient, HttpEvent, HttpEventType, HttpRequest} from '@angular/common/http';
import {environment} from '../../../environments/environment';
declare var Recorder;
@Component({
selector: 'app-audio-recorder',
templateUrl: './audio-recorder.component.html',
styleUrls: ['./audio-recorder.component.scss']
})
export class AudioRecorderComponent implements OnInit, OnChanges, OnDestroy {
_audioUrl: string;
audio = new Audio();
playIcon = 'play';
isPlaying = false;
isRecording = false;
isUploading = false;
type = Type.UPLOAD; // record | upload
Type = Type;
@Input()
withRmBtn = false;
uploadUrl;
uploadData;
@Input()
needRemove = false;
@Input()
audioItem: any = null;
@Input()
set audioUrl(url) {
this._audioUrl = url;
if (url) {
this.audio.src = this._audioUrl;
this.audio.load();
}
this.init();
}
get audioUrl() {
return this._audioUrl;
}
@Output() audioUploaded = new EventEmitter();
@Output() audioUploadFailure = new EventEmitter();
@Output() audioRemoved = new EventEmitter();
percent = 0;
progress = 0;
recorder: any;
audioBlob: any;
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() {
this.playIcon = 'play';
this.isPlaying = false;
this.isRecording = false;
this.isUploading = false;
this.percent = 0;
this.progress = 0;
this.audioBlob = null;
}
ngOnChanges() {
// if (!this.audioItem || !this.audioItem.type) {
// return;
// }
// this.beforeUpload(this.audioItem);
}
ngOnInit() {
this.audio.onplay = () => {
this.onPlay();
};
this.audio.onpause = () => {
this.onPause();
};
this.audio.ontimeupdate = (event) => {
this.onTimeUpdate(event);
};
this.audio.onended = (event) => {
this.onEnded();
};
}
ngOnDestroy() {
this.audio.pause();
this.isPlaying = false;
this.audio.remove();
// if (this.recorder.worker) {
// this.recorder.worker.terminate();
// }
}
progressText(percent) {
return ``;
}
onPlay() {
console.log('play');
this.playIcon = 'pause';
this.isPlaying = true;
}
onPause() {
console.log('pause');
this.playIcon = 'play';
this.isPlaying = false;
}
onEnded() {
console.log('on end');
this.playIcon = 'play';
this.percent = 0;
this.isPlaying = false;
}
onTimeUpdate(event) {
this.percent = Math.floor((this.audio.currentTime / this.audio.duration) * 100);
}
onBtnPlay() {
if (this.isRecording) {
this.nzMessageService.warning('In Recording');
return;
}
if (this.isPlaying) {
this.audio.pause();
} else {
this.audio.play();
}
}
// 开始录音
onBtnRecord = () => {
}
// 切换模式
onBtnSwitchType() {
}
onBtnClearAudio() {
this.audioUrl = null;
this.audioRemoved.emit();
}
onBtnDeleteAudio() {
this.audioUrl = null;
this.audioRemoved.emit();
}
handleChange(info: { type: string, file: UploadFile, event: any }): void {
switch (info.type) {
case 'start':
this.isUploading = true;
this.progress = 0;
break;
case 'success':
this.isUploading = false;
this.uploadSuccess(info.file.response);
this.audioUploaded.emit(info.file.response);
break;
case 'progress':
this.progress = parseInt(info.event.percent, 10);
break;
}
}
checkSelectFile(file: any) {
if (!file) {
return;
}
const isAudio = ['audio/mp3', 'audio/wav', 'audio/ogg'].includes(file.type);
if (!isAudio) {
this.nzMessageService.error('You can only upload Audio file ( mp3 | wav |ogg)');
return;
}
const delta = 25;
const isOverSize = (file.size / 1024 / 1024) < delta;
if (!isOverSize) {
this.nzMessageService.error(`audio file must smaller than ${delta}MB!`);
return false;
}
return true;
}
beforeUpload = (file: File) => {
this.audioUrl = null;
if (!this.checkSelectFile(file)) {
return false;
}
this.isUploading = true;
this.progress = 0;
}
uploadSuccess = (url) => {
this.nzMessageService.info('Upload Success');
this.isUploading = false;
this.audioUrl = url;
}
uploadFailure = (err, file) => {
this.isUploading = false;
if (err.name && err.name === 'cancel') {
return;
}
console.log(err);
this.nzMessageService.error('Upload Error ' + err.message);
this.audioUploadFailure.emit(file);
}
doProgress = (p) => {
if (p > 1) {
p = 1;
}
if (p < 0) {
p = 0;
}
// console.log(Math.floor(p * 100));
this.progress = Math.floor(p * 100);
}
}
enum Type {
RECORD = 1, UPLOAD
}
This diff is collapsed.
<div class="p-image-children-editor">
<h5 style="margin-left: 2.5%;"> preview: </h5>
<div class="preview-box" #wrap>
<canvas id="canvas" #canvas></canvas>
</div>
<div nz-row nzType="flex" nzAlign="middle">
<div nz-col nzSpan="5" nzOffset="1">
<h5> add background: </h5>
<div class="bg-box">
<app-upload-image-with-preview
[picUrl]="bgItem?.url"
(imageUploaded)="onBackgroundUploadSuccess($event)">
</app-upload-image-with-preview>
</div>
</div>
<div nz-col nzSpan="5" nzOffset="1" class="img-box"
*ngFor="let it of hotZoneArr; let i = index">
<div
style="margin: auto; padding: 5px; margin-top: 30px; width:90%; border: 2px dashed #ddd; border-radius: 10px">
<span style="margin-left: 40%;"> item-{{i + 1}}
</span>
<button style="float: right;" nz-button nzType="danger" nzSize="small" (click)="deleteBtnClick(i)">
X
</button>
<nz-divider style="margin-top: 10px;"></nz-divider>
<div style="margin-top: -20px; margin-bottom: 5px">
<nz-radio-group [ngModel]="it.itemType" (ngModelChange)="radioChange($event, it)">
<label *ngIf="isHasRect" nz-radio nzValue="rect">矩形</label>
<label *ngIf="isHasPic" nz-radio nzValue="pic">图片</label>
<label *ngIf="isHasText" nz-radio nzValue="text">文本</label>
</nz-radio-group>
</div>
<div *ngIf="it.itemType == 'pic'">
<app-upload-image-with-preview
[picUrl]="it?.pic_url"
(imageUploaded)="onItemImgUploadSuccess($event, it)">
</app-upload-image-with-preview>
</div>
<div *ngIf="it.itemType == 'text'">
<input type="text" nz-input [(ngModel)]="it.text" (blur)="saveText(it)">
</div>
<div style="width: 100%; margin-top: 5px;">
<app-audio-recorder
[audioUrl]="it.audio_url"
(audioUploaded)="onItemAudioUploadSuccess($event, it)"
></app-audio-recorder>
</div>
</div>
</div>
<div nz-col nzSpan="5" nzOffset="1">
<div class="bg-box">
<button nz-button nzType="dashed" (click)="addBtnClick()"
class="add-btn">
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>
<!--Add Image-->
Add hot zone
</button>
</div>
</div>
</div>
<nz-divider></nz-divider>
<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>
<label style="opacity: 0; position: absolute; top: 0px; font-family: 'BRLNSR_1'">1</label>
.p-image-children-editor {
width: 100%;
height: 100%;
border-radius: 0.5rem;
border: 2px solid #ddd;
.preview-box {
margin: auto;
width: 95%;
height: 35vw;
border: 2px dashed #ddd;
border-radius: 0.5rem;
background-color: #fafafa;
text-align: center;
color: #aaa;
.preview-img {
height: 100%;
width: auto;
}
}
.bg-box{
//width: 100%;
margin-bottom: 1rem;
}
.img-box {
margin-bottom: 1rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.img-box-upload{
width: 80%;
}
.add-btn {
margin-top: 1rem;
width: 200px;
height: 90px;
display: flex;
align-items: center;
justify-content: center;
}
}
.save-box {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
.save-btn {
width: 160px;
height: 40px;
//margin-top: 20px;
margin-bottom: 20px;
display: flex;
align-items: center;
justify-content: center;
}
}
h5 {
margin-top: 1rem;
}
@font-face
{
font-family: 'BRLNSR_1';
src: url("/assets/font/BRLNSR_1.TTF") ;
}
//@import '../../../style/common_mixin';
//
//.p-image-uploader {
// position: relative;
// display: block;
// width: 100%;
// height: 0;
// padding-bottom: 56.25%;
// .p-box {
// position: absolute;
// left: 0;
// top: 0;
// right: 0;
// bottom: 0;
// border: 2px dashed #ddd;
// border-radius: 0.5rem;
// background-color: #fafafa;
// text-align: center;
// color: #aaa;
// .p-upload-icon {
// text-align: center;
// margin: auto;
// .anticon-upload {
// color: #888;
// font-size: 5rem;
// }
// .p-progress-bar {
// position: relative;
// width: 20rem;
// height: 1.5rem;
// border: 1px solid #ccc;
// border-radius: 1rem;
// .p-progress-bg {
// background-color: #1890ff;
// border-radius: 1rem;
// height: 100%;
// }
// .p-progress-value {
// position: absolute;
// top: 0;
// left: 0;
// width: 100%;
// height: 100%;
// text-shadow: 0 0 4px #000;
// color: white;
// text-align: center;
// font-size: 0.9rem;
// line-height: 1.5rem;
// }
// }
// }
// .p-preview {
// width: 100%;
// height: 100%;
// //background-image: url("https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png");
// @include k-img-bg();
// }
// }
//}
//
//.p-btn-delete {
// position: absolute;
// right: -0.5rem;
// top: -0.5rem;
// width: 2rem;
// height: 2rem;
// border: 0.2rem solid white;
// border-radius: 50%;
// font-size: 1.2rem;
// background-color: #fb781a;
// color: white;
// text-align: center;
//}
//
//.p-upload-progress-bg {
// position: absolute;
// width: 100%;
// height: 100%;
// display: flex;
// align-items: center;
// justify-content: center;
// & .i-text {
// position: absolute;
// text-align: center;
// color: white;
// text-shadow: 0 0 2px rgba(0, 0, 0, .85);
// }
// & .i-bg {
// position: absolute;
// left: 0;
// top: 0;
// height: 100%;
// background-color: #27b43f;
// border-radius: 0.5rem;
// }
//}
//
//
//:host ::ng-deep .ant-upload {
// display: block;
//}
<div class="title-config">
<div class="title-wrap">
<div class="row" style="margin: 5px;">
<div class="p-content" style="width:100%">
<div class="p-tool-box d-flex" style="background: #fff;">
<nz-select class="ml-1" style="width: 120px;" [(ngModel)]="__fontFamily"
(ngModelChange)="onChangeFontFamily($event)"
nzPlaceHolder="Font Family"
[nzDropdownMatchSelectWidth]="false">
<nz-option [nzValue]="font" nzCustomContent [nzLabel]="font" *ngFor="let font of fontFamilyList">
<span [ngStyle]="{'font-family': font}" >{{font}}</span>
</nz-option>
</nz-select>
<nz-select class="ml-1" style="width: 110px;" [(ngModel)]="__fontSize"
(ngModelChange)="onChangeFontSize()"
nzPlaceHolder="Font Size">
<nz-option [nzValue]="i" [nzLabel]="'Size - ' + i" *ngFor="let i of fontSizeRange"></nz-option>
</nz-select>
<div class="p-divider"></div>
<div class="i-tool-font-btn d-flex mr-2">
<div class="position-relative fa-icon" (click)="onChangeBold()">
<!-- <div class="fa fa-bold"></div>-->
<fa-icon icon="bold"></fa-icon>
</div>
</div>
<div class="i-tool-font-btn d-flex mr-2">
<div class="position-relative fa-icon" (click)="onChangeItalic()">
<!-- <div class="fa fa-italic"></div>-->
<fa-icon icon="italic"></fa-icon>
</div>
</div>
<div class="i-tool-font-btn d-flex mr-2">
<div class="position-relative fa-icon" (click)="onChangeUnderline()">
<!-- <div class="fa fa-underline"></div>-->
<fa-icon icon="underline"></fa-icon>
</div>
</div>
<div class="i-tool-font-btn d-flex">
<div class="position-relative fa-icon" (click)="onChangeStrikethrough()">
<!-- <div class="fa fa-strikethrough"></div>-->
<fa-icon icon="strikethrough"></fa-icon>
</div>
</div>
<div class="p-divider"></div>
<div class="i-tool-font-color d-flex">
<div class="position-relative i-left flex-fill" (click)="onChangeFontColor($event)">
<!-- <div class="fa fa-font"></div>-->
<fa-icon icon="palette"></fa-icon>
<div class="i-color" [style.background-color]="__fontColor"></div>
</div>
<div class="i-dropdown-menu" nzPlacement="bottom"
nz-popover [(nzVisible)]="isShowFontColorPane" nzTrigger="click"
[nzContent]="colorPane">
<i nz-icon type="down" theme="outline"></i>
</div>
</div>
<div class="p-divider"></div>
<div style="background: #fff;display: block;">
<div class="position-relative">
<app-audio-recorder [audioUrl]="titleObj && titleObj.audio_url" (audioUploaded)="titleAudioUploaded($event)"></app-audio-recorder>
</div>
</div>
</div>
<div class="width-100 d-flex">
<iframe #titleEl id="titleContentEgret" frameborder="0" style="overflow: hidden;width: 100%; height:48px; margin: 0; padding: 0;"></iframe>
</div>
</div>
<ng-template #colorPane>
<div class="p-color-pane" nz-row nzGutter="16" nzType="flex">
<div nz-col class="p-color-item" *ngFor="let color of colorList"
[style.background-color]="color"
(click)="onSelectColor(color)"
>
</div>
</div>
</ng-template>
</div>
</div>
</div>
<div class="cmp-player-content-wrapper" #wrapperEl>
<div class="cmp-cnt-box">
<img [src]="'assets/'+ratio+'.png'" alt="">
<div class="cmp-cnt-main">
<ng-content></ng-content>
</div>
</div>
</div>
\ No newline at end of file
@import '../../style/common_mixin.css';
.cmp-player-content-wrapper{
max-height: 100%;
display: block;
position: relative;
height: 100%;
.cmp-cnt-box{
display: inline-block;
max-width: 100%;
max-height: 100%;
width: auto;
height: 100%;
position: relative;
img{
height: 100%;
width: auto;
}
}
.cmp-cnt-main{
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
flex-direction: column;
}
}
[style*="--aspect-ratio"] > :first-child {
width: 100%;
}
[style*="--aspect-ratio"] > img {
height: auto;
}
@supports (--custom:property) {
[style*="--aspect-ratio"] {
position: relative;
}
[style*="--aspect-ratio"]::before {
content: "";
display: block;
padding-bottom: calc(100% / (var(--aspect-ratio)));
}
[style*="--aspect-ratio"] > :first-child {
position: absolute;
top: 0;
left: 0;
height: 100%;
}
}
import {
AfterViewInit,
Component,
ElementRef,
Input,
OnChanges,
OnDestroy,
OnInit,
ViewChild
} from '@angular/core';
@Component({
selector: 'app-player-content-wrapper',
templateUrl: './player-content-wrapper.component.html',
styleUrls: ['./player-content-wrapper.component.scss']
})
export class PlayerContentWrapperComponent implements OnInit, OnChanges, OnDestroy, AfterViewInit {
@ViewChild('wrapperEl', {static: true }) wrapperEl: ElementRef;
// // aspect ratio?
@Input() ratio;
_w: string;
_h: string;
constructor() {
if (window.innerHeight < window.innerWidth) {
this._h = '100%';
this._w = 'auto';
} else {
this._w = '100%';
this._h = 'auto';
}
}
ngOnInit() {
if (!this.ratio) {
this.ratio = '20-9';
}
}
ngOnChanges() {
}
ngOnDestroy(): void {
}
ngAfterViewInit() {
}
}
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.
<div class="game-container" #wrap>
<canvas id="canvas" #canvas></canvas>
</div>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
global css to mixin
*/
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