hejianhao
2025-03-10 b2322d51b74547b43b37f637bb84058a508e8f22
user冲突
4个文件已添加
1个文件已修改
948 ■■■■■ 已修改文件
src/router/router.js 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/view/systemManage/role/addEdit.vue 354 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/view/systemManage/role/detail.vue 350 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/view/systemManage/role/index.vue 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/view/systemManage/role/service.js 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/router.js
@@ -127,12 +127,42 @@
                }
            },
            {
                path: 'type',
                component: () => import('@/view/car-type'),
                meta: {
                    title: '车辆分类',
                }
            },
            {
                path: 'user',
                component: () => import('@/view/systemManage/user'),
                meta: {
                    title: '用户管理',
                }
            },
            {
                path: 'role',
                component: () => import('@/view/systemManage/role'),
                meta: {
                    title: '角色管理',
                }
            },
            {
                path: 'add-role',
                component: () => import('@/view/systemManage/role/addEdit.vue'),
                meta: {
                    title: '添加角色',
                    hide: true
                }
            },
            {
                path: 'role-detail',
                component: () => import('@/view/systemManage/role/detail'),
                meta: {
                    title: '角色详情',
                    hide: true
                }
            }
        ]
    }
src/view/systemManage/role/addEdit.vue
New file
@@ -0,0 +1,354 @@
<template>
  <div>
    <el-card class="box_card">
      <div class="title_box">
        <div></div>
        <div>角色信息</div>
      </div>
      <el-form ref="form" :inline="true" :model="form" :rules="rules" label-width="80px" class="demo-form-inline">
        <el-form-item label="角色名称" prop="roleName">
          <el-input v-model="form.roleName" placeholder="请输入角色名称"></el-input>
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" placeholder="请输入备注"></el-input>
        </el-form-item>
      </el-form>
      <div class="title_box">
        <div></div>
        <div>操作权限</div>
      </div>
      <div>
        <div class="header">
          <div class="w20">模块名称</div>
          <div class="sconed">
            <div class="subpage">
              <div class="title">页面名称</div>
              <div class="btns">权限</div>
            </div>
          </div>
        </div>
        <div v-for="item in menu" :key="item.menuId">
          <div class="row">
            <div class="w20">
              <el-checkbox v-model="item.selected" @change="(e) => {
                setCheckStatus1(item.menuId, e)
              }" :checked="item.selected">
                {{ item.menuName }}
              </el-checkbox>
            </div>
            <div class="sconed">
              <div class="subpage"
                v-if="(item.children.length > 0 && item.children[0].children.length > 0) || item.children[0].children.menuType != 'F'">
                <div v-for="item1 in item.children" :key="item1.menuId" class="two">
                  <div class="left">
                    <el-checkbox v-model="item1.selected" @change="(e) => {
                      setCheckStatus2(item1.menuId, e, item.menuId)
                    }" :checked="item1.selected">
                      {{ item1.menuName }}
                    </el-checkbox>
                  </div>
                  <div class="right">
                    <div v-for="item2 in item1.children" :key="item2.menuId">
                      <el-checkbox v-model="item2.selected" @change="(e) => {
                        setCheckStatus3(item2.menuId, e, item1.menuId, item.menuId)
                      }" :checked="item2.selected">
                        {{ item2.menuName }}
                      </el-checkbox>
                    </div>
                  </div>
                </div>
              </div>
              <div class="subpage" v-else>
                <div class="two">
                  <!-- <div class="left">
                  </div> -->
                  <div class="right">
                    <div v-for="item1 in item.children" :key="item1.menuId">
                      <el-checkbox v-model="item1.selected" @change="(e) => {
                        setCheckStatus2(item1.menuId, e, item.menuId,)
                      }" :checked="item1.selected">
                        {{ item1.menuName }}
                      </el-checkbox>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="btn_box">
        <el-button @click="$router.go(-1)">返回</el-button>
        <el-button type="primary" @click="onSubmit">保存</el-button>
      </div>
    </el-card>
  </div>
