import "./reset.css";
|
import dayjs from "dayjs";
|
import roleForm from "../form/role.vue";
|
import editForm from "../form/index.vue";
|
// 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 type { FormItemProps, RoleFormItemProps } from "../utils/types";
|
import {
|
getKeyList,
|
isAllEmpty,
|
hideTextAtIndex,
|
deviceDetection
|
} from "@pureadmin/utils";
|
import {
|
getUserList,
|
creatCustormerUsers,
|
changeManager,
|
updataCustormerUsers,
|
delCustormerUsers
|
} from "@/api/system";
|
import {
|
ElForm,
|
ElInput,
|
ElFormItem,
|
ElProgress,
|
ElMessageBox,
|
Elpopover,
|
ElText
|
} from "element-plus";
|
import {
|
type Ref,
|
h,
|
ref,
|
toRaw,
|
watch,
|
computed,
|
reactive,
|
onMounted
|
} from "vue";
|
|
export function useUser(tableRef: Ref, treeRef: Ref) {
|
const form = reactive({
|
// 左侧部门树的id
|
name: "",
|
phoneNumber: "",
|
isEn: true
|
});
|
const formRef = ref();
|
const ruleFormRef = ref();
|
const dataList = ref([]);
|
const loading = ref(true);
|
// 上传头像信息
|
const avatarInfo = ref();
|
const switchLoadMap = ref({});
|
const { switchStyle } = usePublicHooks();
|
const higherDeptOptions = ref();
|
const treeData = ref([]);
|
const treeLoading = ref(true);
|
const selectedNum = ref(0);
|
const pagination = reactive<PaginationProps>({
|
total: 0,
|
pageSize: 10,
|
currentPage: 1,
|
background: true
|
});
|
const columns: TableColumnList = [
|
// {
|
// label: "勾选列", // 如果需要表格多选,此处label必须设置
|
// type: "selection",
|
// fixed: "left",
|
// reserveSelection: true // 数据刷新后保留选项
|
// },
|
{
|
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: "isManager",
|
minWidth: 90,
|
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: "phoneNumber",
|
minWidth: 90,
|
formatter: ({ phoneNumber }) =>
|
hideTextAtIndex(phoneNumber, { start: 3, end: 6 })
|
},
|
{
|
label: "是否启用",
|
prop: "isEn",
|
minWidth: 90,
|
cellRenderer: scope => (
|
<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: "创建时间",
|
width: 160,
|
prop: "createTime",
|
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: 80,
|
slot: "operation"
|
}
|
];
|
const buttonClass = computed(() => {
|
return [
|
"h-[20px]!",
|
"reset-margin",
|
"text-gray-500!",
|
"dark:text-white!",
|
"dark:hover:text-primary!"
|
];
|
});
|
// 重置的新密码
|
const pwdForm = reactive({
|
newPwd: ""
|
});
|
const pwdProgress = [
|
{ color: "#e74242", text: "非常弱" },
|
{ color: "#EFBD47", text: "弱" },
|
{ color: "#ffa500", text: "一般" },
|
{ color: "#1bbf1b", text: "强" },
|
{ color: "#008000", text: "非常强" }
|
];
|
// 当前密码强度(0-4)
|
const curScore = ref();
|
const roleOptions = ref([]);
|
|
function onChange({ row, index }) {
|
ElMessageBox.confirm(
|
`确认要<strong>${
|
row.status === 0 ? "停用" : "启用"
|
}</strong><strong style='color:var(--el-color-primary)'>${
|
row.username
|
}</strong>用户吗?`,
|
"系统提示",
|
{
|
confirmButtonText: "确定",
|
cancelButtonText: "取消",
|
type: "warning",
|
dangerouslyUseHTMLString: true,
|
draggable: true
|
}
|
)
|
.then(() => {
|
switchLoadMap.value[index] = Object.assign(
|
{},
|
switchLoadMap.value[index],
|
{
|
loading: true
|
}
|
);
|
setTimeout(() => {
|
switchLoadMap.value[index] = Object.assign(
|
{},
|
switchLoadMap.value[index],
|
{
|
loading: false
|
}
|
);
|
message("已成功修改用户状态", {
|
type: "success"
|
});
|
}, 300);
|
})
|
.catch(() => {
|
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);
|
}
|
|
function handleDelete(row) {
|
delCustormerUsers({ custormerUserId: row.id }).then(res => {
|
if (res.code == 200) {
|
message("删除成功!", {
|
type: "success"
|
});
|
onSearch();
|
} else {
|
message(res.message || "删除失败!", {
|
type: "error"
|
});
|
}
|
});
|
}
|
|
function handleSizeChange(val: number) {
|
console.log(`${val} items per page`);
|
}
|
|
function handleCurrentChange(val: number) {
|
console.log(`current page: ${val}`);
|
}
|
|
/** 当CheckBox选择项发生变化时会触发该事件 */
|
function handleSelectionChange(val) {
|
selectedNum.value = val.length;
|
// 重置表格高度
|
tableRef.value.setAdaptive();
|
}
|
|
/** 取消选择 */
|
function onSelectionCancel() {
|
selectedNum.value = 0;
|
// 用于多选表格,清空用户的选择
|
tableRef.value.getTableRef().clearSelection();
|
}
|
|
/** 批量删除 */
|
function onbatchDel() {
|
// 返回当前选中的行
|
const curSelected = tableRef.value.getTableRef().getSelectionRows();
|
// 接下来根据实际业务,通过选中行的某项数据,比如下面的id,调用接口进行批量删除
|
message(`已删除用户编号为 ${getKeyList(curSelected, "id")} 的数据`, {
|
type: "success"
|
});
|
tableRef.value.getTableRef().clearSelection();
|
onSearch();
|
}
|
|
async function onSearch() {
|
loading.value = true;
|
const { result } = await getUserList();
|
dataList.value = result;
|
// pagination.total = data.total;
|
// pagination.pageSize = data.pageSize;
|
// pagination.currentPage = data.currentPage;
|
|
// setTimeout(() => {
|
loading.value = false;
|
// }, 500);
|
}
|
|
const resetForm = formEl => {
|
if (!formEl) return;
|
formEl.resetFields();
|
treeRef.value.onTreeReset();
|
onSearch();
|
};
|
|
function onTreeSelect({ id, selected }) {
|
onSearch();
|
}
|
|
function formatHigherDeptOptions(treeList) {
|
// 根据返回数据的status字段值判断追加是否禁用disabled字段,返回处理后的树结构,用于上级部门级联选择器的展示(实际开发中也是如此,不可能前端需要的每个字段后端都会返回,这时需要前端自行根据后端返回的某些字段做逻辑处理)
|
if (!treeList || !treeList.length) return;
|
const newTreeList = [];
|
for (let i = 0; i < treeList.length; i++) {
|
treeList[i].disabled = treeList[i].status === 0 ? true : false;
|
formatHigherDeptOptions(treeList[i].children);
|
newTreeList.push(treeList[i]);
|
}
|
return newTreeList;
|
}
|
|
function openDialog(title = "新增", row?: FormItemProps) {
|
addDialog({
|
title: `${title}用户`,
|
props: {
|
formInline: {
|
title,
|
higherDeptOptions: formatHigherDeptOptions(higherDeptOptions.value),
|
id: row?.id ?? null,
|
cusExtendId: row?.cusExtendId ?? dataList.value[0].cusExtendId,
|
name: row?.name ?? "",
|
nickname: row?.nickname ?? "",
|
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%",
|
draggable: true,
|
fullscreen: deviceDetection(),
|
fullscreenIcon: true,
|
closeOnClickModal: false,
|
contentRenderer: () => h(editForm, { ref: formRef, formInline: null }),
|
beforeSure: (done, { options }) => {
|
const FormRef = formRef.value.getRef();
|
const curData = options.props.formInline as FormItemProps;
|
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(); // 刷新表格数据
|
}
|
FormRef.validate(valid => {
|
if (valid) {
|
console.log("curData", curData);
|
// 表单规则校验通过
|
if (title === "新增") {
|
// 实际开发先调用新增接口,再进行下面操作
|
chores();
|
} else {
|
// 实际开发先调用修改接口,再进行下面操作
|
chores();
|
}
|
}
|
});
|
}
|
});
|
}
|
|
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()
|
// });
|
// }
|
|
// watch();
|
// pwdForm
|
// ({ newPwd }) =>
|
// (curScore.value = isAllEmpty(newPwd) ? -1 : zxcvbn(newPwd).score)
|
|
/** 重置密码 */
|
function handleReset(row) {
|
addDialog({
|
title: `重置 ${row.username} 用户的密码`,
|
width: "30%",
|
draggable: true,
|
closeOnClickModal: false,
|
fullscreen: deviceDetection(),
|
contentRenderer: () => (
|
<>
|
<ElForm ref={ruleFormRef} model={pwdForm}>
|
<ElFormItem
|
prop="newPwd"
|
rules={[
|
{
|
required: true,
|
message: "请输入新密码",
|
trigger: "blur"
|
}
|
]}
|
>
|
<ElInput
|
clearable
|
show-password
|
type="password"
|
v-model={pwdForm.newPwd}
|
placeholder="请输入新密码"
|
/>
|
</ElFormItem>
|
</ElForm>
|
<div class="my-4 flex">
|
{pwdProgress.map(({ color, text }, idx) => (
|
<div
|
class="w-[19vw]"
|
style={{ marginLeft: idx !== 0 ? "4px" : 0 }}
|
>
|
<ElProgress
|
striped
|
striped-flow
|
duration={curScore.value === idx ? 6 : 0}
|
percentage={curScore.value >= idx ? 100 : 0}
|
color={color}
|
stroke-width={10}
|
show-text={false}
|
/>
|
<p
|
class="text-center"
|
style={{ color: curScore.value === idx ? color : "" }}
|
>
|
{text}
|
</p>
|
</div>
|
))}
|
</div>
|
</>
|
),
|
closeCallBack: () => (pwdForm.newPwd = ""),
|
beforeSure: done => {
|
ruleFormRef.value.validate(valid => {
|
if (valid) {
|
// 表单规则校验通过
|
message(`已成功重置 ${row.username} 用户的密码`, {
|
type: "success"
|
});
|
console.log(pwdForm.newPwd);
|
// 根据实际业务使用pwdForm.newPwd和row里的某些字段去调用重置用户密码接口即可
|
done(); // 关闭弹框
|
onSearch(); // 刷新表格数据
|
}
|
});
|
}
|
});
|
}
|
|
/** 分配角色 */
|
async function handleRole(row) {
|
// 选中的角色列表
|
addDialog({
|
title: `分配 ${row.username} 用户的角色`,
|
props: {
|
formInline: {
|
username: row?.username ?? "",
|
nickname: row?.nickname ?? "",
|
roleOptions: roleOptions.value ?? [],
|
ids
|
}
|
},
|
width: "400px",
|
draggable: true,
|
fullscreen: deviceDetection(),
|
fullscreenIcon: true,
|
closeOnClickModal: false,
|
contentRenderer: () => h(roleForm),
|
beforeSure: (done, { options }) => {
|
const curData = options.props.formInline as RoleFormItemProps;
|
console.log("curIds", curData.ids);
|
// 根据实际业务使用curData.ids和row里的某些字段去调用修改角色接口即可
|
done(); // 关闭弹框
|
}
|
});
|
}
|
|
onMounted(async () => {
|
treeLoading.value = true;
|
onSearch();
|
|
// 归属部门
|
// const { data } = await getDeptList();
|
// higherDeptOptions.value = handleTree(data);
|
// treeData.value = handleTree(data);
|
// treeLoading.value = false;
|
|
// 角色列表
|
// roleOptions.value = (await getAllRoleList()).data;
|
});
|
|
return {
|
form,
|
loading,
|
columns,
|
dataList,
|
treeData,
|
treeLoading,
|
selectedNum,
|
pagination,
|
buttonClass,
|
deviceDetection,
|
onSearch,
|
resetForm,
|
onbatchDel,
|
openDialog,
|
onTreeSelect,
|
handleUpdate,
|
handleDelete,
|
// handleUpload,
|
handleReset,
|
handleRole,
|
handleSizeChange,
|
onSelectionCancel,
|
handleCurrentChange,
|
handleSelectionChange
|
};
|
}
|