<template>
  <basic-container>
    <div class="user">
      <div class="user__tree">
        <div class="user__tree__scroll">
          <el-tree
            :data="deptData"
            :props="{
              children: 'children',
              label: 'name'
            }"
            default-expand-all
            :expand-on-click-node="false"
            @node-click="handleNodeClick"
          >
            <template #default="{ data }">
              <el-tooltip v-if="!data.isLock" class="item" effect="dark" content="无数据权限" placement="right-start">
                <span>
                  {{ data.name }}
                  <el-icon><Lock /> </el-icon>
                </span>
              </el-tooltip>
              <span v-else>{{ data.name }}</span>
            </template>
          </el-tree>
        </div>
      </div>
      <div class="user__main">
        <el-form>
          <el-row :gutter="20">
            <el-col :span="8">
              <el-form-item label="用户名称">
                <el-input v-model="searchForm.username" clearable />
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="手机号码">
                <el-input v-model="searchForm.phone" clearable />
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="状态">
                <el-select v-model="searchForm.delFlag">
                  <el-option v-for="item in del_type" :key="item.value" :label="item.label" :value="item.value" />
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>
          <el-row>
            <!-- <el-col :span="12">
              <el-form-item label="创建时间">
                <el-date-picker
                  type="daterange"
                  range-separator="至"
                  start-placeholder="开始时间"
                  end-placeholder="结束时间"
                />
              </el-form-item>
            </el-col> -->
            <el-col :span="24" class="btn_center">
              <el-button :icon="Search" type="primary" @click="getList">查询</el-button>
              <el-button :icon="Refresh" @click="clearSearch">清空</el-button>
              <el-button :icon="Plus" type="primary" @click="addOrUpdateHandle(false)">新增</el-button>
              <!-- <el-button>导入</el-button>
              <el-button>导出</el-button> -->
            </el-col>
          </el-row>
        </el-form>
        <el-table v-loading="tableLoading" border :data="tableData" row-key="id">
          <el-table-column type="index" label="排序" width="60" align="center" />
          <el-table-column prop="username" label="用户名称" align="center" />
          <el-table-column label="部门" align="center" show-overflow-tooltip>
            <template #default="{ row }">
              {{ getLabelFromMutDict(deptData, row.deptId, "id", "abbreviationName") || row.deptName }}
            </template>
          </el-table-column>
          <el-table-column prop="phone" label="手机号码" align="center" />
          <el-table-column prop="lockFlag" label="状态" align="center">
            <template #default="{ row }">
              {{ getValueLabel(del_type, row.lockFlag) }}
            </template>
          </el-table-column>
          <el-table-column prop="createTime" label="创建时间" align="center" />
          <el-table-column label="操作" width="220" align="center" class-name="small-padding fixed-width">
            <template #default="{ row }">
              <div class="table_btn">
                <el-button size="small" @click="addOrUpdateHandle(row)">修改</el-button>
                <el-button size="small" @click="handleDelete(row)">删除</el-button>
                <!-- <el-button size="small"  @click="handleDelete(row)">重置密码</el-button>
                <el-button size="small"  @click="handleDelete(row)">角色分配</el-button> -->
              </div>
            </template>
          </el-table-column>
        </el-table>
        <pagination
          v-show="tablePage.total > 0"
          v-model:page="tablePage.currentPage"
          v-model:limit="tablePage.pageSize"
          :total="tablePage.total"
          @pagination="getList"
        />
      </div>
    </div>
    <el-dialog v-model="dialogVisible" :title="title" widht="50%" :before-close="dialogClose">
      <el-form :model="dialogForm" ref="dialogFormRef" :rules="dialogFormRules" label-width="80px">
        <el-row>
          <el-col :span="12">
            <el-form-item label="用户昵称" prop="name">
              <el-input v-model="dialogForm.name" clearable placeholder="请输入用户名称" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="用户简称">
              <el-input clearable placeholder="请输入用户昵称" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="手机号码">
              <el-input v-model="dialogForm.phone" clearable placeholder="请输入手机号码" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="邮箱">
              <el-input v-model="dialogForm.email" clearable placeholder="请输入邮箱" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="用户名称" prop="username">
              <el-input
                v-model="dialogForm.username"
                clearable
                placeholder="请输入用户昵称"
                :disabled="title === '修改'"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="用户密码" prop="password">
              <el-input v-model="dialogForm.password" clearable placeholder="请输入用户密码" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="用户性别">
              <el-input clearable placeholder="请输入用户名称" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="岗位" prop="deptId">
              <el-tree-select
                placeholder="请选择岗位"
                v-model="dialogForm.deptId"
                :data="deptOptions"
                check-strictly
                disabled
                clearable
                :render-after-expand="false"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="状态" prop="lockFlag">
              <el-select v-model="dialogForm.lockFlag" clearable>
                <el-option v-for="item in del_type" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="角色" prop="role">
              <el-select v-model="dialogForm.role" multiple>
                <el-option v-for="item in roleList" :key="item.roleId" :label="item.roleName" :value="item.roleId" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="备注">
              <el-input type="textarea" :rows="4" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <el-row class="btn_center">
          <el-button @click="addOrUpdateUser" type="primary">确定</el-button>
          <el-button @click="dialogVisible = false">取消</el-button>
        </el-row>
      </template>
    </el-dialog>
  </basic-container>
