feature: fix component name

This commit is contained in:
Sagi 2022-09-24 13:27:34 +08:00
parent cdf6f35522
commit 9ca315e15b
11 changed files with 528 additions and 28 deletions

View File

@ -7,3 +7,13 @@ export interface UseImage {
imageTitle: ComputedRef<string>;
}
export interface ImageFile {
size: number;
name: string;
type: string;
lastModified?: string;
lastModifiedDate?: Date;
state?: string;
base64?: string;
}

View File

@ -1,5 +1,8 @@
import { stringLiteral } from '@babel/types';
import { SetupContext } from 'vue';
import { resourceLimits } from 'worker_threads';
import { AvatarProps } from '../avatar.props';
import { ImageFile } from './types';
export function useFile(props: AvatarProps, context: SetupContext, allowTypes: string[]) {
function getFileData($event: Event) {
@ -39,36 +42,51 @@ export function useFile(props: AvatarProps, context: SetupContext, allowTypes: s
fileInput.value = '';
}
transformFile(getfile: any) {
// const subject = new Subject();
this.imgFileObj = {
size: getfile.size,
name: getfile.name,
type: getfile.type,
lastModified: getfile.lastModified,
lastModifiedDate: getfile.lastModifiedDate
}
this.do(getfile).subscribe(res => {
this.loadingImg = false;
if (res['state'] === 'done') {
this.imgSrc = res['result'];
function readSourceFile(sourceFile: File): Promise<{ state: string; content: string | ArrayBuffer | null }> {
const result = new Promise<{ state: string; content: string | ArrayBuffer | null }>((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(sourceFile);
reader.onload = () => {
resolve({ state: 'done', content: reader.result });
};
reader.onerror = function () {
reject({ state: 'error', content: reader.result });
};
});
return result;
}
//this.onChangeCallback(this.imgSrc);
this.onChangeCallback(this.removeBase64(this.imgSrc));
this.onTouchedCallback();
}
else if (res['state'] === 'error') {
let uploaderrorText = this.localeService.getValue('avatar.uploadError');
function updateImageSrc(imageSrc: string) {}
function removeBase64(imageSrc: string) {}
function transformFile(sourceFile: File) {
// const subject = new Subject();
const imageFile: ImageFile = {
size: sourceFile.size,
name: sourceFile.name,
type: sourceFile.type,
lastModified: String(sourceFile.lastModified),
};
readSourceFile(sourceFile)
.then((result) => {
if (result.state === 'done') {
updateImageSrc(result.content as string);
const imageFileContent = removeBase64(imageSrc);
context.emit('change', imageFileContent);
context.emit('touched');
imageFile.state = result.state;
imageFile.base64 = result.content as string;
context.emit('imageChange', imageFile);
}
})
.catch((reason) => {
const uploadErrorText = this.localeService.getValue('avatar.uploadError');
this.notifyService.error({
type: 'error',
title: '',
msg: uploaderrorText
})
// this.notifyService.error('图片上传失败,请重试!');
}
this.imgFileObj.state = res['state'];
this.imgFileObj.base64 = res['result'];
this.imgChange.emit(this.imgFileObj);
});
msg: uploadErrorText,
});
});
}
}

View File

@ -2,7 +2,7 @@ import { computed, SetupContext } from 'vue';
import { AvatarProps } from '../avatar.props';
import { UseImage } from './types';
export function useImage(props: AvatarProps, context: SetupContext): UseImage {
export function useImage(props: AvatarProps, context: SetupContext, fileInput: HTMLInputElement): UseImage {
const defaultImage = '';
const errorImage = '';
@ -56,5 +56,16 @@ export function useImage(props: AvatarProps, context: SetupContext): UseImage {
return props.readonly ? '' : props.tile;
});
function onClickImage() {
if (this.readonly) {
return;
}
fileInput.click();
}
function getImageFile() {
return this.imgFileObj;
}
return { acceptTypes, imageSrc, imageTitle };
}

View File

