Newer
Older
smart-metering-front / src / views / system / user / listUser.vue
<script lang="ts" setup name="SystemDictListDict">
import { ElButton, ElCard, ElDatePicker, ElInput, ElMessage, ElMessageBox, ElRadio, ElTableColumn, ElTag, ElTree } from 'element-plus'
import { Delete, EditPen, Key, MagicStick, Plus } from '@element-plus/icons-vue'
import type { Ref } from 'vue'
import type { IlistQueryType, TreeStructure, changePageType, userType } from './user-interface'
import AddUser from './userAdd.vue'
import RoleAssignment from './roleAssignment.vue'
import { getDeptTreeList } from '@/api/system/dept'
import { delUser, freezeUserApi, getUserList, resetPwdApi, unfreezeUser } from '@/api/system/user'
import { toTreeList } from '@/utils/structure'
import { RSAencrypt } from '@/utils/security'
import type { TableColumn } from '@/components/NormalTable/table_interface'
// 逻辑代码
interface Tree {
  name: string
  children?: Tree[]
  id: string
}
const select = ref()
const { proxy } = getCurrentInstance() as any
const tagNames = { 已冻结: 'danger', 启用: 'success' }
const btnNames = { 已冻结: '解冻', 启用: '冻结' }
const btnStatus = { 已冻结: '', 启用: 'primary' }
const columns: Ref<TableColumn[]> = ref([])
columns.value = [
  { text: '账号', value: 'account', align: 'center' },
  { text: '所在组织机构', value: 'deptName', align: 'center' },
  { text: '真实姓名', value: 'name', align: 'center' },
  { text: '角色', value: 'roleName', align: 'center' },
  { text: '手机号', value: 'phone', align: 'center' },
  { text: '注册时间', value: 'createtime', align: 'center' },
]
const list = ref([])
const total = ref(0)
const loadingTable = ref<boolean>(false)
const loadingTree = ref<boolean>(false)
const resetPwdFlag = ref<string>('111111')
const logTypeList = ref(null)
const listLoading = ref(true)
const defaultProps = {
  children: 'children',
  label: 'name',
}
// 查询参数
const listQuery: IlistQueryType = reactive({
  keywords: '',
  beginTime: '',
  endTime: '',
  deptId: '',
  offset: 1,
  limit: 20,
  sort: 'id',
  deptType: '',
})
const treeData = ref<TreeStructure[]>([])
// 获取列表数据
const fetchData = (flag: string) => {
  loadingTable.value = true
  select.value = ''
  getUserList(listQuery).then((res) => {
    list.value = res.data.rows
    total.value = res.data.total
    loadingTable.value = false
  }).catch(() => {
    loadingTable.value = false
  })
}
// 点击树形结构
const handleNodeClick = (data: Tree) => {
  listQuery.deptId = data.id as string
  fetchData('click')
}

// 获取组织列表树数据
const fetchTreeData = () => {
  loadingTree.value = true
  getDeptTreeList(listQuery).then((res) => {
    treeData.value = toTreeList<TreeStructure>(res.data, '0', true)
    loadingTree.value = false
  }).catch(() => {
    loadingTree.value = false
  })
}
// 查询数据
const search = () => {
  fetchData('search')
}
const addUserRef = ref()
// 新增用户
const add = () => {
  addUserRef.value.initDialog('create')
}
// 编辑用户
const edit = () => {
  if (select.value) {
    const user: userType = list.value[select.value - 1]
    addUserRef.value.initDialog('update', user)
  }
  else {
    ElMessage.error('必须选中一项')
  }
}
// 重置密码
const resetPwd = () => {
  if (select.value) {
    const user: userType = list.value[select.value - 1]
    ElMessageBox.confirm(
      `确定要重置${user.name}的密码为${resetPwdFlag.value}吗?`,
      '确认重置密码',
      {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning',
      },
    ).then(async () => {
      const params = {
        id: String(user.id),
        newPwd: await RSAencrypt(resetPwdFlag.value),
      }
      resetPwdApi(params).then(() => {
        ElMessage.success('操作成功')
      })
    }).catch(() => { })
  }
  else {
    ElMessage.error('必须选中一项')
  }
}
// 删除用户
const deleteUser = () => {
  if (select.value) {
    const user: userType = list.value[select.value - 1]
    ElMessageBox.confirm(
      `确定要删除${user.name}吗?`,
      'Warning',
      {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning',
      },
    ).then(() => {
      delUser({ id: user.id }).then(() => {
        ElMessage.success('操作成功')
        fetchData('')
      })
    }).catch(() => { })
  }
  else {
    ElMessage.error('必须选中一项')
  }
}
// 冻结/解冻用户
const frozenUser = (row: userType) => {
  ElMessageBox.confirm(
    `确定要${(btnNames as any)[row.statusName]}${row.name}吗?`,
    'Warning',
    {
      confirmButtonText: '确认',
      cancelButtonText: '取消',
      type: 'warning',
    },
  ).then(() => {
    if ((btnNames as any)[row.statusName] === '冻结') {
      // 发送请求
      freezeUserApi({ id: row.id }).then((res) => {
        ElMessage.success('操作成功')
        fetchData('')
      })
    }
    else {
      unfreezeUser({ id: row.id }).then((res) => {
        ElMessage.success('操作成功')
        fetchData('')
      })
    }
  }).catch(() => { })
}
const roleAssignmentRef = ref() // 角色分配弹窗
// 角色分配
const assignmentRole = () => {
  if (select.value) {
    const user: userType = list.value[select.value - 1]
    roleAssignmentRef.value.initDialog(user)
  }
  else {
    ElMessage.error('必须选中一项')
  }
}
// 改变每页条数
const handleSizeChange = (val: number) => {
  listQuery.limit = val
  fetchData('')
}
// 改变当前页数
const handleCurrentChange = (val: number) => {
  listQuery.offset = val
  fetchData('')
}
// 页数发生变化后的操作,可能是页码变化,可能是每页容量变化,此函数必写
const changePage = (val: changePageType) => {
  if (val && val.size) {
    listQuery.limit = val.size
  }
  if (val && val.page) {
    listQuery.offset = val.page
  }
  fetchData('')
}
// 重置页面
const resetData = () => {
  fetchData('')
}
// 挂载
onMounted(() => {
  // 获取树形结构数据
  fetchTreeData()
  // 获取列表数据
  fetchData('click')
})
</script>

