This commit is contained in:
六如
2024-12-12 22:05:25 +08:00
parent 28808ab1e3
commit 3e06fcd799
89 changed files with 3823 additions and 953 deletions

View File

@@ -12,8 +12,8 @@ const apiRouters = [
},
children: [
{
path: "/serve/api/index",
name: "ApiManage",
path: "/serve/api",
name: "ServeApi",
meta: {
title: "接口管理",
roles: ["admin"]
@@ -56,8 +56,8 @@ const apiRouters = [
},
children: [
{
path: "/isv/list/index",
name: "IsvManage",
path: "/isv/list",
name: "IsvList",
meta: {
title: "ISV列表",
roles: ["admin"]
@@ -65,7 +65,7 @@ const apiRouters = [
},
{
path: "/isv/perm/permGroup",
name: "PermGroup",
name: "IsvPermPermGroup",
meta: {
title: "分组管理",
roles: ["admin"]

View File

@@ -3,10 +3,10 @@ import type { PageResult, Result } from "@/model";
// 后端请求接口
const apiUrl: any = createUrl({
page: "/sys/adminuser/page",
add: "/sys/adminuser/add",
update: "/sys/adminuser/update",
del: "/sys/adminuser/delete"
page: "/sys/user/page",
add: "/sys/user/add",
update: "/sys/user/update",
del: "/sys/user/delete"
});
/**

View File

@@ -20,18 +20,66 @@ type ResultTable = {
};
/** 获取系统管理-用户管理列表 */
export const getUserList = (data?: object) => {
return http.request<ResultTable>("post", "/user", { data });
export const getUserList = (params?: object) => {
return http.request<ResultTable>("get", baseUrl("sys/user/page"), { params });
};
/** 获取系统管理-用户管理-添加 */
export const addUser = (data?: object) => {
return http.request<ResultTable>("post", baseUrl("sys/user/add"), {
data
});
};
/** 获取系统管理-用户管理-修改 */
export const updateUser = (data?: object) => {
return http.request<ResultTable>("post", baseUrl("sys/user/update"), {
data
});
};
/** 获取系统管理-用户管理-修改状态 */
export const updateUserStatus = (data?: object) => {
return http.request<ResultTable>("post", baseUrl("sys/user/updateStatus"), {
data
});
};
/** 获取系统管理-用户管理-重置密码 */
export const resetPassword = (data?: object) => {
return http.request<ResultTable>("post", baseUrl("sys/user/resetPassword"), {
data
});
};
/** 获取系统管理-用户管理-批量修改状态 */
export const updateStatusBatch = (data?: object) => {
return http.request<ResultTable>(
"post",
baseUrl("sys/user/updateStatusBatch"),
{ data }
);
};
/** 系统管理-用户管理-根据userId获取对应角色id列表userId用户id */
export const getRoleIds = (params?: object) => {
return http.request<Result>("get", baseUrl("sys/userrole/getUserRoleIds"), {
params
});
};
/** 获取系统管理-用户管理-设置用户角色 */
export const setUserRole = (data?: object) => {
return http.request<ResultTable>(
"post",
baseUrl("sys/userrole/setUserRole"),
{ data }
);
};
/** 系统管理-用户管理-获取所有角色列表 */
export const getAllRoleList = () => {
return http.request<Result>("get", "/list-all-role");
};
/** 系统管理-用户管理-根据userId获取对应角色id列表userId用户id */
export const getRoleIds = (data?: object) => {
return http.request<Result>("post", "/list-role-ids", { data });
return http.request<Result>("get", baseUrl("sys/role/all"));
};
/** 获取系统管理-角色管理列表 */
@@ -39,22 +87,26 @@ export const getRoleList = (params?: object) => {
return http.request<ResultTable>("get", baseUrl("sys/role/page"), { params });
};
/** 添加角色 */
export const addRole = (data?: object) => {
return http.request<ResultTable>("post", baseUrl("sys/role/add"), { data });
};
/** 删除角色状态 */
export const updateRoleStatus = (data?: object) => {
return http.request<ResultTable>("post", baseUrl("sys/role/updateStatus"), {
data
});
};
/** 修改角色 */
export const updateRole = (data?: object) => {
return http.request<ResultTable>("post", baseUrl("sys/role/update"), {
data
});
};
/** 删除角色 */
export const delRole = (data?: object) => {
return http.request<ResultTable>("post", baseUrl("sys/role/delete"), {
data
@@ -63,12 +115,48 @@ export const delRole = (data?: object) => {
/** 获取系统管理-菜单管理列表 */
export const getMenuList = (data?: object) => {
return http.request<Result>("post", "/menu", { data });
return http.request<Result>("get", baseUrl("sys/resource/listAll"), {
data
});
};
/** 获取系统管理-菜单管理-添加 */
export const addMenu = (data?: object) => {
return http.request<Result>("post", baseUrl("sys/resource/add"), { data });
};
/** 获取系统管理-菜单管理-修改 */
export const updateMenu = (data?: object) => {
return http.request<Result>("post", baseUrl("sys/resource/update"), { data });
};
/** 获取系统管理-菜单管理-删除 */
export const deleteMenu = (data?: object) => {
return http.request<Result>("post", baseUrl("sys/resource/delete"), { data });
};
/** 系统管理-角色管理-保存角色菜单 */
export const saveRoleMenu = (data?: object) => {
return http.request<Result>(
"post",
baseUrl("sys/resource/saveRoleResource"),
{ data }
);
};
/** 获取系统管理-部门管理列表 */
export const getDeptList = (data?: object) => {
return http.request<Result>("post", "/dept", { data });
export const getDeptList = (params?: object) => {
return http.request<Result>("get", baseUrl("sys/dept/listAll"), { params });
};
/** 获取系统管理-添加部门 */
export const addDept = (data?: object) => {
return http.request<Result>("post", baseUrl("sys/dept/add"), { data });
};
/** 获取系统管理-修改部门 */
export const updateDept = (data?: object) => {
return http.request<Result>("post", baseUrl("sys/dept/update"), { data });
};
/** 获取系统监控-在线用户列表 */
@@ -97,11 +185,13 @@ export const getSystemLogsDetail = (data?: object) => {
};
/** 获取角色管理-权限-菜单权限 */
export const getRoleMenu = (data?: object) => {
return http.request<Result>("post", "/role-menu", { data });
export const getRoleMenu = () => {
return http.request<Result>("get", baseUrl("sys/resource/listAll"), {});
};
/** 获取角色管理-权限-菜单权限-根据角色 id 查对应菜单 */
export const getRoleMenuIds = (data?: object) => {
return http.request<Result>("post", "/role-menu-ids", { data });
export const getRoleMenuIds = (params?: object) => {
return http.request<Result>("get", baseUrl("sys/resource/listRoleResource"), {
params
});
};

View File

@@ -186,11 +186,17 @@ class PureHttp {
if (response.code && response.code !== "0") {
const msg = response.msg || "后台出错,请查看日志";
ElMessage.error(msg);
reject(response);
} else {
resolve(response);
}
})
.catch(error => {
console.error(error);
if (error) {
const msg = error?.message || "后台出错,请查看日志";
ElMessage.error(msg);
}
reject(error);
});
});

View File

@@ -1,4 +1,4 @@
import { computed, ref } from "vue";
import { computed, onMounted, ref } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { api } from "@/api/doc";
import {
@@ -8,336 +8,354 @@ import {
} from "plus-pro-components";
import { YesOrNoEnum } from "@/model/enums";
export const tabsData = ref<Array<any>>([
{
id: "",
appName: ""
}
]);
export const activeName = ref(0);
const docAppId = ref(0);
export const loading = ref(false);
// 表格对象
export const { tableData, buttons: actionButtons } = useTable<any[]>();
export const filterText = ref("");
export const tableRows = computed(() => {
let search = filterText.value;
if (!search) {
return tableData.value;
}
search = search.toLowerCase();
return searchRow(search, tableData.value, searchContent, isFolder);
});
const isFolder = row => {
return row.isFolder === 1;
};
const searchContent = (searchText, row) => {
return (
(row.docName && row.docName.toLowerCase().indexOf(searchText) > -1) ||
(row.docTitle && row.docTitle.toLowerCase().indexOf(searchText) > -1)
);
};
// 表格字段定义
export const tableColumns: PlusColumn[] = [
{
label: "文档标题",
prop: "docTitle"
},
{
label: "接口名",
prop: "docName"
},
{
label: "版本号",
prop: "docVersion",
width: 80
},
{
label: "描述",
prop: "description",
tableColumnProps: {
showOverflowTooltip: true
export function useDocList() {
const tabsData = ref<Array<any>>([
{
id: "",
appName: ""
}
},
{
label: "发布状态",
prop: "isPublish",
valueType: "select",
width: 100,
options: [
{
label: "已发布",
value: YesOrNoEnum.YES,
color: "green"
},
{
label: "未发布",
value: YesOrNoEnum.NO,
color: "red"
}
],
renderHTML: (value, { row }) => {
if (row.isFolder) {
return "";
}
return value
? `<div style="color:green;">已发布</div>`
: `<div style="color:gray;">未发布</div>`;
}
},
{
width: 160,
label: "添加时间",
prop: "addTime"
},
{
width: 160,
label: "修改时间",
prop: "updateTime"
}
];
// 表格按钮定义
actionButtons.value = [
{
text: "发布",
confirm: {
options: { draggable: false },
popconfirmProps: { width: 300 },
message: params => {
const row = params.row;
return `确定要发布[${row.docTitle}]下所有接口吗?`;
}
},
props: (_: any) => ({
type: "success"
}),
onConfirm(params: ButtonsCallBackParams) {
const data = {
id: params.row.id,
isPublish: params.row.isPublish === 1 ? 0 : 1
};
api.publish(data).then(() => {
ElMessage.success("保存成功");
search();
});
},
show: (row: any) => row.isFolder === 1
},
{
text: "下线",
confirm: {
options: { draggable: false },
popconfirmProps: { width: 300 },
message: params => {
const row = params.row;
const opt = "下线";
return `确定要${opt}[${row.docTitle}]下所有接口吗?`;
}
},
props: {
type: "danger"
},
onConfirm(params: ButtonsCallBackParams) {
const data = {
id: params.row.id,
isPublish: 0
};
api.publish(data).then(() => {
ElMessage.success("下线成功");
search();
});
},
show: (row: any) => row.isFolder === 1
},
{
text: row => (row.isPublish ? "下线" : "发布"),
confirm: {
options: { draggable: false },
popconfirmProps: { width: 300 },
message: params => {
const row = params.row;
const opt = row.isPublish ? "下线" : "发布";
return `确定要${opt}[${row.docTitle}]吗?`;
}
},
props: (row: any) => ({
type: row.isPublish === 1 ? "danger" : "success"
}),
onConfirm(params: ButtonsCallBackParams) {
const data = {
id: params.row.id,
isPublish: params.row.isPublish === 1 ? 0 : 1
};
api.publish(data).then(() => {
ElMessage.success("保存成功");
search();
});
},
show: (row: any) => row.isFolder === 0
},
{
text: "同步",
confirm: {
options: { draggable: false },
popconfirmProps: { width: 300 },
message: params => {
const row = params.row;
return row.isFolder
? `确定要同步[${row.docTitle}]下所有接口吗?`
: `确定要同步[${row.docTitle}]吗?`;
}
},
props: (_: any) => ({
type: "primary"
}),
onConfirm(params: ButtonsCallBackParams) {
loading.value = true;
api
.syncDoc(params.row.id)
.then(() => {
loading.value = false;
ElMessage.success("同步成功");
search();
})
.catch(() => {
loading.value = false;
});
}
}
];
// 点击查询按钮
export const handleSearch = () => {
search();
};
// 查询
const search = async () => {
loadContent(docAppId.value);
};
export function handleSyncApi() {
ElMessageBox.confirm("确定要同步远程接口吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
loading.value = true;
api
.syncAppDoc(docAppId.value)
.then(() => {
loading.value = false;
ElMessage.success("同步成功");
search();
})
.catch(() => {
loading.value = false;
});
})
.catch(() => {});
}
export const handleClick = data => {
const id = data.props.name;
activeTab(id);
};
const activeTab = id => {
docAppId.value = id;
loadContent(id);
};
export const handleAddApp = () => {
ElMessageBox.prompt("请输入Torna应用token", "添加应用", {
confirmButtonText: "确定",
cancelButtonText: "取消",
inputPattern: /\w+/,
inputErrorMessage: "请输入Torna应用token"
})
.then(({ value }) => {
const data = {
tornaToken: value
};
api.addApp(data).then(resp => {
ElMessage.success("添加成功");
loadTabs(resp.data);
});
})
.catch(() => {});
};
const loadTabs = docAppId => {
api.listApp().then(resp => {
tabsData.value = resp.data;
const length = tabsData.value.length;
if (length > 0) {
let targetId;
for (const id of tabsData.value) {
if (id === docAppId) {
targetId = id;
break;
}
}
if (!targetId) {
targetId = tabsData.value[0].id;
}
activeName.value = targetId;
activeTab(targetId);
]);
const activeName = ref(0);
const docAppId = ref(0);
const loading = ref(false);
// 表格对象
const { tableData, buttons: actionButtons } = useTable<any[]>();
const filterText = ref("");
const tableRows = computed(() => {
let search = filterText.value;
if (!search) {
return tableData.value;
}
search = search.toLowerCase();
return searchRow(search, tableData.value, searchContent, isFolder);
});
};
const searchRow = (search, rows, searchHandler, folderHandler) => {
if (!folderHandler) {
folderHandler = isFolder;
}
const ret = [];
for (const row of rows) {
// 找到分类
if (folderHandler(row)) {
if (searchHandler(search, row)) {
ret.push(row);
} else {
// 分类名字没找到,需要从子文档中找
const children = row.children || [];
const searchedChildren = searchRow(
search,
children,
searchHandler,
folderHandler
);
// 如果子文档中有
if (searchedChildren && searchedChildren.length > 0) {
const rowCopy = Object.assign({}, row);
rowCopy.children = searchedChildren;
ret.push(rowCopy);
}
}
} else {
// 不是分类且被找到
if (searchHandler(search, row)) {
ret.push(row);
}
}
}
return ret;
};
const loadContent = id => {
const data = {
docAppId: id
const isFolder = row => {
return row.isFolder === 1;
};
api.listDocTree(data).then(resp => {
tableData.value = resp.data;
});
};
loadTabs(0);
const searchContent = (searchText, row) => {
return (
(row.docName && row.docName.toLowerCase().indexOf(searchText) > -1) ||
(row.docTitle && row.docTitle.toLowerCase().indexOf(searchText) > -1)
);
};
// 表格字段定义
const tableColumns: PlusColumn[] = [
{
label: "文档标题",
prop: "docTitle"
},
{
label: "接口名",
prop: "docName"
},
{
label: "版本号",
prop: "docVersion",
width: 80
},
{
label: "描述",
prop: "description",
tableColumnProps: {
showOverflowTooltip: true
}
},
{
label: "发布状态",
prop: "isPublish",
valueType: "select",
width: 100,
options: [
{
label: "已发布",
value: YesOrNoEnum.YES,
color: "green"
},
{
label: "未发布",
value: YesOrNoEnum.NO,
color: "red"
}
],
renderHTML: (value, { row }) => {
if (row.isFolder) {
return "";
}
return value
? `<div style="color:green;">已发布</div>`
: `<div style="color:gray;">未发布</div>`;
}
},
{
width: 160,
label: "添加时间",
prop: "addTime"
},
{
width: 160,
label: "修改时间",
prop: "updateTime"
}
];
// 表格按钮定义
actionButtons.value = [
{
text: "发布",
confirm: {
options: { draggable: false },
popconfirmProps: { width: 300 },
message: params => {
const row = params.row;
return `确定要发布[${row.docTitle}]下所有接口吗?`;
}
},
props: (_: any) => ({
type: "success"
}),
onConfirm(params: ButtonsCallBackParams) {
const data = {
id: params.row.id,
isPublish: params.row.isPublish === 1 ? 0 : 1
};
api.publish(data).then(() => {
ElMessage.success("保存成功");
search();
});
},
show: (row: any) => row.isFolder === 1
},
{
text: "下线",
confirm: {
options: { draggable: false },
popconfirmProps: { width: 300 },
message: params => {
const row = params.row;
const opt = "下线";
return `确定要${opt}[${row.docTitle}]下所有接口吗?`;
}
},
props: {
type: "danger"
},
onConfirm(params: ButtonsCallBackParams) {
const data = {
id: params.row.id,
isPublish: 0
};
api.publish(data).then(() => {
ElMessage.success("下线成功");
search();
});
},
show: (row: any) => row.isFolder === 1
},
{
text: row => (row.isPublish ? "下线" : "发布"),
confirm: {
options: { draggable: false },
popconfirmProps: { width: 300 },
message: params => {
const row = params.row;
const opt = row.isPublish ? "下线" : "发布";
return `确定要${opt}[${row.docTitle}]吗?`;
}
},
props: (row: any) => ({
type: row.isPublish === 1 ? "danger" : "success"
}),
onConfirm(params: ButtonsCallBackParams) {
const data = {
id: params.row.id,
isPublish: params.row.isPublish === 1 ? 0 : 1
};
api.publish(data).then(() => {
ElMessage.success("保存成功");
search();
});
},
show: (row: any) => row.isFolder === 0
},
{
text: "同步",
confirm: {
options: { draggable: false },
popconfirmProps: { width: 300 },
message: params => {
const row = params.row;
return row.isFolder
? `确定要同步[${row.docTitle}]下所有接口吗?`
: `确定要同步[${row.docTitle}]吗?`;
}
},
props: (_: any) => ({
type: "primary"
}),
onConfirm(params: ButtonsCallBackParams) {
loading.value = true;
api
.syncDoc(params.row.id)
.then(() => {
loading.value = false;
ElMessage.success("同步成功");
search();
})
.catch(() => {
loading.value = false;
});
}
}
];
// 点击查询按钮
const handleSearch = () => {
search();
};
// 查询
const search = async () => {
loadContent(docAppId.value);
};
function handleSyncApi() {
ElMessageBox.confirm("确定要同步远程接口吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
loading.value = true;
api
.syncAppDoc(docAppId.value)
.then(() => {
loading.value = false;
ElMessage.success("同步成功");
search();
})
.catch(() => {
loading.value = false;
});
})
.catch(() => {});
}
const handleClick = data => {
const id = data.props.name;
activeTab(id);
};
const activeTab = id => {
docAppId.value = id;
loadContent(id);
};
const handleAddApp = () => {
ElMessageBox.prompt("请输入Torna应用token", "添加应用", {
confirmButtonText: "确定",
cancelButtonText: "取消",
inputPattern: /\w+/,
inputErrorMessage: "请输入Torna应用token"
})
.then(({ value }) => {
const data = {
tornaToken: value
};
api.addApp(data).then(resp => {
ElMessage.success("添加成功");
loadTabs(resp.data);
});
})
.catch(() => {});
};
const loadTabs = docAppId => {
api.listApp().then(resp => {
tabsData.value = resp.data;
const length = tabsData.value.length;
if (length > 0) {
let targetId;
for (const id of tabsData.value) {
if (id === docAppId) {
targetId = id;
break;
}
}
if (!targetId) {
targetId = tabsData.value[0].id;
}
activeName.value = targetId;
activeTab(targetId);
}
});
};
const searchRow = (search, rows, searchHandler, folderHandler) => {
if (!folderHandler) {
folderHandler = isFolder;
}
const ret = [];
for (const row of rows) {
// 找到分类
if (folderHandler(row)) {
if (searchHandler(search, row)) {
ret.push(row);
} else {
// 分类名字没找到,需要从子文档中找
const children = row.children || [];
const searchedChildren = searchRow(
search,
children,
searchHandler,
folderHandler
);
// 如果子文档中有
if (searchedChildren && searchedChildren.length > 0) {
const rowCopy = Object.assign({}, row);
rowCopy.children = searchedChildren;
ret.push(rowCopy);
}
}
} else {
// 不是分类且被找到
if (searchHandler(search, row)) {
ret.push(row);
}
}
}
return ret;
};
const loadContent = id => {
const data = {
docAppId: id
};
api.listDocTree(data).then(resp => {
tableData.value = resp.data;
});
};
onMounted(() => {
loadTabs(0);
});
return {
activeName,
handleClick,
handleAddApp,
handleSyncApi,
tabsData,
actionButtons,
tableColumns,
tableRows,
filterText,
loading,
handleSearch
};
}

View File

@@ -1,5 +1,11 @@
<script setup lang="ts">
import {
import { useDocList } from "./index";
import { Search } from "@element-plus/icons-vue";
defineOptions({
name: "DocList"
});
const {
activeName,
handleClick,
handleAddApp,
@@ -11,8 +17,7 @@ import {
filterText,
loading,
handleSearch
} from "./index";
import { Search } from "@element-plus/icons-vue";
} = useDocList();
</script>
<template>
<el-card v-loading="loading" shadow="never">

View File

@@ -1,5 +1,8 @@
<script setup lang="ts">
import { state, rules, columns, handleSubmit } from "./index";
defineOptions({
name: "DocSetting"
});
</script>
<template>

View File

@@ -41,6 +41,9 @@ import {
handleUpdateGroup,
settingGroupFormData
} from "@/views/isv/list/isvGroup";
defineOptions({
name: "IsvList"
});
</script>
<template>
<el-card shadow="never">

View File

@@ -17,6 +17,9 @@ import {
tableData
} from "./permGroup";
import PermGroupApi from "./permGroupApi.vue";
defineOptions({
name: "IsvPermPermGroup"
});
</script>
<template>
<el-card shadow="never">

View File

@@ -12,6 +12,9 @@ import {
} from "./permGroupApi";
import { ApiSelect } from "@/components/ApiSelect/index";
import { actionButtons } from "./permGroupApi";
defineOptions({
name: "IsvPermPermGroupApi"
});
</script>
<template>

View File

@@ -66,6 +66,9 @@ const onLogin = async (formEl: FormInstance | undefined) => {
message(t("login.pureLoginFail"), { type: "error" });
}
})
.catch(() => {
loading.value = false;
})
.finally(() => (loading.value = false));
}
});

View File

@@ -18,6 +18,9 @@ import {
tableData,
total
} from "./index";
defineOptions({
name: "ServeApi"
});
</script>
<template>
<el-card shadow="never">

View File

@@ -7,6 +7,7 @@ import { usePublicHooks } from "../hooks";
const props = withDefaults(defineProps<FormProps>(), {
formInline: () => ({
id: 0,
higherDeptOptions: [],
parentId: 0,
name: "",
@@ -71,34 +72,6 @@ defineExpose({ getRef });
/>
</el-form-item>
</re-col>
<re-col :value="12" :xs="24" :sm="24">
<el-form-item label="部门负责人">
<el-input
v-model="newFormInline.principal"
clearable
placeholder="请输入部门负责人"
/>
</el-form-item>
</re-col>
<re-col :value="12" :xs="24" :sm="24">
<el-form-item label="手机号" prop="phone">
<el-input
v-model="newFormInline.phone"
clearable
placeholder="请输入手机号"
/>
</el-form-item>
</re-col>
<re-col :value="12" :xs="24" :sm="24">
<el-form-item label="邮箱" prop="email">
<el-input
v-model="newFormInline.email"
clearable
placeholder="请输入邮箱"
/>
</el-form-item>
</re-col>
<re-col :value="12" :xs="24" :sm="24">
<el-form-item label="排序">

View File

@@ -76,7 +76,7 @@ function onFullscreen() {
</el-form>
<PureTableBar
title="部门管理(仅演示,操作后不生效)"
title=""
:columns="columns"
:tableRef="tableRef?.getTableRef()"
@refresh="onSearch"

View File

@@ -2,7 +2,7 @@ import dayjs from "dayjs";
import editForm from "../form.vue";
import { handleTree } from "@/utils/tree";
import { message } from "@/utils/message";
import { getDeptList } from "@/api/system";
import { addDept, updateDept, getDeptList } from "@/api/system";
import { usePublicHooks } from "../../hooks";
import { addDialog } from "@/components/ReDialog";
import { reactive, ref, onMounted, h } from "vue";
@@ -95,7 +95,7 @@ export function useDept() {
if (!treeList || !treeList.length) return;
const newTreeList = [];
for (let i = 0; i < treeList.length; i++) {
treeList[i].disabled = treeList[i].status === 0 ? true : false;
treeList[i].disabled = treeList[i].status === 0;
formatHigherDeptOptions(treeList[i].children);
newTreeList.push(treeList[i]);
}
@@ -107,6 +107,7 @@ export function useDept() {
title: `${title}部门`,
props: {
formInline: {
id: row?.id ?? 0,
higherDeptOptions: formatHigherDeptOptions(cloneDeep(dataList.value)),
parentId: row?.parentId ?? 0,
name: row?.name ?? "",
@@ -127,23 +128,28 @@ export function useDept() {
beforeSure: (done, { options }) => {
const FormRef = formRef.value.getRef();
const curData = options.props.formInline as FormItemProps;
function chores() {
message(`${title}了部门名称为${curData.name}的这条数据`, {
type: "success"
});
done(); // 关闭弹框
onSearch(); // 刷新表格数据
}
FormRef.validate(valid => {
if (valid) {
console.log("curData", curData);
// console.log("curData", curData);
// 表单规则校验通过
if (title === "新增") {
// 实际开发先调用新增接口,再进行下面操作
chores();
addDept(curData).then(_ => {
message("添加成功", {
type: "success"
});
done(); // 关闭弹框
onSearch(); // 刷新表格数据
});
} else {
// 实际开发先调用修改接口,再进行下面操作
chores();
updateDept(curData).then(_ => {
message("修改成功", {
type: "success"
});
done(); // 关闭弹框
onSearch(); // 刷新表格数据
});
}
}
});

View File

@@ -1,4 +1,5 @@
interface FormItemProps {
id: number;
higherDeptOptions: Record<string, unknown>[];
parentId: number;
name: string;

View File

@@ -19,6 +19,7 @@ import {
const props = withDefaults(defineProps<FormProps>(), {
formInline: () => ({
id: 0,
menuType: 0,
higherMenuOptions: [],
parentId: 0,

View File

@@ -66,7 +66,7 @@ function onFullscreen() {
</el-form>
<PureTableBar
title="菜单管理(仅演示,操作后不生效)"
title=""
:columns="columns"
:isExpandAll="false"
:tableRef="tableRef?.getTableRef()"
@@ -124,7 +124,8 @@ function onFullscreen() {
新增
</el-button>
<el-popconfirm
:title="`是否确认删除菜单名称为${transformI18n(row.title)}的这条数据${row?.children?.length > 0 ? '。注意下级菜单也会一并删除,请谨慎操作' : ''}`"
:title="`确认删除 [${transformI18n(row.title)}] ? ${row?.children?.length > 0 ? '。注意下级菜单也会一并删除,请谨慎操作' : ''}`"
width="250"
@confirm="handleDelete(row)"
>
<template #reference>

View File

@@ -1,7 +1,7 @@
import editForm from "../form.vue";
import { handleTree } from "@/utils/tree";
import { message } from "@/utils/message";
import { getMenuList } from "@/api/system";
import { getMenuList, addMenu, updateMenu, deleteMenu } from "@/api/system";
import { transformI18n } from "@/plugins/i18n";
import { addDialog } from "@/components/ReDialog";
import { reactive, ref, onMounted, h } from "vue";
@@ -136,6 +136,7 @@ export function useMenu() {
title: `${title}菜单`,
props: {
formInline: {
id: row?.id ?? 0,
menuType: row?.menuType ?? 0,
higherMenuOptions: formatHigherMenuOptions(cloneDeep(dataList.value)),
parentId: row?.parentId ?? 0,
@@ -152,7 +153,7 @@ export function useMenu() {
activePath: row?.activePath ?? "",
auths: row?.auths ?? "",
frameSrc: row?.frameSrc ?? "",
frameLoading: row?.frameLoading ?? true,
frameLoading: row?.frameLoading ?? 1,
keepAlive: row?.keepAlive ?? false,
hiddenTag: row?.hiddenTag ?? false,
fixedTag: row?.fixedTag ?? false,
@@ -169,26 +170,25 @@ export function useMenu() {
beforeSure: (done, { options }) => {
const FormRef = formRef.value.getRef();
const curData = options.props.formInline as FormItemProps;
function chores() {
message(
`${title}了菜单名称为${transformI18n(curData.title)}的这条数据`,
{
type: "success"
}
);
done(); // 关闭弹框
onSearch(); // 刷新表格数据
}
FormRef.validate(valid => {
if (valid) {
console.log("curData", curData);
// 表单规则校验通过
if (title === "新增") {
// 实际开发先调用新增接口,再进行下面操作
chores();
addMenu(curData).then(_ => {
message("添加成功", {
type: "success"
});
done(); // 关闭弹框
onSearch(); // 刷新表格数据
});
} else {
// 实际开发先调用修改接口,再进行下面操作
chores();
updateMenu(curData).then(_ => {
message("添加成功", {
type: "success"
});
done(); // 关闭弹框
onSearch(); // 刷新表格数据
});
}
}
});
@@ -197,10 +197,12 @@ export function useMenu() {
}
function handleDelete(row) {
message(`您删除了菜单名称为${transformI18n(row.title)}的这条数据`, {
type: "success"
deleteMenu(row).then(_ => {
message("删除成功", {
type: "success"
});
onSearch(); // 刷新表格数据
});
onSearch();
}
onMounted(() => {

View File

@@ -1,4 +1,5 @@
interface FormItemProps {
id: number;
/** 菜单类型0代表菜单、1代表iframe、2代表外链、3代表按钮*/
menuType: number;
higherMenuOptions: Record<string, unknown>[];

View File

@@ -147,7 +147,7 @@ onMounted(() => {
<PureTableBar
:class="[isShow && !deviceDetection() ? '!w-[60vw]' : 'w-full']"
style="transition: width 220ms cubic-bezier(0.4, 0, 0.2, 1)"
title="角色管理(仅演示,操作后不生效)"
title=""
:columns="columns"
@refresh="onSearch"
>

View File

@@ -16,7 +16,8 @@ import {
getRoleList,
getRoleMenu,
getRoleMenuIds,
updateRole
updateRole,
saveRoleMenu
} from "@/api/system";
import { type Ref, reactive, ref, onMounted, h, toRaw, watch } from "vue";
import { StatusEnum } from "@/model/enums";
@@ -245,11 +246,17 @@ export function useRole(treeRef: Ref) {
/** 菜单权限-保存 */
function handleSave() {
const { id, name } = curRow.value;
const { id } = curRow.value;
// 根据用户 id 调用实际项目中菜单权限修改接口
console.log(id, treeRef.value.getCheckedKeys());
message(`角色名称为${name}的菜单权限修改成功`, {
type: "success"
// console.log(id, treeRef.value.getCheckedKeys());
const data = {
roleId: id,
resourceIds: treeRef.value.getCheckedKeys()
};
saveRoleMenu(data).then(_ => {
message(`修改成功`, {
type: "success"
});
});
}

View File

@@ -7,6 +7,7 @@ import { usePublicHooks } from "../../hooks";
const props = withDefaults(defineProps<FormProps>(), {
formInline: () => ({
id: 0,
title: "新增",
higherDeptOptions: [],
parentId: 0,
@@ -15,7 +16,7 @@ const props = withDefaults(defineProps<FormProps>(), {
password: "",
phone: "",
email: "",
sex: "",
gender: 0,
status: 1,
remark: ""
})
@@ -24,10 +25,14 @@ const props = withDefaults(defineProps<FormProps>(), {
const sexOptions = [
{
value: 0,
label: ""
label: "未知"
},
{
value: 1,
label: "男"
},
{
value: 2,
label: "女"
}
];
@@ -105,7 +110,7 @@ defineExpose({ getRef });
<re-col :value="12" :xs="24" :sm="24">
<el-form-item label="用户性别">
<el-select
v-model="newFormInline.sex"
v-model="newFormInline.gender"
placeholder="请选择用户性别"
class="w-full"
clearable

View File

@@ -35,7 +35,8 @@ const {
deviceDetection,
onSearch,
resetForm,
onbatchDel,
onBatchDisable,
onBatchEnable,
openDialog,
onTreeSelect,
handleUpdate,
@@ -110,11 +111,7 @@ const {
</el-form-item>
</el-form>
<PureTableBar
title="用户管理(仅演示,操作后不生效)"
:columns="columns"
@refresh="onSearch"
>
<PureTableBar title="" :columns="columns" @refresh="onSearch">
<template #buttons>
<el-button
type="primary"
@@ -141,10 +138,17 @@ const {
取消选择
</el-button>
</div>
<el-popconfirm title="是否确认删除?" @confirm="onbatchDel">
<el-popconfirm title="是否确认启用?" @confirm="onBatchEnable">
<template #reference>
<el-button type="success" text class="mr-1">
批量启用
</el-button>
</template>
</el-popconfirm>
<el-popconfirm title="是否确认禁用?" @confirm="onBatchDisable">
<template #reference>
<el-button type="danger" text class="mr-1">
批量删除
批量禁用
</el-button>
</template>
</el-popconfirm>
@@ -180,6 +184,27 @@ const {
>
修改
</el-button>
<el-button
:class="buttonClass"
link
type="primary"
:size="size"
:icon="useRenderIcon(Role)"
@click="handleRole(row)"
>
分配角色
</el-button>
<el-button
:class="buttonClass"
link
type="primary"
:size="size"
:icon="useRenderIcon(Password)"
@click="handleReset(row)"
>
重置密码
</el-button>
<!-- 不支持删除
<el-popconfirm
:title="`是否确认删除用户编号为${row.id}的这条数据`"
@confirm="handleDelete(row)"
@@ -195,7 +220,8 @@ const {
删除
</el-button>
</template>
</el-popconfirm>
</el-popconfirm>-->
<!--
<el-dropdown>
<el-button
class="ml-3 mt-[2px]"
@@ -219,33 +245,10 @@ const {
上传头像
</el-button>
</el-dropdown-item>
<el-dropdown-item>
<el-button
:class="buttonClass"
link
type="primary"
:size="size"
:icon="useRenderIcon(Password)"
@click="handleReset(row)"
>
重置密码
</el-button>
</el-dropdown-item>
<el-dropdown-item>
<el-button
:class="buttonClass"
link
type="primary"
:size="size"
:icon="useRenderIcon(Role)"
@click="handleRole(row)"
>
分配角色
</el-button>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
-->
</template>
</pure-table>
</template>

View File

@@ -12,34 +12,42 @@ import type { PaginationProps } from "@pureadmin/table";
import ReCropperPreview from "@/components/ReCropperPreview";
import type { FormItemProps, RoleFormItemProps } from "../utils/types";
import {
deviceDetection,
getKeyList,
isAllEmpty,
hideTextAtIndex,
deviceDetection
isAllEmpty
} from "@pureadmin/utils";
import {
getRoleIds,
addUser,
getAllRoleList,
getDeptList,
getRoleIds,
getUserList,
getAllRoleList
resetPassword,
setUserRole,
updateStatusBatch,
updateUser,
updateUserStatus
} from "@/api/system";
import {
ElForm,
ElInput,
ElFormItem,
ElProgress,
ElMessageBox
ElInput,
ElMessageBox,
ElProgress
} from "element-plus";
import {
type Ref,
h,
ref,
toRaw,
watch,
computed,
h,
onMounted,
reactive,
onMounted
ref,
type Ref,
toRaw,
watch
} from "vue";
import { StatusEnum } from "@/model/enums";
import CryptoJS from "crypto-js";
export function useUser(tableRef: Ref, treeRef: Ref) {
const form = reactive({
@@ -79,20 +87,20 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
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: "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",
@@ -105,15 +113,15 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
},
{
label: "性别",
prop: "sex",
prop: "gender",
minWidth: 90,
cellRenderer: ({ row, props }) => (
<el-tag
size={props.size}
type={row.sex === 1 ? "danger" : null}
type={row.gender === 2 ? "danger" : null}
effect="plain"
>
{row.sex === 1 ? "女" : "男"}
{row.gender === 0 ? "未知" : row.gender === 2 ? "女" : "男"}
</el-tag>
)
},
@@ -157,7 +165,7 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
{
label: "操作",
fixed: "right",
width: 180,
width: 260,
slot: "operation"
}
];
@@ -185,7 +193,7 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
const curScore = ref();
const roleOptions = ref([]);
function onChange({ row, index }) {
function onChange({ row }) {
ElMessageBox.confirm(
`确认要<strong>${
row.status === 0 ? "停用" : "启用"
@@ -202,28 +210,16 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
}
)
.then(() => {
switchLoadMap.value[index] = Object.assign(
{},
switchLoadMap.value[index],
{
loading: true
}
);
setTimeout(() => {
switchLoadMap.value[index] = Object.assign(
{},
switchLoadMap.value[index],
{
loading: false
}
);
message("已成功修改用户状态", {
updateUserStatus(row).then(_ => {
message("操作成功", {
type: "success"
});
}, 300);
});
})
.catch(() => {
row.status === 0 ? (row.status = 1) : (row.status = 0);
row.status === StatusEnum.DISABLE
? (row.status = StatusEnum.ENABLE)
: (row.status = StatusEnum.DISABLE);
});
}
@@ -258,16 +254,31 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
tableRef.value.getTableRef().clearSelection();
}
/** 批量删除 */
function onbatchDel() {
/** 批量禁用 */
function onBatchDisable() {
// 返回当前选中的行
const curSelected = tableRef.value.getTableRef().getSelectionRows();
// 接下来根据实际业务通过选中行的某项数据比如下面的id调用接口进行批量删除
message(`已删除用户编号为 ${getKeyList(curSelected, "id")} 的数据`, {
type: "success"
doUpdateStatusBatch(getKeyList(curSelected, "id"), StatusEnum.DISABLE);
}
/** 批量启用 */
function onBatchEnable() {
// 返回当前选中的行
const curSelected = tableRef.value.getTableRef().getSelectionRows();
doUpdateStatusBatch(getKeyList(curSelected, "id"), StatusEnum.ENABLE);
}
function doUpdateStatusBatch(ids: any, status: number) {
updateStatusBatch({
ids: ids,
status: status
}).then(_ => {
message("操作成功", {
type: "success"
});
tableRef.value.getTableRef().clearSelection();
onSearch();
});
tableRef.value.getTableRef().clearSelection();
onSearch();
}
async function onSearch() {
@@ -301,7 +312,7 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
if (!treeList || !treeList.length) return;
const newTreeList = [];
for (let i = 0; i < treeList.length; i++) {
treeList[i].disabled = treeList[i].status === 0 ? true : false;
treeList[i].disabled = treeList[i].status === 0;
formatHigherDeptOptions(treeList[i].children);
newTreeList.push(treeList[i]);
}
@@ -313,15 +324,16 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
title: `${title}用户`,
props: {
formInline: {
id: row?.id ?? 0,
title,
higherDeptOptions: formatHigherDeptOptions(higherDeptOptions.value),
parentId: row?.dept.id ?? 0,
parentId: row?.dept?.id ?? 0,
nickname: row?.nickname ?? "",
username: row?.username ?? "",
password: row?.password ?? "",
phone: row?.phone ?? "",
email: row?.email ?? "",
sex: row?.sex ?? "",
gender: row?.gender ?? 0,
status: row?.status ?? 1,
remark: row?.remark ?? ""
}
@@ -335,23 +347,31 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
beforeSure: (done, { options }) => {
const FormRef = formRef.value.getRef();
const curData = options.props.formInline as FormItemProps;
function chores() {
message(`${title}了用户名称为${curData.username}的这条数据`, {
type: "success"
});
done(); // 关闭弹框
onSearch(); // 刷新表格数据
}
FormRef.validate(valid => {
if (valid) {
console.log("curData", curData);
// 表单规则校验通过
if (title === "新增") {
// 实际开发先调用新增接口,再进行下面操作
chores();
const data = {
password: ""
};
Object.assign(data, curData);
const pwd = curData.password;
data.password = CryptoJS.SHA256(pwd).toString();
addUser(data).then(_ => {
message("添加成功", {
type: "success"
});
done(); // 关闭弹框
onSearch(); // 刷新表格数据
});
} else {
// 实际开发先调用修改接口,再进行下面操作
chores();
updateUser(curData).then(_ => {
message("修改成功", {
type: "success"
});
done(); // 关闭弹框
onSearch(); // 刷新表格数据
});
}
}
});
@@ -450,13 +470,18 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
ruleFormRef.value.validate(valid => {
if (valid) {
// 表单规则校验通过
message(`已成功重置 ${row.username} 用户的密码`, {
type: "success"
const pwd = pwdForm.newPwd;
const hash = CryptoJS.SHA256(pwd).toString();
resetPassword({
userId: row.id,
passwordHash: hash
}).then(_ => {
message(`已成功重置 ${row.username} 用户的密码`, {
type: "success"
});
done(); // 关闭弹框
onSearch(); // 刷新表格数据
});
console.log(pwdForm.newPwd);
// 根据实际业务使用pwdForm.newPwd和row里的某些字段去调用重置用户密码接口即可
done(); // 关闭弹框
onSearch(); // 刷新表格数据
}
});
}
@@ -485,9 +510,16 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
contentRenderer: () => h(roleForm),
beforeSure: (done, { options }) => {
const curData = options.props.formInline as RoleFormItemProps;
console.log("curIds", curData.ids);
// 根据实际业务使用curData.ids和row里的某些字段去调用修改角色接口即可
done(); // 关闭弹框
setUserRole({
userId: row.id,
roleIds: curData.ids
}).then(_ => {
message("操作成功", {
type: "success"
});
done(); // 关闭弹框
});
}
});
}
@@ -519,7 +551,8 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
deviceDetection,
onSearch,
resetForm,
onbatchDel,
onBatchDisable,
onBatchEnable,
openDialog,
onTreeSelect,
handleUpdate,

View File

@@ -9,7 +9,7 @@ interface FormItemProps {
password: string;
phone: string | number;
email: string;
sex: string | number;
gender: string | number;
status: number;
dept?: {
id?: number;