EL表单式判断是否为null或者list为empty

本文介绍了一个使用 JdbcTemplate 的简单 ORM 实现方式,通过示例展示了如何进行登录验证,并使用 JSTL 进行页面元素的条件渲染。

http://newnull.com/jdbctemplate%E5%AE%9E%E7%8E%B0%E7%AE%80%E5%8D%95%E7%9A%84orm/

 

@RequestMapping("/login")
	// 请求url地址映射,类似Struts的action-mapping
	public ModelAndView Login(
			@RequestParam(value = "userEmail", required = false) String userEmail,
			@RequestParam(value = "userNick", required = false) String userNick) {
		// @RequestParam是指请求url地址映射中必须含有的参数(除非属性required=false)
		// @RequestParam可简写为:@RequestParam("username")
		//
		// if (!"admin".equals(username) || !"admin".equals(password)) {
		// return "loginError"; //
		// 跳转页面路径(默认为转发),该路径不需要包含spring-servlet配置文件中配置的前缀和后缀
		// }
		// return "loginSuccess";
		String sql = "select * from user_info where user_email=? and password=?";
		UserInfo user = jdbcTemplate.queryForObject(sql,new Object[]{userEmail,userNick},new BeanPropertyRowMapper<UserInfo>(UserInfo.class));
				
		Map<String, UserInfo> model = new HashMap<String, UserInfo>();
		model.put("userlist", user);
		return new ModelAndView("index", model);
	}

 

判断是否为空

 

 

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>           

<c:if test="${userInfo != null}">
						<tr>
							<td>
								<h2>${userInfo.id}</h2>
							</td>
							<td>
								<h2>${userInfo.userNick}</h2>
							</td>
							<td>
								<h2>${userInfo.userEmail}</h2>
							</td>
						</tr>
					</c:if>
 

 

或者使用如下

 

<c:if test="${!empty userInfo}">
				<table>
					<tr align="center"
						<c:if test="${i.index % 2 == 0}"> class="foreach_tr1" </c:if>
						<c:if test="${i.index % 2 == 1}"> class="foreach_tr2" </c:if>>
						<td>
							<h2>${userInfo.id}</h2>
						</td>
						<td>
							<h2>${userInfo.userNick}</h2>
						</td>
						<td>
							<h2>${userInfo.userEmail}</h2>
						</td>
					</tr>
				</table>
			</c:if>
 

 

 

 

 

 

 

 

 

 

 

 

 

 

