zhangwei
2025-08-20 115769e9ad3ddc64e21ad7285450c4c563c745ed
src/views/system/user/utils/hook.tsx
@@ -2,14 +2,14 @@
import dayjs from "dayjs";
import roleForm from "../form/role.vue";
import editForm from "../form/index.vue";
import { zxcvbn } from "@zxcvbn-ts/core";
// import { zxcvbn } from "@zxcvbn-ts/core";
import { handleTree } from "@/utils/tree";
import { message } from "@/utils/message";
import userAvatar from "@/assets/user.jpg";
import { usePublicHooks } from "../../hooks";
import { addDialog } from "@/components/ReDialog";
import type { PaginationProps } from "@pureadmin/table";
import ReCropperPreview from "@/components/ReCropperPreview";
// import ReCropperPreview from "@/components/ReCropperPreview";
import type { FormItemProps, RoleFormItemProps } from "../utils/types";
import {
  getKeyList,
@@ -21,6 +21,9 @@
  getRoleIds,
  getDeptList,
  getUserList,
  creatCustormerUsers,
  changeManager,
  updataCustormerUsers,
  getAllRoleList
} from "@/api/system";
import {
@@ -28,7 +31,9 @@
  ElInput,
  ElFormItem,
  ElProgress,
  ElMessageBox
  ElMessageBox,
  Elpopover,
  ElText
} from "element-plus";
import {
  type Ref,
@@ -44,10 +49,9 @@
export function useUser(tableRef: Ref, treeRef: Ref) {
  const form = reactive({
    // 左侧部门树的id
    deptId: "",
    username: "",
    phone: "",
    status: ""
    name: "",
    phoneNumber: "",
    isEn: true
  });
  const formRef = ref();
  const ruleFormRef = ref();
@@ -68,96 +72,114 @@
    background: true
  });
  const columns: TableColumnList = [
    // {
    //   label: "勾选列", // 如果需要表格多选,此处label必须设置
    //   type: "selection",
    //   fixed: "left",
    //   reserveSelection: true // 数据刷新后保留选项
    // },
    {
      label: "勾选列", // 如果需要表格多选,此处label必须设置
      type: "selection",
      fixed: "left",
      reserveSelection: true // 数据刷新后保留选项
    },
    {
      label: "用户编号",
      prop: "id",
      width: 90
    },
    {
      label: "用户头像",
      prop: "avatar",
      cellRenderer: ({ row }) => (
        <el-image
          fit="cover"
          preview-teleported={true}
          src={row.avatar || userAvatar}
          preview-src-list={Array.of(row.avatar || userAvatar)}
          class="w-[24px] h-[24px] rounded-full align-middle"
        />
      ),
      width: 90
    },
    {
      label: "用户名称",
      prop: "username",
      label: "姓名",
      prop: "name",
      minWidth: 130
    },
    // {
    //   label: "用户头像",
    //   prop: "avatar",
    //   cellRenderer: ({ row }) => (
    //     <el-image
    //       fit="cover"
    //       preview-teleported={true}
    //       src={row.avatar || userAvatar}
    //       preview-src-list={Array.of(row.avatar || userAvatar)}
    //       class="w-[24px] h-[24px] rounded-full align-middle"
    //     />
    //   ),
    //   width: 90
    // },
    // {
    //   label: "用户昵称",
    //   prop: "nickname",
    //   minWidth: 130
    // },
    {
      label: "用户昵称",
      prop: "nickname",
      minWidth: 130
    },
    {
      label: "性别",
      prop: "sex",
      label: "角色",
      prop: "isManager",
      minWidth: 90,
      cellRenderer: ({ row, props }) => (
        <el-tag
          size={props.size}
          type={row.sex === 1 ? "danger" : null}
          effect="plain"
        >
          {row.sex === 1 ? "女" : "男"}
        </el-tag>
      cellRenderer: scope => (
        <div>
          {/* <el-tag
            size={scope.props.size}
            type={scope.row.isManager ? "danger" : null}
            effect="plain"
          >
            {scope.row.isManager ? "管理员" : "员工"}
          </el-tag> */}
          <el-switch
            size={scope.props.size === "small" ? "small" : "default"}
            loading={switchLoadMap.value[scope.index]?.loading}
            v-model={scope.row.isManager}
            active-value={true}
            inactive-value={false}
            active-text="管理员"
            inactive-text="员工"
            inline-prompt
            style={switchStyle.value}
            onChange={() => onManagerChange(scope as any)}
          />
        </div>
      )
    },
    {
      label: "部门",
      prop: "dept.name",
      minWidth: 90
    },
    {
      label: "手机号码",
      prop: "phone",
      prop: "phoneNumber",
      minWidth: 90,
      formatter: ({ phone }) => hideTextAtIndex(phone, { start: 3, end: 6 })
      formatter: ({ phoneNumber }) =>
        hideTextAtIndex(phoneNumber, { start: 3, end: 6 })
    },
    {
      label: "状态",
      prop: "status",
      label: "是否启用",
      prop: "isEn",
      minWidth: 90,
      cellRenderer: scope => (
        <el-switch
          size={scope.props.size === "small" ? "small" : "default"}
          loading={switchLoadMap.value[scope.index]?.loading}
          v-model={scope.row.status}
          active-value={1}
          inactive-value={0}
          active-text="已启用"
          inactive-text="已停用"
          inline-prompt
          style={switchStyle.value}
          onChange={() => onChange(scope as any)}
        />
        <el-tag
          size={scope.props.size}
          type={scope.row.isEn ? null : "danger"}
          effect="plain"
        >
          {scope.row.isEn ? "是" : "否"}
        </el-tag>
        // <el-switch
        //   size={scope.props.size === "small" ? "small" : "default"}
        //   loading={switchLoadMap.value[scope.index]?.loading}
        //   v-model={scope.row.isEn}
        //   active-value={true}
        //   inactive-value={false}
        //   active-text="已启用"
        //   inactive-text="已停用"
        //   inline-prompt
        //   style={switchStyle.value}
        //   onChange={() => onChange(scope as any)}
        // />
      )
    },
    {
      label: "创建时间",
      minWidth: 90,
      width: 160,
      prop: "createTime",
      formatter: ({ createTime }) =>
        dayjs(createTime).format("YYYY-MM-DD HH:mm:ss")
      formatter: ({ createTime }) => dayjs(createTime).format("YYYY-MM-DD")
    },
    {
      label: "备注",
      prop: "remarks",
      width: 180,
      cellRenderer: scope => <el-text truncated>{scope.row.remarks}</el-text>
    },
    {
      label: "操作",
      fixed: "right",
      width: 180,
      width: 80,
      slot: "operation"
    }
  ];
@@ -226,6 +248,42 @@
        row.status === 0 ? (row.status = 1) : (row.status = 0);
      });
  }
  function onManagerChange({ row, index }) {
    ElMessageBox.confirm(
      `确认要设置<strong style='color:var(--el-color-primary)'>${
        row.name
      }</strong>用户为<strong>${
        row.isManager === true ? "管理员" : "员工"
      }</strong>吗?`,
      "更改权限",
      {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
        dangerouslyUseHTMLString: true,
        draggable: true
      }
    )
      .then(() => {
        changeManager({ custormerUserId: row.id }).then(res => {
          if (res.code == 200) {
            message("设置成功!", {
              type: "success"
            });
          } else {
            message(res.message || "设置失败!", {
              type: "error"
            });
          }
          onSearch();
        });
      })
      .catch(() => {
        row.isManager === true
          ? (row.isManager = false)
          : (row.isManager = true);
      });
  }
  function handleUpdate(row) {
    console.log(row);
@@ -272,27 +330,25 @@
  async function onSearch() {
    loading.value = true;
    const { data } = await getUserList(toRaw(form));
    dataList.value = data.list;
    pagination.total = data.total;
    pagination.pageSize = data.pageSize;
    pagination.currentPage = data.currentPage;
    const { result } = await getUserList();
    dataList.value = result;
    // pagination.total = data.total;
    // pagination.pageSize = data.pageSize;
    // pagination.currentPage = data.currentPage;
    setTimeout(() => {
      loading.value = false;
    }, 500);
    // setTimeout(() => {
    loading.value = false;
    // }, 500);
  }
  const resetForm = formEl => {
    if (!formEl) return;
    formEl.resetFields();
    form.deptId = "";
    treeRef.value.onTreeReset();
    onSearch();
  };
  function onTreeSelect({ id, selected }) {
    form.deptId = selected ? id : "";
    onSearch();
  }
@@ -315,15 +371,18 @@
        formInline: {
          title,
          higherDeptOptions: formatHigherDeptOptions(higherDeptOptions.value),
          parentId: row?.dept.id ?? 0,
          id: row?.id ?? null,
          cusExtendId: row?.cusExtendId ?? dataList.value[0].cusExtendId,
          name: row?.name ?? "",
          nickname: row?.nickname ?? "",
          username: row?.username ?? "",
          password: row?.password ?? "",
          phone: row?.phone ?? "",
          email: row?.email ?? "",
          sex: row?.sex ?? "",
          status: row?.status ?? 1,
          remark: row?.remark ?? ""
          phoneNumber: row?.phoneNumber ?? "",
          remarks: row?.remarks ?? "",
          jobTitle: row?.jobTitle ?? "",
          avatar: row?.avatar ?? "",
          isEn: row?.isEn ?? true,
          passWord: row?.passWord ?? "",
          isManager: row?.isManager ?? false,
          signature: row?.signature ?? ""
        }
      },
      width: "46%",