@ -0,0 +1,222 @@
import { Component, Input, ViewChildren, QueryList, AfterContentChecked, OnInit, Output, EventEmitter, NgZone, HostListener } from '@angular/core';
import { NotifyConfig, NotifyData } from './notifiy.options';
import { isFunction } from 'lodash-es';
import { NotifyComponent } from './notify.component';
@Component({
selector: 'farris-notify-container',
template: `
<div [id]="id" class="farris-notify" [ngClass]="[position]" [ngStyle]="style">
<farris-notify *ngFor="let toast of toasts" [toast]="toast" [animateCls]="animateCls" (close)="closeToast(toast)" (btnClick)="btnClickHander($event,toast)"></farris-notify>
</div>
`
})
export class NotifyContainerComponent implements OnInit, AfterContentChecked {
static POSITIONS: Array<String> = ['bottom-right', 'bottom-left',
'top-right', 'top-left', 'top-center', 'bottom-center', 'center-center'];
static ANIMATES: Array<string> = ['bounceInRight', 'bounceInLeft',
'bounceInRight', 'bounceInLeft', 'bounceInDown', 'bounceInUp', 'bounceIn'];
private _position = '';
style = {
'left': '',
'right': '',
'top': '',
'bottom': ''
};
notifyDistance = {
'left': 12,
'right': 12,
'top': 136,
'bottom': 12
};
animateCls = 'fadeIn';
config: NotifyConfig;
id = '';
@ViewChildren(NotifyComponent) notifyCmpList: QueryList<NotifyComponent>;
@Output() empty = new EventEmitter();
@Input() set position(value: string) {
if (value) {
let notFound = true;
for (let i = 0; i < NotifyContainerComponent.POSITIONS.length; i++) {
if (NotifyContainerComponent.POSITIONS[i] === value) {
notFound = false;
break;
}
}
if (notFound) {
value = this.config.position;
}
} else {
value = this.config.position;
}
// console.log(this.config);
// if (value === 'center-center') {
// this.animateCls = 'bounceIn';
// } else {
const i = NotifyContainerComponent.POSITIONS.indexOf(value);
//this.animateCls = NotifyContainerComponent.ANIMATES[i];
this.animateCls = 'fadeIn';
//}
this._position = 'toasty-position-' + value;
if (this.config.left) {
this.notifyDistance.left = this.config.left;
}
if (this.config.right) {
this.notifyDistance.right = this.config.right;
}
if (this.config.top) {
this.notifyDistance.top = this.config.top;
}
if (this.config.bottom) {
this.notifyDistance.bottom = this.config.bottom;
}
this.initstyle();
if (value === 'top-left') {
this.style.left = `${this.notifyDistance.left}px`;
this.style.top = `${this.notifyDistance.top}px`;
}
else if (value === 'top-center') {
this.style.top = `${this.notifyDistance.top}px`;
}
else if (value === 'top-right') {
this.style.right = `${this.notifyDistance.right}px`;
this.style.top = `${this.notifyDistance.top}px`;
}
else if (value === 'bottom-left') {
this.style.left = `${this.notifyDistance.left}px`;
this.style.bottom = `${this.notifyDistance.bottom}px`;
}
else if (value === 'bottom-center') {
this.style.bottom = `${this.notifyDistance.bottom}px`;
}
else if (value === 'bottom-right') {
this.style.right = `${this.notifyDistance.right}px`;
this.style.bottom = `${this.notifyDistance.bottom}px`;
}
}
get position() {
if (this._position) {
return this._position;
} else {
return 'toasty-position-top-center';
}
}
initstyle() {
this.style = {
'left': '',
'right': '',
'top': '',
'bottom': ''
};
}
toasts: Array<NotifyData> = [];
constructor(private ngZone: NgZone) { }
ngOnInit() {}
@HostListener('click', ['$event'])
onContainerClick($event: MouseEvent) {
$event.stopPropagation();
return false;
}
ngAfterContentChecked() {
if (this.notifyCmpList && this.notifyCmpList.length) {
this.notifyCmpList.forEach(cmp => {
cmp.close.subscribe(() => {
this.clear(cmp.toast.id);
});
});
}
}
closeToast(toast: NotifyData) {
this.clear(toast.id);
}
add(notify: NotifyData) {
if (this.toasts.length >= this.config.limit) {
this.toasts.shift();
}
this.toasts.push(notify);
if (notify.timeout) {
this._setTimeout(notify);
}
}
clear(id: number | string) {
if (id) {
this.toasts.forEach((value: any, key: number) => {
if (value.id === id) {
if (value.onRemove && isFunction(value.onRemove)) {
value.onRemove.call(this, value);
}
this.toasts.splice(key, 1);
}
});
if (this.toasts.length === 0) {
this.empty.emit();
}
} else {
throw new Error('Please provide id of Toast to close');
}
}
clearAll() {
this.toasts.forEach((value: any, key: number) => {
if (value.onRemove && isFunction(value.onRemove)) {
value.onRemove.call(this, value);
}
});
this.toasts = [];
this.empty.emit();
}
private findNotifyComponent(id: number | string) {
return this.notifyCmpList.find(item => item.toast.id === id);
}
private _setTimeout(notify: NotifyData) {
// this.ngZone.runOutsideAngular(() => {
window.setTimeout(() => {
// this.clear(notify.id);
const cmp = this.findNotifyComponent(notify.id);
if (cmp) {
cmp.state = true;
cmp.inCls[cmp.animateCls] = false;
}
}, notify.timeout);
// });
}
btnClickHander(ev, notify: NotifyData) {
const cmp = this.findNotifyComponent(notify.id);
ev.callback(ev['ev'], cmp);
}
}

