1. Introduce element-ui --- checkbox + upload + input box
// element-ui
import {Checkbox, Input, Upload, CheckboxGroup } from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.component( 'checkbox', Checkbox );
Vue.component( 'el-input', Input);
Vue.component( 'upload', Upload );
Vue.component( 'CheckboxGroup');
[Upload component]
<template>
<div>
<!--上传头像 type:img-->
<template v-if="type == 'img'">
<el-upload
class="upload-demo"
action="111"
:limit="limit"
:file-list="fileList"
:show-file-list=showFileList
:before-upload="beforeUpload"
:on-remove="handleRemove"
accept = "image/png,image/jpg,image/jpeg,image/gif">
<button class="dc-common-default-btn">
<img src="../assets/img/common/upload-icon.png" alt="">
<span>{
{placeholder}}</span>
</button>
<div class="el-upload__tip" slot="tip">{
{tip}}</div>
</el-upload>
</template>
<!--上传文件 type:file-->
<template v-else-if="type == 'file'">
<el-upload
class="upload-demo"
action="111"
:limit="limit"
:show-file-list=showFileList
:file-list="fileList"
:before-upload="beforeUpload"
:on-remove="handleRemove"
accept = "application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/pdf,application/vnd.ms-powerpoint,text/plain">
<!--accept = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/pdf,application/vnd.ms-powerpoint,text/plain,application/vnd.ms-works">-->
<button class="dc-common-default-btn">
<img src="../assets/img/common/upload-icon.png" alt="">
<span>{
{placeholder}}</span>
</button>
<div class="el-upload__tip" slot="tip">{
{tip}}</div>
</el-upload>
</template>
</div>
</template>
accept: Restrict the uploaded file format
action="111": The uploaded interface address can be written here, but because writing directly here in the project will cause cross-domain problems, so my interface is written in
[Related method]:
1.beforeUpload in the method before uploading. It is judged here whether to obtain the data, and then the interface is uploaded. After the image is uploaded, the preview image is displayed.
2.handleRemove Click the delete method to delete the selected data from showList.
public beforeUpload(val): any {
this.checkImg = true;
const me = this;
if ((this as any).type === 'file') { // 上传简历
const isLt10M = val.size / 1024 / 1024 < 10;
if (!isLt10M) {
// this.$message.error('上传头像图片大小不能超过 10MB!');
}
const form = new FormData();
form.append( 'file' , val);
(this as any).$api.uploadResume(form).then( (resp) => {
(this as any).$commonFun.axiosSuccessFun( {
callBack: ( response ) => {
const res = response.data;
res.name = val.name;
const data = {
name: res.name,
url: res.fullPath,
};
this.fileList.push(data);
this.$emit('before-upload', res, (me as any).str);
},
this: me,
}, resp.data);
} ).catch( ( error ) => {
( this as any ).$commonFun.axiosFailFun( {
this: me,
}, error );
});
} else { // 上传图片
this.imageUrl = URL.createObjectURL(val);
this.imageDefaultUrlData = URL.createObjectURL(val);
const form = new FormData();
form.append( 'file' , val);
(this as any).$api.uploadImage(( this as any).$commonFun.deleteEmpty(form)).then( (resp) => {
(this as any).$commonFun.axiosSuccessFun( {
callBack: ( response ) => {
const res = response.data;
const data = {
name: res.fileName,
url: res.fullPath,
};
this.fileList.push(data);
this.$emit('before-upload', res, (me as any).str);
},
this: me,
}, resp.data);
} ).catch( ( error ) => {
( this as any ).$commonFun.axiosFailFun( {
this: me,
}, error );
});
}
return false; // 屏蔽了action的默认上传
}
// 点击删除方法之后将选择的数据中showList中删除。
public handleRemove(value): any {
const me = this;
if (value.status !== 'ready') {
// this.fileList = [];
this.fileList.forEach( (item, i) => {
if (this.fileList[i].uid === value.uid) {
this.fileList.splice (i, 1);
}
});
}
me.$emit('on-remove', value, (me as any).str);
}
【input】:
1. The input box will be filled automatically. In order to cancel the status
Write a default input first: <input type="text" autocomplete="off" style="display: none">
Then write attributes in the component: readonly; οnfοcus="this.removeAttrbute('readonly')"
2.Textarea type:
Because textarea can't set the height by width and height. You can only use the row row attribute to calculate how many rows.
3.maxlength, minlength limit the maximum and minimum input words
4.handleBlur: a method to check the validity of the input value after input
<template>
<div class="dc-input-wrapper">
<template v-if="type !== 'textarea'">
<input type="text" autocomplete="off" style="display: none">
<el-input
class="input-area"
:type="type"
readonly
onfocus="this.removeAttribute('readonly');"
:placeholder="placeholder"
:maxlength="maxlength"
:minlength="minlength"
:require="require"
ref="input"
:autofocus="autofocus"
v-model="inputValue"
:style="{width:width,height:height}"
@focus="handleFocus"
@blur="handleBlur"
@input="handleInput">
<img v-if="iconType" :src="iconSrcData" slot="prefix" class="el-input__icon img" alt="">
</el-input>
<p class="error-msg" v-if="showTips" ref="error">{
{tipMsg}}</p>
</template>
<template v-else>
<div class="area-box" :style="{width:width,height:textHeight}">
<el-input
class="input-area"
type="textarea"
readonly
onfocus="this.removeAttribute('readonly');"
:placeholder="placeholder"
v-model="inputValue"
:maxlength="maxlength"
:minlength="minlength"
:rows="rows"
@focus="handleFocus"
@blur="handleBlur"
@input="handleInput">
</el-input>
<span class="input-suggest" v-if="maxlength">{
{inputLength}}/{
{maxlength}}</span>
<p class="error error-msg" ref="error" v-if="showTips&&tipMsg!=''">{
{tipMsg}}</p>
</div>
</template>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import Component from 'vue-class-component';
import { Input } from 'element-ui';
@Component({
components: {
'el-input': Input,
},
props: {
type: {
default: 'input',
type: String,
},
placeholder: {
default: '请输入',
type: String,
},
inputType: {
default : '',
type: String,
},
require: {
default : true,
type: Boolean,
},
maxlength: String,
minlength: {
default : '0',
type: String,
},
msg: String,
value: String,
width: String,
height: String,
validated: String,
iconType: {
default: '',
type: String,
},
className: String,
number: Boolean,
autofocus: Boolean,
validType: {
default: 'string',
type: String,
},
rows: String,
str: String,
},
})
export default class DcInput extends Vue {
public inputLength: string = '0';
public inputValue: any = (this as any).value || '';
// public textHeight: string = (parseInt((this as any).height , 10) + 12) + 'px';
public textHeight: string = ((this as any).rows * 20 + 12) + 'px';
public iconType: any;
public iconSrcData: any = (this.iconType ?
require('../assets/img/user/login_alert/' + this.iconType + '_icon.png') :
'');
public showTips: boolean = false;
public tipMsg: string = '';
public handleKeyDown(): void {
this.$emit('handleKeyDown');
}
public handleKeyUp(e): void {
this.$emit('handleKeyUp', e);
}
public handleBlur(): void {
if ((this as any).require) {
if (!this.inputValue) {
this.showTips = true;
this.tipMsg = (this as any).msg ? '请输入' + (this as any).msg : '请输入';
} else {
switch ( (this as any).validType) {
case 'number':
if (this.inputValue.length > (this as any).maxlength
|| this.inputValue.length < (this as any).minlength) {
this.showTips = true;
if ((this as any).minlength && (this as any).maxlength) {
this.tipMsg = '请输入' + (this as any).minlength + '-'
+ (this as any).maxlength + '位' + (this as any).msg;
} else if (!(this as any).minlength && (this as any).maxlength) {
this.tipMsg = '请输入不超过' + (this as any).maxlength + '位' + (this as any).msg;
} else {
this.tipMsg = '请输入正确的' + (this as any).msg;
}
}
break;
case 'phone':
const telephoneExc = /^1[3|5|7|8|][0-9]{9}$/;
if (!telephoneExc.test(this.inputValue)) {
this.showTips = true;
this.tipMsg = '请输入正确的' + (this as any).msg;
}
break;
case 'email':
const emailExc = /^[A-Za-z\d]+([-_.][A-Za-z\d]+)*@([A-Za-z\d]+[-.])+[A-Za-z\d]{2,4}$/ ;
if (!emailExc.test(this.inputValue)) {
this.showTips = true;
this.tipMsg = '请输入正确的' + (this as any).msg;
}
break;
default:
break;
}
}
}
this.iconSrcData = (this.iconType ?
require('../assets/img/user/login_alert/' + this.iconType + '_icon.png') :
'');
this.$emit('handleBlur');
}
public handleInput(): void {
const me = this;
if ((me as any).inputType === 'integer') {
me.inputValue = me.inputValue.replace(/^(0+)|[^\d]+/g, '');
}
me.inputLength = me.inputValue.length;
me.inputValue = me.inputValue.replace(/(^\s*)|(\s*$)/g, '');
this.$emit('handleInput', me.inputValue, (me as any).str);
}
public handleChange(): void {
this.$emit('handleChange');
}
public handleFocus(): void {
this.showTips = false;
this.iconSrcData = (this.iconType ?
require('../assets/img/user/login_alert/' + this.iconType + '_icon_active.png') :
'');
this.$emit('handleFocus');
}
public mounted() {
this.inputValue = (this as any).value || '';
this.inputLength = this.inputValue.length;
}
}
</script>
<style scoped lang="scss">
.dc-input-wrapper {
display: inline-block;
content: '';
box-sizing: border-box;
position: relative;
float: left;
}
.textarea {
display: inline-block;
position: relative;
font-size: 14px;
}
textarea {
border: 1px solid #bdc1cb;
color: #4a596d;
transition: all 0.4s;
outline: none;
resize: none;
width: 100%;
height: 95px;
padding: 5px;
}
textarea:focus {
border: 1px solid #3aa3ff;
}
.num-tip {
color: #d7dbe7;
font-size: 12px;
position: absolute;
right: 20px;
top: 70px;
}
.img {
position: absolute;
width: 42px;
height: 42px;
top: 1px;
left: 1px;
}
input {
border: 1px solid #E3E7ED;
transition: all 0.4s;
box-sizing: border-box;
outline: none;
resize: none;
width: 220px;
height: 44px;
padding: 0 13px 0 42px;
font-size: 14px;
color: #414A60;
}
.input-focus:focus {
border: 1px solid #4C88FF !important;
}
i {
/*background: url(/DCTrain/static/img/user/common/input-enter.png) no-repeat -10px -30px;*/
display: inline-block;
width: 14px;
height: 14px;
position: absolute;
right: 5px;
top: 10px;
cursor: pointer;
}
i:hover {
background-position: -8px -6px;
}
p.error {
color: #FC784A;
text-align: left;
line-height: 18px;
position: relative;
padding-left: 19px;
font-size: 14px;
margin-top: 2px;
}
.search {
width: 30px;
height: 40px;
right: 0;
top: 0;
background-position: -7px -86px;
}
.search:hover {
background-position: -7px -49px;
}
</style>
<style lang="scss">
.input-area{
.el-input__inner{
height: 44px;
line-height: 44px;
}
.el-input__prefix{
left: 0;
}
.el-input__icon{
display: block;
}
}
.input-area.el-input--prefix .el-input__inner{
padding-left: 42px;
}
textarea {
resize: none;
border-radius: 0;
}
.el-textarea__inner{
resize: none;
border-radius: 0;
line-height: 20px;
}
.area-box{
position: relative;
.input-suggest{
width: auto;
position: absolute;
bottom: 10px;
right: 10px;
font-size: 14px;
color: #D2D6DE;
}
}
</style>
[Checkbox--check box]
// 全选
<dc-checkbox v-model="checkAll" @change="handleCheckAllChange"></dc-checkbox>
// 单选
<checkbox-group v-model="checkArray" @change="handleChecked">
<dc-checkbox :label="item"></dc-checkbox>
</checkbox-group>
// 方法
public checkArray: any = []; // 选中数组
public checkAll: boolean = false; // 全选
public listArray: any = []; // 列表数据
// 全选
public handleCheckAllChange(val) {
this.checkArray = val ? this.companyList : [];
}
// 单选
public handleChecked(val) {
const checkedCount = val.length;
this.checkAll = checkedCount === this.listArray.length;
}