<template>
  <!-- 整体的应用容器 div -->
  <div class="app-container">
    <!-- 筛选搜索区域的卡片容器，设置了阴影效果为无 -->
    <el-card class="filter-container" shadow="never">
      <div>
        <!-- 搜索图标 -->
        <i class="el-icon-search"></i>
        <!-- 筛选搜索的文字提示 -->
        <span>筛选搜索</span>
        <!-- 查询搜索按钮，设置了样式为右浮动、按钮类型为主要（primary），点击时调用 handleSearchList 方法，按钮大小为 small -->
        <el-button
          style="float:right"
          type="primary"
          @click="handleSearchList()"
          size="small">
          查询搜索
        </el-button>
        <!-- 重置按钮，设置了样式为右浮动且距离右侧 15px，点击时调用 handleResetSearch 方法，按钮大小为 small -->
        <el-button
          style="float:right;margin-right: 15px"
          @click="handleResetSearch()"
          size="small">
          重置
        </el-button>
      </div>
      <div style="margin-top: 15px">
        <!-- 内联表单，绑定了 listQuery 数据对象，表单大小为 small，标签宽度为 140px -->
        <el-form :inline="true" :model="listQuery" size="small" label-width="140px">
          <!-- 表单项目，标签为“输入搜索：” -->
          <el-form-item label="输入搜索：">
            <!-- 输入框，双向绑定 listQuery.keyword，设置了类名、占位符以及可清空功能 -->
            <el-input v-model="listQuery.keyword" class="input-width" placeholder="帐号/姓名" clearable></el-input>
          </el-form-item>
        </el-form>
      </div>
    </el-card>
    <!-- 操作区域的卡片容器，设置了阴影效果为无 -->
    <el-card class="operate-container" shadow="never">
      <!-- 图标 -->
      <i class="el-icon-tickets"></i>
      <!-- 数据列表的文字提示 -->
      <span>数据列表</span>
      <!-- 添加按钮，大小为 mini，设置了类名，点击时调用 handleAdd 方法，设置了左侧外边距为 20px -->
      <el-button size="mini" class="btn-add" @click="handleAdd()" style="margin-left: 20px">添加</el-button>
    </el-card>
    <!-- 表格容器 div -->
    <div class="table-container">
      <!-- el-table 组件，绑定了 list 数据用于展示表格内容，设置了加载状态绑定、宽度、边框等属性 -->
      <el-table ref="adminTable"
                :data="list"
                style="width: 100%;"
                v-loading="listLoading" border>
        <!-- 表格列，标签为“编号”，设置了宽度和内容居中对齐，通过插槽作用域展示对应行数据的 id 属性 -->
        <el-table-column label="编号" width="100" align="center">
          <template slot-scope="scope">{{scope.row.id}}</template>
        </el-table-column>
        <!-- 表格列，标签为“帐号”，内容居中对齐，通过插槽作用域展示对应行数据的 username 属性 -->
        <el-table-column label="帐号" align="center">
          <template slot-scope="scope">{{scope.row.username}}</template>
        </el-table-column>
        <!-- 表格列，标签为“姓名”，内容居中对齐，通过插槽作用域展示对应行数据的 nickName 属性 -->
        <el-table-column label="姓名" align="center">
          <template slot-scope="scope">{{scope.row.nickName}}</template>
        </el-table-column>
        <!-- 表格列，标签为“邮箱”，内容居中对齐，通过插槽作用域展示对应行数据的 email 属性 -->
        <el-table-column label="邮箱" align="center">
          <template slot-scope="scope">{{scope.row.email}}</template>
        </el-table-column>
        <!-- 表格列，标签为“添加时间”，设置了宽度和内容居中对齐，通过插槽作用域展示对应行数据的 createTime 属性，并使用了 formatDateTime 过滤器进行格式化 -->
        <el-table-column label="添加时间" width="160" align="center">
          <template slot-scope="scope">{{scope.row.createTime | formatDateTime}}</template>
        </el-table-column>
        <!-- 表格列，标签为“最后登录”，设置了宽度和内容居中对齐，通过插槽作用域展示对应行数据的 loginTime 属性，并使用了 formatDateTime 过滤器进行格式化 -->
        <el-table-column label="最后登录" width="160" align="center">
          <template slot-scope="scope">{{scope.row.loginTime | formatDateTime}}</template>
        </el-table-column>
        <!-- 表格列，标签为“是否启用”，设置了宽度和内容居中对齐，通过插槽作用域展示对应行数据的 status 属性，并使用 el-switch 组件进行切换操作，绑定了相关的事件和值 -->
        <el-table-column label="是否启用" width="140" align="center">
          <template slot-scope="scope">
            <el-switch
              @change="handleStatusChange(scope.$index, scope.row)"
              :active-value="1"
              :inactive-value="0"
              v-model="scope.row.status">
            </el-switch>
          </template>
        </el-table-column>
        <!-- 表格列，标签为“操作”，设置了宽度和内容居中对齐，通过插槽作用域展示操作按钮，包括分配角色、编辑、删除按钮，分别绑定了对应的点击事件方法 -->
        <el-table-column label="操作" width="180" align="center">
          <template slot-scope="scope">
            <el-button size="mini"
                       type="text"
                       @click="handleSelectRole(scope.$index, scope.row)">分配角色
            </el-button>
            <el-button size="mini"
                       type="text"
                       @click="handleUpdate(scope.$index, scope.row)">
              编辑
            </el-button>
            <el-button size="mini"
                       type="text"
                       @click="handleDelete(scope.$index, scope.row)">删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <!-- 分页容器 div -->
    <div class="pagination-container">
      <!-- el-pagination 分页组件，设置了背景色、相关页面切换事件绑定、布局样式、当前页、每页数量、可选每页数量数组以及总记录数等属性 -->
      <el-pagination
        background
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        layout="total, sizes,prev, pager, next,jumper"
        :current-page.sync="listQuery.pageNum"
        :page-size="listQuery.pageSize"
        :page-sizes="[10,15,20]"
        :total="total">
      </el-pagination>
    </div>
    <!-- 编辑/添加用户的对话框组件，根据 isEdit 变量来动态设置标题，绑定了显示状态，设置了宽度 -->
    <el-dialog
      :title="isEdit?'编辑用户':'添加用户'"
      :visible.sync="dialogVisible"
      width="40%">
      <!-- 对话框内的表单，绑定了 admin 数据对象，设置了表单引用、标签宽度和大小 -->
      <el-form :model="admin"
               ref="adminForm"
               label-width="150px" size="small">
        <!-- 表单项目，标签为“帐号：”，输入框双向绑定 admin.username -->
        <el-form-item label="帐号：">
          <el-input v-model="admin.username" style="width: 250px"></el-input>
        </el-form-item>
        <!-- 表单项目，标签为“姓名：”，输入框双向绑定 admin.nickName -->
        <el-form-item label="姓名：">
          <el-input v-model="admin.nickName" style="width: 250px"></el-input>
        </el-form-item>
        <!-- 表单项目，标签为“邮箱：”，输入框双向绑定 admin.email -->
        <el-form-item label="邮箱：">
          <el-input v-model="admin.email" style="width: 250px"></el-input>
        </el-form-item>
        <!-- 表单项目，标签为“密码：”，输入框双向绑定 admin.password，设置了密码类型 -->
        <el-form-item label="密码：">
          <el-input v-model="admin.password"  type="password" style="width: 250px"></el-input>
        </el-form-item>
        <!-- 表单项目，标签为“备注：”，输入框双向绑定 admin.note，设置了文本域类型和行数 -->
        <el-form-item label="备注：">
          <el-input v-model="admin.note"
                    type="textarea"
                    :rows="5"
                    style="width: 250px"></el-input>
        </el-form-item>
        <!-- 表单项目，标签为“是否启用：”，使用单选按钮组绑定 admin.status -->
        <el-form-item label="是否启用：">
          <el-radio-group v-model="admin.status">
            <el-radio :label="1">是</el-radio>
            <el-radio :label="0">否</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <!-- 对话框底部的按钮区域，通过插槽定义了取消和确定按钮，分别绑定了对应的点击事件 -->
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false" size="small">取 消</el-button>
        <el-button type="primary" @click="handleDialogConfirm()" size="small">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 分配角色的对话框组件，设置了标题、绑定了显示状态和宽度 -->
    <el-dialog
      title="分配角色"
      :visible.sync="allocDialogVisible"
      width="30%">
      <!-- 多选的下拉选择框，绑定了 allocRoleIds 数据，设置了占位符、大小和宽度，通过循环渲染选项 -->
      <el-select v-model="allocRoleIds" multiple placeholder="请选择" size="small" style="width: 80%">
        <el-option
          v-for="item in allRoleList"
          :key="item.id"
          :label="item.name"
          :value="item.id">
        </el-option>
      </el-select>
      <!-- 对话框底部的按钮区域，通过插槽定义了取消和确定按钮，分别绑定了对应的点击事件 -->
      <span slot="footer" class="dialog-footer">
        <el-button @click="allocDialogVisible = false" size="small">取 消</el-button>
        <el-button type="primary" @click="handleAllocDialogConfirm()" size="small">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
