refactor: keepalive无效问题修复和代码vue社区代码规范调整

Former-commit-id: f661982d54f1738ff9739f1afc993181a466f052
This commit is contained in:
郝先瑞
2022-04-24 00:08:25 +08:00
parent c0b96bfab8
commit 47ed525fcd
71 changed files with 2814 additions and 1912 deletions

View File

@@ -1,3 +1,174 @@
<!-- setup 无法设置组件名称组件名称keepAlive必须 -->
<script lang="ts">
export default {
name: "client"
};
</script>
<script setup lang="ts">
import {
listClientPages,
getClientFormDetial,
addClient,
updateClient,
deleteClients,
} from "@/api/system/client";
import { Search, Plus, Edit, Refresh, Delete } from "@element-plus/icons-vue";
import { onMounted, reactive, getCurrentInstance, ref, toRefs } from "vue";
import { ElForm, ElMessage, ElMessageBox } from "element-plus";
import { ClientFormData, ClientItem, ClientQueryParam, Option } from "@/types";
const { proxy }: any = getCurrentInstance();
const queryFormRef = ref(ElForm);
const dataFormRef = ref(ElForm);
const state = reactive({
loading: true,
// 选中ID数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
queryParams: {
pageNum: 1,
pageSize: 10,
} as ClientQueryParam,
clientList: [] as ClientItem[],
total: 0,
dialog: {
title: "",
visible: false,
type: "create",
},
formData: {} as ClientFormData,
rules: {
clientId: [
{ required: true, message: "客户端ID不能为空", trigger: "blur" },
],
},
authorizedGrantTypesOptions: [] as Option[],
checkedAuthorizedGrantTypes: [] as string[]
});
const {
loading,
ids,
multiple,
queryParams,
clientList,
total,
dialog,
formData,
rules,
authorizedGrantTypesOptions,
checkedAuthorizedGrantTypes,
} = toRefs(state);
function handleQuery() {
listClientPages(state.queryParams).then(({ data }) => {
state.clientList = data.list;
state.total = data.total;
state.loading = false;
});
}
function resetQuery() {
queryFormRef.value.resetFields();
handleQuery();
}
function handleSelectionChange(selection: any) {
state.ids = selection.map((item: any) => item.clientId);
state.single = selection.length !== 1;
state.multiple = !selection.length;
}
function handleAdd() {
proxy.$listDictsByCode("grant_type").then((response: any) => {
state.authorizedGrantTypesOptions = response.data;
});
state.dialog = {
title: "添加客户端",
visible: true,
type: "create",
};
}
function handleUpdate(row: any) {
state.dialog = {
title: "修改客户端",
visible: true,
type: "edit",
};
const clientId = row.clientId || ids;
proxy.$listDictsByCode("grant_type").then((res: any) => {
state.authorizedGrantTypesOptions = res.data;
getClientFormDetial(clientId).then(({ data }) => {
state.formData = data;
state.checkedAuthorizedGrantTypes = data.authorizedGrantTypes?.split(",");
});
});
}
function submitForm() {
dataFormRef.value.validate((isvalid: boolean) => {
if (isvalid) {
state.formData.authorizedGrantTypes =
state.checkedAuthorizedGrantTypes.join(",");
if (state.dialog.type == "edit") {
updateClient(state.formData.clientId, state.formData).then(
() => {
ElMessage.success("修改成功");
state.dialog.visible = false;
cancel();
handleQuery();
}
);
} else {
addClient(state.formData).then(() => {
ElMessage.success("新增成功");
cancel();
handleQuery();
});
}
}
});
}
function resetForm() {
dataFormRef.value.resetFields();
state.checkedAuthorizedGrantTypes = [];
}
function cancel() {
resetForm();
state.dialog.visible = false;
}
function handleDelete(row: any) {
const clientIds = [row.clientId || ids].join(",");
ElMessageBox.confirm("确认删除已选中的数据项?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
deleteClients(clientIds).then(() => {
ElMessage.success("删除成功");
handleQuery();
});
})
.catch(() => ElMessage.info("已取消删除"));
}
onMounted(() => {
handleQuery();
});
</script>
<template>
<div class="app-container">
<!-- 搜索表单 -->
@@ -126,168 +297,4 @@
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import {
listClientPages,
getClientFormDetial,
addClient,
updateClient,
deleteClients,
} from "@/api/system/client";
import { Search, Plus, Edit, Refresh, Delete } from "@element-plus/icons-vue";
import { onMounted, reactive, getCurrentInstance, ref, toRefs } from "vue";
import { ElForm, ElMessage, ElMessageBox } from "element-plus";
import { ClientFormData, ClientItem, ClientQueryParam, Option } from "@/types";
const { proxy }: any = getCurrentInstance();
const queryFormRef = ref(ElForm);
const dataFormRef = ref(ElForm);
const state = reactive({
loading: true,
// 选中ID数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
queryParams: {
pageNum: 1,
pageSize: 10,
} as ClientQueryParam,
clientList: [] as ClientItem[],
total: 0,
dialog: {
title: "",
visible: false,
type: "create",
},
formData: {} as ClientFormData,
rules: {
clientId: [
{ required: true, message: "客户端ID不能为空", trigger: "blur" },
],
},
authorizedGrantTypesOptions: [] as Option[],
checkedAuthorizedGrantTypes: [] as string[],
});
const {
loading,
ids,
multiple,
queryParams,
clientList,
total,
dialog,
formData,
rules,
authorizedGrantTypesOptions,
checkedAuthorizedGrantTypes,
} = toRefs(state);
function handleQuery() {
listClientPages(state.queryParams).then(({ data }) => {
state.clientList = data.list;
state.total = data.total;
state.loading = false;
});
}
function resetQuery() {
queryFormRef.value.resetFields();
handleQuery();
}
function handleSelectionChange(selection: any) {
state.ids = selection.map((item: any) => item.clientId);
state.single = selection.length !== 1;
state.multiple = !selection.length;
}
function handleAdd() {
proxy.$listDictsByCode("grant_type").then((response: any) => {
state.authorizedGrantTypesOptions = response.data;
});
state.dialog = {
title: "添加客户端",
visible: true,
type: "create",
};
}
function handleUpdate(row: any) {
state.dialog = {
title: "修改客户端",
visible: true,
type: "edit",
};
const clientId = row.clientId || ids;
proxy.$listDictsByCode("grant_type").then((res: any) => {
state.authorizedGrantTypesOptions = res.data;
getClientFormDetial(clientId).then(({ data }) => {
state.formData = data;
state.checkedAuthorizedGrantTypes = data.authorizedGrantTypes?.split(",");
});
});
}
function submitForm() {
dataFormRef.value.validate((isvalid: boolean) => {
if (isvalid) {
state.formData.authorizedGrantTypes =
state.checkedAuthorizedGrantTypes.join(",");
if (state.dialog.type == "edit") {
updateClient(state.formData.clientId, state.formData).then(
() => {
ElMessage.success("修改成功");
state.dialog.visible = false;
cancel();
handleQuery();
}
);
} else {
addClient(state.formData).then(() => {
ElMessage.success("新增成功");
cancel();
handleQuery();
});
}
}
});
}
function resetForm() {
dataFormRef.value.resetFields();
state.checkedAuthorizedGrantTypes = [];
}
function cancel() {
resetForm();
state.dialog.visible = false;
}
function handleDelete(row: any) {
const clientIds = [row.clientId || ids].join(",");
ElMessageBox.confirm("确认删除已选中的数据项?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
deleteClients(clientIds).then(() => {
ElMessage.success("删除成功");
handleQuery();
});
})
.catch(() => ElMessage.info("已取消删除"));
}
onMounted(() => {
handleQuery();
});
</script>
</template>