</template>
<script>
import { roleInfoFromUserId, getRoleInfo, add, edit } from './service.js'
export default {
  components: {},
  props: {},
  data() {
    return {
      form: {
        roleName: "",
        remark: "",
      },
      rules: {
        roleName: [
          { required: true, message: "请输入角色名称", trigger: "blur" },
        ],
      },
      menu: [],
    };
  },
  computed: {},
  watch: {},
  created() {
    // roleInfoFromUserId({ userId: 1 }).then(res => {
    //   if (this.$route.query.roleId) {
    //     getRoleInfo({ roleId: this.$route.query.roleId }).then(resp => {
    //       this.menu = this.setSelectedIds(res.data.data, resp.data.data.menus || []);
    //       this.form = {
    //         roleName: resp.data.data.roleName,
    //         remark: resp.data.data.remark,
    //         roleId: resp.data.data.roleId
    //       }
    //     })
    //   } else {
    //     this.menu = res.data.data
    //   }
    // })
  },
  mounted() { },
  methods: {
    setSelectedIds(arr, selectKeyList) {
      function traverse(item) {
        item.selected = selectKeyList.includes(item.menuId);
        if (item.children && item.children.length > 0) {
          item.children.forEach(traverse);
        }
      }
      arr.forEach(traverse);
      return arr;
    },
    onSubmit() {
      this.$refs['form'].validate((valid) => {
        if (valid) {
          if (this.getSelectedIds(this.menu).length == 0) {
            this.$baseMessage('请勾选操作权限', 'warning')
            return
          }
          let obj = {
            ...this.form,
            menuIds: this.getSelectedIds(this.menu)
          }
          if (this.$route.query && this.$route.query.roleId) {
            obj.roleId = this.$route.query.roleId
            edit(obj).then(() => {
              this.$baseMessage('保存成功', 'success')
              this.$router.go(-1)
            })
          } else {
            add(obj).then(() => {
              this.$baseMessage('保存成功', 'success')
              this.$router.go(-1)
            })
          }
        }
      })
    },
    getSelectedIds(arr) {
      let result = [];
      function traverse(item) {
        if (item.selected) {
          result.push(item.menuId);
        }
        if (item.children && item.children.length > 0) {
          for (let children of item.children) {
            traverse(children);
          }
        }
      }
      for (let item of arr) {
        traverse(item);
      }
      return result;
    },
    setCheckStatus1(id, status) { //点击第1级
      if (!status) {
        this.menu = this.menu.map(item => {
          if (item.menuId == id) {
            item.selected = status
            if (item.children.length > 0) {
              item.children = item.children.map(item1 => {
                item1.selected = status
                if (item1.children.length > 0) {
                  item1.children = item1.children.map(item2 => {
                    item2.selected = status
                    return { ...item2 }
                  })
                }
                return { ...item1 }
              })
            }
          }
          return { ...item }
        })
      } else {
        this.menu = this.menu.map(item => {
          if (item.menuId == id) {
            item.selected = true
          }
          return { ...item }
        })
      }
    },
    setCheckStatus2(id, status, aId) { //点击第2级
      this.menu = this.menu.map(item => {
        if (item.menuId == aId) {
          item.selected = true
          if (item.children.length > 0) {
            item.children = item.children.map(item1 => {
              if (item1.menuId == id) {
                item1.selected = status
              }
              return { ...item1 }
            })
          }
        }
        return { ...item }
      })
    },
    setCheckStatus3(id, status, bId, aId) {//点击第3级
      this.menu = this.menu.map(item => {
        if (item.menuId == aId) {
          item.selected = true
          if (item.children.length > 0) {
            item.children = item.children.map(item1 => {
              if (item1.menuId == bId) {
                item1.selected = true
                if (item1.children.length > 0) {
                  item1.children = item1.children.map(item2 => {
                    if (item2.menuId == id) {
                      item2.selected = status
                    }
                    return { ...item2 }
                  })
                }
              }
              return { ...item1 }
            })
          }
        }
        return { ...item }
      })
    }
  },
};
</script>
<style lang="less" scoped>
.box_card {
  margin-bottom: 0;
  .title_box {
    display: flex;
    align-items: center;
    margin-bottom: 20px;
    font-weight: bold;
    div:first-child {
      width: 4px;
      height: 16px;
      background: #598DEC;
      margin-right: 8px;
    }
  }
  .btn_box {
    margin-top: 40px;
    text-align: center;
  }
}
.el-checkbox {
  display: flex;
  align-items: center;
}
.row,
.header {
  display: flex;
  align-items: center;
  border: 1px solid #e8e8e8;
  .w20 {
    width: 15%;
    padding: 8px 20px;
  }
  .sconed {
    flex: 1;
    .subpage {
      .title {
        border: 1px solid #e8e8e8;
        border-top: none;
        border-bottom: none;
      }
      .two {
        display: flex;
        align-items: center;
        border: 1px solid #e8e8e8;
        border-top: none;
        border-right: none;
        .left {
          width: 200px;
          padding: 13px 20px;
          border-right: 1px solid #e8e8e8;
        }
        .right {
          display: flex;
          flex: 1;
          div {
            padding: 13px 0 13px 20px;
          }
        }
      }
      .two:last-child {
        border-bottom: none;
      }
      .btns {
        display: flex;
        align-items: center;
        padding: 0 20px;
      }
    }
  }
}
.header {
  background-color: #e8e8e8;
  .subpage {
    display: flex;
  }
  .title {
    width: 200px;
    padding: 8px 20px;
  }
}
</style>
src/view/systemManage/role/detail.vue
New file
@@ -0,0 +1,350 @@
<template>
  <div>
    <el-card class="box_card">
      <div>{{ form.roleName }}</div>
      <div>备注:{{ form.remark }}</div>
    </el-card>
    <el-card>
      <el-tabs v-model="activeName">
        <el-tab-pane label="操作权限" name="first">
          <div class="header">
            <div class="w20">模块名称</div>
            <div class="sconed">
              <div class="subpage">
                <div class="title">页面名称</div>
                <div class="btns">权限</div>
              </div>
            </div>
          </div>
          <div v-for="item in menu" :key="item.menuId">
            <div class="row">
              <div class="w20">
                <el-checkbox disabled :checked="item.selected">
                  {{ item.menuName }}
                </el-checkbox>
              </div>
              <div class="sconed">
                <div class="subpage"
                  v-if="(item.children.length > 0 && item.children[0].children.length > 0) || item.children[0].children.menuType != 'F'">
                  <div v-for="item1 in item.children" :key="item1.menuId" class="two">
                    <div class="left">
                      <el-checkbox disabled :checked="item1.selected">
                        {{ item1.menuName }}
                      </el-checkbox>
                    </div>
                    <div class="right">
                      <div v-for="item2 in item1.children" :key="item2.menuId">
                        <el-checkbox disabled :checked="item2.selected">
                          {{ item2.menuName }}
                        </el-checkbox>
                      </div>
                    </div>
                  </div>
                </div>
                <div class="subpage" v-else>
                  <div class="two">
                    <!-- <div class="left">
                    </div> -->
                    <div class="right">
                      <div v-for="item1 in item.children" :key="item1.menuId">
                        <el-checkbox disabled :checked="item1.selected">
                          {{ item1.menuName }}
                        </el-checkbox>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </el-tab-pane>
        <el-tab-pane label="人员列表" name="second">
          <el-form :inline="true" class="demo-form-inline">
            <div style="display: flex;justify-content: space-between;">
              <el-form-item label="人员搜索">
                <el-input v-model="nickNameOrPhone" placeholder="请输入姓名/联系电话"></el-input>
              </el-form-item>
              <el-form-item label="所属部门">
                <el-select v-model="deptId" placeholder="请选择(多选)" multiple>
                  <el-option v-for="item in deptList" :key="item.id" :label="item.deptName" :value="item.id">
                  </el-option>
                </el-select>
              </el-form-item>
              <el-form-item label="登陆状态">
                <el-select v-model="status" placeholder="请选择">
                  <el-option
                    v-for="item in [{ label: '全部', value: '' }, { label: '启用', value: 0 }, { label: '禁用', value: 1 }]"
                    :key="item.value" :label="item.label" :value="item.value">
                  </el-option>
                </el-select>
              </el-form-item>
              <el-form-item>
                <el-button @click="reset">重置</el-button>
                <el-button type="primary" @click="onSubmit">查询</el-button>
              </el-form-item>
            </div>
          </el-form>
          <el-table ref="tableSort" v-loading="listLoading" stripe :data="data"
            :element-loading-text="elementLoadingText" :height="height">
            <el-table-column label="序号" type="index" width="50">
            </el-table-column>
            <el-table-column prop="nickName" label="姓名"></el-table-column>
            <el-table-column prop="phonenumber" label="联系电话">
            </el-table-column>
            <el-table-column prop="deptList" label="所属部门">
              <template slot-scope="{ row }">
                <el-tag v-for="(item, index) in row.deptList" :key="index">{{ item }}</el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="roleName" label="角色">
            </el-table-column>
            <el-table-column prop="userName" label="登陆账号">
            </el-table-column>
            <el-table-column prop="remark" label="备注">
            </el-table-column>
            <el-table-column prop="status" label="登录状态">
              <template slot-scope="{row}">
                <div class="status_class">
                  <div :class="row.status == 0 ? 'green' : 'red'"></div>
                  <div>{{ row.status == 0 ? '正常' : '停用' }}</div>
                  <div v-if="row.status == 1" style="cursor: pointer;" @click="dialogVisibleView = true, rowView = row">
                    <i class="el-icon-warning"></i>
                  </div>
                </div>
              </template>
            </el-table-column>
            <el-table-column prop="createTime" label="创建时间"></el-table-column>
          </el-table>
          <div class="pagination">
            <el-pagination layout="slot,sizes,prev,pager,next,jumper" :page-size="pagination.pageSize"
              :current-page="pagination.pageNum" @current-change="handleCurrentChange" @size-change="handleSizeChange"
              :total="pagination.total">
              <span>共{{ pagination.total }}条</span>
            </el-pagination>
          </div>
        </el-tab-pane>
      </el-tabs>
    </el-card>
    <ViewData v-if="dialogVisibleView" :row="rowView" :dialogVisible="dialogVisibleView"
      @close="dialogVisibleView = false, rowView = {}" />
  </div>