</template>

<script setup lang="ts">
import { ref } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import type { FormInstance, FormRules } from "element-plus";
import { Search, Refresh, Plus, Lock } from "@element-plus/icons-vue";

import { ITablePage } from "@/const/interface_type";
import { useDict } from "@/hooks/dict";
import { deepClone, getValueLabel, getLabelFromMutDict } from "@/utils/util";
import { getDeptList, getUserList, getDetails, getRoleList, addUserObj, putUserObj, delUserObj } from "@/api/admin";

const validateUsername = (rule: any, value: any, callback: any) => {
  const flag = /^([a-z\u4e00-\u9fa5\d]+?)$/;
  if (value && !flag.test(value)) {
    callback(new Error("用户名支持小写英文、数字、中文"));
  } else {
    callback();
  }
};

const validateUsernameRepetition = (rule: any, value: any, callback: any) => {
  getDetails(value).then((response) => {
    const result = response.data;
    if (result !== null) {
      callback(new Error("用户名已经存在"));
    } else {
      callback();
    }
  });
};

const validatePass1 = (rule: any, value: any, callback: any) => {
  if (value !== "") {
    var passwordNumber = /^(?![A-Za-z]+$)(?![A-Z\d]+$)(?![A-Z\W]+$)(?![a-z\d]+$)(?![a-z\W]+$)(?![\d\W]+$)\S{8,20}$/;
    if (passwordNumber.test(value)) {
      callback();
    } else {
      callback(new Error("密码格式不规范,至少包含大小写字母、数字、密码长度应在8-20位之间,请重新填写！"));
    }
  }
};

const deptData = ref([]); // 部门数据

const searchForm = ref({
  username: "",
  phone: "",
  delFlag: "",
  deptId: ""
}); // 搜索表格
const tableLoading = ref(false); // 表格loading
const tableData = ref([]); // 表格数据
const tablePage = ref<ITablePage>({
  currentPage: 1,
  pageSize: 10,
  total: 0
});

const { del_type } = useDict("del_type");
const dialogVisible = ref(false); // 弹窗显隐
const title = ref(""); // 弹窗标题
const dialogForm = ref<any>({
  username: "",
  phone: "",
  email: "",
  name: "",
  password: "",
  deptId: "",
  lockFlag: "",
  role: []
});
const dialogFormRef = ref<FormInstance>();
const dialogFormRules = ref<FormRules>({
  name: [{ min: 2, max: 64, required: true, message: "请输入姓名", trigger: "blur" }],
  password: [
    { min: 6, max: 20, required: true, message: "长度在 6 到 20 个字符", trigger: "blur" }
    // { required: true, validator: validatePass1, trigger: "blur" }
  ],
  deptId: [{ required: true, message: "请选择岗位", trigger: "change" }],
  lockFlag: [{ required: true, message: "请选择状态", trigger: "change" }],
  role: [{ required: true, message: "请选择角色", trigger: "change" }]
});
const deptOptions = ref<any>([]); // 部门数据
const roleList = ref<any>([]);

getRoleList().then((res: any) => {
  if (res.code === 0) {
    roleList.value = res.data.records;
  }
});

const handleNodeClick = (data: any) => {
  if (!data.isLock) {
    ElMessage.warning("暂无权限查看该数据");
    return;
  }
  searchForm.value.deptId = data.id;
  dialogForm.value.deptId = data.id;
  getList();
};