View File

@ -0,0 +1,223 @@
import {
Component,
OnInit,
OnChanges,
Input,
Output,
EventEmitter,
ViewChild,
ElementRef,
SimpleChanges,
NgZone,
TemplateRef
} from '@angular/core';
import { NotifyData,NotifyButton } from './notifiy.options';
@Component({
selector: 'farris-notify',
template: `
<div #notifyDiv class="toast" [ngClass]="inCls">
<button *ngIf="toast.showClose" class="toast-close f-btn-icon f-bare" (click)="closeToast($event)">
<span class="f-icon modal_close"></span>
</button>
<section class="modal-tips" *ngIf="toast.title || toast.msg">
<div class="float-left modal-tips-iconwrap">
<span class="f-icon" [ngClass]=" getPurType()"></span>
</div>
<div class="modal-tips-content">
<ng-container *ngIf="toast.title&&toast.msg">
<h5 class="toast-title modal-tips-title" [innerHTML]="toast.title | safe: 'html'"></h5>
<p class="toast-msg" [innerHtml]="toast.msg | safe:'html'"></p>
<div class="after-toast-msg text-right" *ngIf="toast.buttons">
<ng-container [ngTemplateOutlet]="useButtonsTemplate() ? toast.buttons : defaultButtonRef"></ng-container>
</div>
</ng-container>
<ng-container *ngIf="!toast.title&&toast.msg">
<ng-container *ngIf="toast.buttons" >
<div class="toast-title-btns-wrapper d-flex" >
<h5 class="toast-title modal-tips-title only-toast-msg" [innerHtml]="toast.msg | safe:'html'"></h5>
<div class="after-toast-title text-right ml-auto">
<ng-container [ngTemplateOutlet]="useButtonsTemplate() ? toast.buttons : defaultButtonRef"></ng-container>
</div>
</div>
</ng-container>
<ng-container *ngIf="!toast.buttons" >
<h5 class="toast-title modal-tips-title only-toast-msg" [innerHtml]="toast.msg | safe:'html'"></h5>
</ng-container>
</ng-container>
</div>
</section>
</div>
<ng-template #defaultButtonRef>
<span class="'f-preten-link '+btn.cls?btn.cls:''" *ngFor="let btn of toast.buttons; last as isLast"
(click)="clickHandler($event,btn) ">
{{ btn.text }}
</span>
</ng-template>
`,
styles: [
`
.toast-title-beforeshow{
opacity:0;
}
@-webkit-keyframes farrisMoveUpIn {
0% {
transform: translateY(-100%);
transform-origin: 0 0;
opacity: 0
}
100% {
transform: translateY(0);
transform-origin: 0 0;
opacity: 1
}
}
@keyframes farrisMoveUpIn {
0% {
transform: translateY(-100%);
transform-origin: 0 0;
opacity: 0
}
100% {
transform: translateY(0);
transform-origin: 0 0;
opacity: 1
}
}
@-webkit-keyframes farrisMoveUpOut {
0% {
transform: translateY(0);
transform-origin: 0 0;
opacity: 1
}
100% {
transform: translateY(-100%);
transform-origin: 0 0;
opacity: 0
}
}
@keyframes farrisMoveUpOut {
0% {
transform: translateY(0);
transform-origin: 0 0;
opacity: 1
}
100% {
transform: translateY(-100%);
transform-origin: 0 0;
opacity: 0
}
}
.toast.fadeIn {
-webkit-animation: farrisMoveUpIn 0.2s linear;
animation: farrisMoveUpIn 0.2s linear;
}
.toast.fadeOut {
-webkit-animation: farrisMoveUpOut 0.2s linear;
animation: farrisMoveUpOut 0.2s linear;
}
`
]
})
export class NotifyComponent implements OnInit, OnChanges {
@Input() toast: NotifyData;
@Output() close = new EventEmitter();
@Output() btnClick = new EventEmitter();
@ViewChild('notifyDiv') notifyDiv: ElementRef;
_state = false;
@Input() animateCls: string;
outCls = '';
inCls = {};
get state() {
return this._state;
}
set state(value) {
this._state = value;
if (value) {
this.inCls[this.animateCls] = false;
this.inCls['animated'] = value;
this.inCls[this.outCls] = value;
// this.ngZone.runOutsideAngular(() => {
setTimeout(() => {
this.close.next(this.toast);
}, 200);
// });
}
}
constructor(private ngZone: NgZone) { }
ngOnInit() {
if (this.toast.buttons) {
this.ngZone.runOutsideAngular(() => {
setTimeout(() => {
let closeEl = this.notifyDiv.nativeElement.querySelector('.toast-close');
let contentEl =this.notifyDiv.nativeElement.querySelector('.toast-title-btns-wrapper');
if(closeEl['clientHeight']+10<contentEl['clientHeight']){
contentEl.classList.remove('d-flex');
}
contentEl.classList.remove('toast-title-beforeshow');
}, 200);
})
}
}
ngOnChanges(changes: SimpleChanges) {
this.getAnimateCls(changes.animateCls.currentValue);
}
getAnimateCls(cls?: any) {
cls = cls || 'bounceInRight';
// this.outCls = 'bounceOut' + cls.substr(8);
// switch (cls.substr(8)) {
// case 'Up':
// this.outCls = 'bounceOutDown';
// break;
// case 'Down':
// this.outCls = 'bounceOutUp';
// break;
// }
this.outCls = 'fadeOut';
// outCls += tmp;
this.inCls = {
[this.toast.type]: true,
[this.toast.theme]: true,
'animated': false,
[cls]: true,
[this.outCls]: this.state
};
}
closeToast(event: any) {
event.stopPropagation();
event.preventDefault();
this.state = true;
}
getPurType(): string {
if (this.toast && this.toast.type) {
return 'f-icon-' + this.toast.type.replace('toasty-type-', '');
}
return 'f-icon-default';
}
useButtonsTemplate() {
return this.toast.buttons instanceof TemplateRef;
}
//点击事件抛出
clickHandler(ev, btn:NotifyButton) {
if (btn.handle) {
this.btnClick.emit({ ev: ev, callback: btn.handle });
}
}
}

View File

@ -0,0 +1,12 @@
import { defineComponent, SetupContext } from 'vue';
export default defineComponent({
name: 'Notify',
props: {},
emits: [],
setup(props: any, context: SetupContext) {
return () => {
return <div></div>;
};
},
});

View File

@ -0,0 +1,4 @@
import { ExtractPropTypes } from 'vue';
export const notifyProps = {};
export type NotifyProps = ExtractPropTypes<typeof notifyProps>;