import {
Component, OnInit, forwardRef, Input, HostBinding, Output, EventEmitter, Injector,
SimpleChanges, ElementRef, ViewChild, NgZone, HostListener
} from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { DateTimeHelperService } from '@farris/ui-common/date';
import { NumberHelperService } from '@farris/ui-common/number';
import { LocaleService } from '@farris/ui-locale';
@Component({
selector: 'farris-text',
template: `
0?height+'px':null" [style.minHeight]="autoSize&&height>0?height+'px':null"
[style.maxHeight]="autoSize&&maxHeight>0?maxHeight+'px':null">{{text && text.length > 0 ? text : control}}
`,
styles: [],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TextComponent),
multi: true,
}]
})
export class TextComponent implements OnInit, ControlValueAccessor {
@HostBinding('class.f-component-text') cls = true;
@ViewChild('textInner', { read: ElementRef }) textInnerEl: ElementRef;
@Output() textChange = new EventEmitter();
/** 是否为密码输入 */
@Input() isPassword = false;
// 是否多行文本
@Input() isTextArea = false;
// 是否启用自动尺寸
@Input() autoSize = false;
// 设置最大高度
@Input() maxHeight: number;
// 设置高度
@Input() height = 0;
// 控件类型
@Input() type: string;
// 是否是日期范围
@Input() dateRange = false;
// 需要转化类型格式的表达式
@Input() format: any;
// 多语言
@Input() lang: string;
// 转换类型用到的数据
@Input() data: any;
// 千分位符号
@Input() thousand = ',';
// 小数点处符号
@Input() decimal = '.';
// 货币符号及值展现形式
@Input() expression = '%s%v';
@Input() currentLanguage: string;
// formControl显示的文本
@Input() showTime: boolean;
@Input() textField = 'name';
@Input() valueField = 'value';
@Input() returnFormat = ''; // 从服务器端取值是格式化后的
// 文本方向
@Input() textAlign;
// 日期范围模式下input的显示分割符合
@Input() dateRangeDelimiter = '~';
@Input() enumDelimiter = ',';
private _tshowType = 0;
@Input()
set showType(value: number) {
this._tshowType = value;
// 如果是周
if (value == 4) {
this.dateRange = true;
}
}
get showType(): number {
return this._tshowType;
}
/**
* 国际化类型
*/
@Input() localizationType: string;
control: any;
// 普通文本
text: any;
// 货币符号,默认是RMB
currencySymbol = '¥';
// 十进制前面填充的符号
@Input() filledSymbol = '0';
// 普通文本输入值
@Input()
set value(value: any) {
this.text = this.formatValue(value);
this.textChange.emit(this.text);
}
get value() {
return this.text;
}
@HostListener('mouseenter', ['$event']) changeTitle(ev) {
if (!this.isTextArea && !this.isPassword) {
this.mouseEnterChangeTitle();
}
}
// 标签
staticTitle = "";
// 处理中英文情况, 因为多语言暂时不通过这个属性控制
@Input() showTitle = false;
//数值格式参数
_option;
@Input()
set option(value) {
this._option = value;
}
get option() {
return this._option;
}
private localeService: any;
beforeWriteValue: (val: any, options: any) => string = null;
private controlChange = (val) => { };
private controlTouch = (val) => { };
constructor(
private dtHelper: DateTimeHelperService,
private numberHelper: NumberHelperService,
private injector: Injector,
public ngzone: NgZone
) {
this.localeService = this.injector.get(LocaleService);
}
ngOnInit() {
}
ngOnDestroy(): void {
}
ngAfterViewInit(): void {
if (this.isTextArea) {
const clsName = this.textInnerEl.nativeElement.parentElement.className;
this.textInnerEl.nativeElement.parentElement.className = clsName + ' f-cmp-text-is-textarea';
}
}
private mouseEnterChangeTitle() {
if (this.textInnerEl.nativeElement.scrollHeight > this.textInnerEl.nativeElement.clientHeight) {
this.staticTitle = this.text && this.text.length > 0 ? this.text : this.control;
} else {
this.staticTitle = '';
}
}
/**
* 处理多语言,待定
*/
formatLang(value: any) {
return value && value[this.currentLanguage] ? value[this.currentLanguage] : '';
}
/**
* C货币
* D十进制
* F浮点数
* N数字,带千分位
* P百分比
*/
getFormatNumberValue(value: any) {
if (!this.format && !this._option) {
return value.toString();
}
if (this._option && this._option.type && this._option.type == 'number') {
if (this._option.formatter) {
return this._option.formatter(value);
} else {
if (this._option.useThousands) {
if (this._option.precision != undefined) {
this.format = 'n' + this._option.precision;
} else {
this.format = 'n2';
}
} else {
if (this._option.precision != undefined) {
this.format = 'f' + this._option.precision;
} else {
this.format = 'f2';
}
}
}
}
const firstLetter = this.currencyToUpperCase(this.format.substring(0, 1));
const precision = Number(this.format.substring(1));
let config = {};
let result: any;
if (!/C|D|F|N|P/g.test(firstLetter)) {
console.warn(`不支持format为 ${this.format} 类型的数字格式化`);
return;
}
if (this.thousand) {
Object.assign(config, { thousand: this.thousand });
}
if (this.decimal) {
Object.assign(config, { decimal: this.decimal });
}
if (this.expression) {
Object.assign(config, { format: this.expression });
}
switch (firstLetter) {
case 'C':
Object.assign(config, { prefix: this.currencySymbol, precision });
result = this.numberHelper.formatMoney(value, config);
break;
case 'D':
result = this.toDecimal(value, precision);
break;
case 'F':
Object.assign(config, { prefix: '', thousand: '', precision });
result = this.numberHelper.formatMoney(value, config);
break;
case 'N':
Object.assign(config, { prefix: '', precision });
result = this.numberHelper.formatMoney(value, config);
break;
case 'P':
result = this.toPercent(value, precision);
break;
}
return result;
}
/**
* @param value 转换成十进制的数字
* @param precision 十进制数字的长度
*/
toDecimal(value: any, precision: any) {
if (value.toString().indexOf('.') > -1) {
console.warn('十进制转换仅限整型类型');
return;
}
return (Array(precision).join(this.filledSymbol) + value).slice(-precision);
}
/**
* @param value 转换成百分数的数字
* @param decimal 小数点保留几位
*/
toPercent(value: any, precision: any) {
return Number(value * 100).toFixed(Number(precision)) + '%';
}
/**
* 将货币符号首字母转换成大写
*/
currencyToUpperCase(value: any) {
return value.replace(/[a-z]+/g, (word: any) => {
return word.toUpperCase();
});
}
/**
* 处理年,Y=>y, D=>d
*/
dateToUpperCase(value: any) {
let newFormat: any;
if (/Y/g.test(value) === true) {
newFormat = value.replace(/Y/g, 'y');
} else {
newFormat = value;
}
if (/D/g.test(newFormat) === true) {
newFormat = newFormat.replace(/D/g, 'd');
}
return newFormat;
}
/**
* 枚举类型处理
*/
getFormatEnumValue(value: any) {
if (value == undefined || value === null || value === '') {
return '';
}
if (this.data && this.data.length) {
// 可能存在多选枚举,作为分隔符
// let curVals = ('' + value).split(',');
let curVals = ('' + value).split(this.enumDelimiter);
let nameResult = [];
for (let k = 0; k < curVals.length; k++) {
let findObj = this.data.find(item => {
return item[this.valueField] == curVals[k];
});
if (findObj) {
nameResult.push(findObj[this.textField]);
}
else {
nameResult.push(curVals[k]);
}
}
if (nameResult.length > 0) {
// return nameResult.join(',');
return nameResult.join(this.enumDelimiter);
}
return '';
} else {
return value;
}
}
/**
* boolean值处理
*/
getFormatCheckBoxValue(value: boolean) {
if (value === true) {
return this.localeService.getValue('text.yes');
} else if (value === false || value == null || typeof value === 'undefined') {
return this.localeService.getValue('text.no');
} else {
return value;
}
}
private timeFormatTo(value: any, fmt: string, hourSystem = 12) {
}
private makeFormater(fmt: string): string {
return fmt;
}
/*
* 日期格式化
*/
dateformat(value) {
let str;
if (!this.format) {
this.format = 'YYYY-MM-DD';
}
// 当前值是已经格式化后的日期字符串
if (this.returnFormat && this.returnFormat != 'yyyy-MM-dd' && typeof value == 'string') {
value = this.getDateFromFormatedString(value, this.returnFormat);
}
//
if (this.format === 'hh:mm:ss' || this.format === 'HH:mm:ss') {
// 格式化时间 临时处理
str = value;
} else {
// if (this.showTime && value instanceof String) {
// str = value;
// } else {
// const formArr = this.format.split(' ');
// if (this.showTime && formArr.length < 2) {
// formArr.push('HH:mm:ss');
// this.format = formArr.join(' ');
// }
// // 格式化日期
// str = this.dtHelper.formatTo(value, this.dateToUpperCase(this.format));
// }
str = this.dtHelper.formatTo(value, this.dateToUpperCase(this.format));
}
return str;
}
private getDateFromFormatedString(dateString, format) {
var result = { year: 0, month: 0, day: 0, hour: 0, minite: 0, second: 0 }; // 当然这里可以默认1970-1-1日
if (dateString) {
format.replace(/y+|Y+|M+|d+|D+|h+|H+|m+|s+/g, function (m, a, b, c) {// 这里只做了年月日 加时分秒也是可以的
dateString.substring(a).replace(/\d+/, function (d) { c = parseInt(d, 10) });
if (/y+/i.test(m) && !result.year) result.year = c;
if (/M+/.test(m) && !result.month) result.month = c;
if (/d+/i.test(m) && !result.day) result.day = c;
if (/h+/i.test(m) && !result.hour) result.hour = c;
if (/m+/.test(m) && !result.minite) result.minite = c;
if (/s+/.test(m) && !result.second) result.second = c;
});
}
var resultDate = new Date(result.year + '/' + result.month + '/' + result.day + ' ' + result.hour + ':' + result.minite + ':' + result.second);
return resultDate;
}
/**
* 格式化处理
*/
formatValue(value: any) {
let str: any;
if (this.currentLanguage) {
return this.formatLang(value);
}
// if (!value) {
// return '';
// }
if (this.type !== 'boolean' && (value == null || typeof value === 'undefined')) {
return '';
}
switch (this.type) {
case 'string':
str = value;
break;
case 'date':
case 'datetime':
// console.log(this.format);
if (!this.dateRange) {
// if (!this.format) {
// this.format = 'YYYY-MM-DD';
// }
// if (this.format === 'hh:mm:ss') {
// // 格式化时间 临时处理
// str = value;
// } else {
// if (this.showTime) {
// str = value;
// } else {
// // 格式化日期
// str = this.dtHelper.formatTo(value, this.dateToUpperCase(this.format));
// }
// }
str = this.dateformat(value);
// console.log(str);
} else {
const dateValues = value.split(this.dateRangeDelimiter);
let dataStr = [];
if (dateValues && dateValues.length) {
dateValues.forEach(date => {
let val = this.dateformat(date);
dataStr.push(val);
});
}
str = dataStr.join(this.dateRangeDelimiter);
}
break;
// case 'dateTime':
// str = this.timeFormatTo(value, this.makeFormater(this.format));
// break;
case 'number':
str = this.getFormatNumberValue(value);
break;
case 'enum':
str = this.getFormatEnumValue(value);
break;
case 'boolean':
str = this.getFormatCheckBoxValue(value);
break;
default:
break; // throw new Error(`暂不支持 ${this.type} 类型`);
}
return str;
}
private setText2Star(value) {
if (this.isPassword) {
const star = value ? '******' : '';
this.text = star;
this.control = star;
return true;
}
return false;
}
writeValue(value: any): void {
// lucas 2021-08-27
if (this.setText2Star(value)) {
return;
}
// xia 2021-03-13
if (this.beforeWriteValue) {
const options = {
localizationType: this.localizationType,
showTime: this.showTime,
ref: this
};
const text = this.beforeWriteValue(value, options);
if (text !== undefined) {
this.text = text;
return;
}
}
this.control = this.formatValue(value);
this.controlChange(value);
}
registerOnChange(fn: () => {}): void {
this.controlChange = fn;
}
registerOnTouched(fn): void {
this.controlTouch = fn;
}
}