// 获取左侧部门数据
getDeptList().then((res: any) => {
  if (res.code === 0) {
    deptData.value = res.data;
  }
});

// 获取表格数据
const getList = () => {
  const data = {
    current: tablePage.value.currentPage,
    size: tablePage.value.pageSize,
    ...searchForm.value
  };
  tableLoading.value = true;
  getUserList(data).then((res: any) => {
    if (res.code === 0) {
      tableData.value = res.data.records;
      tablePage.value.total = res.data.total;
      tableLoading.value = false;
    }
  });
};

getList();

// 清空表格数据
const clearSearch = () => {
  searchForm.value = {
    username: "",
    phone: "",
    delFlag: "",
    deptId: ""
  };
  dialogForm.value.deptId = "";
  getList();
};

const filterList = (arr: any) => {
  const filterData = arr.map((item: any) => {
    return {
      label: item.name,
      value: item.id,
      children: item.children?.length ? filterList(item.children) : []
    };
  });
  return filterData;
};

// 打开弹窗
const addOrUpdateHandle = (row?: any) => {
  // 获取部门数据
  getDeptList().then((res: any) => {
    if (res.code === 0) {
      deptOptions.value = filterList(res.data);
    }
  });
  if (row) {
    title.value = "修改";
    dialogFormRules.value.username = [
      { required: true, message: "请输入用户名", trigger: "blur" },
      { min: 3, max: 20, message: "长度在 3 到 20 个字符", trigger: "blur" },
      { validator: validateUsername, trigger: "blur" }
    ];
    dialogForm.value = deepClone(row);
    dialogForm.value.role = row.roleList.map((item: any) => item.roleId);
    dialogForm.value.password = "********";
  } else {
    if (dialogForm.value.deptId === "") {
      ElMessage.warning("请先选择左侧部门再进行添加");
      return;
    }
    title.value = "新增";
    dialogFormRules.value.username = [
      { required: true, message: "请输入用户名", trigger: "blur" },
      { min: 3, max: 20, message: "长度在 3 到 20 个字符", trigger: "blur" },
      { validator: validateUsername, trigger: "blur" },
      { validator: validateUsernameRepetition, trigger: "blur" }
    ];
  }
  dialogVisible.value = true;
};

// 提交新增/修改数据
const addOrUpdateUser = () => {
  dialogFormRef.value?.validate((valid: boolean) => {
    if (valid) {
      if (title.value === "新增") {
        addUserObj(dialogForm.value).then((res: any) => {
          if (res.code === 0) {
            ElMessage.success("创建成功");
            clearDialogForm();
          }
        });
      } else {
        if (dialogForm.value.password && dialogForm.value.password.indexOf("******") >= 0) {
          dialogForm.value.password = undefined;
        }
        putUserObj(dialogForm.value).then((res: any) => {
          if (res.code === 0) {
            ElMessage.success("修改成功");
            clearDialogForm();
          }
        });
      }
    } else {
      return false;
    }
  });
};

const handleDelete = (row: any) => {
  ElMessageBox.confirm(`是否确认删除名称为 “${row.username}” 的数据项?`, "警告", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  }).then(() => {
    delUserObj(row.userId).then((res: any) => {
      if (res.code === 0) {
        ElMessage({
          type: "success",
          message: `删除 “${row.username}” 成功`
        });
        getList();
      }
    });
  });
};

// 弹窗关闭前
const dialogClose = (done: () => void) => {
  clearDialogForm();
  done();
};

// 清空弹窗内数据
const clearDialogForm = () => {
  dialogForm.value = {
    username: "",
    phone: "",
    email: "",
    name: "",
    password: "",
    deptId: "",
    lockFlag: "",
    role: []
  };
  dialogFormRef.value?.clearValidate();
  dialogVisible.value = false;
  getList();
};
</script>

<style lang="scss" scoped>
.user {
  height: 100%;
  width: 100%;
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  background-color: #edf4fe;
  box-sizing: border-box;
  &__tree {
    box-sizing: border-box;
    padding-right: 20px;
    overflow: hidden;
    height: 100%;
    width: 400px;
    margin-right: 20px;
    &__scroll {
      height: 100%;
      width: 417px;
      overflow-y: auto;
    }
  }
  &__main {
    flex: 1;
    height: 100%;
    padding: 0 20px;
    box-sizing: border-box;
    background-color: #fff;
  }
}
</style>