<template>
  <!-- 布局 -->
  <app-container>
    <div class="container">
      <!-- 左侧组织机构 -->
      <div class="left-container">
        <div class="dept-div">
          <el-card class="box-card" shadow="always">
            <template #header>
              <div class="clearfix">
                <span>组织机构</span>
              </div>
            </template>
            <el-tree
              v-loading="loadingTree" :data="treeData" :props="defaultProps" default-expand-all
              :expand-on-click-node="false" @node-click="handleNodeClick"
            />
          </el-card>
        </div>
      </div>
      <!-- 右侧表格 -->
      <div ref="tableContainer" class="table">
        <!-- 筛选条件 -->
        <search-area @search="search">
          <search-item>
            <el-input v-model.trim="listQuery.keywords" placeholder="账户/真实姓名/手机号" clearable />
          </search-item>
          <search-item>
            <el-date-picker
              v-model="listQuery.beginTime" type="datetime" format="YYYY-MM-DD HH:mm:ss"
              placeholder="选择开始时间"
            />
          </search-item>
          <search-item>
            <el-date-picker
              v-model="listQuery.endTime" type="datetime" format="YYYY-MM-DD HH:mm:ss"
              placeholder="选择结束时间"
            />
          </search-item>
        </search-area>
        <!-- 表头标题 -->
        <table-container>
          <template #btns-left>
            <!-- 操作 -->
            <div style="margin-bottom: 10px;">
              <el-button v-if="proxy.hasPerm('/sys/mgr/add')" type="primary" :icon="Plus" @click="add">
                新增
              </el-button>
              <el-button v-if="proxy.hasPerm('/sys/mgr/update')" type="primary" :icon="EditPen" @click="edit">
                修改
              </el-button>
              <el-button v-if="proxy.hasPerm('/sys/mgr/delete')" type="primary" :icon="Delete" @click="deleteUser">
                删除
              </el-button>
              <el-button v-if="proxy.hasPerm('/sys/mgr/reset')" type="primary" :icon="Key" @click="resetPwd">
                重置密码
              </el-button>
              <el-button
                v-if="proxy.hasPerm('/sys/mgr/roleAssign')" type="primary" :icon="MagicStick"
                @click="assignmentRole"
              >
                角色分配
              </el-button>
            </div>
          </template>
          <!-- 查询结果Table显示 -->
          <normal-table
            :data="list" :total="total" :columns="columns" :query="listQuery"
            :list-loading="loadingTable" @change="changePage"
          >
            <template #preColumns>
              <el-table-column label="选择" width="55" align="center">
                <template #default="scope">
                  <el-radio v-model="select" :label="scope.$index + 1" class="radio" />
                </template>
              </el-table-column>
              <el-table-column label="#" width="55" align="center">
                <template #default="scope">
                  {{ (listQuery.offset - 1) * listQuery.limit + scope.$index + 1 }}
                </template>
              </el-table-column>
            </template>
            <template #columns>
              <el-table-column label="状态" align="center" width="80">
                <template #default="scope">
                  <el-tag :type="(tagNames as any)[scope.row.statusName]">
                    {{ scope.row.statusName }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column label="操作" align="center" width="80">
                <template #default="scope">
                  <el-button :type="(btnStatus as any)[scope.row.statusName]" size="small" @click="frozenUser(scope.row)">
                    {{ (btnNames as any)[scope.row.statusName] }}
                  </el-button>
                </template>
              </el-table-column>
            </template>
          </normal-table>
        </table-container>
      </div>
    </div>
    <!-- 角色分配 -->
    <role-assignment ref="roleAssignmentRef" @reset-data="resetData" />
    <!-- 添加或修改用户 -->
    <add-user ref="addUserRef" @reset-data="resetData" />
  </app-container>
</template>

<style lang="scss" scoped>
// 样式
.container {
  width: 100%;
  display: flex;

  .left-container {
    width: 22%;
  }

  :deep(.el-radio__label) {
    display: none;
  }

  .table-title {
    background-color: #409eff;

    .title {
      padding: 5px 10px;
      // background-color: ;
      font-size: 15px;
      line-height: 46px;
      color: #fff;
      display: flex;
      align-items: center;

      .text {
        margin-left: 10px;
      }
    }
  }

  .table {
    width: 78%;

    .pagination {
      margin-top: 10px;
      width: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
    }
  }
}

.dept-div {
  padding-right: 12px;

  :deep(.el-card) {
    height: 100vh;
    background-color: #fff;
  }

  .box-card {
    width: 100%;

    .user-dept-scroll {
      width: 100%;
      height: calc(100vh - 265px);
    }
  }
}
</style>