</template>
<script>
import { getRoleInfo, roleInfoFromUserId, getUserList, getDeptList } from './service.js'
import ViewData from '../user/components/viewData.vue'
export default {
  components: {
    ViewData
  },
  props: {},
  data() {
    return {
      form: {},
      activeName: 'first',
      menu: [],
      data: [],
      nickNameOrPhone: '',
      deptId: [],
      deptList: [],
      status: '',
      pagination: {
        total: 10,
        pageNum: 1,
        pageSize: 10,
      },
      rowView: {},
      dialogVisibleView: false,
      listLoading: true,
      timeOutID: null,
      elementLoadingText: '正在加载...',
    };
  },
  computed: {
    height() {
      return this.$baseTableHeight()
    },
  },
  watch: {},
  created() {
    roleInfoFromUserId({ userId: 1 }).then(res => {
      getRoleInfo({ roleId: this.$route.query.roleId }).then(resp => {
        this.menu = this.setSelectedIds(res.data.data, resp.data.data.menus);
        this.form = {
          roleName: resp.data.data.roleName,
          remark: resp.data.data.remark,
        }
      })
    })
    this.getListData()
    getDeptList().then((res) => {
      this.deptList = res.data.data
    })
  },
  mounted() { },
  methods: {
    async getListData() {
      let obj = {
        ...this.pagination,
        nickNameOrPhone: this.nickNameOrPhone,
        deptIds: this.deptId,
        status: this.status,
        roleIds: [this.$route.query.roleId]
      }
      this.listLoading = true
      const { data: { data: { records, total } } } = await getUserList(obj)
      this.data = records
      this.pagination.total = total
      this.timeOutID = setTimeout(() => {
        this.listLoading = false
      }, 500)
    },
    setSelectedIds(arr, selectKeyList) {
      function traverse(item) {
        item.selected = selectKeyList.includes(item.menuId);
        if (item.children && item.children.length > 0) {
          item.children.forEach(traverse);
        }
      }
      arr.forEach(traverse);
      return arr;
    },
    reset() {
      this.nickNameOrPhone = ''
      this.deptId = []
      this.status = ''
      this.pagination.pageNum = 1
      this.getListData()
    },
    onSubmit() {
      this.pagination.pageNum = 1
      this.getListData()
    },
    handleCurrentChange(e) {
      this.pagination.pageNum = e;
      this.getListData()
    },
    handleSizeChange(e) {
      this.pagination.pageSize = e
      this.getListData()
    },
  },
};
</script>
<style lang="less" scoped>
.box_card {
  div:first-child {
    font-size: 18px;
    font-weight: bold;
    margin-bottom: 15px;
  }
  div:last-child {
    font-size: 16px;
    color: rgba(0, 0, 0, 0.65);
  }
}
.row,
.header {
  display: flex;
  align-items: center;
  border: 1px solid #e8e8e8;
  .w20 {
    width: 15%;
    padding: 8px 20px;
  }
  .sconed {
    flex: 1;
    .subpage {
      .title {
        border: 1px solid #e8e8e8;
        border-top: none;
        border-bottom: none;
      }
      .two {
        display: flex;
        align-items: center;
        border: 1px solid #e8e8e8;
        border-top: none;
        border-right: none;
        .left {
          width: 200px;
          padding: 13px 20px;
          border-right: 1px solid #e8e8e8;
        }
        .right {
          display: flex;
          flex: 1;
          div {
            padding: 13px 0 13px 20px;
          }
        }
      }
      .two:last-child {
        border-bottom: none;
      }
      .btns {
        display: flex;
        align-items: center;
        padding: 0 20px;
      }
    }
  }
}
.header {
  background-color: #e8e8e8;
  .subpage {
    display: flex;
  }
  .title {
    width: 200px;
    padding: 8px 20px;
  }
}
.status_class {
  display: flex;
  align-items: center;
  div:nth-child(1) {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    margin-right: 5px;
  }
  div:nth-child(2) {
    margin-right: 8px;
  }
}
/* 当复选框禁用时覆盖默认样式 */
::v-deep .el-checkbox__input.is-disabled.is-checked .el-checkbox__inner {
  background-color: #409eff;
  border-color: #409eff;
}
::v-deep .el-checkbox.is-disabled .el-checkbox__inner::after {
  border-color: #fff;
}
</style>
src/view/systemManage/role/index.vue
New file
@@ -0,0 +1,173 @@
<template>
  <div>
    <el-card>
      <el-form :inline="true" class="demo-form-inline">
        <el-form-item label="角色名称">
          <el-input v-model="roleName" placeholder="请输入角色名称"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button @click="reset">重置</el-button>
          <el-button type="primary" @click="onSubmit">查询</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <el-card style="margin-top: 20px;">
      <div class="add_btn">
        <el-button  icon="el-icon-plus" @click="add"
          type="primary">添加角色</el-button>
      </div>
      <el-table ref="tableSort" v-loading="listLoading" stripe :data="data" :element-loading-text="elementLoadingText"
        >
        <el-table-column type="index" width="55" label="序号"></el-table-column>
        <el-table-column prop="roleName" label="角色名称"></el-table-column>
        <el-table-column prop="remark" label="备注"></el-table-column>
        <el-table-column prop="createTime" label="创建时间"></el-table-column>
        <el-table-column label="操作" width="300">
          <template slot-scope="{row}">
            <div>
              <el-button  type="text"
                @click="$router.push(`/systemManage/role-detail?roleId=${row.roleId}`)">详情</el-button>
              <el-button  type="text"
                @click="$router.push(`/systemManage/add-role?roleId=${row.roleId}`)">编辑</el-button>
              <el-button  type="text"
                @click="del(row)">删除</el-button>
            </div>
          </template>
        </el-table-column>
      </el-table>
      <div class="pagination">
        <el-pagination layout="slot,sizes,prev,pager,next,jumper" :page-size="pagination.pageSize"
          :current-page="pagination.pageNum" @current-change="handleCurrentChange" @size-change="handleSizeChange"
          :total="pagination.total">
          <span>共{{ pagination.total }}条</span>
        </el-pagination>
      </div>
    </el-card>
    <ShowDelConfirm :show="delShow" @close="delShow = false" @confirm="delConfirm" />
  </div>
