
13 changed files with 1216 additions and 57 deletions
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.2 KiB |
@ -0,0 +1,177 @@ |
|||
export const rules = () => { |
|||
return [ |
|||
{ |
|||
field: 'id', |
|||
type: 'select', |
|||
label: '部门', |
|||
multiple:false, |
|||
placeholder: '请选择部门', |
|||
colWidth: 'el-col-10', |
|||
options: [ |
|||
{ |
|||
label: '部门一', |
|||
value: 90000, |
|||
}, |
|||
{ |
|||
label: '部门二', |
|||
value: 50000, |
|||
} |
|||
], |
|||
rules: [ |
|||
{ |
|||
required: true, |
|||
message: '请选择部门', |
|||
trigger: 'change' |
|||
}, |
|||
] |
|||
}, |
|||
{ |
|||
field: 'id1', |
|||
type: 'select', |
|||
label: '部门1', |
|||
multiple:false, |
|||
placeholder: '请选择部门1', |
|||
colWidth: 'el-col-10', |
|||
options: [ |
|||
{ |
|||
label: '部门一1', |
|||
value: 2345678, |
|||
}, |
|||
{ |
|||
label: '部门二2', |
|||
value: 6543450, |
|||
} |
|||
], |
|||
rules: [ |
|||
{ |
|||
required: true, |
|||
message: '请选择部门', |
|||
trigger: 'change' |
|||
}, |
|||
] |
|||
}, |
|||
{ |
|||
field: 'name', |
|||
label: '用户名', |
|||
placeholder: '请输入活动名称', |
|||
type: 'input', |
|||
maxLenght: 20, |
|||
colWidth: 'el-col-24', |
|||
rules: [ |
|||
{ required: true, message: '请输入活动名称', trigger: ['blur', 'change'] }, |
|||
] |
|||
}, |
|||
{ |
|||
field: 'radioId', |
|||
type: 'radio', |
|||
label: '备选项', |
|||
colWidth: 'el-col-24', |
|||
options: [ |
|||
{ |
|||
label: '选项一', |
|||
value: '1', |
|||
}, |
|||
{ |
|||
label: '选项二', |
|||
value: '2', |
|||
} |
|||
], |
|||
rules: [ |
|||
{ |
|||
required: true, |
|||
message: '请选择备选项', |
|||
trigger: 'blur' |
|||
}, |
|||
] |
|||
}, |
|||
{ |
|||
field: 'checkboxId', |
|||
type: 'checkbox', |
|||
label: '状态', |
|||
colWidth: 'el-col-24', |
|||
cities: ['上海', '北京', '广州', '深圳'], |
|||
rules: [ |
|||
{ |
|||
required: true, |
|||
message: '请选择状态', |
|||
trigger: 'change' |
|||
}, |
|||
] |
|||
}, |
|||
|
|||
{ |
|||
field: 'textareaIner', |
|||
label: '内容', |
|||
placeholder: '请输入内容', |
|||
maxLenght: 300, |
|||
type: 'textarea', |
|||
rowsHeight: 4, |
|||
colWidth: 'el-col-24', |
|||
rules: [ |
|||
{ required: true, message: '请输入内容', trigger: ['blur', 'change'] } |
|||
] |
|||
}, |
|||
{ |
|||
field: 'dateTime', |
|||
label: '内容', |
|||
placeholder: '请输入内容', |
|||
type: 'date', |
|||
pickerOptions: pickerOptions(), |
|||
colWidth: 'el-col-24', |
|||
rules: [ |
|||
{ required: true, message: '请输入内容', trigger: 'blur' } |
|||
] |
|||
}, |
|||
{ |
|||
field: 'uploadList', |
|||
label: '附件', |
|||
headers: {}, |
|||
action: '/action', |
|||
type: 'upload', |
|||
multiple: true, |
|||
colWidth: 'el-col-24', |
|||
rules: [ |
|||
{ required: true, message: '请上传附件', trigger: ['blur', 'change'] }, |
|||
callback() |
|||
] |
|||
}, |
|||
] |
|||
} |
|||
|
|||
function callback() { |
|||
return { |
|||
validator: function (rule, value, callback) { |
|||
console.log(rule, value); |
|||
if (value) { |
|||
callback() |
|||
} |
|||
} |
|||
} |
|||
} |
|||
function pickerOptions() { |
|||
return { |
|||
disabledDate(time) { |
|||
return time.getTime() > Date.now(); |
|||
}, |
|||
shortcuts: [{ |
|||
text: '今天', |
|||
onClick(picker) { |
|||
picker.$emit('pick', new Date()); |
|||
} |
|||
}, { |
|||
text: '昨天', |
|||
onClick(picker) { |
|||
const date = new Date(); |
|||
date.setTime(date.getTime() - 3600 * 1000 * 24); |
|||
picker.$emit('pick', date); |
|||
} |
|||
}, { |
|||
text: '一周前', |
|||
onClick(picker) { |
|||
const date = new Date(); |
|||
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); |
|||
picker.$emit('pick', date); |
|||
} |
|||
}] |
|||
} |
|||
} |
@ -0,0 +1,247 @@ |
|||
<!-- Dom模板 --> |
|||
<template> |
|||
<div> |
|||
<!-- Dom内容 --> |
|||
<el-form |
|||
:model="ruleForm" |
|||
ref="ruleForm" |
|||
:label-width="labelWidth" |
|||
class="el-row demo-ruleForm" |
|||
:label-position="labelPosition" |
|||
> |
|||
<el-form-item |
|||
v-for="(item, index) in formList" |
|||
:key="index" |
|||
:label="item.label" |
|||
:prop="item.field" |
|||
:rules="detail ? false : item.rules" |
|||
:class="item.colWidth" |
|||
> |
|||
<!-- 输入框 --> |
|||
<template v-if="item.type === 'input'"> |
|||
<el-input |
|||
:placeholder="item.placeholder" |
|||
clearable |
|||
:disabled="disabled" |
|||
v-model="ruleForm[`${item.field}`]" |
|||
/> |
|||
</template> |
|||
<!-- 下拉框 --> |
|||
<template v-if="item.type === 'select'"> |
|||
<el-select |
|||
v-model="ruleForm[`${item.field}`]" |
|||
:placeholder="item.placeholder" |
|||
:disabled="disabled" |
|||
:multiple="item.multiple" |
|||
style="width: 100%" |
|||
@change="changeSelect" |
|||
> |
|||
<el-option |
|||
v-for="(element, i) in item.options" |
|||
:label="element.label" |
|||
:value="`${element.value}`" |
|||
:key="i" |
|||
/> |
|||
</el-select> |
|||
</template> |
|||
<!-- 单选框 --> |
|||
<template v-if="item.type === 'radio'"> |
|||
<el-radio-group |
|||
v-model="ruleForm[`${item.field}`]" |
|||
:disabled="disabled" |
|||
> |
|||
<el-radio |
|||
v-for="(element, i) in item.options" |
|||
:key="i" |
|||
:label="`${element.value}`" |
|||
> |
|||
{{ element.label }} |
|||
</el-radio> |
|||
</el-radio-group> |
|||
</template> |
|||
<!-- 复选框 --> |
|||
<template v-if="item.type === 'checkbox'"> |
|||
<el-checkbox-group |
|||
v-model="ruleForm[`${item.field}`]" |
|||
:disabled="disabled" |
|||
> |
|||
<el-checkbox |
|||
v-for="(city, i) in item.cities" |
|||
:label="city" |
|||
:name="city" |
|||
:key="i" |
|||
> |
|||
{{ city }} |
|||
</el-checkbox> |
|||
</el-checkbox-group> |
|||
</template> |
|||
<!--文本框 --> |
|||
<template v-if="item.type === 'textarea'"> |
|||
<el-input |
|||
:maxlength="item.maxLenght" |
|||
type="textarea" |
|||
:rows="item.rowsHeight" |
|||
:disabled="disabled" |
|||
:placeholder="item.placeholder" |
|||
v-model="ruleForm[`${item.field}`]" |
|||
/> |
|||
</template> |
|||
<!-- 时间选择 --> |
|||
<template v-if="item.type === 'date'"> |
|||
<el-date-picker |
|||
v-model="ruleForm[`${item.field}`]" |
|||
align="right" |
|||
style="width: 100%" |
|||
value-format="yyyy-MM-dd HH:mm:ss" |
|||
:disabled="disabled" |
|||
type="date" |
|||
placeholder="选择日期" |
|||
:picker-options="item.pickerOptions" |
|||
> |
|||
</el-date-picker> |
|||
</template> |
|||
<!-- 附件 --> |
|||
<template v-if="item.type === 'upload'"> |
|||
<el-upload |
|||
:action="item.action" |
|||
list-type="picture-card" |
|||
:headers="item.headers" |
|||
:disabled="disabled" |
|||
class="upload-demo" |
|||
:multiple="item.multiple" |
|||
:data="ruleForm[`${item.field}`]" |
|||
:file-list="ruleForm[`${item.field}`]" |
|||
:on-change="uploadFile" |
|||
:auto-upload="false" |
|||
:on-preview="handlePictureCardPreview" |
|||
:on-remove="handleRemove" |
|||
> |
|||
<i slot="default" class="el-icon-plus"></i> |
|||
</el-upload> |
|||
</template> |
|||
</el-form-item> |
|||
</el-form> |
|||
<el-dialog :visible.sync="dialogVisible"> |
|||
<img width="100%" :src="dialogImageUrl" alt="" /> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
props: { |
|||
detail: { |
|||
type: Boolean, |
|||
default: () => false, |
|||
}, |
|||
disabled: { |
|||
type: Boolean, |
|||
default: () => false, |
|||
}, |
|||
//回显数据 |
|||
fromItem: { |
|||
type: Object, |
|||
default: () => null, |
|||
}, |
|||
labelWidth: { |
|||
type: String, |
|||
default: () => "100px", |
|||
}, |
|||
// 表单数据 |
|||
formNewList: { |
|||
type: Array, |
|||
default: () => [], |
|||
}, |
|||
labelPosition: { |
|||
type: String, |
|||
default: () => "right", |
|||
}, |
|||
}, |
|||
watch: { |
|||
formNewList: { |
|||
immediate: true, // 立即触发监听函数 |
|||
handler() { |
|||
this.formList = this.formNewList; |
|||
this.defaultFun(); |
|||
}, |
|||
}, |
|||
}, |
|||
data() { |
|||
return { |
|||
ruleForm: {}, |
|||
formList: [], |
|||
dialogImageUrl: "", |
|||
dialogVisible: false, |
|||
}; |
|||
}, |
|||
methods: { |
|||
//下拉框下拉事件 |
|||
changeSelect(row) { |
|||
// console.log(row); |
|||
this.$emit("changeSelect", row); |
|||
}, |
|||
//上传附件 |
|||
uploadFile(file, fileList) { |
|||
this.formList.forEach((item) => { |
|||
if (item.type === "upload") { |
|||
this.$set(this.ruleForm, item.field, fileList); |
|||
} |
|||
}); |
|||
}, |
|||
//删除附件 |
|||
handleRemove(file) { |
|||
this.formList.forEach((item) => { |
|||
let fileList = this.ruleForm[`${item.field}`]; |
|||
if (item.type === "upload") { |
|||
fileList.forEach((element, i) => { |
|||
if (file.uid === element.uid) { |
|||
fileList.splice(i, 1); |
|||
} |
|||
}); |
|||
} |
|||
this.$set(this.ruleForm, item.field, fileList); |
|||
}); |
|||
}, |
|||
//附件预览 |
|||
handlePictureCardPreview(file) { |
|||
console.log(file); |
|||
this.dialogImageUrl = file.url; |
|||
this.dialogVisible = true; |
|||
}, |
|||
//表单默认状态 |
|||
defaultFun() { |
|||
if (this.fromItem !== null) { |
|||
// 数据回显 |
|||
this.ruleForm = { ...this.ruleForm, ...this.fromItem }; |
|||
} else { |
|||
//设置默认值 |
|||
this.formList.forEach((item) => { |
|||
if (item.cities) { |
|||
this.$set(this.ruleForm, item.field, []); |
|||
} else { |
|||
this.$set(this.ruleForm, item.field, ""); |
|||
} |
|||
if (item.type === "radio") { |
|||
this.$set(this.ruleForm, item.field, "1"); |
|||
} |
|||
if (item.type === "upload") { |
|||
this.$set(this.ruleForm, item.field, []); |
|||
} |
|||
}); |
|||
} |
|||
console.log(this.ruleForm); |
|||
}, |
|||
//from表单点击事件 |
|||
submitForm(formName) { |
|||
this.$refs[formName].validate((valid) => { |
|||
if (valid) { |
|||
this.$emit("headdenForm", this.ruleForm); |
|||
} |
|||
}); |
|||
}, |
|||
//清空表单 |
|||
resetForm(formName) { |
|||
this.$refs[formName].resetFields(); |
|||
}, |
|||
}, |
|||
}; |
|||
</script> |
@ -0,0 +1,107 @@ |
|||
<template> |
|||
<div |
|||
:class="[{'column':column},{'error':hasError},{'w510':addClass=='w510'},{'w388':addClass=='w388'},'form-item']"> |
|||
<div class="form-item-top"> |
|||
<label v-if="label" for="">{{ label }} |
|||
<img src="../assets/require.svg" v-if="required" alt=""> |
|||
</label> |
|||
<template > |
|||
<slot name="formLeft"></slot> |
|||
</template> |
|||
<template > |
|||
<slot name="formRight"></slot> |
|||
</template> |
|||
</div> |
|||
<div class="form-item-bottom"> |
|||
<template > |
|||
<slot name="formDom"></slot> |
|||
</template> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
name: 'GuipFormItem', |
|||
props:['label','required','addClass','column'], |
|||
data() { |
|||
return { |
|||
hasError: false, |
|||
// 目前这两个宽度用的最多,其余宽度自定义类名修改吧 |
|||
classList:{ |
|||
'w510':'w510', |
|||
'w388':'w388' |
|||
} |
|||
} |
|||
}, |
|||
computed: { |
|||
// dynamicClasses() { |
|||
// return { |
|||
// active: this.isActive, // 如果isActive为true,则添加'active'类 |
|||
// error: this.hasError, // 如果hasError为true,则添加'error'类 |
|||
// highlighted: this.isHighlighted, // 如果isHighlighted为true,则添加'highlighted'类 |
|||
// }; |
|||
// } |
|||
}, |
|||
mounted(){ |
|||
console.log(this.required,'required----'); |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
.form-item{ |
|||
display: flex; |
|||
align-items: center; |
|||
label{ |
|||
min-width: 54px; |
|||
margin-right: 8px; |
|||
} |
|||
.form-item-top{ |
|||
display: flex; |
|||
align-items: center; |
|||
text-align: left; |
|||
} |
|||
.form-item-bottom{ |
|||
flex: 1; |
|||
} |
|||
.rightdesc{ |
|||
flex: 1; |
|||
text-align: right; |
|||
font-size: 12px; |
|||
line-height: 13px; |
|||
letter-spacing: 0.08em; |
|||
font-variation-settings: "opsz" auto; |
|||
color: #8A9099; |
|||
} |
|||
} |
|||
.w510{ |
|||
width: 510px; |
|||
} |
|||
.w388{ |
|||
width: 388px; |
|||
} |
|||
.column{ |
|||
display: flex; |
|||
flex-direction: column !important; |
|||
align-items: self-start; |
|||
.form-item-top{ |
|||
width: 100%; |
|||
margin-bottom: 12px; |
|||
justify-content: space-between; |
|||
} |
|||
.form-item-bottom{ |
|||
width: 100%; |
|||
} |
|||
} |
|||
.form-top-icon{ |
|||
display: flex; |
|||
align-items: center; |
|||
img{ |
|||
width: 16px; |
|||
height: 16px; |
|||
margin-right: 8px; |
|||
} |
|||
span{ |
|||
color: #1E2226; |
|||
} |
|||
} |
|||
</style> |
@ -1,25 +1,121 @@ |
|||
<template> |
|||
<el-input |
|||
type="text" |
|||
:style="{...styleObject}" |
|||
:rows="2" |
|||
placeholder="请输入内容" |
|||
:disabled="disabled" |
|||
v-model="textarea"> |
|||
</el-input> |
|||
|
|||
<el-input |
|||
:type="type" |
|||
:style="{...style,width:width,height:height,...styleObject}" |
|||
:placeholder="placeholder1" |
|||
:disabled="disabled" |
|||
:maxlength="maxlength1" |
|||
:minLength="minLength1" |
|||
:show-word-limit="showWordLimit" |
|||
@input="$emit('input', $event)" |
|||
@change="$emit('change', $event)" |
|||
@blur="$emit('blur', value)" |
|||
@focus="$emit('focus', value)" |
|||
v-model="value"> |
|||
<!-- 自定义前面小图标 --> |
|||
<template v-slot:prepend> |
|||
<slot name="prependshow"></slot> |
|||
</template> |
|||
<template v-slot:prefix> |
|||
<slot name="prefix"></slot> |
|||
</template> |
|||
<!-- 清除小图标 --> |
|||
<template v-slot:suffix> |
|||
<slot name="suffix"></slot> |
|||
</template> |
|||
<template v-slot:append> |
|||
<slot name="appendshow"></slot> |
|||
</template> |
|||
<!-- <i slot="suffix" v-if="empty" class="el-icon-close" @click="handleClear">h</i> --> |
|||
<!-- <el-button slot="append" v-if="hasBtn" type="primary" @click="$emit('enter',value)">搜索</el-button> --> |
|||
</el-input> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'GuipInput', |
|||
props:['styleObject','disabled'], |
|||
props:['styleObject','disabled','defaultValue','placeholder','maxlength','minLength','clear','width','height','showWordLimit','type'], |
|||
data() { |
|||
return { |
|||
textarea: '' |
|||
value: '', |
|||
maxlength1: '', |
|||
minLength1: 0, |
|||
style:{ |
|||
width:'200px', |
|||
height:'38px' |
|||
}, |
|||
placeholder1:'请输入内容' |
|||
} |
|||
}, |
|||
watch: { // 监听外部传来的 value prop 的变化,以便同步到内部状态 inputValue 上(可选) |
|||
defaultValue(newVal) { |
|||
console.log(newVal,'newVal'); |
|||
this.value = newVal; |
|||
} |
|||
}, |
|||
created(){ |
|||
// 默认值赋值 |
|||
if(this.defaultValue != null){ |
|||
this.value = this.defaultValue; |
|||
} |
|||
// 默认提示语 |
|||
if(this.placeholder){ |
|||
this.placeholder1 = this.placeholder; |
|||
} |
|||
// 默认提示语 |
|||
if(this.maxlength){ |
|||
this.maxlength1 = this.maxlength; |
|||
} |
|||
// 默认提示语 |
|||
if(this.minLength){ |
|||
this.minLength1 = this.minLength; |
|||
} |
|||
}, |
|||
mounted(){ |
|||
|
|||
this.$nextTick(()=>{ |
|||
let els = document.querySelectorAll('.el-input'); |
|||
els.forEach(item=>{ |
|||
item.onmouseover= function(){ |
|||
item.classList.add("hoverclass") |
|||
} |
|||
item.onmouseout= function(){ |
|||
item.classList.remove("hoverclass") |
|||
} |
|||
// item.addEventListener('mouseover',function(){ |
|||
// console.log('滑过'); |
|||
// item.classList.add("hoverclass") |
|||
// }) |
|||
// item.addEventListener('mouseoout',function(){ |
|||
// console.log('滑出'); |
|||
// item.classList.remove("hoverclass") |
|||
// }) |
|||
// item.addEventListener('mouseoenter',function(){ |
|||
// console.log('滑---'); |
|||
// item.classList.add("hoverclass") |
|||
// }) |
|||
// item.addEventListener('mouseoleave',function(){ |
|||
// console.log('滑出'); |
|||
// item.classList.remove("hoverclass") |
|||
// }) |
|||
}) |
|||
// console.log(el,'====9999'); |
|||
// if(el&& this.styleObject){ |
|||
// for(var key in this.styleObject){ |
|||
// el.style[key] = this.styleObject[key] |
|||
// } |
|||
// } |
|||
}) |
|||
}, |
|||
methods:{ |
|||
// input 事件 |
|||
// changeInput(event){ |
|||
// this.$emit('input', event); |
|||
// } |
|||
// handleClear(){ |
|||
// console.log('清除---'); |
|||
// this.$emit('clear', '清楚逻辑') |
|||
// } |
|||
} |
|||
} |
|||
</script> |
@ -0,0 +1,76 @@ |
|||
<template> |
|||
<div class="flex"> |
|||
<GuipInput |
|||
ref="phoneNumber" |
|||
width="277px" |
|||
height="38px" |
|||
placeholder="请输入手机号码"/> |
|||
<GuipButton type="reverseMild" @click="sendCode" :btnstyle="{width:'99px',height:'38px'}" :disabled="isCounting">{{ countdownText }}</GuipButton> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
// import axios from 'axios'; |
|||
import GuipButton from '@/components/GuipButton.vue'; |
|||
import GuipInput from '@/components/GuipInput.vue'; |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
phoneValue: '', |
|||
countdown: 60, // 倒计时时间(秒) |
|||
isCounting: false, // 是否正在倒计时 |
|||
}; |
|||
}, |
|||
components: { |
|||
GuipButton, |
|||
GuipInput, |
|||
}, |
|||
computed: { |
|||
countdownText() { |
|||
return this.isCounting ? `${this.countdown}秒后重试` : '获取验证码'; |
|||
} |
|||
}, |
|||
methods: { |
|||
async sendCode() { |
|||
if (!/^1\d{10}$/.test(this.$refs.phoneNumber.value)) { |
|||
alert('请输入有效的手机号码'); |
|||
return; |
|||
} |
|||
this.phoneValue = this.$refs.phoneNumber.value; |
|||
this.startCountdown(); |
|||
// 根据实际接口请求 |
|||
// try { |
|||
// const response = await axios.post('你的后端API地址', { phoneNumber: this.$refs.phoneNumber.value }); // 替换为实际API地址和参数名 |
|||
// if (response.data.success) { // 根据后端返回的结构调整这里的判断条件 |
|||
// alert('验证码已发送'); |
|||
// this.startCountdown(); |
|||
// } else { |
|||
// throw new Error(response.data.message || '发送失败'); // 使用后端返回的错误信息或者默认信息 |
|||
// } |
|||
// } catch (error) { |
|||
// console.error('发送验证码失败:', error); // 处理错误信息,可以在这里做更多的错误处理逻辑,比如重试机制等。 |
|||
// alert('发送验证码失败,请稍后再试'); // 显示错误信息给用户。 |
|||
// } |
|||
}, |
|||
startCountdown() { |
|||
this.isCounting = true; |
|||
const interval = setInterval(() => { |
|||
this.countdown--; |
|||
if (this.countdown <= 0) { |
|||
clearInterval(interval); |
|||
this.isCounting = false; |
|||
this.countdown = 60; // 重置倒计时时间 |
|||
} |
|||
}, 1000); |
|||
} |
|||
} |
|||
}; |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.flex{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
} |
|||
</style> |
Loading…
Reference in new issue