提交 678bb557 authored 作者: 王鹏飞's avatar 王鹏飞

add tabs component

上级 45ad879d
<template>
<div id="app">
<vue-form :options="formOptions" :model="formModel" :items="formItems" @submit="onSubmit"></vue-form>
<ezj-tab-form title="填写报名表" :tabs="tabs"></ezj-tab-form>
<!-- <ezj-tabs title="填写报名表" v-model="activeName">
<ezj-tab-pane label="个人信息" name="one" :required="true">
<ezj-form :options="formOptions" :model="formModel" :items="formItems" @submit="onSubmit"></ezj-form>
</ezj-tab-pane>
<ezj-tab-pane label="教育背景" name="two" :required="true">
<ezj-form :options="formOptions" :model="formModel" :items="formItems" @submit="onSubmit"></ezj-form>
</ezj-tab-pane>
<ezj-tab-pane label="工作经验" name="three" :required="true"></ezj-tab-pane>
<ezj-tab-pane label="学习目的" name="four" :required="true"></ezj-tab-pane>
<ezj-tab-pane label="资料上传" name="five" :required="true"></ezj-tab-pane>
<ezj-tab-pane label="所受培训" name="six"></ezj-tab-pane>
<ezj-tab-pane label="荣誉奖励" name="seven"></ezj-tab-pane>
<ezj-tab-pane label="最终检查" name="eight" :required="true"></ezj-tab-pane>
<ezj-tab-pane label="申请声明" name="nine" :required="true"></ezj-tab-pane>
</ezj-tabs>-->
</div>
</template>
<script>
......@@ -8,6 +23,7 @@ export default {
name: 'app',
data() {
return {
activeName: 'one',
formOptions: {
labelWidth: '160px'
},
......@@ -191,6 +207,340 @@ export default {
model: 'channel',
required: true
}
],
tabs: [
{
title: '个人信息',
progress: 0,
get: {
action: '/api/v1/enrollment/profiles?project_id=1001'
},
update: {
action: '/api/v1/enrollment/profiles/6614756225840054272'
},
form: {
options: {
labelWidth: '160px'
},
model: {
real_name_cn: '王鹏飞',
real_name_en: 'Max',
id_type: '0',
id_number: 'xxxxxxx',
birthday: '1994-02-19',
gender: '1',
nationality: '1',
city: '2,52',
date_of_starting_to_work: '2010',
phone_number: 'xxxx',
email: 'xxxxx@163.com',
qq_account: 'xxxx',
we_chat_account: 'xxxx',
mailing_address: '北京',
emergency_contact_name: 'xxxxxx',
emergency_contacts_phone: 'xxxxx',
english_level: '2',
english_score: '12',
channel: '12',
address_province: '2',
address_city: '52',
project_id: '1001'
},
items: [
{
type: 'input',
label: '姓名',
model: 'real_name_cn',
placeholder: '123123',
rules: [
{
required: true,
message: '请输入活动名称',
trigger: 'blur'
},
{
min: 3,
max: 5,
message: '长度在 3 到 5 个字符',
trigger: 'blur'
}
]
},
{
type: 'input',
label: '英文名(姓名全拼)',
model: 'real_name_en',
required: true
},
{
type: 'select',
values: [
{ label: '居民身份证', value: '0' },
{ label: '港澳台身份证', value: '1' },
{ label: '护照号', value: '2' },
{ label: '军官证', value: '3' },
{ label: '其他', value: '9' }
],
label: '证件类型',
model: 'id_type',
required: true
},
{
type: 'input',
label: '证件号码',
model: 'id_number',
required: true
},
{
type: 'datePicker',
label: '出生日期',
model: 'birthday',
required: true,
attrs: { type: 'date', 'value-format': 'yyyy-MM-dd' }
},
{
type: 'radioGroup',
values: [
{ label: '男', value: '1' },
{ label: '女', value: '2' }
],
label: '性别',
model: 'gender',
required: true
},
{
type: 'select',
values: [
{ label: '中国', value: '1' },
{ label: '其他国家', value: '9' }
],
label: '国籍',
model: 'nationality',
required: true
},
{
type: 'datePicker',
label: '参加工作年份',
model: 'date_of_starting_to_work',
required: true,
attrs: { type: 'year', 'value-format': 'yyyy' }
},
{
type: 'input',
label: '手机号',
model: 'phone_number',
required: true
},
{
type: 'input',
label: '邮箱',
model: 'email',
required: true,
hint: '(后续报名信息将发送至此邮箱,请认真填写)'
},
{
type: 'input',
label: 'QQ号',
model: 'qq_account',
required: true
},
{
type: 'input',
label: '微信号',
model: 'we_chat_account',
required: true
},
{
type: 'input',
label: '邮寄地址',
model: 'mailing_address',
required: true
},
{
type: 'input',
label: '紧急联系人',
model: 'emergency_contact_name',
required: true
},
{
type: 'input',
label: '紧急联系电话',
model: 'emergency_contacts_phone',
required: true
},
{
type: 'select',
values: [
{ label: '请选择', value: '0' },
{ label: '四级', value: '4' },
{ label: '六级', value: '3' },
{ label: '托福', value: '1' },
{ label: '雅思', value: '2' }
],
label: '英语水平',
model: 'english_level',
required: true
},
{
type: 'input',
label: '托福/雅思成绩',
model: 'english_score',
required: true
},
{
type: 'select',
values: [
{ label: '请选择', value: '0' },
{ label: '紫荆教育官方网站', value: '11' },
{ label: '紫荆教育官方微信公众号', value: '12' },
{ label: '紫荆教育学位项目老学员推荐', value: '13' },
{ label: '紫荆教育Kelley项目系列活动', value: '14' },
{
label: '紫荆教育其他活动公开课、大讲堂、沙龙等',
value: '15'
},
{ label: '紫荆教育员工或者老师推荐', value: '16' },
{ label: '公司人力资源推荐', value: '17' },
{
label:
'报纸杂志网站广告微博微信公众号论坛等第三方媒体、社交平台',
value: '18'
},
{ label: '网络搜索,如百度、必应、谷歌等', value: '19' },
{ label: '其他', value: '9' }
],
label: '了解途径',
model: 'channel',
required: true
}
]
}
},
{
title: '教育背景',
progress: 0,
get: {
action: '/api/v1/enrollment/profiles?project_id=1001'
},
update: {
action: '/api/v1/enrollment/profiles/6614756225840054272'
},
form: {
options: {
labelWidth: '160px'
},
model: {
real_name_cn: '王鹏飞',
real_name_en: 'Max',
id_type: '0',
id_number: 'xxxxxxx',
birthday: '1994-02-19',
gender: '1',
nationality: '1',
city: '2,52',
date_of_starting_to_work: '2010',
phone_number: 'xxxx',
email: 'xxxxx@163.com',
qq_account: 'xxxx',
we_chat_account: 'xxxx',
mailing_address: '北京',
emergency_contact_name: 'xxxxxx',
emergency_contacts_phone: 'xxxxx',
english_level: '2',
english_score: '12',
channel: '12',
address_province: '2',
address_city: '52',
project_id: '1001'
},
items: [
{
type: 'input',
label: '姓名',
model: 'real_name_cn',
placeholder: '123123',
rules: [
{
required: true,
message: '请输入活动名称',
trigger: 'blur'
},
{
min: 3,
max: 5,
message: '长度在 3 到 5 个字符',
trigger: 'blur'
}
]
},
{
type: 'input',
label: '英文名(姓名全拼)',
model: 'real_name_en',
required: true
},
{
type: 'select',
values: [
{ label: '居民身份证', value: '0' },
{ label: '港澳台身份证', value: '1' },
{ label: '护照号', value: '2' },
{ label: '军官证', value: '3' },
{ label: '其他', value: '9' }
],
label: '证件类型',
model: 'id_type',
required: true
},
{
type: 'input',
label: '证件号码',
model: 'id_number',
required: true
},
{
type: 'datePicker',
label: '出生日期',
model: 'birthday',
required: true,
attrs: { type: 'date', 'value-format': 'yyyy-MM-dd' }
},
{
type: 'radioGroup',
values: [
{ label: '男', value: '1' },
{ label: '女', value: '2' }
],
label: '性别',
model: 'gender',
required: true
},
{
type: 'select',
values: [
{ label: '中国', value: '1' },
{ label: '其他国家', value: '9' }
],
label: '国籍',
model: 'nationality',
required: true
},
{
type: 'datePicker',
label: '参加工作年份',
model: 'date_of_starting_to_work',
required: true,
attrs: { type: 'year', 'value-format': 'yyyy' }
},
{
type: 'input',
label: '手机号',
model: 'phone_number',
required: true
}
]
}
}
]
}
},
......
......@@ -20,6 +20,7 @@
"README.md"
],
"dependencies": {
"axios": "^0.19.0",
"element-ui": "^2.13.0"
},
"devDependencies": {
......
......@@ -71,7 +71,7 @@
<script>
export default {
name: 'VueForm',
name: 'EzjForm',
props: {
options: {
type: Object,
......@@ -126,7 +126,7 @@ export default {
},
onSubmit() {
this.validate().then(() => {
this.$emit('submit', this.model)
this.$emit('onSubmit', this.model)
})
}
}
......
<template>
<div class="ezj-form-pane">
<!-- 多个表单 -->
<template v-if="isMultiple">
<template v-for="(form, index) in form">
<ezj-form
:options="form.options"
:model="form.model"
:items="form.items"
@onSubmit="onSubmit"
:key="index"
>
<el-button>增加一项</el-button>
<el-button>保存</el-button>
</ezj-form>
</template>
</template>
<!-- 一个表单 -->
<template v-else>
<ezj-form
:options="form.options"
:model="form.model"
:items="form.items"
@onSubmit="onSubmit"
></ezj-form>
</template>
</div>
</template>
<script>
import EzjForm from './Form'
import axios from 'axios'
export default {
name: 'EzjFormPane',
components: { EzjForm },
props: {
title: String,
get: {
type: Object,
default() {
return {}
}
},
update: {
type: Object,
default() {
return {}
}
},
data: Object,
headers: Object,
form: [Object, Array]
},
computed: {
isMultiple() {
return Array.isArray(this.form)
}
},
methods: {
init() {
this.getData()
},
// 获取
getData() {
const { action, data = {} } = this.get
console.log(action, this.get)
axios.get(action, { params: data }).then(res => {
console.log(res)
})
},
// 更新
updateData() {
const { action, data = {} } = this.update
axios.post(action, { data }).then(res => {
console.log(res)
})
},
onSubmit() {}
},
beforeMount() {
this.init()
}
}
</script>
<style lang="scss">
</style>
<template>
<div class="ezj-tab-form">
<div class="ezj-tab-form__title">{{title}}</div>
<el-tabs :tab-position="tabPosition">
<template v-for="(tab, index) in tabs">
<el-tab-pane :key="index" :label="tab.title" :lazy="true">
<template v-slot:label>
<i class="el-icon-user"></i>
<span class="title">{{tab.title}}</span>
<!-- 是否必选 -->
<template v-if="showRequired">{{tab.required ? '': '(可选)'}}</template>
<!-- 进度 -->
<template v-if="showProgress">
<span
:class="tab.progress ? 'is-success' : 'is-error'"
>{{tab.progress ? '(已完成)': '(未完成)'}}</span>
</template>
</template>
<ezj-form-pane v-bind="tab"></ezj-form-pane>
</el-tab-pane>
</template>
</el-tabs>
</div>
</template>
<script>
import EzjFormPane from './FormPane'
export default {
name: 'EzjTabForm',
components: { EzjFormPane },
props: {
title: String,
showProgress: { type: Boolean, default: true },
showRequired: { type: Boolean, default: true },
tabs: {
type: Array,
default() {
return []
}
}
},
data() {
return {
tabPosition: 'left'
}
}
}
</script>
<style lang="scss">
.ezj-tab-form__title {
position: absolute;
left: 0;
top: 0;
width: 295px;
font-size: 18px;
line-height: 60px;
color: #fff;
text-align: center;
background-color: #c41230;
}
.ezj-tab-form {
position: relative;
.el-tabs__header {
margin-top: 60px;
width: 295px;
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.08);
}
.el-tabs__active-bar {
display: none;
}
.el-tabs__nav-wrap::after {
display: none;
}
.el-tabs--left .el-tabs__nav-wrap.is-left {
margin-right: 0;
}
.el-tabs--left .el-tabs__item.is-left {
text-align: left;
}
.el-tabs--left,
.el-tabs--right {
overflow: inherit;
}
.el-tabs__item.is-active .title {
color: #c41230;
}
.el-tabs__item {
font-size: 18px;
color: #000;
.is-success {
color: #12c44a;
}
.is-error {
color: #c41230;
}
}
}
</style>
<template>
<div class="ezj-tab-nav__scroll">
<template v-for="(pane, index) in panes">
<div
class="ezj-tab-nav__item"
:key="index"
@click="(e) => $emit('onTabClick', pane, pane.name || pane.index, e)"
>
<span>{{pane.label}}</span>
<span v-if="pane.showRequired">{{pane.required ? '(可选)' : ''}}</span>
<span v-if="pane.showPorgess">{{pane.progress ? '(已完成)' : '(未完成)'}}</span>
</div>
</template>
</div>
</template>
<script>
export default {
name: 'EzjTabNav',
props: {
panes: Array
},
data() {
return {}
},
computed: {},
methods: {}
}
</script>
<style lang="scss">
.ezj-tab-nav__scroll {
overflow-y: auto;
}
.ezj-tab-nav__item {
margin: 20px;
font-size: 18px;
line-height: 20px;
}
</style>
<template>
<div class="ezj-tab-pane">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'EzjTabPane',
props: {
label: String,
name: String,
lazy: Boolean
},
data() {
return {
index: null,
loaded: false
}
},
computed: {
active() {
const active = this.$parent.currentName === (this.name || this.index)
return active
},
paneName() {
return this.name || this.index
}
},
updated() {
this.$parent.$emit('tab-nav-update')
}
}
</script>
<template>
<div class="ezj-tabs">
<div class="ezj-tab-nav">
<div class="ezj-tab-nav__title">{{title}}</div>
<tab-nav :panes="panes" @onTabClick="handleTabClick"></tab-nav>
</div>
<div class="ezj-tab-content">
<slot></slot>
</div>
</div>
</template>
<script>
import TabNav from './TabNav'
export default {
name: 'EzjTabs',
props: {
title: String,
activeName: String,
value: {}
},
components: { TabNav },
data() {
return {
currentName: this.value || this.activeName,
panes: []
}
},
watch: {
activeName(value) {
this.setCurrentName(value)
},
value(value) {
this.setCurrentName(value)
}
},
methods: {
calcPaneInstances() {
if (this.$slots.default) {
const paneSlots = this.$slots.default.filter(
vnode =>
vnode.tag &&
vnode.componentInstance &&
vnode.componentOptions &&
vnode.componentOptions.Ctor.options.name === 'EzjTabPane'
)
this.panes = paneSlots.map(({ componentInstance }) => componentInstance)
} else {
this.panes = []
}
},
handleTabClick(tab, tabName, event) {
this.setCurrentName(tabName)
this.$emit('tab-click', tab, event)
},
setCurrentName(value) {
this.currentName = value
this.$emit('input', value)
}
},
mounted() {
this.calcPaneInstances()
},
update() {
this.calcPaneInstances()
}
}
</script>
<style lang="scss">
.ezj-tabs {
display: flex;
align-items: flex-start;
}
.ezj-tab-nav {
width: 295px;
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.08);
}
.ezj-tab-nav__title {
font-size: 18px;
line-height: 60px;
color: #fff;
text-align: center;
background-color: #c41230;
}
.ezj-tab-content {
flex: 1;
overflow: hidden;
}
</style>
......@@ -16,14 +16,23 @@ import {
TimePicker,
Form,
FormItem,
Tabs,
TabPane,
Upload,
Progress,
ColorPicker
} from 'element-ui'
import VueForm from './VueForm'
import EzjForm from './Form'
import EzjTabs from './Tabs'
import EzjTabPane from './TabPane'
import EzjTabForm from './TabForm'
const components = [EzjForm, EzjTabs, EzjTabPane, EzjTabForm]
const install = function(Vue) {
if (install.installed) return
VueForm.install = function(Vue) {
Vue.use(Input)
Vue.use(InputNumber)
Vue.use(Radio)
......@@ -41,11 +50,24 @@ VueForm.install = function(Vue) {
Vue.use(TimePicker)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Tabs)
Vue.use(TabPane)
Vue.use(Upload)
Vue.use(Progress)
Vue.use(ColorPicker)
Vue.component(VueForm.name, VueForm)
// 遍历注册全局组件
components.map(component => Vue.component(component.name, component))
}
export default VueForm
// 判断是否是直接引入文件
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export default {
// 导出的对象必须具有 install,才能被 Vue.use() 方法安装
install,
// 以下是具体的组件列表
...components
}
......@@ -3,5 +3,8 @@ module.exports = {
index: {
entry: 'examples/main.js'
}
},
devServer: {
proxy: 'https://kelley.ezijing.com'
}
}
......@@ -1537,6 +1537,14 @@ aws4@^1.8.0:
resolved "https://registry.npm.taobao.org/aws4/download/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c"
integrity sha1-JDkOatYThrCnRyZXVNKhchnehiw=
axios@^0.19.0:
version "0.19.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8"
integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==
dependencies:
follow-redirects "1.5.10"
is-buffer "^2.0.2"
babel-code-frame@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
......@@ -3159,6 +3167,13 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
dependencies:
ms "2.0.0"
debug@=3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
debug@^3.0.0, debug@^3.1.1, debug@^3.2.5:
version "3.2.6"
resolved "https://registry.npm.taobao.org/debug/download/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
......@@ -4151,6 +4166,13 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3"
readable-stream "^2.3.6"
follow-redirects@1.5.10:
version "1.5.10"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==
dependencies:
debug "=3.1.0"
follow-redirects@^1.0.0:
version "1.9.0"
resolved "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.9.0.tgz#8d5bcdc65b7108fe1508649c79c12d732dcedb4f"
......@@ -4925,6 +4947,11 @@ is-buffer@^1.1.5:
resolved "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha1-76ouqdqg16suoTqXsritUf776L4=
is-buffer@^2.0.2:
version "2.0.4"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623"
integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==
is-callable@^1.1.4, is-callable@^1.1.5:
version "1.1.5"
resolved "https://registry.npm.taobao.org/is-callable/download/is-callable-1.1.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-callable%2Fdownload%2Fis-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab"
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论