</template>
<script>
import { getList, delRole } from './service'
import ShowDelConfirm from '@/components/ShowDelConfirm'
export default {
  components: {
    ShowDelConfirm,
  },
  data() {
    return {
      delShow: false,
      data: [],
      roleName: '',
      pagination: {
        total: 10,
        pageNum: 1,
        pageSize: 10,
      },
      delId: '',
      listLoading: true,
      timeOutID: null,
      elementLoadingText: '正在加载...',
    };
  },
  computed: {
    // height() {
    //   // return this.$baseTableHeight()
    // },
  },
  watch: {},
  created() {
    this.getListData()
  },
  mounted() { },
  methods: {
    add() {
      this.$router.push('/systemManage/add-role')
    },
    delConfirm() {
      delRole(this.delId).then(() => {
        this.delShow = false
        this.disbRow = {}
        this.getListData()
        this.$baseMessage('删除成功', 'success')
      })
    },
    del(row) {
      this.delShow = true
      this.delId = row.roleId
    },
    async getListData() {
      let obj = {
        roleName: this.roleName,
        pageNum: this.pagination.pageNum,
        pageSize: this.pagination.pageSize
      }
      this.listLoading = true
      // const { data: { data: { records, total } } } = await getList(obj)
      // this.data = records
      this.pagination.total = 10||total
      this.timeOutID = setTimeout(() => {
        this.listLoading = false
      }, 500)
    },
    reset() {
      this.roleName = ''
      this.pagination.pageNum = 1
      this.getListData()
    },
    onSubmit() {
      this.pagination.pageNum = 1
      this.getListData()
    },
    handleCurrentChange(e) {
      this.pagination.pageNum = e;
      this.getListData()
    },
    handleSizeChange(e) {
      this.pagination.pageSize = e
      this.getListData()
    },
  },
};
</script>
<style lang="less" scoped>
.green {
  background-color: green;
}
.red {
  background-color: red;
}
.demo-form-inline {
  display: flex;
  justify-content: space-between;
}
.add_btn {
  margin-bottom: 20px;
}
.pagination {
  display: flex;
  justify-content: flex-end;
  margin-top: 20px;
}
.status_class {
  display: flex;
  align-items: center;
  div:nth-child(1) {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    margin-right: 5px;
  }
  div:nth-child(2) {
    margin-right: 8px;
  }
}
</style>
src/view/systemManage/role/service.js
New file
@@ -0,0 +1,41 @@
import axios from '@/utils/request';
// 列表
export const getList = (data) => {
  return axios.post('/system/role/list', { ...data })
}
// 添加
export const add = (data) => {
  return axios.post('/system/role/add', { ...data })
}
// 编辑
export const edit = (data) => {
  return axios.put('/system/role', { ...data })
}
// 删除
export const delRole = (id) => {
  return axios.delete(`/system/role/deleteById/${id}`)
}
// 获取菜单树
export const roleInfoFromUserId = (params) => {
  return axios.get(`/system/role/roleInfoFromUserId`, { params })
}
// 获取角色详情
export const getRoleInfo = (params) => {
  return axios.get(`/system/role/roleInfo`, { params })
}
// 列表
export const getUserList = (data) => {
  return axios.post('/system/user/list', { ...data })
}
export const getDeptList = (params) => {
  return axios.post('/t-dept/listAll')
}