View File

@@ -1,85 +1,9 @@
<template>
<div class="app-container">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item>
<el-button type="success" :icon="Plus" @click="handleAdd">新增</el-button>
<el-button type="danger" :icon="Delete" :disabled="single" @click="handleDelete">删除
</el-button>
</el-form-item>
<el-form-item prop="name">
<el-input v-model="queryParams.name" placeholder="请输入部门名称" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item prop="status">
<el-select v-model="queryParams.status" placeholder="部门状态" clearable>
<el-option :value="1" label="正常" />
<el-option :value="0" label="禁用" />
</el-select>
</el-form-item>
<el-form-item>
<el-button class="filter-item" type="primary" :icon="Search" @click="handleQuery">
搜索
</el-button>
<el-button :icon="Refresh" @click="resetQuery"> 重置 </el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="deptList" row-key="id" default-expand-all
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column prop="name" label="部门名称" />
<el-table-column prop="status" label="状态" width="100">
<template #default="scope">
<el-tag v-if="scope.row.status == 1" type="success">正常</el-tag>
<el-tag v-else type="info">禁用</el-tag>
</template>
</el-table-column>
<el-table-column prop="sort" label="显示排序" width="200" />
<el-table-column label="操作" align="center" width="150">
<template #default="scope">
<el-button type="primary" :icon="Edit" circle plain @click.stop="handleUpdate(scope.row)">
</el-button>
<el-button type="success" :icon="Plus" circle plain @click.stop="handleAdd(scope.row)">
</el-button>
<el-button type="danger" :icon="Delete" circle plain @click.stop="handleDelete(scope.row)">
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 添加或修改部门对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="600px" @closed="cancel">
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="80px">
<el-form-item label="上级部门" prop="parentId">
<el-tree-select v-model="formData.parentId" placeholder="选择上级部门" :data="deptOptions" filterable check-strictly />
</el-form-item>
<el-form-item label="部门名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入部门名称" />
</el-form-item>
<el-form-item label="显示排序" prop="sort">
<el-input-number v-model="formData.sort" controls-position="right" style="width: 100px" :min="0" />
</el-form-item>
<el-form-item label="部门状态">
<el-radio-group v-model="formData.status">
<el-radio :label="1">正常</el-radio>
<el-radio :label="0">禁用</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<!-- setup 无法设置组件名称组件名称keepAlive必须 -->
<script lang="ts">
export default {
name: "dept"
};
</script>
<script setup lang="ts">
// Vue依赖
@@ -92,7 +16,7 @@ import {
updateDept,
addDept,
listSelectDepartments,
listTableDepartments,
listTableDepartments
} from "@/api/system/dept";
// 组件依赖
@@ -195,7 +119,7 @@ async function loadDeptData() {
*/
function handleAdd(row: any) {
loadDeptData();
state.formData.id=undefined
state.formData.id = undefined
state.formData.parentId = row.id;
state.dialog = {
title: "添加部门",
@@ -278,3 +202,85 @@ onMounted(() => {
handleQuery();
});
</script>
<template>
<div class="app-container">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item>
<el-button type="success" :icon="Plus" @click="handleAdd">新增</el-button>
<el-button type="danger" :icon="Delete" :disabled="single" @click="handleDelete">删除
</el-button>
</el-form-item>
<el-form-item prop="name">
<el-input v-model="queryParams.name" placeholder="请输入部门名称" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item prop="status">
<el-select v-model="queryParams.status" placeholder="部门状态" clearable>
<el-option :value="1" label="正常" />
<el-option :value="0" label="禁用" />
</el-select>
</el-form-item>
<el-form-item>
<el-button class="filter-item" type="primary" :icon="Search" @click="handleQuery">
搜索
</el-button>
<el-button :icon="Refresh" @click="resetQuery"> 重置 </el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="deptList" row-key="id" default-expand-all
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column prop="name" label="部门名称" />
<el-table-column prop="status" label="状态" width="100">
<template #default="scope">
<el-tag v-if="scope.row.status == 1" type="success">正常</el-tag>
<el-tag v-else type="info">禁用</el-tag>
</template>
</el-table-column>
<el-table-column prop="sort" label="显示排序" width="200" />
<el-table-column label="操作" align="center" width="150">
<template #default="scope">
<el-button type="primary" :icon="Edit" circle plain @click.stop="handleUpdate(scope.row)">
</el-button>
<el-button type="success" :icon="Plus" circle plain @click.stop="handleAdd(scope.row)">
</el-button>
<el-button type="danger" :icon="Delete" circle plain @click.stop="handleDelete(scope.row)">
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 添加或修改部门对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="600px" @closed="cancel">
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="80px">
<el-form-item label="上级部门" prop="parentId">
<el-tree-select v-model="formData.parentId" placeholder="选择上级部门" :data="deptOptions" filterable check-strictly />
</el-form-item>
<el-form-item label="部门名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入部门名称" />
</el-form-item>
<el-form-item label="显示排序" prop="sort">
<el-input-number v-model="formData.sort" controls-position="right" style="width: 100px" :min="0" />
</el-form-item>
<el-form-item label="部门状态">
<el-radio-group v-model="formData.status">
<el-radio :label="1">正常</el-radio>
<el-radio :label="0">禁用</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>

View File

@@ -1,3 +1,10 @@
<!-- setup 无法设置组件名称组件名称keepAlive必须 -->
<script lang="ts">
export default {
name: "dict"
};
</script>
<template>
<div class="app-container">
<!-- 搜索表单 -->

View File

@@ -57,26 +57,30 @@
<el-input v-model="formData.name" placeholder="请输入菜单名称" />
</el-form-item>
<el-form-item label="是否外链">
<el-radio-group v-model="isExternalPath">
<el-radio :label="false"></el-radio>
<el-radio :label="true"></el-radio>
<el-form-item label="菜单类型">
<el-radio-group v-model="formData.type" @change="handleMenuTypeChange">
<el-radio label="MENU">菜单</el-radio>
<el-radio label="CATALOG">目录</el-radio>
<el-radio label="EXTLINK">外链</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="isExternalPath" label="外链地址" prop="path">
<!-- 路由路径(浏览器地址栏显示) -->
<el-form-item v-if="formData.type == 'EXTLINK'" label="外链地址" prop="path">
<el-input v-model="formData.path" placeholder="请输入外链完整路径" />
</el-form-item>
<el-form-item v-if="!isExternalPath" label="页面路径" prop="component">
<el-form-item v-else label="路由路径" prop="path">
<el-input v-if="formData.type == 'CATALOG'" v-model="formData.path" placeholder="/system (注意:目录以/开头)" />
<el-input v-else v-model="formData.path" placeholder="user" />
</el-form-item>
<!-- 组件页面完整路径 -->
<el-form-item v-if="formData.type == 'MENU'" label="组件路径" prop="component">
<el-input v-model="formData.component" placeholder="system/user/index" style="width: 95%">
<template v-if="formData.parentId != '0'" #prepend>src/views/</template>
<template v-if="formData.parentId != '0'" #append>.vue</template>
</el-input>
<el-tooltip effect="dark" content="请输入组件路径,如果是父组件填写 Layout 即可" placement="right">
<i class="el-icon-info" style="margin-left: 10px; color: darkseagreen"></i>
</el-tooltip>
</el-form-item>
<el-form-item label="图标" prop="icon">
@@ -93,6 +97,10 @@
</el-popover>
</el-form-item>
<el-form-item label="跳转路由">
<el-input v-model="formData.redirect" placeholder="跳转路由路径" maxlength="50" />
</el-form-item>
<el-form-item label="状态">
<el-radio-group v-model="formData.visible">
<el-radio :label="1">显示</el-radio>
@@ -104,9 +112,7 @@
<el-input-number v-model="formData.sort" style="width: 100px" controls-position="right" :min="0" />
</el-form-item>
<el-form-item label="跳转路径">
<el-input v-model="formData.redirect" placeholder="请输入跳转路径" maxlength="50" />
</el-form-item>
</el-form>
<template #footer>
@@ -125,7 +131,6 @@ import { reactive, ref, onMounted, toRefs } from "vue";
import { Search, Plus, Edit, Refresh, Delete } from "@element-plus/icons-vue";
import { ElForm, ElMessage, ElMessageBox, ElPopover } from "element-plus";
import { isExternal } from "@/utils/validate";
import {
Dialog,
Option,
@@ -164,20 +169,28 @@ const state = reactive({
dialog: { visible: false } as Dialog,
formData: {
parentId: "0",
name: '',
visible: 1,
sort: 1,
component: "Layout",
component: 'Layout',
type: 'MENU'
} as MenuFormData,
rules: {
parentId: [{ required: true, message: "请选择顶级菜单", trigger: "blur" }],
name: [{ required: true, message: "请输入菜单名称", trigger: "blur" }],
component: [{ required: true, message: "请输入页面路径", trigger: "blur" }],
type: [{ required: true, message: "请选择菜单类型", trigger: "blur" }],
path: [{ required: true, message: "请输入路由路径", trigger: "blur" }],
component: [{ required: true, message: "请输入组件完整路径", trigger: "blur" }]
},
menuOptions: [] as Option[],
currentRow: undefined,
isExternalPath: false,
// Icon选择器显示状态
iconSelectVisible: false
iconSelectVisible: false,
cacheData: {
menuType: '',
menuPath: ''
}
});
const {
@@ -188,8 +201,8 @@ const {
formData,
rules,
menuOptions,
isExternalPath,
iconSelectVisible
iconSelectVisible,
cacheData
} = toRefs(state);
/**
@@ -237,26 +250,29 @@ async function handleAdd(row: any) {
title: "添加菜单",
visible: true
};
if (row.id) {
// 行点击新增
if (row.id) { // 行点击新增
state.formData.parentId = row.id;
if (row.id == '0') {
state.formData.component = "Layout";
state.formData.type = 'CATALOG';
} else {
state.formData.component = undefined;
state.formData.type = 'MENU';
}
} else {
} else { // 工具栏新增
if (state.currentRow) {
// 工具栏新增
state.formData.parentId = (state.currentRow as any).id;
state.formData.component = undefined;
state.formData.type = 'MENU';
} else {
state.formData.parentId = "0";
state.formData.component = "Layout";
state.formData.type = 'CATALOG';
}
}
}
/**
* 修改弹窗
*/
async function handleUpdate(row: any) {
await loadMenuData();
state.dialog = {
@@ -266,13 +282,25 @@ async function handleUpdate(row: any) {
const id = row.id || state.ids;
getMenuDetail(id).then(({ data }) => {
state.formData = data;
// 判断是否外部链接
state.isExternalPath = isExternal(state.formData.path);
cacheData.value.menuType = data.type
cacheData.value.menuPath = data.path
});
}
/**
* 菜单表单提交
* 菜单类型change事件
*/
function handleMenuTypeChange(val: any) {
if (val !== cacheData.value.menuType) {
formData.value.path = ''
} else {
formData.value.path = cacheData.value.menuPath
}
}
/**
* 菜单提交
*/
function submitForm() {
dataFormRef.value.validate((isValid: boolean) => {
@@ -326,7 +354,6 @@ function selected(name: string) {
state.iconSelectVisible = false;
}
onMounted(() => {
handleQuery();
});

View File

@@ -1,33 +1,23 @@
<template>
<div class="menu-container">
<el-row>
<el-col :span="12">
<el-button plain :icon="Switch" @click="toggleExpandAll">展开/折叠</el-button>
</el-col>
<el-col :span="12" style="text-align: right">
<el-button type="primary" :icon="Check" @click="handleSubmit">提交</el-button>
</el-col>
</el-row>
<el-tree class="menu-container__tree" ref="menuRef" v-if="refreshTree" :default-expanded-keys="expandedKeys" :default-expand-all="isExpandAll"
:data="menuOptions" show-checkbox node-key="value" empty-text="加载菜单中..." :check-strictly="checkStrictly"
highlight-current @node-click="handleNodeClick" />
</div>
</template>
<!-- setup 无法设置组件名称组件名称keepAlive必须 -->
<script lang="ts">
export default {
name: "cmenu"
};
</script>
<script setup lang="ts">
import { nextTick, onMounted, reactive, ref, toRefs, watch } from "vue";
import { listSelectMenus } from "@/api/system/menu";
import { listRoleMenuIds, updateRoleMenu } from "@/api/system/role";
import { ElTree, ElMessage } from "element-plus";
import { Switch, Check } from "@element-plus/icons-vue";
import { Switch, Position } from "@element-plus/icons-vue";
import { Option } from "@/types";
const emit = defineEmits(["menuClick"]);
const props = defineProps({
role: {
type: Object,
default: () => { }
default: () => {}
},
});
@@ -99,10 +89,25 @@ onMounted(() => {
});
</script>
<template>
<div class="app-container">
<el-row>
<el-col :span="12">
<el-button plain :icon="Switch" @click="toggleExpandAll">展开/折叠</el-button>
</el-col>
<el-col :span="12" style="text-align: right">
<el-button type="primary" :icon="Position" @click="handleSubmit">提交</el-button>
</el-col>
</el-row>
<el-tree class="menu-tree" ref="menuRef" v-if="refreshTree" :default-expanded-keys="expandedKeys"
:default-expand-all="isExpandAll" :data="menuOptions" show-checkbox node-key="value" empty-text="加载菜单中..."
:check-strictly="checkStrictly" highlight-current @node-click="handleNodeClick" />
</div>
</template>
<style lang="scss" scoped>
.menu-container {
&__tree{
margin-top: 10px;
}
.menu-tree {
margin-top: 10px;
}
</style>

View File

@@ -7,7 +7,7 @@
</el-checkbox>
</el-col>
<el-col :span="12" style="text-align: right">
<el-button type="primary" :icon="Check" @click="handleSubmit">提交</el-button>
<el-button type="primary" :icon="Position" @click="handleSubmit">提交</el-button>
</el-col>
</el-row>
@@ -36,7 +36,7 @@ import { onMounted, reactive, toRefs, watch } from "vue";
import { listPerms } from "@/api/system/perm";
import { listRolePerms, saveRolePerms } from "@/api/system/role";
import { ElMessage } from "element-plus";
import { Check } from "@element-plus/icons-vue";
import { Position } from "@element-plus/icons-vue";
import { PermQueryParam } from "@/types";
const props = defineProps({

View File

@@ -1,72 +1,9 @@
<template>
<div class="role-container">
<!-- 搜索表单 -->
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item>
<el-button type="success" :icon="Plus" @click="handleAdd">新增</el-button>
<el-button type="danger" :icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
</el-form-item>
<el-form-item prop="name">
<el-input v-model="queryParams.name" placeholder="角色名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
<el-button :icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 数据表格 -->
<el-table ref="dataTableRef" v-loading="loading" :data="roleList" @selection-change="handleSelectionChange"
@row-click="handleRowClick" highlight-current-row border>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="角色名称" prop="name" />
<el-table-column label="角色编码" prop="code" />
<el-table-column label="操作" align="center" width="120">
<template #default="scope">
<el-button type="primary" :icon="Edit" circle plain @click.stop="handleUpdate(scope.row)" />
<el-button type="danger" :icon="Delete" circle plain @click.stop="handleDelete(scope.row)" />
</template>
</el-table-column>
</el-table>
<!-- 分页工具条 -->
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
@pagination="handleQuery" />
<!-- 表单弹窗 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" @close="cancel" width="450px">
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="100px">
<el-form-item label="角色名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入角色名称" />
</el-form-item>
<el-form-item label="角色编码" prop="code">
<el-input v-model="formData.code" placeholder="请输入角色编码" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number v-model="formData.sort" controls-position="right" :min="0" style="width: 100px" />
</el-form-item>
<el-form-item label="状态">
<el-radio-group v-model="formData.status">
<el-radio :label="1">正常</el-radio>
<el-radio :label="0">停用</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<!-- setup 无法设置组件名称组件名称keepAlive必须 -->
<script lang="ts">
export default {
name: "role"
};
</script>
<script setup lang="ts">
import { onMounted, reactive, ref, toRefs } from "vue";
@@ -107,7 +44,7 @@ const state = reactive({
rules: {
name: [{ required: true, message: "请输入角色名称", trigger: "blur" }],
code: [{ required: true, message: "请输入角色编码", trigger: "blur" }],
},
}
});
const {
@@ -215,8 +152,77 @@ onMounted(() => {
});
</script>
<template>
<div class="app-container">
<!-- 搜索表单 -->
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item>
<el-button type="success" :icon="Plus" @click="handleAdd">新增</el-button>
<el-button type="danger" :icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
</el-form-item>
<el-form-item prop="name">
<el-input v-model="queryParams.name" placeholder="角色名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
<el-button :icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 数据表格 -->
<el-table ref="dataTableRef" v-loading="loading" :data="roleList" @selection-change="handleSelectionChange"
@row-click="handleRowClick" highlight-current-row border>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="角色名称" prop="name" />
<el-table-column label="角色编码" prop="code" />
<el-table-column label="操作" align="center" width="120">
<template #default="scope">
<el-button type="primary" :icon="Edit" circle plain @click.stop="handleUpdate(scope.row)" />
<el-button type="danger" :icon="Delete" circle plain @click.stop="handleDelete(scope.row)" />
</template>
</el-table-column>
</el-table>
<!-- 分页工具条 -->
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="handleQuery" />
<!-- 表单弹窗 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" @close="cancel" width="450px">
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="100px">
<el-form-item label="角色名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入角色名称" />
</el-form-item>
<el-form-item label="角色编码" prop="code">
<el-input v-model="formData.code" placeholder="请输入角色编码" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number v-model="formData.sort" controls-position="right" :min="0" style="width: 100px" />
</el-form-item>
<el-form-item label="状态">
<el-radio-group v-model="formData.status">
<el-radio :label="1">正常</el-radio>
<el-radio :label="0">停用</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<style lang="scss" scoped>
.role-container {
width: 100%;
}
</style>

View File

@@ -1,189 +1,9 @@
<template>
<div class="app-container">
<el-row :gutter="20">
<!-- 部门树 -->
<el-col :span="4" :xs="24">
<el-card class="box-card">
<el-input v-model="deptName" placeholder="部门名称" clearable :prefix-icon="Search" style="margin-bottom: 20px" />
<el-tree ref="deptTreeRef" :data="deptOptions" :props="{ children: 'children', label: 'label', disabled: '' }"
:expand-on-click-node="false" :filter-node-method="filterDeptNode" default-expand-all
@node-click="handleDeptNodeClick"></el-tree>
</el-card>
</el-col>
<!-- 用户数据 -->
<el-col :span="20" :xs="24">
<el-card class="box-card">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-row>
<el-col :span="18" :xs="24" >
<el-form-item>
<el-button type="success" :icon="Plus" @click="handleAdd" v-hasPerm="['sys:user:add']">新增</el-button>
<el-button type="danger" :icon="Delete" :disabled="multiple" @click="handleDelete"
v-hasPerm="['sys:user:delete']">删除</el-button>
</el-form-item>
<el-form-item prop="keywords">
<el-input v-model="queryParams.keywords" placeholder="用户名/昵称/手机号" clearable style="width: 200px"
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item prop="status">
<el-select v-model="queryParams.status" placeholder="用户状态" clearable style="width: 200px">
<el-option label="正常" value="1" />
<el-option label="停用" value="0" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
<el-button :icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-col>
<el-col :span="6" :xs="24" style="text-align: right;">
<el-form-item>
<el-dropdown split-button style="margin-left: 12px;">
导入
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :icon="Download" @click="handleDownloadTemplate">下载模板</el-dropdown-item>
<el-dropdown-item :icon="Top" @click="showImportDialog">导入数据</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-button :icon="Download" style="margin-left: 12px;" @click="handleExport">导出</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column key="id" label="用户编号" align="center" prop="id" />
<el-table-column key="username" label="用户名" align="center" prop="username" />
<el-table-column label="用户昵称" align="center" prop="nickname" />
<el-table-column label="性别" align="center" prop="gender" />
<el-table-column label="部门" align="center" prop="deptName" />
<el-table-column label="手机号码" align="center" prop="mobile" width="120" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<el-switch v-model="scope.row.status" :inactive-value="0" :active-value="1"
@change="handleStatusChange(scope.row)" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="gmtCreate" width="180"></el-table-column>
<el-table-column label="操作" align="center" width="150">
<template #default="scope">
<el-button type="primary" :icon="Edit" circle plain @click="handleUpdate(scope.row)"
v-hasPerm="['sys:user:edit']"></el-button>
<el-button type="danger" :icon="Delete" circle plain @click="handleDelete(scope.row)"
v-hasPerm="['sys:user:delete']"></el-button>
<el-button type="warning" :icon="Lock" circle plain @click="resetPassword(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="handleQuery" />
</el-card>
</el-col>
</el-row>
<!-- 添加或修改参数配置对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="600px" append-to-body @close="cancel">
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="80px">
<el-form-item label="用户名" prop="username">
<el-input :readonly="!!formData.id" v-model="formData.username" placeholder="请输入用户名" />
</el-form-item>
<el-form-item label="用户昵称" prop="nickname">
<el-input v-model="formData.nickname" placeholder="请输入用户昵称" />
</el-form-item>
<el-form-item label="所属部门" prop="deptId">
<el-tree-select v-model="formData.deptId" placeholder="请选择所属部门" :data="deptOptions" filterable />
</el-form-item>
<el-form-item label="手机号码" prop="mobile">
<el-input v-model="formData.mobile" placeholder="请输入手机号码" maxlength="11" />
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="formData.email" placeholder="请输入邮箱" maxlength="50" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio :label="1">正常</el-radio>
<el-radio :label="0">禁用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="用户性别" prop="gender">
<el-select v-model="formData.gender" placeholder="请选择">
<el-option label="未知" :value="0" />
<el-option label="男" :value="1" />
<el-option label="女" :value="2" />
</el-select>
</el-form-item>
<el-form-item label="角色" prop="roleIds">
<el-select v-model="formData.roleIds" multiple placeholder="请选择">
<el-option v-for="item in roleOptions" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
<el-dialog :title="importDialog.title" v-model="importDialog.visible" width="600px" append-to-body
@close="closeImportDialog">
<el-form ref="importFormRef" :model="importFormData" :rules="rules" label-width="80px">
<el-form-item label="所属部门" prop="deptId">
<el-tree-select v-model="formData.deptId" placeholder="请选择所属部门" :data="deptOptions" filterable />
</el-form-item>
<el-form-item label="角色" prop="roleIds">
<el-select v-model="importFormData.roleIds" multiple placeholder="请选择">
<el-option v-for="item in roleOptions" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="Excel">
<el-upload class="upload-demo" action="" drag :auto-upload="false"
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
:file-list="excelFilelist" :on-change="handleExcelChange" :limit="1">
<el-icon class="el-icon--upload">
<upload-filled />
</el-icon>
<div class="el-upload__text">
将文件拖到此处
<em>点击上传</em>
</div>
<template #tip>
<div class="el-upload__tip">xls/xlsx files </div>
</template>
</el-upload>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitImportForm"> </el-button>
<el-button @click="closeImportDialog"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<!-- setup 无法设置组件名称组件名称keepAlive必须 -->
<script lang="ts">
export default {
name: "user"
};
</script>
<script setup lang='ts'>
// Vue依赖
@@ -348,10 +168,10 @@ function filterDeptNode(value: string, data: any) {
}
/**
* 部门树节点点击
* 部门树节点点击事件
*/
function handleDeptNodeClick(data: { [key: string]: any }) {
state.queryParams.deptId = data.id;
state.queryParams.deptId = data.value;
handleQuery();
}
@@ -572,7 +392,7 @@ async function showImportDialog() {
state.importDialog.visible = true
}
// Excel文件上传
function handleExcelChange(file: UploadFile) {
if (!/\.(xlsx|xls|XLSX|XLS)$/.test(file.name)) {
ElMessage.warning('上传Excel只能为xlsx、xls格式');
@@ -645,6 +465,192 @@ onMounted(() => {
loadData();
});
</script>
<template>
<div class="app-container">
<el-row :gutter="20">
<!-- 部门树 -->
<el-col :span="4" :xs="24">
<el-card class="box-card">
<el-input v-model="deptName" placeholder="部门名称" clearable :prefix-icon="Search" style="margin-bottom: 20px" />
<el-tree ref="deptTreeRef" :data="deptOptions" :props="{ children: 'children', label: 'label', disabled: '' }"
:expand-on-click-node="false" :filter-node-method="filterDeptNode" default-expand-all
@node-click="handleDeptNodeClick"></el-tree>
</el-card>
</el-col>
<!-- 用户数据 -->
<el-col :span="20" :xs="24">
<el-card class="box-card">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-row>
<el-col :span="18" :xs="24" >
<el-form-item>
<el-button type="success" :icon="Plus" @click="handleAdd" v-hasPerm="['sys:user:add']">新增</el-button>
<el-button type="danger" :icon="Delete" :disabled="multiple" @click="handleDelete"
v-hasPerm="['sys:user:delete']">删除</el-button>
</el-form-item>
<el-form-item prop="keywords">
<el-input v-model="queryParams.keywords" placeholder="用户名/昵称/手机号" clearable style="width: 200px"
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item prop="status">
<el-select v-model="queryParams.status" placeholder="用户状态" clearable style="width: 200px">
<el-option label="正常" value="1" />
<el-option label="停用" value="0" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
<el-button :icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-col>
<el-col :span="6" :xs="24" style="text-align: right;">
<el-form-item>
<el-dropdown split-button style="margin-left: 12px;">
导入
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :icon="Download" @click="handleDownloadTemplate">下载模板</el-dropdown-item>
<el-dropdown-item :icon="Top" @click="showImportDialog">导入数据</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-button :icon="Download" style="margin-left: 12px;" @click="handleExport">导出</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column key="id" label="用户编号" align="center" prop="id" />
<el-table-column key="username" label="用户名" align="center" prop="username" />
<el-table-column label="用户昵称" align="center" prop="nickname" />
<el-table-column label="性别" align="center" prop="gender" />
<el-table-column label="部门" align="center" prop="deptName" />
<el-table-column label="手机号码" align="center" prop="mobile" width="120" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<el-switch v-model="scope.row.status" :inactive-value="0" :active-value="1"
@change="handleStatusChange(scope.row)" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="gmtCreate" width="180"></el-table-column>
<el-table-column label="操作" align="center" width="150">
<template #default="scope">
<el-button type="primary" :icon="Edit" circle plain @click="handleUpdate(scope.row)"
v-hasPerm="['sys:user:edit']"></el-button>
<el-button type="danger" :icon="Delete" circle plain @click="handleDelete(scope.row)"
v-hasPerm="['sys:user:delete']"></el-button>
<el-button type="warning" :icon="Lock" circle plain @click="resetPassword(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="handleQuery" />
</el-card>
</el-col>
</el-row>
<!-- 添加或修改参数配置对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="600px" append-to-body @close="cancel">
<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="80px">
<el-form-item label="用户名" prop="username">
<el-input :readonly="!!formData.id" v-model="formData.username" placeholder="请输入用户名" />
</el-form-item>
<el-form-item label="用户昵称" prop="nickname">
<el-input v-model="formData.nickname" placeholder="请输入用户昵称" />
</el-form-item>
<el-form-item label="所属部门" prop="deptId">
<el-tree-select v-model="formData.deptId" placeholder="请选择所属部门" :data="deptOptions" filterable check-strictly />
</el-form-item>
<el-form-item label="手机号码" prop="mobile">
<el-input v-model="formData.mobile" placeholder="请输入手机号码" maxlength="11" />
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="formData.email" placeholder="请输入邮箱" maxlength="50" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio :label="1">正常</el-radio>
<el-radio :label="0">禁用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="用户性别" prop="gender">
<el-select v-model="formData.gender" placeholder="请选择">
<el-option label="未知" :value="0" />
<el-option label="男" :value="1" />
<el-option label="女" :value="2" />
</el-select>
</el-form-item>
<el-form-item label="角色" prop="roleIds">
<el-select v-model="formData.roleIds" multiple placeholder="请选择">
<el-option v-for="item in roleOptions" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
<el-dialog :title="importDialog.title" v-model="importDialog.visible" width="600px" append-to-body
@close="closeImportDialog">
<el-form ref="importFormRef" :model="importFormData" :rules="rules" label-width="80px">
<el-form-item label="部门" prop="deptId">
<el-tree-select v-model="formData.deptId" placeholder="请选择部门" :data="deptOptions" filterable check-strictly />
</el-form-item>
<el-form-item label="角色" prop="roleIds">
<el-select v-model="importFormData.roleIds" multiple placeholder="请选择">
<el-option v-for="item in roleOptions" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="Excel">
<el-upload class="upload-demo" action="" drag :auto-upload="false"
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
:file-list="excelFilelist" :on-change="handleExcelChange" :limit="1">
<el-icon class="el-icon--upload">
<upload-filled />
</el-icon>
<div class="el-upload__text">
将文件拖到此处
<em>点击上传</em>
</div>
<template #tip>
<div class="el-upload__tip">xls/xlsx files </div>
</template>
</el-upload>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitImportForm"> </el-button>
<el-button @click="closeImportDialog"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<style lang="scss" scoped>
</style>