From d8b62a10cc2237abc7787b56cf7be8cb10ae3d9a Mon Sep 17 00:00:00 2001
From: lmz <limingzhe@iplayabc.com>
Date: Fri, 27 Sep 2019 14:05:25 +0800
Subject: [PATCH] add upload-image-width-preview

---
 src/app/app.component.ts                      |   8 +-
 src/app/app.module.ts                         |  18 ++-
 .../upload-image-with-preview.component.html  |  37 +++++
 .../upload-image-with-preview.component.scss  | 101 ++++++++++++
 .../upload-image-with-preview.component.ts    | 149 ++++++++++++++++++
 src/app/pipes/background-image.pipe.ts        |  23 +++
 src/index.html                                |   8 +-
 tslint.json                                   |   9 +-
 8 files changed, 338 insertions(+), 15 deletions(-)
 create mode 100644 src/app/common/upload-image-with-preview/upload-image-with-preview.component.html
 create mode 100644 src/app/common/upload-image-with-preview/upload-image-with-preview.component.scss
 create mode 100644 src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts
 create mode 100644 src/app/pipes/background-image.pipe.ts

diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 9ffb6bc..c918314 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -1,4 +1,4 @@
-import { Component ,OnInit} from '@angular/core';
+import { Component , OnInit} from '@angular/core';
 
 @Component({
   selector: 'app-root',
@@ -6,11 +6,11 @@ import { Component ,OnInit} from '@angular/core';
   styleUrls: ['./app.component.scss']
 })
 export class AppComponent implements OnInit{
-  type = 'play';  
+  type = 'play';
 
-  constructor() { 
+  constructor() {
     let tp = this.getQueryString("type");
-    if(tp){
+    if (tp){
       this.type = tp;
     }
   }
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index ebea714..7d45083 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -3,20 +3,24 @@ import { BrowserModule } from '@angular/platform-browser';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
 import { NgModule } from '@angular/core';
 import { FormsModule } from '@angular/forms';
-import { HttpClientModule } from '@angular/common/http'; 
+import { HttpClientModule } from '@angular/common/http';
 import { NgZorroAntdModule, NZ_I18N, zh_CN } from 'ng-zorro-antd';
 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 { PlayComponent } from "./play/play.component";
+
+
 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'; 
+import { PlayerContentWrapperComponent } from './common/player-content-wrapper/player-content-wrapper.component';
 
 /** 配置 angular i18n **/
 import { registerLocaleData } from '@angular/common';
 import zh from '@angular/common/locales/zh';
+import {UploadImageWithPreviewComponent} from "./common/upload-image-with-preview/upload-image-with-preview.component";
+import {BackgroundImagePipe} from "./pipes/background-image.pipe";
 registerLocaleData(zh);
 
 @NgModule({
@@ -26,15 +30,19 @@ registerLocaleData(zh);
     PlayComponent,
     LessonTitleConfigComponent,
     AudioRecorderComponent,
+    UploadImageWithPreviewComponent,
+    BackgroundImagePipe,
+
     PlayerContentWrapperComponent
   ],
-  imports: [ 
+  imports: [
     FormsModule,
     HttpClientModule,
     BrowserAnimationsModule,
     BrowserModule,
     Angular2FontawesomeModule,
-    NgZorroAntdModule
+    NgZorroAntdModule,
+
   ],
   /** 配置 ng-zorro-antd 国际化(文案 及 日期) **/
   providers   : [
diff --git a/src/app/common/upload-image-with-preview/upload-image-with-preview.component.html b/src/app/common/upload-image-with-preview/upload-image-with-preview.component.html
new file mode 100644
index 0000000..5fdf4f1
--- /dev/null
+++ b/src/app/common/upload-image-with-preview/upload-image-with-preview.component.html
@@ -0,0 +1,37 @@
+<div class="position-relative">
+  <nz-upload class="p-image-uploader" [nzDisabled]="disableUpload"
+             [nzShowUploadList]="false"
+             nzAccept = "image/*"
+             [nzAction]="uploadUrl"
+             [nzData]="uploadData"
+              (nzChange)="handleChange($event)">
+             <!--[nzBeforeUpload]="customUpload">-->
+    <div class="p-box d-flex align-items-center">
+      <div class="p-upload-icon" *ngIf="!picUrl && !uploading">
+        <i nz-icon type="cloud-upload" theme="outline" [style.font-size]="iconSize + 'em'"></i>
+        <div class="m-3"></div>
+        <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 class="p-upload-progress-bg" *ngIf="uploading">
+        <div class="i-bg" [style.width]="progress+'%'"></div>
+        <div class="i-text">
+          <fa name="cloud-upload"></fa>
+          Uploading...
+        </div>
+      </div>
+      <div class="p-preview" *ngIf="!uploading && picUrl "
+           [style.background-image]="picUrl | backgroundImage ">
+      </div>
+    </div>
+  </nz-upload>
+  <div class="p-btn-delete" *ngIf="canDelete"
+       nz-popconfirm nzTitle="Are you sure ?"
+       (nzOnConfirm)="onDelete()"
+  >
+    <i nz-icon type="close" theme="outline"></i>
+  </div>
+</div>
diff --git a/src/app/common/upload-image-with-preview/upload-image-with-preview.component.scss b/src/app/common/upload-image-with-preview/upload-image-with-preview.component.scss
new file mode 100644
index 0000000..6008c35
--- /dev/null
+++ b/src/app/common/upload-image-with-preview/upload-image-with-preview.component.scss
@@ -0,0 +1,101 @@
+@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;
+}
diff --git a/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts b/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts
new file mode 100644
index 0000000..88aa192
--- /dev/null
+++ b/src/app/common/upload-image-with-preview/upload-image-with-preview.component.ts
@@ -0,0 +1,149 @@
+import {Component, EventEmitter, Input, OnChanges, OnDestroy, Output} from '@angular/core';
+import { NzMessageService, UploadXHRArgs, UploadFile } from 'ng-zorro-antd';
+
+
+@Component({
+  selector: 'app-upload-image-with-preview',
+  templateUrl: './upload-image-with-preview.component.html',
+  styleUrls: ['./upload-image-with-preview.component.scss']
+})
+export class UploadImageWithPreviewComponent implements OnDestroy, OnChanges {
+  uploading = false;
+  progress = 0;
+  @Input()
+  picUrl;
+  @Input()
+  canDelete = false;
+  @Output()
+  imageUploaded = new EventEmitter();
+  @Output()
+  imageUploadFailure = new EventEmitter();
+  @Output()
+  delete = new EventEmitter();
+  @Input()
+  picItem = null;
+  @Input()
+  iconSize = 2;
+  @Input()
+  TIP = 'Click here to upload image';
+  @Input()
+  disableUpload = false;
+
+  uploadUrl = (<any> window).courseware.uploadUrl();
+  uploadData = (<any> window).courseware.uploadData();
+
+  constructor(private nzMessageService: NzMessageService) {
+  }
+  ngOnChanges() {
+    if (!this.picItem) {
+      return;
+    }
+  }
+
+
+
+
+
+  handleChange(info: { type: string, file: UploadFile, event: any }): void {
+
+    console.log('info:' , info);
+
+    switch (info.type) {
+      case 'start':
+        // this.isUploading = true;
+        // this.progress = 0;
+
+        this.picUrl = null;
+        // this.beforeUpload(item.file as any);
+        if (!this.checkSelectFile(info.file)) {
+          return;
+        }
+        this.uploading = true;
+        this.progress = 0;
+
+        break;
+
+      case 'success':
+        // this.isUploading = false;
+        // this.uploadSuccess(info.file.response);
+        // this.audioUploaded.emit(info.file.response);
+
+        this.uploadSuccess(info.file);
+
+        break;
+      case 'progress':
+        this.progress = parseInt(info.event.percent, 10);
+        this.doProgress(this.progress);
+        break;
+    }
+  }
+
+  onDelete() {
+    this.delete.emit();
+  }
+  checkSelectFile(file) {
+    const isImg = ['image/jpeg', 'image/png', 'image/jpeg', 'image/gif', 'image/bmp'].includes(file.type);
+    if (!isImg) {
+      this.nzMessageService.error('You can only upload Image file (jpg|gif|png|bmp)');
+      return false;
+    }
+    const isGif = !['image/jpeg', 'image/png', 'image/jpeg', 'image/bmp'].includes(file.type);
+    const delta = isGif ? 20 : 5;
+    const isOverSize = file.size / 1024 / 1024 < delta;
+    if (!isOverSize) {
+      this.nzMessageService.error(`${isGif ? 'Gif' : 'Image'} must smaller than ${delta}MB!`);
+      return false;
+    }
+    return true;
+  }
+
+  uploadSuccess = (file) => {
+    this.nzMessageService.info('Upload Success');
+    this.uploading = false;
+    this.picUrl = file.response.url ;
+    // this.uploadFinished(url);
+    // if (!inOSS) {
+    const img = new Image();
+    img.addEventListener('load', () => {
+
+      const height = img.naturalHeight;
+      const width = img.naturalWidth;
+      file['height'] = height;
+      file['width'] = width;
+      img.remove();
+      this.imageUploaded.emit(file.response);
+      // this.resService.updateImage(id, {width, height}).then( () => {
+      //   this.imageUploaded.emit({res_id: id, id, name, hash, url});
+      // });
+
+    });
+    img.src = file.response.url;
+    // } else {
+    //   this.imageUploaded.emit({res_id: id, id, name, hash, url});
+    // }
+  }
+
+  uploadFailure = (err, file) => {
+    this.uploading = false;
+    if (err.name && err.name === 'cancel') {
+      return;
+    }
+    console.log(err);
+    this.nzMessageService.error('Upload Error ' + err.message);
+    this.imageUploadFailure.emit(file);
+  }
+
+  doProgress = function(p) {
+    if (p > 1) {
+      p = 1;
+    }
+    if (p < 0) {
+      p = 0;
+    }
+    // console.log(Math.floor(p * 100));
+    this.progress =  Math.floor(p * 100);
+  }
+  ngOnDestroy() {
+  }
+
+}
diff --git a/src/app/pipes/background-image.pipe.ts b/src/app/pipes/background-image.pipe.ts
new file mode 100644
index 0000000..bc15f66
--- /dev/null
+++ b/src/app/pipes/background-image.pipe.ts
@@ -0,0 +1,23 @@
+import {Pipe, PipeTransform} from '@angular/core';
+// import {ElectronUtil} from '../util/ElectronUtil';
+
+declare const APP_PATH;
+// const isInElectron = localStorage.getItem('electron');
+
+@Pipe({
+  name: 'backgroundImage'
+})
+export class BackgroundImagePipe implements PipeTransform {
+
+  transform(value: any, coursewareSid?: string) {
+    // const ret = value ? `url(${value})` : '';
+    const ret = value ? `url(${value})` : '';
+    return ret;
+    // let ret = value > 0 ? `url(/api/media-resource/${value}/file)` : '';
+    // if (isInElectron && ElectronUtil.hasCached(coursewareSid, value)) {
+    //   ret = `url(file://${APP_PATH}/courseware_cache/${coursewareSid}/${value})`;
+    // }
+    // return ret;
+  }
+
+}
diff --git a/src/index.html b/src/index.html
index 3e1848f..df57d46 100644
--- a/src/index.html
+++ b/src/index.html
@@ -33,7 +33,7 @@
                 }
               });
             },
-            setData: function(data,callback){ 
+            setData: function(data,callback){
               let str = JSON.stringify(data);
               net.getData("setCoursewareData",{id: id,data: str},function(res){
                 if(res){
@@ -58,7 +58,7 @@
         } else {
           return {
             getData: function(callback){
-              let data = localStorage.getItem("courseware_data");  
+              let data = localStorage.getItem("courseware_data");
               if(data){
                 data = JSON.parse(data);
               }
@@ -70,10 +70,10 @@
               callback&&callback();
             },
             uploadUrl: function(){
-              return "";
+              return 'http://localhost:3000/api/test';
             },
             uploadData: function(){
-              return "";
+              return {};
             }
           }
         }
diff --git a/tslint.json b/tslint.json
index f0adae9..f29eef2 100644
--- a/tslint.json
+++ b/tslint.json
@@ -62,6 +62,9 @@
     "no-switch-case-fall-through": true,
     "no-use-before-declare": true,
     "no-var-requires": false,
+
+    "no-shadowed-variable": false,
+
     "object-literal-key-quotes": [
       true,
       "as-needed"
@@ -84,9 +87,11 @@
     "template-banana-in-box": true,
     "template-no-negated-async": true,
     "use-lifecycle-interface": true,
-    "use-pipe-transform-interface": true
+    "use-pipe-transform-interface": true,
+    "no-trailing-whitespace": false,
+    "variable-name": false
   },
   "rulesDirectory": [
     "codelyzer"
   ]
-}
\ No newline at end of file
+}
-- 
2.21.0