feat: 💥 新增多表单验证以及重构代码结构

This commit is contained in:
zouzhibing 2022-12-05 09:10:25 +08:00
parent 22cd6da835
commit 1caf9733e2
24 changed files with 295 additions and 55 deletions

View File

@ -25,7 +25,6 @@
"core-js": "^3.6.5", "core-js": "^3.6.5",
"dayjs": "^1.11.4", "dayjs": "^1.11.4",
"echarts": "^5.3.1", "echarts": "^5.3.1",
"echarts-liquidfill": "^3.1.0",
"element-plus": "^2.2.21", "element-plus": "^2.2.21",
"exceljs": "^4.3.0", "exceljs": "^4.3.0",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",

View File

@ -0,0 +1,18 @@
.m-container-layout {
width: 100%;
height: 100%;
display: flex;
padding: 10px 12px;
box-sizing: border-box;
.m-container-layout-inner {
flex: 1;
display: flex;
flex-direction: column;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
background: white;
padding: 20px;
width: 100%;
height: 100%;
box-sizing: border-box;
}
}

View File

@ -0,0 +1,13 @@
<template>
<div class="m-container-layout">
<div class="m-container-layout-inner">
<slot></slot>
</div>
</div>
</template>
<script lang="ts" setup></script>
<style lang="scss" scoped>
@import "./index.scss";
</style>

View File

@ -11,11 +11,11 @@
<script lang="ts" setup> <script lang="ts" setup>
import GlobalComSize from './components/globalComSize.vue' import GlobalComSize from './components/globalComSize.vue'
import HeaderSearch from './components/HeaderSearch' import HeaderSearch from './components/HeaderSearch.vue'
import Remind from './components/Remind' import Remind from './components/Remind.vue'
import ScreenFull from './components/ScreenFull.vue' import ScreenFull from './components/ScreenFull.vue'
import Setting from './components/Setting.vue' import Setting from './components/Setting.vue'
import Avatar from './components/Avatar' import Avatar from './components/Avatar.vue'
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -30,7 +30,6 @@
let { device } = useResizeHandler() let { device } = useResizeHandler()
watch(()=>device.value,(val)=>{ watch(()=>device.value,(val)=>{
console.log('themeConfig.value.mode',themeConfig.value.mode)
let vertical = val==='mobile'?'vertical':themeConfig.value.mode let vertical = val==='mobile'?'vertical':themeConfig.value.mode
const body = document.body as HTMLElement; const body = document.body as HTMLElement;
body.setAttribute("class", `layout-${vertical}`); body.setAttribute("class", `layout-${vertical}`);

View File

@ -3,6 +3,9 @@ import App from './App.vue'
import router from './routers' import router from './routers'
import pinia from "./store"; import pinia from "./store";
import {registerElIcons} from "@/plugins/ElIcons"
// 引入全局组件布局
import PageWrapLayout from '@/components/PageWrapLayout/index.vue'
// 权限路由 // 权限路由
import './permission' import './permission'
// svg-icons注册导入 // svg-icons注册导入
@ -19,24 +22,12 @@ import "@/styles/element-dark.scss";
import "@/assets/iconfont/iconfont.css"; import "@/assets/iconfont/iconfont.css";
import "@/assets/iconfont/iconfont.js"; import "@/assets/iconfont/iconfont.js";
// 引入全局组件布局
import UContainerLayout from '@/components/u-container-layout/index.vue'
const app = createApp(App) const app = createApp(App)
registerElIcons(app)
app.component('svg-icon',SvgIcon) app.component('svg-icon',SvgIcon)
app.component('u-container-layout',UContainerLayout) app.component('PageWrapLayout',PageWrapLayout)
// 注册icon组件
import * as ElIconsModules from '@element-plus/icons-vue'
// 全局注册element-plus icon图标组件
Object.keys(ElIconsModules).forEach((key) => {//循环遍历组件名称
if ("Menu" !== key) {//如果不是图标组件不是Menu就跳过否则加上ICon的后缀
app.component(key, ElIconsModules[key]);
} else {
app.component(key + "Icon", ElIconsModules[key]);
}
});
app.use(pinia) app.use(pinia)
app.use(router) app.use(router)

16
src/plugins/ElIcons.ts Normal file
View File

@ -0,0 +1,16 @@
// 注册icon组件
import * as ElIconsModules from '@element-plus/icons-vue'
export const registerElIcons = (app)=>{
// 全局注册element-plus icon图标组件
Object.keys(ElIconsModules).forEach((key) => {//循环遍历组件名称
if ("Menu" !== key) {//如果不是图标组件不是Menu就跳过否则加上ICon的后缀
app.component(key, ElIconsModules[key]);
} else {
app.component(key + "Icon", ElIconsModules[key]);
}
});
}

View File

@ -32,6 +32,12 @@ const formRouter = [{
name: 'appendForm', name: 'appendForm',
meta: { title: '增删 Form', keepAlive: true , icon: 'MenuIcon'} meta: { title: '增删 Form', keepAlive: true , icon: 'MenuIcon'}
}, },
{
path: 'moreForm',
component: () => import('@/views/form/moreForm/index.vue'),
name: 'moreForm',
meta: { title: '多表单验证', keepAlive: true , icon: 'MenuIcon'}
},
] ]
}] }]

