实现动态表格表单组件:处理活动读写权限
在前端开发中,动态表格表单组件的实现常常需要处理复杂的逻辑和交互,尤其是在涉及权限管理的情况下。在本文中,我们将详细介绍如何使用 Vue.js 和 Element UI 实现一个处理活动读写权限的动态表格表单组件。
功能概述
这个组件的主要功能包括:
- 显示参与者的角色和权限。
- 支持动态添加和删除参与者。
- 通过懒加载和远程搜索获取用户列表。
- 表单验证和提交。
实现步骤
1. 定义组件结构
使用 el-dialog 组件创建一个弹窗,包含一个表单和一个表格。表单用于验证输入,表格用于显示和操作数据。
<template>
<el-dialog
:title="$t('globalSetParticipants')"
:visible.sync="participantDialogVisible"
width="50%"
@open="participantOpen"
@close="participantClose"
:close-on-click-modal="false"
class="participant-dialog"
>
<el-form :rules="participantRules" ref="participantForm" :model="participantFormData">
<el-table
row-key="uuid"
:header-cell-style="{ backgroundColor: '#F7F8FA' }"
:data="participantFormData.participantTable"
ref="participantTable"
border
stripe
:height="540"
v-loading="participantTableLoading"
>
<el-table-column prop="roleId" align="center" :label="$t('umRole')">
<template slot-scope="scope">
<el-form-item
:rules="participantRules.roleId"
:prop="'participantTable.' + scope.$index + '.roleId'"
>
<el-select @change="rolesChange(scope.row)" filterable placeholder="" v-model="scope.row.roleId">
<el-option
v-for="roleId in participantRoles"
:key="roleId.id"
:label="roleId.name"
:value="roleId.id"
></el-option>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="userIdArr" align="center" :label="$t('globalpersonnel')">
<template slot-scope="scope">
<el-form-item
:rules="participantRules.userIdArr"
:prop="'participantTable.' + scope.$index + '.userIdArr'"
>
<el-select
:key="scope.row.uuid"
:disabled="scope.row.roleId === ''"
ret="select"
@visible-change="(flag) => removeKeyword(flag, scope.row.roleId)"
v-selectLoad="() => load(scope.row.roleId)"
filterable
remote
multiple
reserve-keyword
:remote-method="(query) => remoteMethod(query, scope.row.roleId)"
v-model="scope.row.userIdArr"
placeholder=""
>
<el-option
v-for="(item, i) in userInfoOptions"
:key="i"
:label="item.name"
:value="item.id"
></el-option>
<el-option v-if="loadMore" :label="'End'" value="End" disabled />
<el-option v-else-if="participantUserLoading" :label="'Loading...'" value="Loading" disabled />
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="permission" align="center" width="60" :label="$t('globalread-only')">
<template slot-scope="scope">
<el-radio-group v-model="scope.row.permission">
<el-radio label="ReadOnly">{{ "" }}</el-radio>
</el-radio-group>
</template>
</el-table-column>
<el-table-column prop="permission" align="center" width="60" :label="$t('globalReadingandwriting')">
<template slot-scope="scope">
<el-radio-group v-model="scope.row.permission">
<el-radio label="ReadAndWrite">{{ "" }}</el-radio>
</el-radio-group>
</template>
</el-table-column>
<el-table-column align="center" width="100">
<template #header>
<el-button size="mini" type="primary" @click="addParticipant()">{{ $t("globalAdd") }}</el-button>
</template>
<template slot-scope="scope">
<el-button :disabled="participantFormData.participantTable.length === 1" type="danger" size="mini" icon="el-icon-minus" circle @click="removeParticipant(scope.$index)"></el-button>
</template>
</el-table-column>
</el-table>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="participantDialogVisible = false">{{ $t("globalCancel") }}</el-button>
<el-button type="primary" @click="submitParticipants">{{ $t("globalConfirm") }}</el-button>
</span>
</el-dialog>
</template>
2. 定义数据和验证规则
在 data 方法中定义组件所需的数据和验证规则。
data() {
const participantRole = (rule, value, callback) => {
if (value === "") {
callback(new Error("请选择角色"));
} else {
callback();
}
};
const participantPersonnel = (rule, value, callback) => {
if (value.length === 0) {
callback(new Error("请选择人员"));
} else {
callback();
}
};
return {
getUserpageNum: 1,
getUserquery: "",
participantRules: {
roleId: [
{
required: true,
validator: participantRole
}
],
userIdArr: [
{
required: true,
validator: participantPersonnel
}
]
},
participantDialogVisible: false,
participantTableLoading: false,
participantLoadQuery: "",
participantFormData: {
participantTable: []
},
participantRoles: [],
userInfoOptions: [],
selectedCookieList: [],
participantUserLoading: false,
currentPage: 1,
loadMore: true
};
}
3. 定义方法
在 methods 中定义处理表单操作、数据加载和交互逻辑的方法。
methods: {
async participantOpen() {
this.participantTableLoading = true;
if (this.participantRoles.length === 0) {
await this.getRoleList();
}
this.getDiDataPermissionList();
},
participantClose() {
this.userInfoOptions = [];
this.participantFormData.participantTable = [];
},
async getDiDataPermissionList() {
const { code, data } = await diDataPermissionList(this.currentProcessId);
if (code === "00000") {
data.forEach(item => {
if (item.userList && item.userList.length > 0) {
this.userInfoOptions.push(...item.userList);
}
});
this.userInfoOptions = Array.from(new Set(this.userInfoOptions.map(a => a.id)))
.map(id => this.userInfoOptions.find(a => a.id === id));
this.participantFormData.participantTable = data.map(item => ({
roleId: item.roleId,
userIdArr: item.userList ? item.userList.map(item => item.id) : [],
permission: item.permission || "ReadOnly",
processId: item.processId || this.currentProcessId,
uuid: vprivacyGetUUID()
}));
if (this.participantFormData.participantTable.length === 0) {
this.participantFormData.participantTable.push({
roleId: "",
userIdArr: [],
permission: "ReadOnly",
processId: this.currentProcessId,
uuid: vprivacyGetUUID()
});
}
this.participantTableLoading = false;
}
},
async getRoleList() {
const { code, data } = await getAllUserRoles();
if (code === "00000") {
this.participantRoles = data;
}
},
async load(roleId) {
if (this.participantUserLoading || this.allLoaded) {
return;
}
this.selectLazyLoad(roleId);
},
removeKeyword(flag, roleId) {
this.participantLoadQuery = "";
this.currentPage = 1;
this.userInfoOptions = [];
if (flag) {
this.selectLazyLoad(roleId);
}
},
async selectLazyLoad(roleId) {
this.participantUserLoading = true;
const { code, data } = await getUserListByRoldId(roleId, {
search: this.participantLoadQuery,
pageNum: this.currentPage,
pageSize: 10
});
if (code === "00000") {
this.currentPage++;
this.participantUserLoading = false;
this.userInfoOptions = this.userInfoOptions.concat(data[0].userDTOList.map(item => ({
name: item.displayName,
id: item.userId
})));
this.userInfoOptions = Array.from(new Set(this.userInfoOptions.map(a => a.id)))
.map(id => {
return this.userInfoOptions.find(a => a.id === id);
});
this.loadMore = data[0].userDTOList >= 20;
}
},
async remoteMethod(query, roleId) {
this.userInfoOptions = [];
this.currentPage = 1;
this.participantLoadQuery = query;
await this.selectLazyLoad(roleId);
},
rolesChange(row) {
row.userIdArr = [];
this.userInfoOptions = [];
},
addParticipant() {
this.participantFormData.participantTable.push({
roleId: "",
userIdArr: [],
permission: "ReadOnly",
processId: this.currentProcessId,
uuid: vprivacyGetUUID()
});
this.$nextTick(() => {
this.$refs.participantTable.bodyWrapper.scrollTop = this.$refs.participantTable.bodyWrapper.scrollHeight;
});
},
removeParticipant(index) {
this.$set(this.participantFormData, "participantTable", this.participantFormData.participantTable.filter((_, i) => i !== index));
},
submitParticipants() {
this.$refs.participantForm.validate(async (valid) => {
if (valid) {
this.participantFormData.participantTable.forEach(item => {
item.processId = this.currentProcessId;
});
const { code, data } = await addDiDataPermission(this.participantFormData.participantTable);
if (code === "00000") {
this.participantDialogVisible = false;
this.$message({
message: this.$t("globalSetsuccessfully"),
type: "success"
});
await this.getList(this.saveSelectObj);
}
}
});
}
}
}
</script>
4. 指令的定义
为了实现懒加载功能,我们需要定义一个自定义指令 selectLoad,用于监听下拉框的滚动事件。
directives: {
selectLoad: {
inserted(el, binding) {
const dom = el.querySelector(".el-select-dropdown .el-select-dropdown__wrap");
dom.addEventListener("scroll", function() {
const condition = this.scrollHeight - this.scrollTop - this.clientHeight <= 1;
if (condition) {
binding.value();
}
});
}
}
}
5. API 请求
在实际项目中,我们需要与后端进行数据交互,这里假设我们有以下 API 请求方法:
diDataPermissionList(processId): 获取参与者列表。getAllUserRoles(): 获取所有角色列表。getUserListByRoldId(roleId, params): 根据角色 ID 获取用户列表。addDiDataPermission(data): 提交参与者数据。
6.style补充
.participant-dialog {
//显示滚动条
/deep/ .el-table__body-wrapper {
overflow-y: auto;
}
.el-table--border {
/deep/ .el-form-item {
margin-bottom: 0;
// 让校验失败的文字在下拉框中显示
.el-form-item__error {
font-size: 14px;
top: 25%;
left: 10px;
}
}
}
}
总结
通过以上步骤,我们实现了一个动态表格表单组件,用于处理活动读写权限。这个组件支持动态添加和删除参与者,使用懒加载获取用户列表,并提供表单验证和数据提交功能。希望本文能够帮助你在实际项目中实现类似的功能。
如需完整代码或更多细节,请参考项目的实际需求和实现。Happy coding!