首先总结需求:
基于elementui使用vue脚手架写一个教师管理界面:https://demo.bestvike.com/bv-train-cli/#/
教师列表是标题,新增弹窗界面:失去焦点,检验空,编号姓名验重
搜索框空的时候点搜索就是初始界面:可以按地址查询,可以按姓名查询,教师编号,也可以按照日期
所以说数字和字段包含所有里面搜搜,只要含有就展示
高级搜索点击搜索框变成多个,高级搜索编程收起;空值查询的时候为初界面
多选的时候,新增按钮变为红色删除按钮;只有一个选中的时候有修改和删除按钮,成功之后都会弹窗成功
修改跳转新的界面
https://demo.bestvike.com/bv-train-cli/#/
modify?id=001&
name=%E5%88%98%E6%94%BF%E5%A7%94&sex=1&
inDate=2024-04-09&
address=qwe&
subject=2
姓名带有超链接,
https://demo.bestvike.com/bv-train-cli/#/
detail?id=001&
name=%E5%88%98%E6%94%BF%E5%A7%94&
sex=1&
inDate=2024-04-09&
address=qwe&
subject=2
教师详情界面展示基本信息,返回按钮跳转页面
工程目录结构
public/index.html
—将组件写到html里面,重要的就是如图所示蓝色部分
router/index.js
–在这里配置路由,不同的路由跳转不同的界面,如图根目录的组件是list,另外导入组件有两种方式,第一种就是在页面一开始import,另外一种就是在配置路由的那一行中进行import,如图所示
store/global.js
–用来存储一些都可以用到的固定数据,在这里是性别和学科的字典
store/index.js
vuex
–vuex用来存储组件之间用到的数据,state中存储共享数据,teachers就是初始化一个数据;mutations就是实际执行的方法,由action中的函数进行调用,比如说,在组件中this.$store.dispatch(‘updateTeacher’, updatedTeachers),其中黄色部分就是type类型,actions就会根据type进行具体的操作updateTeacher({ commit }, updatedTeachers) {commit(‘UPDATE_TEACHER’, updatedTeachers); } updatedTeachers就是传过来的数据,经由actions的commit操作之后,就会调用mutations中的**‘UPDATE_TEACHER’**函数,然后进行函数的操作
views文件夹
中的组件就是我所要展示的不同界面
== 重要的一件事,在组件中的template标签中,只能有一个根标签,所以可以写一个div,在div中可以写很多的标签 ==
list.vue、detail.vue、modify.vue
App.vue --父组件
index.html展示的就是这个组件,在这个组件中缓存主页面list,另外标签中就是展示的router配置好的东西进行展示,这里有点展示了父子组件的意思
main.js
–main.js
文件通常是一个程序或项目的入口文件,特别是在使用 JavaScript 进行前端开发时。这个文件负责导入其他模块或脚本,并通常包含启动应用的逻辑。在 Node.js 环境中,main.js
也可以作为应用的启动脚本,它将调用应用的其他部分。
以下是一些常见的用途:
入口点:对于很多 JavaScript 项目来说,
main.js
是整个应用的启动点。它通常会导入其他的模块或脚本,并开始执行应用的逻辑。初始化代码:在这个文件中,你可以执行一些初始化操作,比如设置应用的状态,配置全局变量,或者启动某些后台任务。
依赖管理:
main.js
也常用于导入和初始化项目所需的第三方依赖或模块。路由和系统配置:在 web 应用中,
main.js
可能包含路由配置,决定用户请求哪个页面或功能。同时,它也可能包含系统级别的配置,如数据库连接、API 端点等。错误处理和日志:该文件可能包含错误处理和日志记录的设置,确保应用运行时能够记录重要的信息和错误。
渲染和显示:在前端项目中,
main.js
可能会包含将数据渲染到 DOM 的逻辑,或者控制用户界面显示的脚本。
每个项目都有其特定的结构和需求,所以main.js
的具体内容和作用可能会有所不同。在 Node.js 环境中,main.js
常常是package.json
文件中指定的启动脚本的目标文件。在 ECMAScript 模块系统中,它可能是一个模块导出的目的地,或者是一个模块的顶级作用域。我来用通俗的语言解释一下 `main.js` 文件是干啥用的。
想象一下,一个大的商场或者超市,里面有很多不同的部门和商品,比如食品区、服装区、家电区等等。每个部门都有自己的工作人员和货物。那么,有一个地方是所有工作人员和货物都必须经过的,这个地方就是商场的入口。
在这个情况下,main.js
就像是这个商场的入口。它是整个项目或者应用的开始的地方,所有的事情都是从这里开始的。就像顾客进入商场后,才能去到不同的部门一样,当你的应用开始运行时,它会首先执行 main.js
里面的代码,然后才能使用其他的功能和模块。
main.js
里面通常会做一些事情,比如:
打招呼:应用启动时,可能首先会显示一个欢迎信息。
准备购物车:在应用开始时,可能需要初始化一些数据结构,比如购物车。
安排工作人员:加载和配置需要用到的各种功能模块,就像是安排商场的各个部门的工作人员。
摆放货物:加载和显示商场的商品,也就是展示应用的内容。
处理顾客的需求:根据用户的行为和请求,做出相应的响应和处理。
所以,main.js
就像是商场的入口,是整个购物体验的开始,没有它,顾客就无法进入商场,也就无法购物了。我来举一些例子,帮你更好地理解 `main.js` 文件的用途:
网站的首页:在一个网页项目中,
main.js
可能会包含加载首页所需的所有资源和逻辑,比如图片轮播、导航栏的动画效果等。应用的启动逻辑:在一个 Node.js 应用中,
main.js
可能包含了启动服务器、设置监听端口等初始化操作。游戏的主循环:在一个游戏项目中,
main.js
可能包含了游戏的主循环,负责更新游戏状态、渲染画面等。数据处理:
main.js
可能包含了处理用户输入、从数据库读取数据、计算结果等逻辑。用户界面交互:在前端项目中,
main.js
可能会包含各种用户界面的交互逻辑,比如点击按钮弹出提示框、下拉菜单的变化等。动画和特效:在一些项目中,
main.js
可能会包含实现动画和特效的代码,比如滚动时变化的背景、旋转的图标等。网络请求:
main.js
可能负责发送网络请求,比如从其他服务器获取数据、上传图片等。模块导出:在一个模块化的大型项目中,
main.js
可能是一个模块的导出目的地,用于将其他文件中的功能或数据导出,方便其他文件或项目使用。错误处理和日志记录:在各种应用中,
main.js
可能会包含错误处理和日志记录的逻辑,帮助开发者和用户更好地了解应用的运行状况。配置和设置:在一些复杂的项目中,
main.js
可能会包含各种配置和设置,比如环境变量的设置、第三方服务的接入等。
总的来说,main.js
是一个项目的核心文件,负责整合和调度项目的各种功能和资源。具体它能干什么,取决于项目的需求和开发者的设计。
其中这里创建了父组件App
list.vue–首页面
整体框架
观察界面先把大的框架写出来,按行来分可以分为教师列表,新增按钮(修改删除按钮),搜索栏(高级搜索栏),表单
之前提到的根标签div,可以设置他的位置是居中的还有它的宽度
钩子函数
创建的时候献给teachers赋一个初始值—传值还有接受
新增修改删除按钮
新增按钮:
新增按钮是在列表中没有选中的情况下才会出现,居最右
复选框
给每个教师定义一个属性isSelected,根据复选框的状态,来定义变量(布尔型)用来展示新增修改删除按钮
// 根据选中的行数来决定是否显示删除按钮修改按钮
if (val.length > 0) {
this.showDeleteButton = true
if (val.length === 1) {
this.showEditButton = true
} else {
this.showEditButton = false
}
} else {
this.showDeleteButton = false
this.showEditButton = false
}
},
展示新增按钮
<el-col v-show="!showDeleteButton" >
<div style="text-align: right;">
<el-button type="primary" @click="dialogFormVisible = true" icon="el-icon-plus">新增</el-button>
</div>
新增教师弹窗
点击新增按钮之后会跳出新增用户表单弹窗dialog,这里使用了新增按钮的点击事件,会使dialogFormVisible 的值为true,即会显示dialog,定义dialog全局居左,就是里面的元素都是靠左。
弹窗里面是一个form表单,:model就是表单绑定的数据,:rules就是绑定的表单验证规则,其中rules在data中声明,ref就是一定要有,后续在判断表单验证是否全部通过的时候起到很重要的作用
使用来进行每一行的分割,其中前两行由于有两个元素所以使用和来进行元素之间的间距。
教师编号和教师姓名
**label**就是指的输入框前面显示的文字 **prop**的值"number"表示这个表单项对应的是teacher对象中的number属性。 输入框中:v-model双向数据绑定,style调整宽度,clearable就是可以清除input数据,不需要加等号 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/21a43716ee4643b490a5d1bea934dbdf.png)性别和学科
<el-radio-group 中v-model进行双向数据绑定,
<el-radio 中使用v-for遍历字典中的对象(就是{对应关系})
== 疑问==
<el-select 中placeholder显示初始值
<el-option 中使用v-for遍历字典中的对象(就是{对应关系})
入职日期
<el-date-picker type="date"写不写都无所谓,这里绑定的值是:Wed Apr 17 2024 00:00:00 GMT+0800 (中国标准时间)
后边添加教师的函数中需要进行格式转换,转换为yyyy-mm-dd的字符串日期形式:
// const date=new Date(this.teacher.date)
// this.teacher.date=date.getFullYear() + “-” + (date.getMonth() + 1).toString().padStart(2, ‘0’) + “-” + date.getDate().toString().padStart(2, ‘0’);
地址
maxlength=“200” show-word-limit 字数限制并展示
表单验证规则rules
格式如下:验空如第一行所示
{required: true, message: ‘请输入编号’, trigger: ‘blur’},
验重的时候需要自定义函数
{ validator: this.numberRepeat, message: ‘编号重复’, trigger: ‘blur’ },
另外失去焦点时blur,改变时change
确定取消按钮
在dialog界面中居中显示,
点击函数,这里的函数名add(‘teacher’),中间的是表明,与ref保持一致,并且需要加引号
添加教师的函数 add(teacher):---->这里teacher的值就是 'teacher’表名,不是什么对象
①这里的teacher就是函数中的那个参数就是上面的teacher
this.$refs[teacher].validate((valid) => {
if (valid) { //如果合法要执行的操作
}
});
②首先就是对于日期的格式化
const date=new Date(this.teacher.date)
this.teacher.date=date.getFullYear() + “-” + (date.getMonth() + 1).toString().padStart(2, ‘0’) + “-” + date.getDate().toString().padStart(2, ‘0’);
③复制一个teacher并且push到teachers中,将teachers传到vuex中,每执行一次add函数都会更新一次
④清空表单信息,设置展示弹窗的flag为false,展示成功信息
取消按钮 同理
修改删除按钮:
点击修改调用modify方法进行路由跳转
点击删除调用deleteSome方法进行路由跳转
搜索与高级搜索
此处设计三个flag,第一个:isSearching—模糊搜索中
第二个:changeAdvancedSearching—搜索栏由模糊搜索转换为高级搜索栏
第三个:isAdvancedSearching—高级搜索中
模糊查询:
首先前面有输入框还有一个🔍,输入框有回车事件@keyup.native.enter,点击🔍都会触发搜索,
这个搜索是模糊查询
切换到高级搜索是用了文字按钮,切换两种搜索状态通过设置一个flag,点击高级搜索的时候,令flag为true从而实现切换。
高级搜索:
对于入职时间是一个时间选择器,其中type:daterange至关重要,v-model绑定的值是一个数组有两个值
点击查询会调用高级查询的方法 注意逻辑
点击收起,转换为初始的模糊搜索状态
教师列表
切换表格数据
因为展示的情况有不同,初始状态下展示原教师列表,搜索状态下展示搜索后的教师列表,所以使用:
== :data="!isSearching && !AdvancedSearching?teachers:filteredTeachers ==
表格包含复选框、教师编号、教师姓名、性别、学科、入职时间、地址
其中:
复选框使用 type=selection 不用做其他的特殊处理;
教师姓名要带有超链接可以跳转详情页,在标签中定义一个引入插槽
<el-button type=“text” @click=“detail(scope.row)” size=“small”>{{scope.row.name}}
点击姓名就可以跳转路由,这里要传参,传点击姓名的当前行数据
复选框的选择判断
@selection-change=“handleSelectionChange”
当你把鼠标悬停在一个复选框上,并且点击它时,复选框会被选中或者取消选中。
当你选择了一个复选框,或者多个复选框时,这个事件就会发生。
然后,Vue.js会调用handleSelectionChange这个方法,并且把当前选中的行的数据作为一个参数传递给它。
你在handleSelectionChange方法中可以定义当用户选择或者取消选择行时,你想执行的逻辑,比如更新状态、发送请求等。
设置每个teacher的isSelected的值
设置展示修改删除按钮的flag
关于scope
我们可以将 “scope” 想象为一个内部通道,它允许表格组件(el-table)的每个列(el-table-column)与它的父组件之间进行数据交换。
当你在 el-table-column 组件中使用 slot-scope 属性时,你实际上是在创建一个可以向父组件暴露数据的通道。在这个通道中,“scope” 就是那个可以携带数据的包裹。
具体来说,在这个例子中:
每个 el-table-column 都有一个 slot-scope 属性,它的值被设定为 “scope”。
当父组件渲染表格时,它会为每个列创建一个插槽。这个插槽可以用来定制列的内容。
通过 slot-scope,父组件可以访问到当前列的数据。这就像是一个小型的作用域,它让你可以在插槽内容中访问 row 对象,即当前行的数据。
源码
<template>
<div class="center-block" style=" width: 1300px;">
<el-container>
<el-header>
<h3>教师列表</h3>
</el-header>
<el-main>
<!--新增修改删除-->
<el-row>
<el-col v-show="!showDeleteButton" >
<div style="text-align: right;">
<el-button type="primary" @click="dialogFormVisible = true" icon="el-icon-plus">新增</el-button>
</div>
<!--点击新增按钮后的弹窗界面-->
<div style="text-align: left;">
<el-dialog title="教师新增" :visible.sync="dialogFormVisible" >
<el-form :model="teacher" :rules="rules" ref="teacher" >
<el-form-item >
<el-row :gutter="50">
<el-col :span="12" >
<el-form-item label="教师编号:" prop="number">
<el-input v-model="teacher.number" style="width: 180px;" clearable></el-input>
</el-form-item>
</el-col>
<el-col :span="12" >
<el-form-item label="教师姓名:" prop="name" >
<el-input v-model="teacher.name" style="width: 180px;" clearable></el-input>
</el-form-item>
</el-col >
</el-row>
</el-form-item>
<el-form-item>
<el-row :gutter="50">
<el-col :span="12">
<el-form-item label="性别:" prop="sex">
<el-radio-group v-model="teacher.sex" style="width: 200px;" clearable>
<el-radio v-for="option in sexOptions" :key="option.value" :label="option.value" :value="option.value">{{option.label}}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="学科" prop="subject">
<el-select v-model="teacher.subject" placeholder="请选择学科" style="width: 200px;" clearable>
<el-option v-for="option in subjectOptions" :key="option.value" :label="option.label" :value="option.value"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="入职日期:" prop="date" required>
<el-date-picker type="date" placeholder="选择日期" v-model="teacher.date" style="width: 200px;" clearable></el-date-picker>
</el-form-item>
<el-form-item label="地址:" prop="address">
<el-input type="textarea" v-model="teacher.address" style="width: 500px;" maxlength="200" show-word-limit clearable></el-input>
</el-form-item>
<el-form-item >
<el-row type="flex" justify="center" align="middle" style="margin-top: 10px;">
<el-button type="primary" @click="add('teacher')" icon="el-icon-check">确 定</el-button>
<el-button @click="resetForm('teacher')" icon="el-icon-circle-close">取 消</el-button>
</el-row>
</el-form-item>
</el-form>
</el-dialog>
</div>
</el-col>
<el-col :span="24" class="right">
<el-button v-show="showEditButton" @click="modify" icon="el-icon-edit">修改</el-button>
<el-button type="danger" v-show="showDeleteButton" @click="deleteSome" icon="el-icon-folder-delete">删除</el-button>
</el-col>
</el-row>
<el-divider></el-divider>
<!--搜索与高级搜索-->
<el-row>
<!--搜索-->
<template v-if="!changeAdvancedSearching">
<el-col :span="15" style="margin-top: 15px;">
<el-input placeholder="请输入内容" v-model="fuzzySearchInput" @keyup.native.enter="handleEnter" el-icon-circle-close clearable>
<el-button slot="append" icon="el-icon-search" @click="handleEnter"></el-button>
</el-input>
</el-col>
<!-- 高级搜索-->
<el-col :span="9" class="right" style="margin-top: 15px;">
<el-button type="text" @click="changeAdvancedSearching = true" icon="el-icon-arrow-down el-icon--right">
高级搜索<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
</el-col>
</template>
<template v-else>
<el-row>
<!-- 教师姓名-->
<el-col :span="4" style="margin-top: 15px;">
教师姓名:<el-input placeholder="请输入" v-model="nameSearchInput" style="width: 120px;" clearable></el-input>
</el-col>
<!-- 学科-->
<el-col :span="5" >
<div style="margin-top: 15px;">
学科:<el-select v-model="subjectSearchInput" slot="prepend" placeholder="请选择" style="width: 180px;" clearable>
<el-option v-for="option in subjectOptions" :key="option.value" :label="option.label" :value="option.value">{{ option.label}}</el-option>
</el-select>
</div >
</el-col>
<!--入职时间-->
<el-col :span="9" style="margin-top: 15px;">
入职时间:
<el-date-picker type="daterange" v-model="dateSearchInput"
format="yyyy-MM-dd "value-format="yyyy-MM-dd " style="width: 300px;"
start-placeholder="开始日期" end-placeholder="结束日期" range-separator="至" >
</el-date-picker>
</el-col>
<!--查询-->
<el-col :span="2" style="margin-top: 15px;">
<el-button type="primary" icon="el-icon-search" @click="advancedSearching">
查询
</el-button>
</el-col>
<!-- 收起-->
<el-col :span="4" class="right" style="margin-top: 15px;">
<el-button type="text" @click="putAway">
收起<i class="el-icon-arrow-up el-icon--right"></i>
</el-button>
</el-col>
</el-row>
</template>
</el-row>
<br>
<!--表单-->
<el-table ref="teachers" :data="!isSearching && !AdvancedSearching?teachers:filteredTeachers" tooltip-effect="dark" border style="width: 100%" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="number" label="教师编号" width="90"></el-table-column>
<el-table-column prop="name" label="教师姓名" width="120">
<template slot-scope="scope">
<el-button type="text" @click="detail(scope.row)" size="small">{{scope.row.name}}</el-button>
</template>
</el-table-column>
<el-table-column prop="sex" label="性别" width="50">
<template slot-scope="scope">
{{ sexOptions.find(option => option.value === scope.row.sex).label }}
</template>
</el-table-column>
<el-table-column prop="subject" label="学科" width="60">
<template slot-scope="scope">
{{ subjectOptions.find(option => option.value === scope.row.subject).label }}
</template>
</el-table-column>
<el-table-column prop="date" label="入职时间" width="200">
<template slot-scope="scope">{{ scope.row.date }}</template>
</el-table-column>
<el-table-column prop="address" label="地址" show-overflow-tooltip>
</el-table-column>
</el-table>
</el-main>
</el-container>
</div>
</template>
<script>
import { subjectOptions } from '@/store/global';
import { sexOptions } from '@/store/global';
export default {
name: "list",
data() {
return {
isSearching: false,
changeAdvancedSearching: false,
AdvancedSearching: false,
fuzzySearchInput: '',
nameSearchInput: '',
subjectSearchInput: '',
dateSearchInput: [],
subjectOptions: subjectOptions,
sexOptions: sexOptions,
dialogFormVisible: false,
teachers: [],
selectedTeachers: [],
filteredTeachers: [],
teacher: {
isSelected: false,
number: '',
name: '',
sex: '1',
subject: '',
date: '',
address: ''
},
formLabelWidth: '120px',
showDeleteButton: false,
showEditButton: false,
rules: {
number: [
{required: true, message: '请输入编号', trigger: 'blur'},
{ validator: this.numberRepeat, message: '编号重复', trigger: 'blur' },
],
name: [
{required: true, message: '请输入姓名', trigger: 'blur'},
{ validator: this.nameRepeat, trigger: 'blur' },
],
sex: [
{required: true, message: '请选择性别', trigger: 'change'}
],
subject: [
{required: true, message: '请选择学科', trigger: 'change'}
],
date: [
{ required: true, message: '请选择日期', trigger: 'change'}
],
address: [
{required: true, message: '请输入地址', trigger: 'blur'}
]
}
}
},
created(){
this.$store.dispatch('initTeachers', this.teachers);
},
methods: {
numberRepeat(rule, value, callback) {
if (this.teachers.some(teacher => value === teacher.number)) {
callback(new Error('编号重复'));
}else{
callback()
}
},
nameRepeat(rule, value, callback) {
if (this.teachers.some(teacher => value === teacher.name)) {
callback(new Error('姓名重复'));
}else{
callback()
}
},
//新增教师
add(teacher) {
this.$refs[teacher].validate((valid) => {
if (valid) {
const date=new Date(this.teacher.date)
this.teacher.date=date.getFullYear() + "-" + (date.getMonth() + 1).toString().padStart(2, '0') + "-" + date.getDate().toString().padStart(2, '0');
this.teachers.push({...this.teacher})
this.$store.dispatch('updateTeacher', this.teachers);
this.$refs[teacher].resetFields();
this.dialogFormVisible = false
this.$message({
message: '新增成功',
type: 'success'
})
console.log(this.teachers);
}
});
},
//取消增加
resetForm(teacher) {
this.$refs[teacher].resetFields();
this.dialogFormVisible = false
},
//模糊搜寻(回车)
handleEnter() {
if (this.fuzzySearchInput) {
// 创建一个正则表达式,用于匹配包含模糊查询字符串的属性
const regex = new RegExp(this.fuzzySearchInput.toLowerCase(), 'i');
// 只针对编号、姓名、时间、地址进行过滤
this.filteredTeachers = this.teachers.filter(teacher => {
return ['number', 'name', 'date', 'address'].some(key => {
return regex.test(String(teacher[key]).toLowerCase());
});
});
// 如果过滤结果为空,则重置为原始教师列表
if (this.filteredTeachers.length === 0) {
this.filteredTeachers = this.teachers;
}
this.isSearching = true;
} else {
this.filteredTeachers = this.teachers;
this.isSearching = false;
}
},
//点击收起
putAway() {
this.isSearching = false
this.changeAdvancedSearching = false
this.AdvancedSearching=false
this.fuzzySearchInput = ''
},
//高级查询
advancedSearching() {
this.filteredTeachers = this.teachers; // 初始化过滤后的教师数组
// 根据输入的搜索条件过滤教师
if (this.nameSearchInput) {
this.filteredTeachers = this.filteredTeachers.filter(teacher => teacher.name === this.nameSearchInput);
}
if (this.subjectSearchInput) {
this.filteredTeachers = this.filteredTeachers.filter(teacher => teacher.subject === this.subjectSearchInput);
}
if (this.dateSearchInput && this.dateSearchInput.length > 1) {
const startDate = new Date(this.dateSearchInput[0]);
const endDate = new Date(this.dateSearchInput[1]);
this.filteredTeachers = this.filteredTeachers.filter(teacher => {
const teacherDate = new Date(teacher.date);
return teacherDate >= startDate && teacherDate <= endDate;
});
}
this.AdvancedSearching = true; // 设置高级搜索状
},
//复选框状态
handleSelectionChange(val) {
this.selectedTeachers = val;
if (val) {
val.forEach(teacher => {
teacher.isSelected = true
})
}
// 根据选中的行数来决定是否显示删除按钮修改按钮
if (val.length > 0) {
this.showDeleteButton = true
if (val.length === 1) {
this.showEditButton = true
} else {
this.showEditButton = false
}
} else {
this.showDeleteButton = false
this.showEditButton = false
}
},
//删除
deleteSome(){
let i=this.teachers.length
while (i--){
if (this.teachers[i].isSelected){
this.teachers.splice(i, 1)
}
}
this.$message({
message: '删除成功',
type: 'success'
})
},
//跳转详情页
detail(teacher) {
this.$router.push({
path: '/detail',
query: {
number: teacher.number,
name: teacher.name,
sex: teacher.sex,
date: teacher.date,
address: teacher.address,
subject: teacher.subject
}
});
},
//修改
modify() {
this.$router.push({
path: '/modify',
query: {
teacher: this.teachers.filter(teacher => teacher.isSelected)[0]
}
})
},
},
}
</script>
<style>
.el-form-item__content {
text-align: left;
}
.right{
text-align: right;
}
.center-block {
margin-left: auto;
margin-right: auto;
}
.el-dialog__title {
text-align: left; /* 将标题文字对齐到左边 */
margin-left: 10px; /* 在标题和对话框边缘之间添加一些间距 */
}
</style>
detail.vue -详情页
展示界面:
返回:
数据和钩子函数
源码
<template>
<div class="center-block" style=" width: 1200px;">
<h3>教师详情</h3>
<el-divider></el-divider>
<el-form class="el-form-item__content">
<el-row>
<el-col :span="12">
<el-form-item label="教师编号:" :label-width="formLabelWidth">
{{teacher.number}}
</el-form-item>
</el-col >
<el-col :span="12">
<el-form-item label="教师姓名:" :label-width="formLabelWidth">
{{teacher.name}}
</el-form-item>
</el-col >
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="性别:" :label-width="formLabelWidth">
{{ sexOptions.find(option => option.value === teacher.sex).label }}
</el-form-item>
</el-col >
<el-col :span="12">
<el-form-item label="学科:" :label-width="formLabelWidth">
{{ subjectOptions.find(option => option.value === teacher.subject).label }}
</el-form-item>
</el-col >
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="入职日期:" :label-width="formLabelWidth">
{{teacher.date}}
</el-form-item>
</el-col >
</el-row>
<el-row>
<el-form-item label="地址:" :label-width="formLabelWidth">
{{teacher.address}}
</el-form-item>
</el-row>
</el-form>
<router-link to="/" ><el-button style="text-align: right;">返回</el-button></router-link>
</div>
</template>
<script>
import {sexOptions, subjectOptions} from "@/store/global";
export default {
name: "detail",
data(){
return{
sexOptions: sexOptions,
subjectOptions: subjectOptions,
teacher: {
number: '',
name: '',
sex:'',
subject: '',
date: '',
address: ''
},
formLabelWidth: '120px',
}
},
created() {
this.teacher.number=this.$route.query.number
this.teacher.name=this.$route.query.name
this.teacher.sex=this.$route.query.sex
this.teacher.date=this.$route.query.date
this.teacher.address=this.$route.query.address
this.teacher.subject=this.$route.query.subject
},
}
</script>
modify.vue -修改界面
获取vuex中的数据
源码
<template>
<div class="center-block" style=" width: 1200px;">
<h3>教师修改</h3>
<el-divider></el-divider>
<el-form :model="teacher" :rules="rules" ref="teacher" >
<el-form-item >
<el-row :gutter="50">
<el-col :span="12" >
<el-form-item label="教师编号:" prop="number">
{{ teacher.number }}
</el-form-item>
</el-col>
<el-col :span="12" >
<el-form-item label="教师姓名:" prop="name" >
<el-input v-model="teacher.name" style="width: 180px;" clearable></el-input>
</el-form-item>
</el-col >
</el-row>
</el-form-item>
<el-form-item>
<el-row :gutter="50">
<el-col :span="12">
<el-form-item label="性别:" prop="sex">
<el-radio-group v-model="teacher.sex" style="width: 200px;" clearable>
<el-radio v-for="option in sexOptions" :key="option.value" :label="option.value" :value="option.value">{{option.label}}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="学科:" prop="subject">
<el-select v-model="teacher.subject" placeholder="请选择学科" style="width: 200px;" clearable>
<el-option v-for="option in subjectOptions" :key="option.value" :label="option.label" :value="option.value"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="入职日期:" prop="date" required>
<el-date-picker type="date" placeholder="选择日期" v-model="teacher.date" style="width: 200px;" clearable></el-date-picker>
</el-form-item>
<el-form-item label="地址:" prop="address">
<el-input type="textarea" v-model="teacher.address" style="width: 500px;" maxlength="200" show-word-limit clearable></el-input>
</el-form-item>
<el-form-item>
<el-row type="flex" justify="center" align="middle" style="margin-top: 10px;">
<el-button type="primary" @click="updateTeacher('teacher')" icon="el-icon-check">确 定</el-button>
<el-button @click="goBack" icon="el-icon-circle-close">取 消</el-button>
</el-row>
</el-form-item>
</el-form>
</div>
</template>
<script>
import {sexOptions, subjectOptions} from "@/store/global";
export default {
name: "modify",
data(){
return{
sexOptions: sexOptions,
subjectOptions: subjectOptions,
rules: {
name: [
{required: true, message: '请输入姓名', trigger: 'blur'},
{ validator: this.nameRepeat, trigger: 'blur' },
],
sex:[
{required: true, message: '请输入性别', trigger: 'blur'},
],
subject: [
{ required: true, message: '请选择学科', trigger: 'change' }
],
date: [
{ required: true, message: '请选择日期', trigger: 'change' }
],
address: [
{ required: true, message: '请输入地址', trigger: 'blur' }
]
},
teacher: {
isSelected: true,
number: '',
name: '',
sex:'',
subject: '',
date: '',
address: ''
},
formLabelWidth: '120px',
}
},
created() {
this.teacher=this.$route.query.teacher
},
methods:{
nameRepeat(rule, value, callback) {
if (this.teachers.filter(teacher =>teacher.number!==this.teacher.number).some(teacher => value === teacher.name)) {
callback(new Error('姓名重复'));
}else{
callback()
}
},
updateTeacher(teacher) {
this.$refs[teacher].validate((valid) => {
if (valid) {
const date=new Date(this.teacher.date)
this.teacher.date=date.getFullYear() + "-" + (date.getMonth() + 1).toString().padStart(2, '0') + "-" + date.getDate().toString().padStart(2, '0');
const updatedTeachers = this.teachers
const index = this.teachers.findIndex(teacher => teacher.number === this.teacher.number)
if (index !== -1) {
updatedTeachers.splice(index, 1, this.teacher)
}
this.$store.dispatch('updateTeacher', updatedTeachers)
this.$message({
message: '修改成功',
type: 'success'
})
this.$router.push('/')
}
});
},
goBack(){
this.$router.push('/')
}
},
computed: {
teachers() {
return this.$store.state.teachers;
}
},
}
</script>