View File

@ -6,6 +6,7 @@ body {
overflow-x: hidden; overflow-x: hidden;
margin: 0; margin: 0;
padding: 0; padding: 0;
font-size: 14px;
} }
body{ body{
background: #f0f2f5; background: #f0f2f5;

View File

@ -1,5 +1,5 @@
<template> <template>
<u-container-layout style="width: 100%"> <PageWrapLayout style="width: 100%">
<el-row class="row-bg" :gutter="10"> <el-row class="row-bg" :gutter="10">
<el-col :xs="24" :sm="12" :lg="8"> <el-col :xs="24" :sm="12" :lg="8">
<el-card class="box-card"> <el-card class="box-card">
@ -92,7 +92,7 @@
</el-card> </el-card>
</el-col> </el-col>
</el-row> </el-row>
</u-container-layout> </PageWrapLayout>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import LineCharts from './components/line.vue' import LineCharts from './components/line.vue'

View File

@ -1,5 +1,5 @@
<template> <template>
<u-container-layout class="m-upload-excel"> <PageWrapLayout class="m-upload-excel">
<el-upload <el-upload
style="width: 100%" style="width: 100%"
class="upload-demo" class="upload-demo"
@ -23,7 +23,7 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
</u-container-layout> </PageWrapLayout>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">

View File

@ -0,0 +1,48 @@
<template>
<el-card header="表单组件1">
<el-form :model="form" :rules="rules" ref="formRuleOneRef" label-width="100px" >
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" >
<el-form-item label="姓名" prop="name">
<el-input v-model="form.name" placeholder="请输入姓名" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" >
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" placeholder="请输入用户邮箱" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" >
<el-form-item label="用户名" prop="autograph">
<el-input v-model="form.autograph" placeholder="请输入登陆账户名" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" >
<el-form-item label="职务" prop="occupation">
<el-select v-model="form.occupation" placeholder="请选择职务" clearable >
<el-option label="计算机 / 互联网 / 通信" value="1"></el-option>
<el-option label="生产 / 工艺 / 制造" value="2"></el-option>
<el-option label="医疗 / 护理 / 制药" value="3"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
</template>
<script lang="ts" setup>
import {reactive, ref} from 'vue';
// const formRuleOneRef = ref()
const form = reactive({ name: '', email: '', autograph: '', occupation: '' })
const rules = reactive({
name: { required: true, message: '请输入姓名', trigger: 'blur' },
email: { required: true, message: '请输入用户邮箱', trigger: 'blur' },
autograph: { required: true, message: '请输入登陆账户名', trigger: 'blur' },
});
</script>

View File

@ -0,0 +1,42 @@
<template>
<el-card header="表单组件3">
<el-form :model="form" :rules="rules" ref="formRuleThreeRef" label-width="100px" >
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" >
<el-form-item label="创建用户" prop="createUser">
<el-input v-model="form.createUser" placeholder="请输入创建用户" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" >
<el-form-item label="修改用户" prop="editUser">
<el-input v-model="form.editUser" placeholder="请输入修改用户" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" >
<el-form-item label="所属用户" prop="user">
<el-input v-model="form.user" placeholder="请输入所属用户" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" >
<el-form-item label="所属部门" prop="department">
<el-input v-model="form.department" placeholder="请输入所属部门" clearable></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
</template>
<script lang="ts" setup>
import {reactive, ref} from 'vue';
const formRuleThreeRef = ref()
const form = reactive( { createUser: '', editUser: '', user: '', department: '' })
const rules = reactive( {
createUser: { required: true, message: '请输入创建用户', trigger: 'blur' },
editUser: { required: true, message: '请输入修改用户', trigger: 'blur' },
user: { required: true, message: '请输入所属用户', trigger: 'blur' },
department: { required: true, message: '请输入所属部门', trigger: 'blur' },
})
</script>

View File

@ -0,0 +1,44 @@
<template>
<el-card header="表单组件2">
<el-form :model="form" :rules="rules" ref="formRuleTwoRef" label-width="100px" >
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" >
<el-form-item label="手机" prop="phone">
<el-input v-model="form.phone" placeholder="请输入手机" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" >
<el-form-item label="性别">
<el-select v-model="form.sex" placeholder="请选择性别" clearable class="w100">
<el-option label="男" value="1"></el-option>
<el-option label="女" value="2"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" >
<el-form-item label="登录密码" prop="password">
<el-input v-model="form.password" placeholder="请输入登录密码" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" >
<el-form-item label="权限角色" prop="auth">
<el-input v-model="form.auth" placeholder="请输入权限角色" clearable></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
</template>
<script lang="ts" setup>
import {reactive, ref} from 'vue';
const formRuleTwoRef = ref()
const form = reactive({ phone: '', sex: '', password: '', auth: '' })
const rules = reactive( {
phone: { required: true, message: '请输入手机', trigger: 'blur' },
password: { required: true, message: '请输入登录密码', trigger: 'blur' },
auth: { required: true, message: '请输入权限角色', trigger: 'blur' },
})
</script>

View File

@ -0,0 +1,12 @@
.m-more-form{
width: 100%;
padding: 10px;
box-sizing: border-box;
:deep(.el-card){
margin-bottom: 10px;
}
.footer{
width: 100%;
text-align: center;
}
}

View File

@ -0,0 +1,57 @@
<template>
<div class="m-more-form">
<FormOne ref="formRuleOne"/>
<FormTwo ref="formRuleTwo"/>
<FormThree ref="formRuleThree"/>
<div class="footer">
<el-button @click="onResetForm">重置</el-button>
<el-button type="primary" @click="onSubmitForm">验证表单</el-button>
</div>
</div>
</template>
<script lang="ts" setup>
import {getCurrentInstance} from 'vue'
import { ElMessage } from 'element-plus';
import FormOne from './components/FormOne.vue'
import FormTwo from './components/FormTwo.vue'
import FormThree from './components/FormThree.vue'
const { proxy } = <any>getCurrentInstance();
//
const formRulesValidate = (pageRef: string, sonRef: string) => {
return new Promise((resolve) => {
proxy.$refs[pageRef].$refs[sonRef].validate((valid: boolean) => {
if (valid) resolve(valid);
});
});
};
const formRulesResetFields = ()=>{
proxy.$refs.formRuleOne.$refs.formRuleOneRef.resetFields();
proxy.$refs.formRuleTwo.$refs.formRuleTwoRef.resetFields();
proxy.$refs.formRuleThree.$refs.formRuleThreeRef.resetFields();
}
const onSubmitForm = ()=>{
Promise.all([
formRulesValidate('formRuleOne','formRuleOneRef'),
formRulesValidate('formRuleTwo','formRuleTwoRef'),
formRulesValidate('formRuleThree','formRuleThreeRef'),
]).then(res=>{
ElMessage.success('表单全部验证成功');
})
}
//
const onResetForm = () => {
formRulesResetFields();
};
</script>
<style lang="scss" scoped>
@import "./index.scss";
</style>

View File

@ -1,6 +1,6 @@
<template> <template>
<u-container-layout> <PageWrapLayout>
<div style="max-width: 800px"> <div style="max-width: 800px">
<el-form <el-form
ref="ruleFormRef" ref="ruleFormRef"
@ -68,7 +68,7 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
</u-container-layout> </PageWrapLayout>
</template> </template>
<script lang="ts" setup > <script lang="ts" setup >

View File

@ -1,5 +1,5 @@
<template> <template>
<u-container-layout class="components-container"> <PageWrapLayout class="components-container">
<div class="content-box"> <div class="content-box">
<el-alert <el-alert
title="普通引入方式 Font Class" title="普通引入方式 Font Class"
@ -40,7 +40,7 @@
</div> </div>
</div> </div>
</u-container-layout> </PageWrapLayout>
</template> </template>

View File

@ -1,5 +1,5 @@
<template> <template>
<u-container-layout class="mark-down"> <PageWrapLayout class="mark-down">
<el-alert <el-alert
title="Markdown 是基于 md-editor-v3 插件完成, 官方文档请查看 https://imzbf.github.io/md-editor-v3/index" title="Markdown 是基于 md-editor-v3 插件完成, 官方文档请查看 https://imzbf.github.io/md-editor-v3/index"
type="warning" type="warning"
@ -11,27 +11,21 @@
<div style="margin-top: 20px; flex-shrink: 0"> <div style="margin-top: 20px; flex-shrink: 0">
<el-button type="primary" @click="submit">提交</el-button> <el-button type="primary" @click="submit">提交</el-button>
</div> </div>
</u-container-layout> </PageWrapLayout>
</template> </template>
<script lang="ts">
// https://www.jianshu.com/p/0b06128a6117 <script lang="ts" setup>
import { defineComponent } from 'vue' import {ref} from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage } from 'element-plus'
import MdEditor from 'md-editor-v3' import MdEditor from 'md-editor-v3'
import 'md-editor-v3/lib/style.css' import 'md-editor-v3/lib/style.css'
export default defineComponent({ const text = ref( '## 你好呀,欢迎!' )
components: { MdEditor },
data() { const submit = ()=> {
return { text: '## 你好呀,欢迎!' } console.log('this.text', text.value)
}, ElMessage.success(`提交数据:${text.value}`)
methods: { }
submit() {
console.log('this.text', this.text)
ElMessage.success(`提交数据:${this.text}`)
},
},
})
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@ -1,5 +1,5 @@
<template> <template>
<u-container-layout> <PageWrapLayout>
<div id="wrap" style="margin-bottom: 20px"> <div id="wrap" style="margin-bottom: 20px">
<div> <div>
<el-button type="primary" @click="print(1)" >打印图片</el-button> <el-button type="primary" @click="print(1)" >打印图片</el-button>
@ -30,7 +30,7 @@
<el-descriptions-item label="honorColor"> 要以彩色打印文本请将此属性设置为true默认情况下所有文本都将以黑色打印 </el-descriptions-item> <el-descriptions-item label="honorColor"> 要以彩色打印文本请将此属性设置为true默认情况下所有文本都将以黑色打印 </el-descriptions-item>
<el-descriptions-item label="css"> 这允许我们传递一个或多个应该应用于正在打印的html的css文件URL值可以是包含单个URL的字符串也可以是包含多个URL的数组 </el-descriptions-item> <el-descriptions-item label="css"> 这允许我们传递一个或多个应该应用于正在打印的html的css文件URL值可以是包含单个URL的字符串也可以是包含多个URL的数组 </el-descriptions-item>
</el-descriptions> </el-descriptions>
</u-container-layout> </PageWrapLayout>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

View File

@ -1,5 +1,5 @@
<template> <template>
<u-container-layout> <PageWrapLayout>
<div style="display: flex"> <div style="display: flex">
<el-input v-model="inputData" placeholder="请输入" style="width: 400px; max-width: 100%" /> <el-input v-model="inputData" placeholder="请输入" style="width: 400px; max-width: 100%" />
<el-button type="primary" @click="handleQrcode(1)"> <el-button type="primary" @click="handleQrcode(1)">
@ -26,7 +26,7 @@
<el-descriptions-item label="colorLight"> 空白区的颜色 </el-descriptions-item> <el-descriptions-item label="colorLight"> 空白区的颜色 </el-descriptions-item>
<el-descriptions-item label="callback"> 生成的二维码 Data URI 可以在回调中取得,第一个参数为二维码 data URL, 第二个参数为 props 传过来的 qid(因为二维码生成是异步的,所以加个 id 用于排序) </el-descriptions-item> <el-descriptions-item label="callback"> 生成的二维码 Data URI 可以在回调中取得,第一个参数为二维码 data URL, 第二个参数为 props 传过来的 qid(因为二维码生成是异步的,所以加个 id 用于排序) </el-descriptions-item>
</el-descriptions> </el-descriptions>
</u-container-layout> </PageWrapLayout>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue' import { ref } from 'vue'

View File

@ -1,8 +1,8 @@
<template> <template>
<u-container-layout style="min-height: 300px"> <PageWrapLayout style="min-height: 300px">
<el-button @contextmenu.prevent="rightClick" style="width: 200px">右键菜单</el-button> <el-button @contextmenu.prevent="rightClick" style="width: 200px">右键菜单</el-button>
<RightClickMenu :left="clientX" :top="clientY" @ok="operatingRightAction" :data="data" /> <RightClickMenu :left="clientX" :top="clientY" @ok="operatingRightAction" :data="data" />
</u-container-layout> </PageWrapLayout>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

View File

@ -1,5 +1,5 @@
<template> <template>
<u-container-layout class="components-container"> <PageWrapLayout class="components-container">
<div class="content-box"> <div class="content-box">
<el-alert <el-alert
title="SVG 图标目前使用 vite-plugin-svg-icons 插件完成,官方文档请查看 https://github.com/vbenjs/vite-plugin-svg-icons" title="SVG 图标目前使用 vite-plugin-svg-icons 插件完成,官方文档请查看 https://github.com/vbenjs/vite-plugin-svg-icons"
@ -26,7 +26,7 @@
<el-descriptions-item label="iconStyle"> 图标的样式默认样式为 { width: "1em", height: " 1em" } </el-descriptions-item> <el-descriptions-item label="iconStyle"> 图标的样式默认样式为 { width: "1em", height: " 1em" } </el-descriptions-item>
</el-descriptions> </el-descriptions>
</div> </div>
</u-container-layout> </PageWrapLayout>
</template> </template>

View File

@ -1,5 +1,5 @@
<template> <template>
<u-container-layout> <PageWrapLayout>
<div style="margin-bottom: 20px"> <div style="margin-bottom: 20px">
<div style="display: flex; justify-content: flex-end"> <div style="display: flex; justify-content: flex-end">
<el-radio-group v-model="radio"> <el-radio-group v-model="radio">
@ -36,7 +36,7 @@
<el-descriptions-item label="onChange"> 数据实时改变 </el-descriptions-item> <el-descriptions-item label="onChange"> 数据实时改变 </el-descriptions-item>
</el-descriptions> </el-descriptions>
</u-container-layout> </PageWrapLayout>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>