<template> <div class="app-container"> <!-- 添加或修改群组信息对话框 --> <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> <el-form ref="form" :model="form" :rules="rules" label-width="80px"> <el-form-item label="群组名称" prop="name"> <el-input v-model="form.name" placeholder="请输入群组名称" /> </el-form-item> <el-form-item label="创建者id" prop="creatorId"> <el-input v-model="form.creatorId" placeholder="请输入创建者id" /> </el-form-item> <el-form-item label="群组图标" prop="avatar"> <el-input v-model="form.avatar" placeholder="请输入群组图标" /> </el-form-item> <el-form-item label="群组公告" prop="announcement"> <el-input v-model="form.announcement" type="textarea" placeholder="请输入内容" /> </el-form-item> <el-form-item label="聊天室" prop="room"> <el-input v-model="form.room" placeholder="请输入聊天室" /> </el-form-item> <el-form-item label="创建时间" prop="createdAt"> <el-date-picker clearable v-model="form.createdAt" type="date" value-format="yyyy-MM-dd" placeholder="请选择创建时间"> </el-date-picker> </el-form-item> <el-form-item label="修改时间" prop="updatedAt"> <el-date-picker clearable v-model="form.updatedAt" type="date" value-format="yyyy-MM-dd" placeholder="请选择修改时间"> </el-date-picker> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button type="primary" @click="submitForm">确 定</el-button> <el-button @click="cancel">取 消</el-button> </div> </el-dialog> </div> </template> <script> import { listIm_groupc, getIm_groupc, delIm_groupc, addIm_groupc, updateIm_groupc } from "@/im/sys/api/im_groupc" export default { name: "Im_groupc", data() { return { // 遮罩层 loading: true, // 选中数组 ids: [], // 单个禁用 single: true, // 多个禁用 multiple: true, // 显示搜索条件 showSearch: true, // 总条数 total: 0, // 群组信息表格数据 im_groupcList: [], // 弹出层标题 title: "", // 是否显示弹出层 open: false, // 查询参数 queryParams: { pageNum: 1, pageSize: 10, name: null, creatorId: null, avatar: null, announcement: null, room: null, createdAt: null, updatedAt: null }, // 表单参数 form: {}, // 表单校验 rules: { name: [ { required: true, message: "群组名称不能为", trigger: "blur" } ], creatorId: [ { required: true, message: "创建者id不能为", trigger: "blur" } ], createdAt: [ { required: true, message: "创建时间不能为", trigger: "blur" } ], } } }, created() { this.getList() }, methods: { /** 查询群组信息列表 */ getList() { this.loading = true listIm_groupc(this.queryParams).then(response => { this.im_groupcList = response.rows this.total = response.total this.loading = false }) }, // 取消按钮 cancel() { this.open = false this.reset() }, // 表单重置 reset() { this.form = { id: null, name: null, creatorId: null, avatar: null, announcement: null, room: null, createdAt: null, updatedAt: null } this.resetForm("form") }, /** 搜索按钮操作 */ handleQuery() { this.queryParams.pageNum = 1 this.getList() }, /** 重置按钮操作 */ resetQuery() { this.resetForm("queryForm") this.handleQuery() }, // 多选框选中数据 handleSelectionChange(selection) { this.ids = selection.map(item => item.id) this.single = selection.length !== 1 this.multiple = !selection.length }, /** 新增按钮操作 */ handleAdd() { this.reset() this.open = true this.title = "添加群组信息" }, /** 修改按钮操作 */ handleUpdate(row) { this.reset() const id = row.id || this.ids getIm_groupc(id).then(response => { this.form = response.data this.open = true this.title = "修改群组信息" }) }, /** 提交按钮 */ submitForm() { this.$refs["form"].validate(valid => { if (valid) { if (this.form.id != null) { updateIm_groupc(this.form).then(response => { this.$modal.msgSuccess("修改成功") this.open = false this.getList() }) } else { addIm_groupc(this.form).then(response => { this.$modal.msgSuccess("新增成功") this.open = false this.getList() }) } } }) }, /** 删除按钮操作 */ handleDelete(row) { const ids = row.id || this.ids this.$modal.confirm('是否确认删除群组信息编号为"' + ids + '"的数据项?').then(function () { return delIm_groupc(ids) }).then(() => { this.getList() this.$modal.msgSuccess("删除成功") }).catch(() => { }) }, /** 导出按钮操作 */ handleExport() { this.download('mod/im_groupc/export', { ...this.queryParams }, `im_groupc_${new Date().getTime()}.xlsx`) } } } </script> 以上为若依前端代码,是新建群组的方法,以下是新建成员的方法,如何将两个文件整合成一个文件,请按此格进行修改,给出修改后的完整代码<template> <div class="app-container"> <!-- 添加或修改群组成员对话框 --> <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> <el-form ref="form" :model="form" :rules="rules" label-width="80px"> <el-form-item label="群组id" prop="groupId"> <el-input v-model="form.groupId" placeholder="请输入群组id" /> </el-form-item> <el-form-item label="用户id" prop="userId"> <el-input v-model="form.userId" placeholder="请输入用户id" /> </el-form-item> <el-form-item label="用户姓名" prop="nickname"> <el-input v-model="form.nickname" placeholder="请输入用户姓名" /> </el-form-item> <el-form-item label="创建时间" prop="createdAt"> <el-date-picker clearable v-model="form.createdAt" type="date" value-format="yyyy-MM-dd" placeholder="请选择创建时间"> </el-date-picker> </el-form-item> <el-form-item label="更新时间" prop="updatedAt"> <el-date-picker clearable v-model="form.updatedAt" type="date" value-format="yyyy-MM-dd" placeholder="请选择更新时间"> </el-date-picker> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button type="primary" @click="submitForm">确 定</el-button> <el-button @click="cancel">取 消</el-button> </div> </el-dialog> </div> </template> <script> import { listIm_groups, getIm_groups, delIm_groups, addIm_groups, updateIm_groups } from "@/im/sys/api/im_groups" export default { name: "Im_groups", data() { return { // 遮罩层 loading: true, // 选中数组 ids: [], // 单个禁用 single: true, // 多个禁用 multiple: true, // 显示搜索条件 showSearch: true, // 总条数 total: 0, // 群组成员表格数据 im_groupsList: [], // 弹出层标题 title: "", // 是否显示弹出层 open: false, // 查询参数 queryParams: { pageNum: 1, pageSize: 10, groupId: null, userId: null, nickname: null, createdAt: null, updatedAt: null }, // 表单参数 form: {}, // 表单校验 rules: { groupId: [ { required: true, message: "群组id不能为", trigger: "blur" } ], userId: [ { required: true, message: "用户id不能为", trigger: "blur" } ], nickname: [ { required: true, message: "用户姓名不能为", trigger: "blur" } ], createdAt: [ { required: true, message: "创建时间不能为", trigger: "blur" } ], } } }, created() { this.getList() }, methods: { /** 查询群组成员列表 */ getList() { this.loading = true listIm_groups(this.queryParams).then(response => { this.im_groupsList = response.rows this.total = response.total this.loading = false }) }, // 取消按钮 cancel() { this.open = false this.reset() }, // 表单重置 reset() { this.form = { id: null, groupId: null, userId: null, nickname: null, createdAt: null, updatedAt: null } this.resetForm("form") }, /** 搜索按钮操作 */ handleQuery() { this.queryParams.pageNum = 1 this.getList() }, /** 重置按钮操作 */ resetQuery() { this.resetForm("queryForm") this.handleQuery() }, // 多选框选中数据 handleSelectionChange(selection) { this.ids = selection.map(item => item.id) this.single = selection.length!==1 this.multiple = !selection.length }, /** 新增按钮操作 */ handleAdd() { this.reset() this.open = true this.title = "添加群组成员" }, /** 修改按钮操作 */ handleUpdate(row) { this.reset() const id = row.id || this.ids getIm_groups(id).then(response => { this.form = response.data this.open = true this.title = "修改群组成员" }) }, /** 提交按钮 */ submitForm() { this.$refs["form"].validate(valid => { if (valid) { if (this.form.id != null) { updateIm_groups(this.form).then(response => { this.$modal.msgSuccess("修改成功") this.open = false this.getList() }) } else { addIm_groups(this.form).then(response => { this.$modal.msgSuccess("新增成功") this.open = false this.getList() }) } } }) }, /** 删除按钮操作 */ handleDelete(row) { const ids = row.id || this.ids this.$modal.confirm('是否确认删除群组成员编号为"' + ids + '"的数据项?').then(function() { return delIm_groups(ids) }).then(() => { this.getList() this.$modal.msgSuccess("删除成功") }).catch(() => {}) }, /** 导出按钮操作 */ handleExport() { this.download('mod/im_groups/export', { ...this.queryParams }, `im_groups_${new Date().getTime()}.xlsx`) } } } </script>以下整合思路供参考,此为若依前端代码<template> <div class="app-container"> <el-row :gutter="20"> <!-- 群组列表 --> <el-col :span="6"> <el-card class="group-list-card"> <div slot="header" class="clearfix"> <span>微信群组</span> <el-button style="float: right; padding: 3px 0" type="text" icon="el-icon-plus" @click="handleAddGroup"> 创建群组 </el-button> </div> <!-- 群组搜索 --> <el-form :model="groupQueryParams" ref="groupQueryForm" size="mini"> <el-form-item> <el-input v-model="groupQueryParams.name" placeholder="搜索群组名称" prefix-icon="el-icon-search" clearable @keyup.enter.native="handleGroupQuery" /> </el-form-item> </el-form> <!-- 群组列表 --> <div class="group-list"> <div v-for="group in im_groupcList" :key="group.id" :class="['group-item', { 'active': selectedGroup && selectedGroup.id === group.id }]" @click="handleGroupSelect(group)"> <div class="group-avatar"> <img v-if="group.avatar" :src="group.avatar" alt="群组头像"> <div v-else class="group-avatar-default">{{ group.name.charAt(0) }}</div> </div> <div class="group-info"> <div class="group-name">{{ group.name }}</div> <div class="group-members">{{ group.memberCount }} 成员</div> </div> <div class="group-actions"> <el-dropdown trigger="click" @command="(command) => handleGroupAction(command, group)"> <span class="el-dropdown-link"> <i class="el-icon-more"></i> </span> <el-dropdown-menu slot="dropdown"> <el-dropdown-item command="edit"><i class="el-icon-edit"></i> 编辑群组</el-dropdown-item> <el-dropdown-item command="addMember"><i class="el-icon-user"></i> 添加成员</el-dropdown-item> <el-dropdown-item command="delete" divided><i class="el-icon-delete"></i> 删除群组</el-dropdown-item> </el-dropdown-menu> </el-dropdown> </div> </div> </div> <pagination v-show="groupTotal > 0" :total="groupTotal" :page.sync="groupQueryParams.pageNum" :limit.sync="groupQueryParams.pageSize" @pagination="getGroupList" small /> </el-card> </el-col> <!-- 成员管理 --> <el-col :span="18"> <el-card v-if="selectedGroup" class="member-management-card"> <div slot="header" class="clearfix"> <span>群组成员 - {{ selectedGroup.name }}</span> <el-button style="float: right; padding: 3px 0" type="text" icon="el-icon-plus" @click="handleAddMember"> 添加成员 </el-button> </div> <!-- 成员搜索 --> <el-form :model="memberQueryParams" ref="memberQueryForm" :inline="true" size="mini"> <el-form-item> <el-input v-model="memberQueryParams.nickname" placeholder="搜索成员名称" prefix-icon="el-icon-search" clearable @keyup.enter.native="handleMemberQuery" /> </el-form-item> <el-form-item> <el-button type="primary" @click="handleMemberQuery">搜索</el-button> <el-button @click="resetMemberQuery">重置</el-button> </el-form-item> </el-form> <!-- 成员列表 --> <el-table v-loading="memberLoading" :data="im_groupsList" @selection-change="handleMemberSelectionChange" style="width: 100%"> <el-table-column type="selection" width="55" align="center" /> <el-table-column label="用户ID" align="center" prop="userId" width="80" /> <el-table-column label="用户姓名" align="center" prop="nickname" /> <el-table-column label="角色" align="center" width="100"> <template slot-scope="scope"> <el-tag v-if="scope.row.userId === selectedGroup.creatorId" type="danger" size="small"> 群主 </el-tag> <el-tag v-else type="info" size="small">成员</el-tag> </template> </el-table-column> <el-table-column label="加入时间" align="center" prop="createdAt" width="120"> <template slot-scope="scope"> <span>{{ parseTime(scope.row.createdAt, '{y}-{m}-{d}') }}</span> </template> </el-table-column> <el-table-column label="操作" align="center" width="120"> <template slot-scope="scope"> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDeleteMember(scope.row)" :disabled="scope.row.userId === currentUserId || scope.row.userId === selectedGroup.creatorId"> 移除 </el-button> </template> </el-table-column> </el-table> <pagination v-show="memberTotal > 0" :total="memberTotal" :page.sync="memberQueryParams.pageNum" :limit.sync="memberQueryParams.pageSize" @pagination="getMemberList" /> </el-card> <!-- 状态 --> <el-card v-else class="empty-card"> <div class="empty-content"> <i class="el-icon-chat-dot-round" style="font-size: 48px; color: #909399;"></i> <p>请选择一个群组以管理成员</p> </div> </el-card> </el-col> </el-row> <!-- 添加或修改群组信息对话框 --> <el-dialog :title="groupTitle" :visible.sync="groupOpen" width="500px" append-to-body> <el-form ref="groupForm" :model="groupForm" :rules="groupRules" label-width="80px"> <el-form-item label="群组名称" prop="name"> <el-input v-model="groupForm.name" placeholder="请输入群组名称" /> </el-form-item> <el-form-item label="群组图标" prop="avatar"> <el-upload class="avatar-uploader" action="#" :show-file-list="false" :before-upload="beforeAvatarUpload"> <img v-if="groupForm.avatar" :src="groupForm.avatar" class="avatar"> <i v-else class="el-icon-plus avatar-uploader-icon"></i> </el-upload> </el-form-item> <el-form-item label="群组公告" prop="announcement"> <el-input v-model="groupForm.announcement" type="textarea" placeholder="请输入群组公告" rows="4" /> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="cancelGroup">取 消</el-button> <el-button type="primary" @click="submitGroupForm">确 定</el-button> </div> </el-dialog> <!-- 添加群组成员对话框 --> <el-dialog title="添加群组成员" :visible.sync="memberAddOpen" width="600px" append-to-body> <el-form :model="memberAddForm" ref="memberAddForm" label-width="80px"> <el-form-item label="选择用户"> <el-select v-model="memberAddForm.selectedUsers" multiple filterable remote reserve-keyword placeholder="请输入用户名或昵称搜索" :remote-method="searchUsers" :loading="userSearchLoading" style="width: 100%"> <el-option v-for="user in userList" :key="user.userId" :label="user.nickName || user.userName" :value="user.userId"> <span style="float: left">{{ user.nickName || user.userName }}</span> <span style="float: right; color: #8492a6; font-size: 13px">{{ user.userId }}</span> </el-option> </el-select> </el-form-item> <el-form-item label="已选用户" v-if="memberAddForm.selectedUsers.length > 0"> <div class="selected-users"> <el-tag v-for="userId in memberAddForm.selectedUsers" :key="userId" closable @close="removeSelectedUser(userId)" style="margin: 4px"> {{ getUserName(userId) }} </el-tag> </div> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="memberAddOpen = false">取 消</el-button> <el-button type="primary" @click="submitAddMember">确 定</el-button> </div> </el-dialog> </div> </template> <script> import { listIm_groupc, getIm_groupc, delIm_groupc, addIm_groupc, updateIm_groupc } from "@/im/sys/api/im_groupc" import { listIm_groups, getIm_groups, delIm_groups, addIm_groups, updateIm_groups } from "@/im/sys/api/im_groups" import { getUserProfile, listUser } from "@/api/system/user" import { parseTime } from "@/utils/ruoyi" export default { name: "WechatGroupManagement", data() { return { // 当前用户信息 currentUserId: null, currentUser: {}, // 群组信息相关数据 groupLoading: true, groupIds: [], im_groupcList: [], selectedGroup: null, groupTitle: "", groupOpen: false, groupTotal: 0, groupQueryParams: { pageNum: 1, pageSize: 10, name: undefined, creatorId: undefined }, groupForm: { id: null, name: "", creatorId: null, avatar: "", announcement: "", room: "" }, groupRules: { name: [ { required: true, message: "群组名称不能为", trigger: "blur" }, { min: 2, max: 20, message: "群组名称长度在 2 到 20 个字符", trigger: "blur" } ] }, // 群组成员相关数据 memberLoading: true, memberIds: [], im_groupsList: [], memberTotal: 0, memberQueryParams: { pageNum: 1, pageSize: 10, groupId: null, nickname: undefined }, memberAddOpen: false, memberAddForm: { selectedUsers: [] }, // 用户搜索相关 userSearchLoading: false, userList: [] } }, created() { this.getCurrentUser() this.getGroupList() }, methods: { parseTime, // 获取当前用户信息 getCurrentUser() { getUserProfile().then(response => { this.currentUser = response.data this.currentUserId = response.data.userId this.groupForm.creatorId = this.currentUserId this.groupQueryParams.creatorId = this.currentUserId }) }, // ========== 群组信息相关方法 ========== /** 查询群组信息列表 */ getGroupList() { this.groupLoading = true listIm_groupc(this.groupQueryParams).then(response => { this.im_groupcList = response.rows.map(group => { return { ...group, memberCount: group.memberCount || 0 } }) this.groupTotal = response.total this.groupLoading = false // 如果没有选中群组,默认选中第一个 if (!this.selectedGroup && this.im_groupcList.length > 0) { this.handleGroupSelect(this.im_groupcList[0]) } }).catch(() => { this.groupLoading = false }) }, // 选择群组 handleGroupSelect(group) { this.selectedGroup = group this.memberQueryParams.groupId = group.id this.getMemberList() }, // 群组操作 handleGroupAction(command, group) { switch (command) { case 'edit': this.handleUpdateGroup(group) break case 'addMember': this.handleGroupSelect(group) this.handleAddMember() break case 'delete': this.handleDeleteGroup(group) break } }, // 取消按钮 cancelGroup() { this.groupOpen = false this.resetGroup() }, // 表单重置 resetGroup() { this.groupForm = { id: null, name: "", creatorId: this.currentUserId, avatar: "", announcement: "", room: "" } this.resetForm("groupForm") }, /** 搜索按钮操作 */ handleGroupQuery() { this.groupQueryParams.pageNum = 1 this.getGroupList() }, /** 新增按钮操作 */ handleAddGroup() { this.resetGroup() this.groupOpen = true this.groupTitle = "创建群组" }, /** 修改按钮操作 */ handleUpdateGroup(row) { this.resetGroup() const id = row.id getIm_groupc(id).then(response => { this.groupForm = response.data this.groupOpen = true this.groupTitle = "修改群组信息" }) }, /** 提交按钮 */ submitGroupForm() { this.$refs["groupForm"].validate(valid => { if (valid) { if (this.groupForm.id != null) { updateIm_groupc(this.groupForm).then(response => { this.$modal.msgSuccess("修改成功") this.groupOpen = false this.getGroupList() }) } else { addIm_groupc(this.groupForm).then(response => { this.$modal.msgSuccess("创建成功") this.groupOpen = false this.getGroupList() // 创建群组后自动加入当前用户 this.addCreatorToGroup(response.data.id) }) } } }) }, // 将创建者添加到群组 addCreatorToGroup(groupId) { const memberData = { groupId: groupId, userId: this.currentUserId, nickname: this.currentUser.nickName || this.currentUser.userName } addIm_groups(memberData).then(() => { console.log("群主已加入群组") }) }, /** 删除按钮操作 */ handleDeleteGroup(row) { const ids = row.id this.$modal.confirm('是否确认删除群组"' + row.name + '"?此操作将同时删除所有群成员。').then(() => { return delIm_groupc(ids) }).then(() => { this.getGroupList() this.$modal.msgSuccess("删除成功") // 如果删除的是当前选中的群组,清选中状态 if (this.selectedGroup && this.selectedGroup.id === row.id) { this.selectedGroup = null this.im_groupsList = [] } }).catch(() => { }) }, // ========== 群组成员相关方法 ========== /** 查询群组成员列表 */ getMemberList() { if (!this.selectedGroup) return this.memberLoading = true listIm_groups(this.memberQueryParams).then(response => { this.im_groupsList = response.rows this.memberTotal = response.total this.memberLoading = false }).catch(() => { this.memberLoading = false }) }, /** 搜索按钮操作 */ handleMemberQuery() { this.memberQueryParams.pageNum = 1 this.getMemberList() }, /** 重置按钮操作 */ resetMemberQuery() { this.memberQueryParams.nickname = undefined this.handleMemberQuery() }, // 多选框选中数据 handleMemberSelectionChange(selection) { this.memberIds = selection.map(item => item.id) }, // 搜索用户 searchUsers(query) { if (query !== '') { this.userSearchLoading = true listUser({ userName: query, nickName: query, pageSize: 10 }).then(response => { this.userList = response.rows this.userSearchLoading = false }).catch(() => { this.userSearchLoading = false }) } else { this.userList = [] } }, // 获取用户名称 getUserName(userId) { const user = this.userList.find(u => u.userId === userId) return user ? (user.nickName || user.userName) : `用户${userId}` }, // 移除已选用户 removeSelectedUser(userId) { this.memberAddForm.selectedUsers = this.memberAddForm.selectedUsers.filter(id => id !== userId) }, // 添加成员按钮 handleAddMember() { if (!this.selectedGroup) { this.$message.warning('请先选择群组') return } this.memberAddForm.selectedUsers = [] this.userList = [] this.memberAddOpen = true }, // 提交添加成员 submitAddMember() { if (!this.memberAddForm.selectedUsers.length) { this.$message.warning('请选择要添加的用户') return } const members = this.memberAddForm.selectedUsers.map(userId => { const user = this.userList.find(u => u.userId === userId) return { groupId: this.selectedGroup.id, userId: userId, nickname: user ? (user.nickName || user.userName) : '用户' } }) batchAddIm_groups(members).then(() => { this.$modal.msgSuccess("添加成功") this.memberAddOpen = false this.getMemberList() // 更新群组成员数量 this.getGroupList() }) }, /** 删除成员按钮操作 */ handleDeleteMember(row) { if (row.userId === this.currentUserId) { this.$message.warning('不能移除自己') return } if (row.userId === this.selectedGroup.creatorId) { this.$message.warning('不能移除群主') return } this.$modal.confirm('是否确认将用户 "' + row.nickname + '" 移出群组?').then(() => { return delIm_groups(row.id) }).then(() => { this.getMemberList() this.$modal.msgSuccess("移除成功") // 更新群组成员数量 this.getGroupList() }).catch(() => { }) } } } </script> <style scoped> .app-container { padding: 20px; } .group-list-card, .member-management-card, .empty-card { margin-bottom: 20px; min-height: 600px; } .empty-content { text-align: center; padding: 60px 0; color: #909399; } .group-list { max-height: 480px; overflow-y: auto; } .group-item { display: flex; align-items: center; padding: 12px; border-radius: 8px; margin-bottom: 8px; cursor: pointer; transition: background-color 0.3s; } .group-item:hover { background-color: #f5f7fa; } .group-item.active { background-color: #ecf5ff; border-left: 3px solid #409EFF; } .group-avatar { width: 40px; height: 40px; border-radius: 50%; margin-right: 12px; flex-shrink: 0; } .group-avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; } .group-avatar-default { width: 100%; height: 100%; border-radius: 50%; background-color: #409EFF; color: white; display: flex; align-items: center; justify-content: center; font-weight: bold; } .group-info { flex: 1; min-width: 0; } .group-name { font-weight: 500; margin-bottom: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .group-members { font-size: 12px; color: #909399; } .group-actions { flex-shrink: 0; } .el-dropdown-link { cursor: pointer; color: #909399; padding: 4px; } .el-dropdown-link:hover { color: #409EFF; } .avatar-uploader ::v-deep .el-upload { border: 1px dashed #d9d9d9; border-radius: 6px; cursor: pointer; position: relative; overflow: hidden; } .avatar-uploader ::v-deep .el-upload:hover { border-color: #409EFF; } .avatar-uploader-icon { font-size: 28px; color: #8c939d; width: 100px; height: 100px; line-height: 100px; text-align: center; } .avatar { width: 100px; height: 100px; display: block; } .selected-users { max-height: 120px; overflow-y: auto; border: 1px solid #dcdfe6; border-radius: 4px; padding: 8px; } </style>
09-16
<template> <div class="app-container"> <!-- 查询表单 --> <div class="filter-container"> <el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd" style="width: 280px; margin-right: 10px" /> <el-input v-model="queryParams.userName" placeholder="员工姓名/账号" clearable style="width: 180px; margin-right: 10px" /> <el-select v-model="queryParams.deptId" placeholder="所属部门" clearable style="width: 160px" > <el-option v-for="dept in deptOptions" :key="dept.deptId" :label="dept.deptName" :value="dept.deptId" /> </el-select> <el-button type="primary" icon="el-icon-search" @click="getList" >搜索</el-button > <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button> </div> <!-- 操作按钮 --> <el-row :gutter="10" class="mb8"> <el-col :span="1.5"> <el-button type="primary" plain icon="el-icon-plus" @click="openAddDialog" v-hasPermi="['system:schedule:add']" > 新增排班 </el-button> </el-col> <el-col :span="1.5"> <el-button type="danger" plain icon="el-icon-delete" :disabled="selectedSchedules.length === 0" @click="handleDelete(null)" v-hasPermi="['system:schedule:remove']" > 批量删除 </el-button> </el-col> </el-row> <!-- 排班列表 --> <el-table ref="scheduleTable" v-loading="loading" :data="list" @selection-change="handleSelectionChange" border > <el-table-column type="selection" width="50" align="center" /> <el-table-column label="员工" width="200"> <template slot-scope="scope"> <div style="display: flex; align-items: center"> <el-avatar size="small" :src="scope.row.avatar || 'https://via.placeholder.com/32'" style="margin-right: 8px" ></el-avatar> <div> <div> <strong>{{ scope.row.nickName }}</strong> </div> <div style="font-size: 12px; color: #999"> {{ scope.row.user_name }} </div> </div> </div> </template> </el-table-column> <el-table-column label="部门" prop="deptName" width="150" /> <el-table-column label="排班日期" width="120"> <template slot-scope="scope"> {{ parseTime(scope.row.scheduleDate, "{y}-{m}-{d}") }} </template> </el-table-column> <el-table-column label="班次" width="100"> <template slot-scope="scope"> <el-tag :type="getShiftType(scope.row.shiftType)"> {{ getShiftText(scope.row.shiftType) }} </el-tag> </template> </el-table-column> <el-table-column label="备注" prop="remark" min-width="120" show-overflow-tooltip /> <el-table-column label="操作" fixed="right" align="center" width="180"> <template slot-scope="scope"> <el-button size="mini" type="text" icon="el-icon-edit" @click="handleEdit(scope.row)" v-hasPermi="['system:schedule:edit']" > 修改 </el-button> <el-button size="mini" type="text" icon="el-icon-view" @click="handleViewDetail(scope.row)" > 详情 </el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:schedule:remove']" > 删除 </el-button> </template> </el-table-column> </el-table> <!-- 分页 --> <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" /> <!-- 主表单:新增/编辑排班 --> <el-dialog :title="dialogTitle" :visible.sync="open" width="800px" append-to-body destroy-on-close @closed="resetDialogForm" > <el-form :model="tempSchedule" label-width="100px"> <!-- 员工选择(通过弹窗) --> <el-form-item label="选择员工" required> <el-button type="primary" size="small" @click="openUserSelector"> + 选择员工 </el-button> <div v-if="selectedUsers.length > 0" style="margin-top: 10px; color: #666" > 已选 {{ selectedUsers.length }} 人: <el-tag v-for="user in selectedUsers" :key="user.userId" size="mini" closable @close="removeSelectedUser(user)" style="margin-right: 5px" > {{ user.nickName }} </el-tag> </div> </el-form-item> <!-- 排班时间 --> <el-form-item label="排班时间" required> <el-date-picker v-model="tempSchedule.dates" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd" style="width: 100%" /> </el-form-item> <!-- 班次类型 --> <el-form-item label="班次类型" required> <el-radio-group v-model="tempSchedule.shiftType"> <el-radio label="morning">早班 08:00-16:00</el-radio> <el-radio label="afternoon">晚班 16:00-24:00</el-radio> <el-radio label="night">夜班 00:00-08:00</el-radio> <el-radio label="off">休息</el-radio> </el-radio-group> </el-form-item> <!-- 备注 --> <el-form-item label="备注"> <el-input v-model="tempSchedule.remark" type="textarea" rows="2" /> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="open = false">取 消</el-button> <el-button type="primary" :loading="submitLoading" @click="submitSchedule" > 确 定 </el-button> </div> </el-dialog> <!-- 用户选择弹窗 --> <el-dialog title="选择员工" :visible.sync="userSelectorVisible" width="800px" append-to-body destroy-on-close > <div class="filter-container" style="margin-bottom: 15px"> <el-input v-model="userQueryParams.userName" placeholder="姓名/账号" clearable style="width: 180px; margin-right: 10px" /> <el-select v-model="userQueryParams.deptId" placeholder="所属部门" clearable style="width: 160px" > <el-option v-for="dept in deptOptions" :key="dept.deptId" :label="dept.deptName" :value="dept.deptId" /> </el-select> <el-button type="primary" icon="el-icon-search" @click="getUserList" >查询</el-button > <el-button icon="el-icon-refresh" @click="resetUserQuery" >重置</el-button > </div> <el-table :data="userList" @selection-change="handleUserSelectionChange" border height="300" style="width: 100%" > <el-table-column type="selection" width="50" align="center" /> <el-table-column label="头像" width="60" align="center"> <template slot-scope="scope"> <el-avatar size="small" :src="scope.row.avatar || 'https://via.placeholder.com/24'" /> </template> </el-table-column> <el-table-column label="昵称" prop="nickName" min-width="100" /> <el-table-column label="账号" prop="userName" min-width="120" /> <el-table-column label="部门" prop="deptName" min-width="120" /> </el-table> <pagination v-show="userTotal > 0" :total="userTotal" :page.sync="userQueryParams.pageNum" :limit.sync="userQueryParams.pageSize" @pagination="getUserList" /> <div slot="footer" class="dialog-footer"> <el-button @click="userSelectorVisible = false">取 消</el-button> <el-button type="primary" @click="confirmSelectUsers">确 定</el-button> </div> </el-dialog> <!-- 详情弹窗 --> <el-dialog title="排班详情" :visible.sync="detailOpen" width="600px" append-to-body destroy-on-close > <div style="line-height: 2" v-if="currentRow"> <p> <b>员工:</b>{{ currentRow.nickName }} ({{ currentRow.user_name }}) </p> <p><b>部门:</b>{{ currentRow.deptName }}</p> <p> <b>排班日期:</b >{{ parseTime(currentRow.scheduleDate, "{y}-{m}-{d}") }} </p> <p> <b>班次:</b> <el-tag :type="getShiftType(currentRow.shiftType)"> {{ getShiftText(currentRow.shiftType) }} </el-tag> </p> <p><b>备注:</b>{{ currentRow.remark || "-" }}</p> <p><b>创建人:</b>{{ currentRow.create_by }}</p> <p><b>创建时间:</b>{{ parseTime(currentRow.create_time) }}</p> </div> <div v-else> <el-empty description="暂无数据"></el-empty> </div> </el-dialog> </div> </template> <script> import { listUser } from "@/api/system/user"; import { listDept } from "@/api/system/dept"; import { listSchedule, addSchedule, updateSchedule, delSchedule, } from "@/api/system/schedule"; import { parseTime } from "@/utils"; export default { name: "ScheduleManagement", data() { return { loading: false, submitLoading: false, list: [], total: 0, queryParams: { pageNum: 1, pageSize: 10, userName: undefined, deptId: undefined, }, dateRange: [], selectedSchedules: [], currentRow: null, // 主弹窗控制 open: false, detailOpen: false, dialogTitle: "", // 临时排班数据 tempSchedule: { userIds: [], dates: [], shiftType: "morning", remark: "", }, // 用户选择弹窗相关 userSelectorVisible: false, userList: [], userTotal: 0, userQueryParams: { pageNum: 1, pageSize: 10, userName: undefined, deptId: undefined, }, selectedUserIds: [], // 当前在弹窗中选中的 ID 数组 selectedUsers: [], // 最终确认的用户对象列表(用于展示) allUserList: [], // 所有员工缓存(可选) deptOptions: [], // 部门选项 }; }, computed: { isSuperAdmin() { return this.$store.getters.roles.includes("admin"); }, }, created() { this.getDepts(); this.getList(); }, methods: { parseTime, getDepts() { listDept().then((res) => { this.deptOptions = res.data || []; }); }, getList() { this.loading = true; const params = { ...this.queryParams, startTime: this.dateRange?.[0], endTime: this.dateRange?.[1], }; listSchedule(params) .then((res) => { this.list = res.rows || []; this.total = res.total || 0; }) .finally(() => { this.loading = false; }); }, resetQuery() { this.dateRange = []; this.queryParams = { pageNum: 1, pageSize: 10, userName: undefined, deptId: undefined, }; this.getList(); }, handleSelectionChange(selection) { this.selectedSchedules = selection; }, openAddDialog() { this.dialogTitle = "新增排班"; this.open = true; }, handleEdit(row) { this.dialogTitle = "修改排班"; this.tempSchedule = { userIds: [row.userId], dates: [row.scheduleDate, row.scheduleDate], shiftType: row.shiftType, remark: row.remark, }; // 回显已选用户(仅一个) const user = this.allUserList.find((u) => u.userId === row.userId); this.selectedUsers = user ? [user] : []; this.open = true; }, handleViewDetail(row) { this.currentRow = row; this.detailOpen = true; }, // 打开用户选择器 openUserSelector() { this.userSelectorVisible = true; this.getUserList(); // 加载用户数据 }, getUserList() { const params = { ...this.userQueryParams }; listUser(params).then((res) => { this.userList = res.rows || []; this.userTotal = res.total || 0; }); }, resetUserQuery() { this.userQueryParams = { pageNum: 1, pageSize: 10, userName: undefined, deptId: undefined, }; this.getUserList(); }, handleUserSelectionChange(selection) { this.selectedUserIds = selection.map((u) => u.userId); }, confirmSelectUsers() { const selected = this.userList.filter((u) => this.selectedUserIds.includes(u.userId) ); const existIds = new Set(this.selectedUsers.map((u) => u.userId)); const newUsers = selected.filter((u) => !existIds.has(u.userId)); this.selectedUsers.push(...newUsers); this.tempSchedule.userIds = this.selectedUsers.map((u) => u.userId); this.userSelectorVisible = false; this.$message.success(`已选择 ${newUsers.length} 名员工`); }, removeSelectedUser(user) { this.selectedUsers = this.selectedUsers.filter( (u) => u.userId !== user.userId ); this.tempSchedule.userIds = this.selectedUsers.map((u) => u.userId); }, submitSchedule() { if (!this.tempSchedule.userIds.length) { this.$message.warning("请至少选择一名员工"); return; } if (!this.tempSchedule.dates || this.tempSchedule.dates.length !== 2) { this.$message.warning("请选择完整的日期范围"); return; } this.submitLoading = true; const [start, end] = this.tempSchedule.dates; const scheduleData = []; const currentDate = new Date(start); const endDate = new Date(end); while (currentDate <= endDate) { const dateStr = this.formatDate(currentDate); this.tempSchedule.userIds.forEach((userId) => { const userData = this.allUserList.find((u) => u.userId === userId); scheduleData.push({ userId: userId, deptId: userData?.deptId, scheduleDate: dateStr, shiftType: this.tempSchedule.shiftType, remark: this.tempSchedule.remark, }); }); currentDate.setDate(currentDate.getDate() + 1); } console.log(scheduleData.deptId); addSchedule(scheduleData) .then(() => { this.$modal.msgSuccess?.("排班创建成功") || this.$message.success("排班创建成功"); this.open = false; this.getList(); }) .catch(() => { this.$message.error("保存失败,请检查网络或数据"); }) .finally(() => { this.submitLoading = false; }); }, handleDelete(row) { const ids = row ? [row.id] : this.selectedSchedules.map((s) => s.id); this.$confirm(`确认删除 ${ids.length} 条排班记录?`, "警告", { type: "warning", }).then(() => { this.loading = true; delSchedule(ids) .then(() => { this.$message.success("删除成功"); this.getList(); }) .finally(() => { this.loading = false; }); }); }, formatDate(date) { const d = new Date(date); const year = d.getFullYear(); const month = String(d.getMonth() + 1).padStart(2, "0"); const day = String(d.getDate()).padStart(2, "0"); return `${year}-${month}-${day}`; }, getShiftText(type) { const map = { morning: "早班", afternoon: "晚班", night: "夜班", off: "休息", }; return map[type] || "未知"; }, getShiftType(type) { return ( { morning: "success", afternoon: "warning", night: "danger", off: "info", }[type] || "" ); }, resetDialogForm() { this.tempSchedule = { userIds: [], dates: [], shiftType: "morning", remark: "", }; this.selectedUsers = []; this.selectedUserIds = []; }, }, }; </script> <style scoped> ::v-deep .el-table th { background-color: #f5f7fa; font-weight: bold; } .mb8 { margin-bottom: 15px; } .dialog-footer { text-align: right; } </style>
09-28
# 题目重述 用户提供了一张图片,内容是一个 JSP 页面(`addStudent.jsp`)在编辑器中的截图,页面中包含一个 HTML 表单,用于添加学生信息。当前存在如下错误提示: ``` 17 个问题 - 已定义变量 'errorMsg' (冗余) - 冗余的默认特性值赋值:x2 - 表单输入没有相关的 label:x6 - 冗余的默认特性值赋值:x2 ``` 同时,在 JSP 代码中存在以下片段: ```jsp <% String errorMsg = (String) request.getAttribute("errorMsg"); %> <% if (errorMsg != null) { %> <p class="error"><%= errorMsg %></p> <% } %> <form action="studentServlet?action=add" method="post"> 学号:<input type="text" name="studentId" placeholder="请输入学号" required><br> 姓名:<input type="text" name="name" placeholder="请输入姓名" required><br> 性别:<input type="text" name="gender" placeholder="男/女" required><br> 年龄:<input type="number" name="age" placeholder="请输入年龄" required><br> 专业:<input type="text" name="major" placeholder="请输入专业" required><br> 班级:<input type="text" name="class" placeholder="请输入班级" required><br> <button type="submit">提交</button> <button type="button" onclick="location.href='studentServlet?action=list'">返回</button> </form> ``` 问题:**为什么出错?应该如何修改?** --- # 详解 ## ❌ 错误原因分析 ### 1. **变量 'errorMsg' 已定义(冗余声明)** - 在 `<% String errorMsg = ... %>` 中重复定义了变量。 - 如果该 JSP 被包含在其他页面中(如通过 `<%@ include %>` 或 `<jsp:include>`),可能导致多次声明。 - 特别是如果 `errorMsg` 已在前面的代码或父页面中定义,则此处会报“已定义”警告。 ### 2. **表单输入没有相关的 label** - 所有 `<input>` 元素都没有使用 `<label>` 标签关联。 - 正确做法是每个输入框都应有对应的 `<label for="id">文字</label>`,并与 input 的 `id` 关联。 - 当前写法: ```html 姓名:<input type="text" name="name"> ``` 属于“内联文本 + input”,不符合无障碍(Accessibility)标准,会被现代开发工具标记为错误。 ### 3. **冗余的默认特性值赋值** - 某些属性如 `type="text"` 在 `<input>` 中已是默认类型,若显写出且未必要,某些静态分析工具认为“冗余”。 - 但此警告较宽松,一般不影响功能,多数情况下可忽略或依团队规范处理。 --- ## ✅ 修改建议 ### ✔️ 修改 1:避免变量重复定义(改进 JSP 脚本) 将脚本片段改为更安全的方,避免重复声明: ```jsp <% Object msgObj = request.getAttribute("errorMsg"); String errorMsg = (msgObj != null) ? msgObj.toString() : null; %> <% if (errorMsg != null) { %> <p class="error"><%= errorMsg %></p> <% } %> ``` 或者使用 JSTL + EL 更加推荐: ```jsp <c:if test="${not empty errorMsg}"> <p class="error">${errorMsg}</p> </c:if> ``` > ⚠️ 推荐使用 JSTL 替代 Java 脚本(`<% %>`),提高可维护性。 --- ### ✔️ 修改 2:为每个输入框添加 `<label>` 修改所有表单项,加入 `id` 和 `<label>` 关联: ```jsp <form action="studentServlet?action=add" method="post"> <label for="studentId">学号:</label> <input type="text" id="studentId" name="studentId" placeholder="请输入学号" required><br> <label for="name">姓名:</label> <input type="text" id="name" name="name" placeholder="请输入姓名" required><br> <label for="gender">性别:</label> <input type="text" id="gender" name="gender" placeholder="男/女" required><br> <label for="age">年龄:</label> <input type="number" id="age" name="age" placeholder="请输入年龄" required><br> <label for="major">专业:</label> <input type="text" id="major" name="major" placeholder="请输入专业" required><br> <label for="class">班级:</label> <input type="text" id="class" name="class" placeholder="请输入班级" required><br> <button type="submit">提交</button> <button type="button" onclick="location.href='studentServlet?action=list'">返回</button> </form> ``` --- ### ✔️ 修改 3:关于“冗余默认特性值” - 如 `type="text"` 是 `<input>` 的默认类型,可以省略(但保留也无妨)。 - 若工具严格检查,可考虑移除不必要的 `type="text"`,但会影响语义清晰度,**建议保留以增强可读性**。 --- ## 📌 最佳实践建议 | 问题 | 推荐解决方案 | |------|---------------| | JSP 脚本混乱 | 使用 JSTL 和 EL 替代 `<% %>` 脚本 | | 无障碍支持不足 | 所有表单控件必须有 `<label>` 关联 | | 可维护性差 | 分离表现层与业务逻辑,避免 Java 代码嵌入前端 | --- # 知识点 - **JSP 中的 scriptlet 使用规范**:避免在 JSP 中直接使用 `<% %>` 定义变量,易引发作用域和重复定义问题。 - **HTML 表单可访问性**:每个输入框应通过 `<label for="id">` 与标签关联,提升用户体验和合规性。 - **JSTL 与 EL 表达式**:使用 `${}` 和 `<c:if>` 等替代 Java 脚本,使 JSP 更简洁、安全、易于维护。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值