|
@@ -0,0 +1,317 @@
|
|
|
+<script setup>
|
|
|
+import { nextTick, reactive, ref } from 'vue';
|
|
|
+import { useRoute, useRouter } from 'vue-router';
|
|
|
+import { apiCustomerUser } from '@/api/customer'
|
|
|
+
|
|
|
+const router = useRouter();
|
|
|
+const route = useRoute();
|
|
|
+const treeRef = ref()
|
|
|
+const ruleFormRef = ref()
|
|
|
+const levelId = route.query.levelId ? +route.query.levelId : 0;
|
|
|
+
|
|
|
+const formData = reactive({
|
|
|
+ LevelRank:'',
|
|
|
+ LevelName:'',
|
|
|
+ State:1,
|
|
|
+});
|
|
|
+const dataLoading = ref(false);
|
|
|
+
|
|
|
+const checkBoxObj = reactive({
|
|
|
+ permissionChecked:false,
|
|
|
+ permissionIndeterminate:false,
|
|
|
+})
|
|
|
+
|
|
|
+const rules = reactive({
|
|
|
+ LevelRank: [
|
|
|
+ { required: true, message: '请输入等级', trigger: 'change' },
|
|
|
+ {
|
|
|
+ validator: (rule, value, callback) => {
|
|
|
+ const reg = /^[1-9][0-9]?$/
|
|
|
+ if (!reg.test(value)) {
|
|
|
+ callback(new Error('等级必须为2位数以内的正整数'))
|
|
|
+ } else {
|
|
|
+ callback()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ trigger: ['change']
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ LevelName: [{ required: true, message: '请输入等级名称', trigger: 'change' }],
|
|
|
+ State:[{ required: true, message: '请选择状态', trigger: 'change' }],
|
|
|
+})
|
|
|
+
|
|
|
+const treeData = ref([])
|
|
|
+const defaultProps = {
|
|
|
+ children: 'Child',
|
|
|
+ label: 'ClassifyName'
|
|
|
+}
|
|
|
+
|
|
|
+function getAllLeafNodeIds(nodes) {
|
|
|
+ const ids = []
|
|
|
+ const traverse = (nodeList) => {
|
|
|
+ nodeList.forEach((node) => {
|
|
|
+ if (!node.Child || node.Child.length === 0) {
|
|
|
+ ids.push(node.Id)
|
|
|
+ } else {
|
|
|
+ traverse(node.Child)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ traverse(nodes)
|
|
|
+ return ids
|
|
|
+}
|
|
|
+const handlePermissionCheckboxChange = (val) => {
|
|
|
+ if(!treeRef.value) return;
|
|
|
+ if (val) {
|
|
|
+ // 全选所有节点
|
|
|
+ const allNodeIds = getAllLeafNodeIds(treeData.value)
|
|
|
+ treeRef.value.setCheckedKeys(allNodeIds)
|
|
|
+ checkBoxObj.permissionIndeterminate = false
|
|
|
+ } else {
|
|
|
+ // 清空所有选择
|
|
|
+ treeRef.value.setCheckedKeys([])
|
|
|
+ checkBoxObj.permissionIndeterminate = false
|
|
|
+ }
|
|
|
+};
|
|
|
+async function getLevelInfo(){
|
|
|
+ if(!levelId) return;
|
|
|
+ const res = await apiCustomerUser.getUserLevelDetail({
|
|
|
+ UserLevelId:levelId,
|
|
|
+ });
|
|
|
+ if(res.Ret !== 200) return;
|
|
|
+ formData.LevelRank = res.Data.LevelRank;
|
|
|
+ formData.LevelName = res.Data.LevelName;
|
|
|
+ formData.State = res.Data.State;
|
|
|
+ treeRef.value.setCheckedKeys(res.Data.ClassifyIds || []);
|
|
|
+ await nextTick();
|
|
|
+ onTreeCheck();
|
|
|
+};
|
|
|
+
|
|
|
+async function getClassifyList(){
|
|
|
+ dataLoading.value = true;
|
|
|
+ const res = await apiCustomerUser.usersReportClassifyTree();
|
|
|
+ dataLoading.value = false;
|
|
|
+ if(res.Ret !== 200) return;
|
|
|
+ treeData.value = res.Data || [];
|
|
|
+ await nextTick();
|
|
|
+ if(levelId) getLevelInfo();
|
|
|
+};
|
|
|
+getClassifyList();
|
|
|
+
|
|
|
+const onTreeCheck = async () => {
|
|
|
+ await nextTick();
|
|
|
+ if(!treeRef.value) return;
|
|
|
+ const checkedKeys = treeRef.value.getCheckedKeys(true)
|
|
|
+ const allLeafKeys = getAllLeafNodeIds(treeData.value)
|
|
|
+ if (checkedKeys.length === 0) {
|
|
|
+ checkBoxObj.permissionChecked = false
|
|
|
+ checkBoxObj.permissionIndeterminate = false
|
|
|
+ } else if (checkedKeys.length === allLeafKeys.length) {
|
|
|
+ checkBoxObj.permissionChecked = true
|
|
|
+ checkBoxObj.permissionIndeterminate = false
|
|
|
+ } else {
|
|
|
+ checkBoxObj.permissionChecked = false
|
|
|
+ checkBoxObj.permissionIndeterminate = true
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const saveHandle = async () => {
|
|
|
+ ruleFormRef.value && ruleFormRef.value.validate(async (valid) => {
|
|
|
+ if (!valid) return;
|
|
|
+ const permissions = treeRef.value.getCheckedKeys(true);
|
|
|
+ if(!permissions || permissions.length === 0) return ElMessage.error('请选择阅读权限');
|
|
|
+ let params = {
|
|
|
+ LevelRank: +formData.LevelRank,
|
|
|
+ LevelName: formData.LevelName,
|
|
|
+ State: +formData.State,
|
|
|
+ ClassifyIds: permissions
|
|
|
+ };
|
|
|
+ if(levelId) {
|
|
|
+ params.UserLevelId = +levelId;
|
|
|
+ }
|
|
|
+ const res = levelId ? await apiCustomerUser.editUserLevel(params) : await apiCustomerUser.addUserLevel(params);
|
|
|
+ if(res.Ret != 200) return;
|
|
|
+ ElMessage.success(levelId ? '编辑成功' : '添加成功');
|
|
|
+ router.back();
|
|
|
+ })
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <el-card v-loading="dataLoading">
|
|
|
+ <div class="user-level-edit-page">
|
|
|
+ <el-form
|
|
|
+ ref="ruleFormRef"
|
|
|
+ :model="formData"
|
|
|
+ :rules="rules"
|
|
|
+ label-width="auto"
|
|
|
+ >
|
|
|
+ <el-form-item label="等级" prop="LevelRank" style="width: 360px;">
|
|
|
+ <el-input v-model="formData.LevelRank" size="large" placeholder="请输入等级会员,正整数"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="等级名称" prop="LevelName" style="width: 360px;">
|
|
|
+ <el-input v-model="formData.LevelName" size="large" placeholder="请输入等级名称"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <template #label>
|
|
|
+ <span class="red-star">*</span> 阅读权限
|
|
|
+ </template>
|
|
|
+ <div v-if="treeData && treeData.length" class="permission-checkbox">
|
|
|
+ <el-checkbox
|
|
|
+ v-model="checkBoxObj.permissionChecked"
|
|
|
+ :indeterminate="checkBoxObj.permissionIndeterminate"
|
|
|
+ @change="handlePermissionCheckboxChange"
|
|
|
+ >全选</el-checkbox>
|
|
|
+ <el-tree
|
|
|
+ ref="treeRef"
|
|
|
+ :data="treeData"
|
|
|
+ show-checkbox
|
|
|
+ node-key="Id"
|
|
|
+ :default-expand-all="false"
|
|
|
+ :props="defaultProps"
|
|
|
+ @check="onTreeCheck"
|
|
|
+ style="max-height: 50vh;overflow-y: auto;overflow-x: hidden;"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="状态" prop="State">
|
|
|
+ <template #label>
|
|
|
+ <span style="display: flex;align-items: center;">
|
|
|
+ <span>状态</span>
|
|
|
+ <el-tooltip
|
|
|
+ effect="dark"
|
|
|
+ content="禁用后,设置用户等级时,不支持配置该等级;已配置等级的用户,禁用后,不支持查看该等级所拥有权限的报告。"
|
|
|
+ placement="top"
|
|
|
+ >
|
|
|
+ <img src="@/assets/imgs/icons/status_tip.png" style="width: 14px;height: 14px;vertical-align: middle;margin-left: 4px;">
|
|
|
+ </el-tooltip>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ <el-radio-group v-model="formData.State">
|
|
|
+ <el-radio :value="1">启用</el-radio>
|
|
|
+ <el-radio :value="0">禁用</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ <div style="text-align: center;">
|
|
|
+ <el-button type="primary" size="large" style="width: 120px;margin-right: 30px;" @click="saveHandle">保存</el-button>
|
|
|
+ <el-button size="large" style="width: 120px;" @click="router.back()">取消</el-button>
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.user-level-edit-page{
|
|
|
+ position: relative;
|
|
|
+ width: 100%;
|
|
|
+ height: calc(100vh - 200px);
|
|
|
+ padding: 20px 40px;
|
|
|
+ overflow: auto;
|
|
|
+ box-sizing: border-box;
|
|
|
+ .red-star{
|
|
|
+ color: var(--el-color-danger);
|
|
|
+ content: "*";
|
|
|
+ margin-right: 4px;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|
|
|
+<style lang="scss">
|
|
|
+.user-level-edit-page{
|
|
|
+ .el-form-item {
|
|
|
+ margin-bottom: 30px;
|
|
|
+ }
|
|
|
+ .el-tree {
|
|
|
+ border-top: 1px solid #e5e7ed;
|
|
|
+ border-left: 1px solid #e5e7ed;
|
|
|
+ border-right: 1px solid #e5e7ed;
|
|
|
+ width: 99%;
|
|
|
+ .el-tree-node__label {
|
|
|
+ margin: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-tree-node__content {
|
|
|
+ min-width: 300px;
|
|
|
+ width: 300px;
|
|
|
+ white-space: normal;
|
|
|
+ box-sizing: border-box;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-tree-node {
|
|
|
+ .el-tree-node {
|
|
|
+ .el-tree-node__children {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-tree-node {
|
|
|
+ &:not(:first-child) {
|
|
|
+ border-top: 1px solid #e5e7ed;
|
|
|
+ }
|
|
|
+ .el-tree-node__content {
|
|
|
+ border-right: 1px solid #e5e7ed;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-tree-node__content {
|
|
|
+ padding: 5px 10px !important;
|
|
|
+ height: auto;
|
|
|
+ }
|
|
|
+
|
|
|
+ > .el-tree-node {
|
|
|
+ padding: 0 !important;
|
|
|
+ display: flex;
|
|
|
+ border-bottom: 1px solid #e5e7ed;
|
|
|
+
|
|
|
+ > .el-tree-node__children {
|
|
|
+ width: 100%;
|
|
|
+
|
|
|
+ > .el-tree-node {
|
|
|
+ &:not(:first-child) {
|
|
|
+ border-top: 1px solid #e5e7ed;
|
|
|
+ }
|
|
|
+
|
|
|
+ > .el-tree-node__content {
|
|
|
+ border-left: 1px solid #e5e7ed;
|
|
|
+ border-right: 1px solid #e5e7ed;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-tree-node__children {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+
|
|
|
+ .el-tree-node {
|
|
|
+ display: flex;
|
|
|
+ flex: 1;
|
|
|
+ padding: 0px !important;
|
|
|
+
|
|
|
+ .el-tree-node__content {
|
|
|
+ border-bottom: none;
|
|
|
+
|
|
|
+ .custom-tree-node {
|
|
|
+ height: 24px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ .tree-btn {
|
|
|
+ margin-left: 10px;
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-button {
|
|
|
+ padding: 0px !important;
|
|
|
+ border-radius: 4px;
|
|
|
+ background: #363554;
|
|
|
+ color: #ffffff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|