// 从 @/api/login 模块中导入多个 API 函数，用于获取列表、创建管理员、更新管理员、更新状态、删除管理员、获取管理员角色、分配角色等操作
import {fetchList,createAdmin,updateAdmin,updateStatus,deleteAdmin,getRoleByAdmin,allocRole} from '@/api/login';
// 从 @/api/role 模块中导入获取所有角色列表的 API 函数
import {fetchAllRoleList} from '@/api/role';
// 从 @/utils/date 模块中导入日期格式化函数
import {formatDate} from '@/utils/date';

// 默认的列表查询参数对象，包含当前页码、每页数量、搜索关键字等初始值
const defaultListQuery = {
  pageNum: 1,
  pageSize: 10,
  keyword: null
};
// 默认的管理员对象，包含各个管理员相关属性的初始值，如 id、用户名、密码、姓名、邮箱、备注、状态等
const defaultAdmin = {
  id: null,
  username: null,
  password: null,
  nickName: null,
  email: null,
  note: null,
  status: 1
};

export default {
  name: 'adminList',
  data() {
    return {
      // 列表查询参数对象，初始化为 defaultListQuery 的副本，用于存储当前的查询条件
      listQuery: Object.assign({}, defaultListQuery),
      // 存储列表数据
      list: null,
      // 总记录数
      total: null,
      // 列表加载状态，用于控制加载动画显示
      listLoading: false,
      // 编辑/添加用户对话框的显示状态
      dialogVisible: false,
      // 当前操作的管理员对象，初始化为 defaultAdmin 的副本，用于存储编辑或添加时的数据
      admin: Object.assign({}, defaultAdmin),
      // 是否为编辑状态的标识
      isEdit: false,
      // 分配角色对话框的显示状态
      allocDialogVisible: false,
      // 已分配的角色 ID 数组，用于存储当前管理员已分配的角色 ID
      allocRoleIds:[],
      // 所有角色列表数据
      allRoleList:[],
      // 当前要分配角色的管理员 ID
      allocAdminId:null
    }
  },
  created() {
    // 在组件创建时，调用获取列表数据的方法和获取所有角色列表的方法
    this.getList();
    this.getAllRoleList();
  },
  filters: {
    formatDateTime(time) {
      // 如果传入的时间为空或 null，则返回 'N/A'
      if (time == null || time === '') {
        return 'N/A';
      }
      // 将传入的时间字符串转换为 Date 对象
      let date = new Date(time);
      // 使用 formatDate 函数对日期进行格式化并返回
      return formatDate(date, 'yyyy-MM-dd hh:mm:ss')
    }
  },
  methods: {
    handleResetSearch() {
      // 重置列表查询参数为默认值
      this.listQuery = Object.assign({}, defaultListQuery);
    },
    handleSearchList() {
      // 将当前页码重置为 1，然后调用获取列表数据的方法，用于执行筛选搜索操作
      this.listQuery.pageNum = 1;
      this.getList();
    },
    handleSizeChange(val) {
      // 当每页数量改变时，将当前页码重置为 1，更新每页数量为传入的值，然后调用获取列表数据的方法，用于重新加载数据
      this.listQuery.pageNum = 1;
      this.listQuery.pageSize = val;
      this.getList();
    },
    handleCurrentChange(val) {
      // 当当前页码改变时，更新当前页码为传入的值，然后调用获取列表数据的方法，用于加载对应页码的数据
      this.listQuery.pageNum = val;
      this.getList();
    },
    handleAdd() {
      // 显示编辑/添加用户对话框，设置为添加状态，将管理员对象重置为默认值
      this.dialogVisible = true;
      this.isEdit = false;
      this.admin = Object.assign({},defaultAdmin);
    },
    handleStatusChange(index, row) {
      // 弹出确认框，询问是否要修改状态
      this.$confirm('是否要修改该状态?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        // 如果确认修改，调用更新状态的 API 函数，传入对应行的 ID 和要更新的状态数据，成功后显示成功提示消息
        updateStatus(row.id, {status: row.status}).then(response => {
          this.$message({
            type: 'success',
            message: '修改成功!'
          });
        });
      }).catch(() => {
        // 如果取消修改，显示取消修改的提示消息，并重新获取列表数据
        this.$message({
          type: 'info',
          message: '取消修改'
        });
        this.getList();
      });
    },
    handleDelete(index, row) {
      // 弹出确认框，询问是否要删除用户
      this.$confirm('是否要删除该用户?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        // 如果确认删除，调用删除管理员的 API 函数，传入对应行的 ID，成功后显示删除成功提示消息，并重新获取列表数据
        deleteAdmin(row.id).then(response => {
          this.$message({
            type: 'success',
            message: '删除成功!'
          });
          this.getList();
        });
      });
    },
    handleUpdate(index, row) {
      // 显示编辑/添加用户对话框，设置为编辑状态，将管理员对象赋值为当前要编辑的行数据
      this.dialogVisible = true;
      this.isEdit = true;
      this.admin = Object.assign({},row);
    },
    handleDialogConfirm() {
      // 弹出确认框，询问是否要确认当前操作（编辑或添加）
      this.$confirm('是否要确认?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        // 判断当前是否为编辑状态
        if (this.isEdit) {
          // 如果是编辑状态，调用更新管理员信息的 API 函数，传入当前管理员的 ID 和管理员数据对象
          // 成功后显示修改成功的提示消息，关闭编辑/添加对话框，并重新获取列表数据，以更新界面显示
          updateAdmin(this.admin.id,this.admin).then(response => {
            this.$message({
              message: '修改成功！',
              type: 'success'
            });
            this.dialogVisible =false;
            this.getList();
          })
        } else {
          // 如果是添加状态，调用创建管理员的 API 函数，传入管理员数据对象
          // 成功后显示添加成功的提示消息，关闭编辑/添加对话框，并重新获取列表数据，以更新界面显示
          createAdmin(this.admin).then(response => {
            this.$message({
              message: '添加成功！',
              type: 'success'
            });
            this.dialogVisible =false;
            this.getList();
          })
        }
      })
    },
    handleAllocDialogConfirm(){
      // 弹出确认框，询问是否要确认分配角色操作
      this.$confirm('是否要确认?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        // 创建 URLSearchParams 对象，用于构建请求参数
        let params = new URLSearchParams();
        // 将当前要分配角色的管理员 ID 添加到请求参数中
        params.append("adminId", this.allocAdminId);
        // 将已选择的角色 ID 数组添加到请求参数中
        params.append("roleIds", this.allocRoleIds);
        // 调用分配角色的 API 函数，传入构建好的请求参数
        // 成功后显示分配成功的提示消息，并关闭分配角色对话框
        allocRole(params).then(response => {
          this.$message({
            message: '分配成功！',
            type: 'success'
          });
          this.allocDialogVisible = false;
        })
      })
    },
    handleSelectRole(index,row){
      // 记录当前要分配角色的管理员 ID
      this.allocAdminId = row.id;
      // 显示分配角色对话框
      this.allocDialogVisible = true;
      // 调用获取指定管理员已分配角色列表的方法，传入管理员 ID，用于初始化分配角色对话框中的已选角色数据
      this.getRoleListByAdmin(row.id);
    },
    getList() {
      // 设置列表加载状态为正在加载，用于显示加载动画等提示
      this.listLoading = true;
      // 调用获取列表数据的 API 函数，传入当前的列表查询参数对象
      fetchList(this.listQuery).then(response => {
        // 获取数据成功后，将列表加载状态设置为加载完成
        this.listLoading = false;
        // 将获取到的列表数据赋值给 list 属性，用于在界面上展示
        this.list = response.data.list;
        // 将获取到的总记录数赋值给 total 属性，用于分页等相关功能
        this.total = response.data.total;
      });
    },
    getAllRoleList() {
      // 调用获取所有角色列表的 API 函数
      fetchAllRoleList().then(response => {
        // 将获取到的所有角色列表数据赋值给 allRoleList 属性，用于在分配角色等相关功能中使用
        this.allRoleList = response.data;
      });
    },
    getRoleListByAdmin(adminId) {
      // 调用获取指定管理员已分配角色列表的 API 函数，传入管理员 ID
      getRoleByAdmin(adminId).then(response => {
        // 获取到已分配角色列表数据
        let allocRoleList = response.data;
        // 初始化已分配的角色 ID 数组为空
        this.allocRoleIds=[];
        // 如果已分配角色列表不为空且有数据
        if(allocRoleList!=null&&allocRoleList.length>0){
          // 遍历已分配角色列表，将每个角色的 ID 添加到已分配的角色 ID 数组中
          for(let i=0;i<allocRoleList.length;i++){
            this.allocRoleIds.push(allocRoleList[i].id);
          }
        }
      });
    }
  }
}
</script>
<style></style>