@@ -335,10 +394,22 @@
      beforeSure: (done, { options }) => {
        const FormRef = formRef.value.getRef();
        const curData = options.props.formInline as FormItemProps;
        function chores() {
          message(`您${title}了用户名称为${curData.username}的这条数据`, {
            type: "success"
          });
        async function chores() {
          let res;
          if (title == "新增") {
            res = await creatCustormerUsers(curData);
          } else {
            res = await updataCustormerUsers(curData);
          }
          if (res.code != "200") {
            message(res.message, {
              type: "error"
            });
          } else {
            message(`${title}成功!`, {
              type: "success"
            });
          }
          done(); // 关闭弹框
          onSearch(); // 刷新表格数据
        }
@@ -361,33 +432,32 @@
  const cropRef = ref();
  /** 上传头像 */
  function handleUpload(row) {
    addDialog({
      title: "裁剪、上传头像",
      width: "40%",
      closeOnClickModal: false,
      fullscreen: deviceDetection(),
      contentRenderer: () =>
        h(ReCropperPreview, {
          ref: cropRef,
          imgSrc: row.avatar || userAvatar,
          onCropper: info => (avatarInfo.value = info)
        }),
      beforeSure: done => {
        console.log("裁剪后的图片信息:", avatarInfo.value);
        // 根据实际业务使用avatarInfo.value和row里的某些字段去调用上传头像接口即可
        done(); // 关闭弹框
        onSearch(); // 刷新表格数据
      },
      closeCallBack: () => cropRef.value.hidePopover()
    });
  }
  // function handleUpload(row) {
  //   addDialog({
  //     title: "裁剪、上传头像",
  //     width: "40%",
  //     closeOnClickModal: false,
  //     fullscreen: deviceDetection(),
  //     contentRenderer: () =>
  //       h(ReCropperPreview, {
  //         ref: cropRef,
  //         imgSrc: row.avatar || userAvatar,
  //         onCropper: info => (avatarInfo.value = info)
  //       }),
  //     beforeSure: done => {
  //       console.log("裁剪后的图片信息:", avatarInfo.value);
  //       // 根据实际业务使用avatarInfo.value和row里的某些字段去调用上传头像接口即可
  //       done(); // 关闭弹框
  //       onSearch(); // 刷新表格数据
  //     },
  //     closeCallBack: () => cropRef.value.hidePopover()
  //   });
  // }
  watch(
    pwdForm,
    ({ newPwd }) =>
      (curScore.value = isAllEmpty(newPwd) ? -1 : zxcvbn(newPwd).score)
  );
  // watch();
  // pwdForm
  // ({ newPwd }) =>
  //   (curScore.value = isAllEmpty(newPwd) ? -1 : zxcvbn(newPwd).score)
  /** 重置密码 */
  function handleReset(row) {
@@ -466,7 +536,6 @@
  /** 分配角色 */
  async function handleRole(row) {
    // 选中的角色列表
    const ids = (await getRoleIds({ userId: row.id })).data ?? [];
    addDialog({
      title: `分配 ${row.username} 用户的角色`,
      props: {
@@ -497,13 +566,13 @@
    onSearch();
    // 归属部门
    const { data } = await getDeptList();
    higherDeptOptions.value = handleTree(data);
    treeData.value = handleTree(data);
    treeLoading.value = false;
    // const { data } = await getDeptList();
    // higherDeptOptions.value = handleTree(data);
    // treeData.value = handleTree(data);
    // treeLoading.value = false;
    // 角色列表
    roleOptions.value = (await getAllRoleList()).data;
    // roleOptions.value = (await getAllRoleList()).data;
  });
  return {
@@ -524,7 +593,7 @@
    onTreeSelect,
    handleUpdate,
    handleDelete,
    handleUpload,
    // handleUpload,
    handleReset,
    handleRole,
    handleSizeChange,