Эх сурвалжийг харах

租户字典模块,业务字典模块

asd26269546 2 жил өмнө
parent
commit
d896398ad0

+ 6 - 2
src/components/byTable/index.vue

@@ -1,5 +1,5 @@
 <template>
-	<div class="header-actions">
+	<div class="header-actions" v-if="getActionList.length != 0">
 		<div class="overflow-box">
 			<el-button
 				v-for="(item, index) in getActionList"
@@ -19,7 +19,7 @@
 		<header v-if="false" class="header">
 			<h2>{{ title }}</h2>
 		</header>
-		<div class="by-search">
+		<div class="by-search" v-if="!hideSearch">
 			<div style="display: flex;">
 				<div class="by-dropdown"  v-for="i in selectConfigCopy" :key="i.prop" style="margin-right:10px">
 					<div class="by-dropdown-title">
@@ -146,6 +146,10 @@ export default defineComponent({
 		ComponentsMapping,
 	},
 	props: {
+		hideSearch: {
+			type: Boolean,
+			default: false,
+		},
 		hideTable: {
 			type: Boolean, 
 			default: false,

+ 74 - 63
src/components/headerBar/header-bar.vue

@@ -4,17 +4,24 @@
 			<ul class="nav">
 				<div class="logo">ByteSailing</div>
 				<li class="header-bar-hover-warp nav-li">
-					<div @click="isChildMenu = !isChildMenu" class="menu-modal" style="font-size: 12px;">
+					<div
+						@click="isChildMenu = !isChildMenu"
+						class="menu-modal"
+						style="font-size: 12px"
+					>
 						功能导览
 						<i class="el-icon-arrow-down el-icon--right"></i>
 					</div>
-					
 				</li>
-				
+
 				<li class="nav-li" v-for="i in barData" :key="i.id">
 					<span>{{ i.name }}</span>
 				</li>
-				<div class="header-bar-warp"  v-if="isChildMenu" @click.stop="isChildMenu = false">
+				<div
+					class="header-bar-warp"
+					v-if="isChildMenu"
+					@click.stop="isChildMenu = false"
+				>
 					<div class="header-bar-hover" @click.stop>
 						<div class="header-bar-hover-content">
 							<div class="left-banner">
@@ -45,18 +52,21 @@
 								</div> -->
 							</div>
 							<div class="menu-warp">
-								<div class="first-order-title">
-									外贸ERP
-								</div>
+								<div class="first-order-title">外贸ERP</div>
 								<ul class="second-level">
-									<div v-for="(i, index) in sidebarRouters"
-											:key="index">
+									<div
+										v-for="(i, index) in sidebarRouters"
+										:key="index"
+									>
 										<li
 											v-if="i.isNone"
 											class="menu-ul"
-											style="cursor: auto;"
+											style="cursor: auto"
 										></li>
-										<li class="menu-title" v-else-if="i.isTitle">
+										<li
+											class="menu-title"
+											v-else-if="i.isTitle"
+										>
 											<el-icon size="16" color="#0084FF">
 												<edit />
 											</el-icon>
@@ -71,9 +81,7 @@
 											{{ i.meta.title }}
 										</li>
 									</div>
-									
 								</ul>
-								
 							</div>
 						</div>
 					</div>
@@ -131,13 +139,13 @@
   
 <script setup>
 import Cookies from 'js-cookie'
-import { ElMessageBox,ElNotification } from 'element-plus'
+import { ElMessageBox, ElNotification } from 'element-plus'
 import useUserStore from '@/store/modules/user'
 import usePermissionStore from '@/store/modules/permission'
 const router = useRouter()
 const userStore = useUserStore()
 const permissionStore = usePermissionStore()
-
+const { proxy } = getCurrentInstance()
 const sidebarRouters = ref([])
 const input1 = ref('')
 const isChildMenu = ref(false)
@@ -145,47 +153,50 @@ const menuData = ref([])
 const barData = ref([])
 const userData = ref(Cookies.get('username') || '')
 
-const routerInit = (() => {
+const routerInit = () => {
 	//二维转一维
 	const arr = []
 	for (let i = 0; i < permissionStore.addRoutes.length; i++) {
-		const element = permissionStore.addRoutes[i];
-		if(element.type === 1) {
+		const element = permissionStore.addRoutes[i]
+		if (element.type === 1) {
 			element.isTitle = true
 			arr.push(element)
 		}
-		
-		if(element.children && element.children.length > 0){
+
+		if (element.children && element.children.length > 0) {
 			for (let j = 0; j < element.children.length; j++) {
-				const jelement = element.children[j];
+				const jelement = element.children[j]
 				jelement.isTitle = false
-				arr.push({...jelement, fatherPath:element.path})
+				if (jelement.type === 1) {
+					arr.push({ ...jelement, fatherPath: element.path })
+				}
 			}
-		}		
+		}
 	}
 	let num = 0
 	//添加剩余子元素,补齐一列
 	for (let i = 0; i < arr.length; i++) {
-		const element = arr[i];
-		if(element.isTitle) {
-			//判断是否存在
-			if(element.children && element.children.length > 0){
-				//判断余数加上子项列会不会爆掉
-				if(num % 11 + element.children.length > 11 && element.children.length < 11){
-					element.pushNum = 11 - num % 11
-					for (let j = 0; j < 11 - num % 11; j++) {
-						arr.splice(i, 0, {...element,isNone:true})
-						i++
-					}
+		const element = arr[i]
+		if (element.isTitle) {
+			//判断余数加上子项列会不会爆掉
+			if (
+				element.children &&
+				element.children.length > 0 &&
+				(num % 11) + element.children.length > 11 &&
+				element.children.length < 11
+			) {
+				for (let j = 0; j < 11 - (num % 11); j++) {
+					arr.splice(i, 0, { ...element, isNone: true })
+					i++
 				}
+				num++
 			}
-			num ++ 
-		}else{
-			num ++ 
+			
 		}
+		num++
 	}
 	sidebarRouters.value = arr
-})
+}
 function handleCommand(command) {
 	switch (command) {
 		case 'setLayout':
@@ -199,9 +210,7 @@ function handleCommand(command) {
 	}
 }
 
-
 function logout() {
-	
 	ElMessageBox.confirm('确定注销并退出系统吗?', '提示', {
 		confirmButtonText: '确定',
 		cancelButtonText: '取消',
@@ -220,11 +229,13 @@ function routerPush(i) {
 	isChildMenu.value = false
 }
 
-onMounted(()=>{
+onMounted(() => {
 	routerInit()
+	proxy.get('/getInfo').then(res=>{
+		userData.value = res.user.userName
+	})
+	
 })
-
-
 </script>
   
 <style  lang="scss">
@@ -236,7 +247,6 @@ onMounted(()=>{
 	bottom: 0;
 	background: rgba(0, 0, 0, 0.5);
 	z-index: 1100;
-	
 }
 .header-bar {
 	background: #20222a;
@@ -245,7 +255,8 @@ onMounted(()=>{
 	left: 0;
 	right: 0;
 	z-index: 1100;
-	ul,li{
+	ul,
+	li {
 		list-style: none;
 		padding: 0;
 	}
@@ -270,11 +281,11 @@ onMounted(()=>{
 		.header-bar-hover-content {
 			display: flex;
 			text-align: left;
-			.left-banner{
+			.left-banner {
 				width: 230px;
-				ul{
-					background: #F1F1F1;
-					li{
+				ul {
+					background: #f1f1f1;
+					li {
 						height: 50px;
 						line-height: 50px;
 						padding: 0 50px;
@@ -282,15 +293,15 @@ onMounted(()=>{
 						cursor: pointer;
 					}
 				}
-				.first-order{
+				.first-order {
 					height: 50px;
 					padding: 0 20px;
 					line-height: 50px;
 					font-size: 14px;
 					font-weight: bold;
-					background: #F9F9F9;
+					background: #f9f9f9;
 					cursor: pointer;
-					i{
+					i {
 						position: relative;
 						top: 3px;
 						margin-right: 5px;
@@ -317,34 +328,34 @@ onMounted(()=>{
 			padding: 0 40px;
 			height: 500px;
 			overflow-y: auto;
-			.first-order-title{
+			.first-order-title {
 				height: 70px;
 				line-height: 70px;
 				color: #333333;
 				font-size: 15px;
 				font-weight: bold;
 			}
-			.second-level{
+			.second-level {
 				overflow: hidden;
-				height:420px;
+				height: 420px;
 				display: flex;
-				flex-wrap:wrap;
-				flex-direction:column;
-				flex-grow:0;
-				flex-basis:auto;
+				flex-wrap: wrap;
+				flex-direction: column;
+				flex-grow: 0;
+				flex-basis: auto;
 			}
 			.menu-title {
 				font-weight: 600;
-				color: #0084FF;
+				color: #0084ff;
 				height: 40px;
 				line-height: 40px;
 				border-bottom: 1px solid #ddd;
 				font-size: 14px;
 				width: 140px;
 				margin: 0 100px 0 0;
-				i{
+				i {
 					position: relative;
-					top:3px;
+					top: 3px;
 					margin-right: 5px;
 				}
 			}
@@ -360,7 +371,7 @@ onMounted(()=>{
 				font-weight: 400;
 				cursor: pointer;
 			}
-			.menu-ul:hover{
+			.menu-ul:hover {
 				color: #0084ff;
 			}
 		}

+ 3 - 0
src/utils/request.js

@@ -125,6 +125,7 @@ service.interceptors.response.use(res => {
       })
       return Promise.reject('error')
     } else {
+      
       return Promise.resolve(res.data)
     }
   },
@@ -213,6 +214,8 @@ export function post(url, data = {}, method) {
       data: data,
     }).then(res => {
       resolve(res.data);
+    }).catch(err => {
+      reject(err)
     })
 
   })

+ 306 - 0
src/views/system/dict/dictCommonDtl.vue

@@ -0,0 +1,306 @@
+<template>
+	<div class="dictTenantDtl">
+		<el-button type="primary" @click="openModal">添加</el-button>
+		<div class="content">
+			<byTable
+				:source="sourceList.data"
+				:pagination="sourceList.pagination"
+				:config="config"
+				:loading="loading"
+				highlight-current-row
+				:hideSearch="true"
+				@get-list="getList"
+			>
+				<template #slotName="{ item }">
+					{{ item.createTime }}
+				</template>
+			</byTable>
+		</div>
+		<el-dialog
+			:title="modalType == 'add' ? '新增' : '编辑'"
+			v-model="dialogVisible"
+			width="400"
+			v-loading="loading"
+		>
+			<byForm
+				:formConfig="formConfig"
+				:formOption="formOption"
+				v-model="formData.data"
+				:rules="rules"
+				ref="byform"
+			>
+			</byForm>
+			<template #footer>
+				<el-button @click="dialogVisible = false" size="large"
+					>取 消</el-button
+				>
+				<el-button
+					type="primary"
+					@click="submitForm('byform')"
+					size="large"
+					:loading="submitLoading"
+				>
+					确 定
+				</el-button>
+			</template>
+		</el-dialog>
+	</div>
+</template>
+    
+  <script setup>
+/* eslint-disable vue/no-unused-components */
+import { ElMessage, ElMessageBox } from 'element-plus'
+import byTable from '@/components/byTable/index'
+import byForm from '@/components/byForm/index'
+import { computed, defineComponent, ref, watch } from 'vue'
+import { get } from '@vueuse/shared'
+const { proxy } = getCurrentInstance()
+const loading = ref(false)
+const submitLoading = ref(false)
+const dictCommonModal = ref(true)
+defineProps({
+	data: {
+		type: Object,
+		default: false,
+	},
+})
+watch(proxy.data, (newValue, oldValue) => {
+	console.log(proxy.data)
+	getList()
+})
+const sourceList = ref({
+	data: [],
+	pagination: {
+		total: 3,
+		pageNum: 1,
+		pageSize: 10,
+	},
+})
+let dialogVisible = ref(false)
+let roomDialogVisible = ref(false)
+let modalType = ref('add')
+let rules = ref({
+	dictKey: [{ required: true, message: '请输入key', trigger: 'blur' }],
+	dictValue: [{ required: true, message: '请输入val', trigger: 'blur' }],
+	sort: [{ required: true, message: '请输入排序', trigger: 'blur' }],
+})
+
+const selectConfig = computed(() => {
+	return [
+		{
+			label: '状态',
+			prop: 'status',
+			data: [
+				{
+					label: '禁用',
+					value: '0',
+				},
+				{
+					label: '启用',
+					value: '1',
+				},
+			],
+		},
+	]
+})
+const config = computed(() => {
+	return [
+		{
+			attrs: {
+				label: '键',
+				prop: 'dictKey',
+			},
+		},
+		{
+			attrs: {
+				label: '值',
+				prop: 'dictKey',
+			},
+		},
+		{
+			attrs: {
+				label: '排序',
+				prop: 'sort',
+			},
+		},
+		{
+			attrs: {
+				label: '操作',
+				width: '200',
+				align: 'right',
+			},
+			// 渲染 el-button,一般用在最后一列。
+			renderHTML(row) {
+				return [
+					{
+						attrs: {
+							label: '修改',
+							type: 'primary',
+							text: true,
+						},
+						el: 'button',
+						click() {
+							getDtl(row)
+						},
+					},
+					{
+						attrs: {
+							label: '删除',
+							type: 'primary',
+							text: true,
+						},
+						el: 'button',
+						click() {
+							// 弹窗提示是否删除
+							ElMessageBox.confirm(
+								'此操作将删除该数据, 是否继续?',
+								'提示',
+								{
+									confirmButtonText: '确定',
+									cancelButtonText: '取消',
+									type: 'warning',
+								}
+							).then(() => {
+								// 删除
+								proxy
+									.post('/dictCommonData/delete', {
+										id: row.id,
+									})
+									.then((res) => {
+										ElMessage({
+											message: '删除成功',
+											type: 'success',
+										})
+										getList()
+									})
+							})
+						},
+					},
+				]
+			},
+		},
+	]
+})
+
+let formData = reactive({
+	data: {},
+	treeData: [],
+})
+const formOption = reactive({
+	inline: true,
+	labelWidth: 100,
+	itemWidth: 100,
+	rules: [],
+})
+const byform = ref(null)
+const treeData = ref([])
+const formConfig = computed(() => {
+	return [
+		{
+			type: 'input',
+			prop: 'dictKey',
+			label: '键',
+			required: true,
+		},
+		{
+			type: 'input',
+			prop: 'dictValue',
+			label: '值',
+		},
+		{
+			label: '排序',
+			prop: 'sort',
+			type: 'input',
+			itemType: 'number',
+		},
+	]
+})
+const getList = async (req) => {
+	console.log(proxy.data.data.code)
+	sourceList.value.pagination = {
+		...sourceList.value.pagination,
+		...req,
+		dictCode: proxy.data.data.code,
+		tenantId: proxy.data.data.tenantId,
+	}
+	loading.value = true
+	proxy
+		.post('/dictCommonData/page', sourceList.value.pagination)
+		.then((message) => {
+			console.log(message)
+			sourceList.value.data = message.rows
+			sourceList.value.pagination.total = message.total
+			setTimeout(() => {
+				loading.value = false
+			}, 200)
+		})
+}
+const openModal = () => {
+	dialogVisible.value = true
+	modalType.value = 'add'
+	formData.data = {}
+}
+
+const submitForm = () => {
+	console.log(byform.value)
+	byform.value.handleSubmit((valid) => {
+		submitLoading.value = true
+		formData.data.dictCode = proxy.data.data.code
+		formData.data.tenantId = proxy.data.data.tenantId
+		proxy
+			.post('/dictCommonData/' + modalType.value, formData.data)
+			.then((res) => {
+				ElMessage({
+					message: modalType.value == 'add' ? '添加成功' : '编辑成功',
+					type: 'success',
+				})
+				dialogVisible.value = false
+				submitLoading.value = false
+				getList()
+			})
+			.catch((err) => {
+				submitLoading.value = false
+			})
+	})
+}
+
+const getDtl = (row) => {
+	formData.data = { ...row }
+	modalType.value = 'edit'
+	dialogVisible.value = true
+}
+
+const changeStatus = (row) => {
+	modalType.value = 'edit'
+	let status = row.status ? 0 : 1
+	proxy.post('/tenantInfo/detail', { id: row.id }).then((res) => {
+		res.status = status
+		formData.data = res
+		ElMessageBox.confirm('你是否确认此操作?', '提示', {
+			confirmButtonText: '确定',
+			cancelButtonText: '取消',
+			type: 'warning',
+		}).then(() => {
+			// 删除
+			proxy
+				.post('/tenantInfo/' + modalType.value, formData.data)
+				.then((res) => {
+					ElMessage({
+						message: '操作成功',
+						type: 'success',
+					})
+					getList()
+				})
+		})
+	})
+}
+getList()
+</script>
+    
+  <style lang="scss" scoped>
+.dictTenantDtl {
+}
+.tenant {
+	padding: 20px;
+}
+</style>

+ 360 - 0
src/views/system/dict/dictCommonType.vue

@@ -0,0 +1,360 @@
+<template>
+	<div class="tenant">
+		<!-- <Banner /> -->
+		<div class="content">
+			<byTable
+				:source="sourceList.data"
+				:pagination="sourceList.pagination"
+				:config="config"
+				:loading="loading"
+				highlight-current-row
+				:selectConfig="selectConfig"
+				:table-events="{
+					//element talbe事件都能传
+					select: select,
+				}"
+				:action-list="[
+					{
+						text: '添加',
+						action: () => openModal('add'),
+					},
+				]"
+				@get-list="getList"
+			>
+				<template #slotName="{ item }">
+					{{ item.createTime }}
+				</template>
+			</byTable>
+		</div>
+		<el-dialog
+			:title="modalType == 'add' ? '新增' : '编辑'"
+			v-model="dialogVisible"
+			width="400"
+			v-loading="loading"
+		>
+			<byForm
+				:formConfig="formConfig"
+				:formOption="formOption"
+				v-model="formData.data"
+				:rules="rules"
+				ref="byform"
+			>
+			</byForm>
+			<template #footer>
+				<el-button @click="dialogVisible = false" size="large"
+					>取 消</el-button
+				>
+				<el-button
+					type="primary"
+					@click="submitForm('byform')"
+					size="large"
+					:loading="submitLoading"
+				>
+					确 定
+				</el-button>
+			</template>
+		</el-dialog>
+        <!-- 详情table -->
+        <el-dialog
+			:title="modalType == 'add' ? '新增' : '编辑'"
+			v-model="dictCommonModal"
+			width="1000"
+			v-loading="loading"
+		>
+			<dictCommonDtl :data="dtlData"></dictCommonDtl>
+			<template #footer>
+				<el-button @click="dictCommonModal = false" size="large"
+					>关闭</el-button
+				>
+				
+			</template>
+		</el-dialog>
+	</div>
+</template>
+    
+  <script setup>
+/* eslint-disable vue/no-unused-components */
+import { ElMessage, ElMessageBox } from 'element-plus'
+import byTable from '@/components/byTable/index'
+import byForm from '@/components/byForm/index'
+import dictCommonDtl from './dictCommonDtl'
+import { computed, defineComponent, ref } from 'vue'
+const loading = ref(false)
+const submitLoading = ref(false)
+const dictCommonModal = ref(false)
+const sourceList = ref({
+	data: [],
+	pagination: {
+		total: 3,
+		pageNum: 1,
+		pageSize: 10,
+	},
+})
+let dialogVisible = ref(false)
+let roomDialogVisible = ref(false)
+let modalType = ref('add')
+let rules = ref({
+	code: [{ required: true, message: '请输入字典编码', trigger: 'blur' }],
+	name: [{ required: true, message: '请输入字典名称', trigger: 'blur' }],
+	status: [
+		{ required: true, message: '请选择字典状态', trigger: 'blur' },
+	],
+})
+const { proxy } = getCurrentInstance()
+const selectConfig = computed(() => {
+	return [
+		{
+			label: '状态',
+			prop: 'status',
+			data: [
+				{
+					label: '禁用',
+					value: '0',
+				},
+				{
+					label: '启用',
+					value: '1',
+				},
+			],
+		},
+	]
+})
+const config = computed(() => {
+	return [
+        {
+			attrs: {
+				label: '字典编码',
+			},
+			renderHTML(row) {
+				return [
+					{
+						attrs: {
+							label: row.code,
+							type: 'primary',
+							text: true,
+						},
+						el: 'button',
+						click() {
+							openDtlModal(row)
+						},
+					},
+				]
+			},
+		},
+		{
+			attrs: {
+				label: '字典名称',
+				prop: 'name',
+			},
+		},
+
+		{
+			attrs: {
+				label: '状态',
+				width: 100,
+				prop: 'status',
+			},
+			render(status) {
+				//1审核中 2审核通过 3审核不通过
+				return status == 0
+					? '禁用'
+					: '启用'
+					
+			},
+		},
+		{
+			attrs: {
+				label: '备注',
+				prop: 'remark',
+			},
+		},
+		{
+			attrs: {
+				label: '创建时间',
+				prop: 'createTime',
+			},
+		},
+		{
+			attrs: {
+				label: '操作',
+				width: '200',
+				align: 'right',
+			},
+			// 渲染 el-button,一般用在最后一列。
+			renderHTML(row) {
+				return [
+					{
+					  attrs: {
+					    label: "修改",
+					    type: "primary",
+					    text: true,
+					  },
+					  el: "button",
+					  click() {
+					    getDtl(row);
+					  },
+					},
+					{
+						attrs: {
+							label: row.status == 1 ? '禁用' : '启用',
+							type: 'primary',
+							text: true,
+						},
+						el: 'button',
+						click() {
+							changeStatus(row)
+						},
+					},
+				]
+			},
+		},
+	]
+})
+let dtlData = reactive({
+	data: {},
+})
+let formData = reactive({
+	data: {},
+	treeData: [],
+})
+const formOption = reactive({
+	inline: true,
+	labelWidth: 100,
+	itemWidth: 100,
+	rules: [],
+})
+const byform = ref(null)
+const treeData = ref([])
+const formConfig = computed(() => {
+	return [
+		{
+			type: 'input',
+			prop: 'code',
+			label: '字典编码',
+			required: true,
+		},
+		{
+			type: 'input',
+			prop: 'name',
+			label: '字典名称',
+		},
+        {
+            label: '启用状态',
+            prop: 'status',
+            type: 'select',
+            data: [
+                {
+                    label: '禁用',
+                    value: '0',
+                },
+                {
+                    label: '启用',
+                    value: '1',
+                },
+            ],
+        },
+		{
+			type: 'input',
+			prop: 'remark',
+			label: '备注',
+			border: true,
+		},
+        
+		
+	]
+})
+const getList = async (req) => {
+	sourceList.value.pagination = { ...sourceList.value.pagination, ...req }
+	loading.value = true
+	proxy
+		.post('/dictCommonType/page', sourceList.value.pagination)
+		.then((message) => {
+			console.log(message)
+			sourceList.value.data = message.rows
+			sourceList.value.pagination.total = message.total
+			setTimeout(() => {
+				loading.value = false
+			}, 200)
+		})
+}
+
+const openDtlModal = (row) => {
+    dtlData.data = {...row}
+    dictCommonModal.value = true
+}
+const openModal = () => {
+	dialogVisible.value = true
+	modalType.value = 'add'
+	formData.data = {}
+}
+const selection = ref({
+	data: [],
+})
+const select = (_selection, row) => {
+	selection.value.data = _selection
+	console.log(_selection.length)
+}
+
+const tree = ref(null)
+const submitTree = () => {
+	proxy
+		.post('/tenantInfo/bindingMenu', {
+			tenantId: selection.value.data[0].tenantId,
+			menuIdList: tree.value.getCheckedKeys(),
+		})
+		.then((res) => {
+			ElMessage({
+				message: '保存成功',
+				type: 'success',
+			})
+			roomDialogVisible.value = false
+		})
+}
+
+const submitForm = () => {
+	console.log(byform.value)
+	byform.value.handleSubmit((valid) => {
+		submitLoading.value = true
+
+		proxy
+			.post('/tenantInfo/' + modalType.value, formData.data)
+			.then((res) => {
+				ElMessage({
+					message: modalType.value == 'add' ? '添加成功' : '编辑成功',
+					type: 'success',
+				})
+				dialogVisible.value = false
+				submitLoading.value = false
+				getList()
+			})
+	})
+}
+
+const getDtl = (row) => {
+	proxy.post('/tenantInfo/detail', { id: row.id }).then((res) => {
+		formData.data = res
+		console.log(formData)
+		modalType.value = 'edit'
+		dialogVisible.value = true
+	})
+}
+
+const changeStatus = (row) => {
+	modalType.value = 'edit'
+	let status = row.status ? 0 : 1
+	proxy.post('/dictCommonType/edit', { ...row,status:(row.status === 0) ? 1 : 0 }).then((res) => {
+		ElMessage({
+            message: '操作成功',
+            type: 'success',
+        })
+        getList()
+	})
+}
+getList()
+</script>
+    
+  <style lang="scss" scoped>
+.tenant {
+	padding: 20px;
+}
+</style>

+ 307 - 0
src/views/system/dict/dictTenantDtl.vue

@@ -0,0 +1,307 @@
+<template>
+	<div class="dictTenantDtl">
+		<el-button type="primary" @click="openModal">添加</el-button>
+		<div class="content">
+			<byTable
+				:source="sourceList.data"
+				:pagination="sourceList.pagination"
+				:config="config"
+				:loading="loading"
+				highlight-current-row
+				:hideSearch="true"
+				@get-list="getList"
+			>
+				<template #slotName="{ item }">
+					{{ item.createTime }}
+				</template>
+			</byTable>
+		</div>
+		<el-dialog
+			:title="modalType == 'add' ? '新增' : '编辑'"
+			v-model="dialogVisible"
+			width="400"
+			v-loading="loading"
+		>
+			<byForm
+				:formConfig="formConfig"
+				:formOption="formOption"
+				v-model="formData.data"
+				:rules="rules"
+				ref="byform"
+			>
+			</byForm>
+			<template #footer>
+				<el-button @click="dialogVisible = false" size="large"
+					>取 消</el-button
+				>
+				<el-button
+					type="primary"
+					@click="submitForm('byform')"
+					size="large"
+					:loading="submitLoading"
+				>
+					确 定
+				</el-button>
+			</template>
+		</el-dialog>
+	</div>
+</template>
+    
+  <script setup>
+/* eslint-disable vue/no-unused-components */
+import { ElMessage, ElMessageBox } from 'element-plus'
+import byTable from '@/components/byTable/index'
+import byForm from '@/components/byForm/index'
+import { computed, defineComponent, ref,watch} from 'vue'
+import { get } from '@vueuse/shared'
+const { proxy } = getCurrentInstance()
+const loading = ref(false)
+const submitLoading = ref(false)
+const dictCommonModal = ref(true)
+defineProps({
+	data: {
+		type: Object,
+		default: false,
+	},
+})
+watch(proxy.data, (newValue, oldValue) => {
+  getList()
+});
+const sourceList = ref({
+	data: [],
+	pagination: {
+		total: 3,
+		pageNum: 1,
+		pageSize: 10,
+	},
+})
+let dialogVisible = ref(false)
+let roomDialogVisible = ref(false)
+let modalType = ref('add')
+let rules = ref({
+	dictKey: [{ required: true, message: '请输入key', trigger: 'blur' }],
+	dictValue: [{ required: true, message: '请输入val', trigger: 'blur' }],
+	sort: [{ required: true, message: '请输入排序', trigger: 'blur' }],
+})
+
+const selectConfig = computed(() => {
+	return [
+		{
+			label: '状态',
+			prop: 'status',
+			data: [
+				{
+					label: '禁用',
+					value: '0',
+				},
+				{
+					label: '启用',
+					value: '1',
+				},
+			],
+		},
+	]
+})
+const config = computed(() => {
+	return [
+		{
+			attrs: {
+				label: '键',
+				prop: 'dictKey',
+			},
+		},
+		{
+			attrs: {
+				label: '值',
+				prop: 'dictKey',
+			},
+		},
+		{
+			attrs: {
+				label: '排序',
+				prop: 'sort',
+			},
+		},
+		{
+			attrs: {
+				label: '操作',
+				width: '200',
+				align: 'right',
+			},
+			// 渲染 el-button,一般用在最后一列。
+			renderHTML(row) {
+				if (row.type == 2) {
+					return [
+						{
+							attrs: {
+								label: '修改',
+								type: 'primary',
+								text: true,
+							},
+							el: 'button',
+							click() {
+								getDtl(row)
+							},
+						},
+						{
+							attrs: {
+								label: '删除',
+								type: 'primary',
+								text: true,
+							},
+							el: 'button',
+							click() {
+								// 弹窗提示是否删除
+								ElMessageBox.confirm(
+									'此操作将删除该数据, 是否继续?',
+									'提示',
+									{
+										confirmButtonText: '确定',
+										cancelButtonText: '取消',
+										type: 'warning',
+									}
+								).then(() => {
+									// 删除
+									proxy
+										.post('/dictTenantData/delete', {
+											id: row.id,
+										})
+										.then((res) => {
+											ElMessage({
+												message: '删除成功',
+												type: 'success',
+											})
+											getList()
+										})
+								})
+							},
+						},
+					]
+				}
+			},
+		},
+	]
+})
+
+let formData = reactive({
+	data: {},
+	treeData: [],
+})
+const formOption = reactive({
+	inline: true,
+	labelWidth: 100,
+	itemWidth: 100,
+	rules: [],
+})
+const byform = ref(null)
+const treeData = ref([])
+const formConfig = computed(() => {
+	return [
+		{
+			type: 'input',
+			prop: 'dictKey',
+			label: '键',
+			required: true,
+		},
+		{
+			type: 'input',
+			prop: 'dictValue',
+			label: '值',
+		},
+		{
+			label: '排序',
+			prop: 'sort',
+			type: 'input',
+			itemType: 'number',
+		},
+	]
+})
+const getList = async (req) => {
+	console.log(proxy.data.data.code)
+	sourceList.value.pagination = {
+		...sourceList.value.pagination,
+		...req,
+		dictCode: proxy.data.data.code,
+		tenantId: proxy.data.data.tenantId,
+	}
+	loading.value = true
+	proxy
+		.post('/dictTenantData/page', sourceList.value.pagination)
+		.then((message) => {
+			console.log(message)
+			sourceList.value.data = message.rows
+			sourceList.value.pagination.total = message.total
+			setTimeout(() => {
+				loading.value = false
+			}, 200)
+		})
+}
+const openModal = () => {
+	dialogVisible.value = true
+	modalType.value = 'add'
+	formData.data = {}
+}
+
+const submitForm = () => {
+	console.log(byform.value)
+	byform.value.handleSubmit((valid) => {
+		submitLoading.value = true
+		formData.data.dictCode = proxy.data.data.code
+		formData.data.tenantId = proxy.data.data.tenantId
+		proxy
+			.post('/dictTenantData/' + modalType.value, formData.data)
+			.then((res) => {
+				ElMessage({
+					message: modalType.value == 'add' ? '添加成功' : '编辑成功',
+					type: 'success',
+				})
+				dialogVisible.value = false
+				submitLoading.value = false
+				getList()
+			})
+			.catch((err) => {
+				submitLoading.value = false
+			})
+	})
+}
+
+const getDtl = (row) => {
+	formData.data = { ...row }
+	modalType.value = 'edit'
+	dialogVisible.value = true
+}
+
+const changeStatus = (row) => {
+	modalType.value = 'edit'
+	let status = row.status ? 0 : 1
+	proxy.post('/tenantInfo/detail', { id: row.id }).then((res) => {
+		res.status = status
+		formData.data = res
+		ElMessageBox.confirm('你是否确认此操作?', '提示', {
+			confirmButtonText: '确定',
+			cancelButtonText: '取消',
+			type: 'warning',
+		}).then(() => {
+			// 删除
+			proxy
+				.post('/tenantInfo/' + modalType.value, formData.data)
+				.then((res) => {
+					ElMessage({
+						message: '操作成功',
+						type: 'success',
+					})
+					getList()
+				})
+		})
+	})
+}
+getList()
+</script>
+    
+  <style lang="scss" scoped>
+.dictTenantDtl {
+}
+.tenant {
+	padding: 20px;
+}
+</style>

+ 452 - 0
src/views/system/dict/dictTenantType.vue

@@ -0,0 +1,452 @@
+<template>
+	<div class="user">
+		<div class="tree">
+			<treeList
+				:data="treeListData"
+				v-model="sourceList.pagination.tenantId"
+				node-key="id"
+				@change="treeChange"
+			>
+			</treeList>
+		</div>
+		<div class="content">
+			<byTable
+				:source="sourceList.data"
+				:pagination="sourceList.pagination"
+				:config="config"
+				:loading="loading"
+				highlight-current-row
+				:selectConfig="selectConfig"
+				searchKey="userName"
+				:table-events="{
+					//element talbe事件都能传
+					select: select,
+				}"
+				:action-list="[
+					{
+						text: '添加字典',
+						action: () => openModal('add'),
+						disabled: !sourceList.pagination.tenantId,
+					},
+				]"
+				@get-list="getList"
+			>
+				<template #slotName="{ item }">
+					{{ item.createTime }}
+				</template>
+			</byTable>
+		</div>
+		<el-dialog
+			:title="modalType == 'add' ? '新增' : '编辑'"
+			v-model="dialogVisible"
+			width="500"
+			v-loading="loading"
+		>
+			<byForm
+				:formConfig="formConfig"
+				:formOption="formOption"
+				v-model="formData.data"
+				:rules="rules"
+				ref="byform"
+			>
+				<template #account>
+					<el-input
+						style="width: 150px; margin-right: 10px"
+						v-model="formData.data.userName"
+						placeholder="请输入用户名"
+					></el-input>
+					<el-input
+						style="width: 150px; margin-right: 10px"
+						v-model="formData.data.password"
+						placeholder="密码"
+					></el-input>
+					<span
+						style="color: #409eff; cursor: pointer"
+						@click="newPassword"
+						>随机生成</span
+					>
+				</template>
+			</byForm>
+			<template #footer>
+				<el-button @click="dialogVisible = false" size="large"
+					>取 消</el-button
+				>
+				<el-button
+					type="primary"
+					@click="submitForm('byform')"
+					size="large"
+					:loading="submitLoading"
+				>
+					确 定
+				</el-button>
+			</template>
+		</el-dialog>
+		<el-dialog
+			title="字典维护"
+			v-model="dictCommonModal"
+			width="1000"
+            class="dictCommonModal"
+			v-loading="loading"
+		>
+			<dictTenantDtl :data="formData"></dictTenantDtl>
+			<template #footer>
+				<el-button @click="dictCommonModal = false" size="large"
+					>关闭</el-button
+				>
+				
+			</template>
+        </el-dialog>
+	</div>
+</template>
+    
+  <script setup>
+/* eslint-disable vue/no-unused-components */
+import { ElMessage, ElMessageBox } from 'element-plus'
+import byTable from '@/components/byTable/index'
+import byForm from '@/components/byForm/index'
+import dictTenantDtl from './dictTenantDtl.vue'
+import treeList from '@/components/treeList/index'
+import { computed, defineComponent, ref } from 'vue'
+const dictCommonModal = ref(false)
+const loading = ref(false)
+const submitLoading = ref(false)
+const sourceList = ref({
+	data: [],
+	pagination: {
+		total: 3,
+		pageNum: 1,
+		pageSize: 10,
+	},
+})
+let dialogVisible = ref(false)
+let modalType = ref('add')
+let rules = ref({
+	code: [{ required: true, message: '请输入字典编码', trigger: 'blur' }],
+	name: [{ required: true, message: '请输入字典名称', trigger: 'blur' }],
+	status: [{ required: true, message: '请选择字典状态', trigger: 'blur' }],
+})
+const { proxy } = getCurrentInstance()
+const selectConfig = computed(() => {
+	return [
+		{
+			label: '字典来源',
+			prop: 'type',
+			data: [
+				{
+					label: '业务字典',
+					value: '1',
+				},
+				{
+					label: '自定义字典',
+					value: '2',
+				},
+			],
+		},
+		{
+			label: '状态',
+			prop: 'status',
+			data: [
+				{
+					label: '禁用',
+					value: '0',
+				},
+				{
+					label: '启用',
+					value: '1',
+				},
+			],
+		},
+	]
+})
+const config = computed(() => {
+	return [
+		{
+			attrs: {
+				label: '字典类型',
+				prop: 'type',
+			},
+			render(type) {
+				//1审核中 2审核通过 3审核不通过
+				return type == 2 ? '自定义字典' : '业务字典'
+			},
+		},
+		{
+			attrs: {
+				label: '字典编码',
+			},
+			renderHTML(row) {
+				return [
+					{
+						attrs: {
+							label: row.code,
+							type: 'primary',
+							text: true,
+						},
+						el: 'button',
+						click() {
+							openDtlModal(row)
+						},
+					},
+				]
+			},
+		},
+		{
+			attrs: {
+				label: '字典名称',
+				prop: 'name',
+			},
+		},
+
+		{
+			attrs: {
+				label: '状态',
+				width: 100,
+				prop: 'status',
+			},
+			render(status) {
+				//1审核中 2审核通过 3审核不通过
+				return status == 0 ? '禁用' : '启用'
+			},
+		},
+		{
+			attrs: {
+				label: '备注',
+				prop: 'remark',
+			},
+		},
+
+		{
+			attrs: {
+				label: '操作',
+				width: '200',
+				align: 'right',
+			},
+			// 渲染 el-button,一般用在最后一列。
+			renderHTML(row) {
+				if (row.type == 2) {
+					return [
+						{
+							attrs: {
+								label: '修改',
+								type: 'primary',
+								text: true,
+							},
+							el: 'button',
+							click() {
+								getDtl(row)
+							},
+						},
+						{
+							attrs: {
+								label: '删除',
+								type: 'primary',
+								text: true,
+							},
+							el: 'button',
+							click() {
+								// 弹窗提示是否删除
+								ElMessageBox.confirm(
+									'此操作将删除该数据, 是否继续?',
+									'提示',
+									{
+										confirmButtonText: '确定',
+										cancelButtonText: '取消',
+										type: 'warning',
+									}
+								).then(() => {
+									// 删除
+									proxy
+										.post(
+											'/dictTenantType/delete',
+											{
+												id: row.id,
+											},
+
+										)
+										.then((res) => {
+											ElMessage({
+												message: '删除成功',
+												type: 'success',
+											})
+											getList()
+										})
+								})
+							},
+						},
+					]
+				}
+			},
+		},
+	]
+})
+
+let formData = reactive({
+	data: {},
+})
+const formOption = reactive({
+	inline: true,
+	labelWidth: 100,
+	itemWidth: 100,
+	rules: [],
+})
+const byform = ref(null)
+const treeListData = ref([])
+const formConfig = computed(() => {
+	return [
+		{
+			type: 'input',
+			prop: 'code',
+			label: '字典编码',
+			required: true,
+		},
+		{
+			type: 'input',
+			prop: 'name',
+			label: '字典名称',
+		},
+		{
+			label: '启用状态',
+			prop: 'status',
+			type: 'select',
+			data: [
+				{
+					label: '禁用',
+					value: '0',
+				},
+				{
+					label: '启用',
+					value: '1',
+				},
+			],
+		},
+		{
+			type: 'input',
+			prop: 'remark',
+			label: '备注',
+			border: true,
+		},
+	]
+})
+const newPassword = () => {
+	formData.data.password = generatePassword()
+}
+const generatePassword = () => {
+	var length = 12,
+		charset =
+			'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
+		password = ''
+	for (var i = 0, n = charset.length; i < length; ++i) {
+		password += charset.charAt(Math.floor(Math.random() * n))
+	}
+	return password
+}
+
+const openDtlModal = (row) => {
+    formData.data = {...row,tenantId:sourceList.value.pagination.tenantId}
+    dictCommonModal.value = true
+}
+
+const getTreeList = () => {
+	proxy.post('/tenantInfo/list').then((message) => {
+		message.map((item) => {
+			item.label = item.enterpriseName
+			item.id = item.tenantId
+			item.children = []
+		})
+        treeChange(message[0])
+		treeListData.value = message
+		console.log(treeListData.value)
+	})
+}
+const getList = async (req) => {
+	sourceList.value.pagination = { ...sourceList.value.pagination, ...req }
+	loading.value = true
+	proxy
+		.post('/dictTenantType/page', sourceList.value.pagination)
+		.then((message) => {
+			sourceList.value.data = message.rows
+			sourceList.value.pagination.total = message.total
+			setTimeout(() => {
+				loading.value = false
+			}, 200)
+		})
+}
+
+const treeChange = (e) => {
+	console.log(e)
+	sourceList.value.pagination.tenantId = e.id
+	getList({ tenantId: e.id })
+}
+
+const openModal = () => {
+	dialogVisible.value = true
+	modalType.value = 'add'
+	formData.data = {
+		userType: 1,
+	}
+}
+const TreetenantId = ref('')
+const selection = ref({
+	data: [],
+})
+const select = (_selection, row) => {
+	selection.value.data = _selection
+	console.log(_selection.length)
+}
+
+const tree = ref(null)
+const submitForm = () => {
+	byform.value.handleSubmit((valid) => {
+		
+		proxy
+			.post(
+				'/dictTenantType/' +
+					(modalType.value == 'add' ? 'add' : 'edit'),
+				{
+					...formData.data,
+					tenantId: sourceList.value.pagination.tenantId,
+				},
+			)
+			.then((res) => {
+				ElMessage({
+					message: modalType.value == 'add' ? '添加成功' : '编辑成功',
+					type: 'success',
+				})
+				dialogVisible.value = false
+				getList()
+			})
+	})
+}
+
+const getDept = () => {
+	proxy.get('/system/user/deptTree').then((res) => {
+		formConfig.value[0].data = res.data
+	})
+}
+
+const getDtl = (row) => {
+	formData.data = { ...row }
+	modalType.value = 'edit'
+	console.log(modalType.value)
+	dialogVisible.value = true
+}
+getTreeList()
+getDept()
+</script>
+    
+  <style lang="scss" scoped>
+  .dictCommonModal .el-dialog__body{
+    background: #eee;
+  }
+.user {
+	padding: 20px;
+	display: flex;
+	justify-content: space-between;
+	.tree {
+		width: 300px;
+	}
+	.content {
+		width: calc(100% - 320px);
+	}
+}
+</style>

+ 35 - 0
src/views/system/menu/index.vue

@@ -185,6 +185,7 @@
                      <el-input v-model="form.component" placeholder="请输入组件路径" />
                   </el-form-item>
                </el-col>
+               
                <el-col :span="12" v-if="form.menuType != 'M'">
                   <el-form-item>
                      <el-input v-model="form.perms" placeholder="请输入权限标识" maxlength="100" />
@@ -211,6 +212,7 @@
                      </template>
                   </el-form-item>
                </el-col>
+               
                <el-col :span="12" v-if="form.menuType == 'C'">
                   <el-form-item>
                      <template #label>
@@ -265,6 +267,39 @@
                      </el-radio-group>
                   </el-form-item>
                </el-col>
+               <el-col :span="12">
+                  <el-form-item>
+                     <template #label>
+                        <span>
+                           菜单类型
+                        </span>
+                     </template>
+                     <el-radio-group v-model="form.type">
+                        <el-radio label="1">web菜单</el-radio>
+                        <el-radio label="2">app菜单</el-radio>
+                     </el-radio-group>
+                  </el-form-item>
+               </el-col>
+               <el-col :span="12">
+                  <el-form-item>
+                     <template #label>
+                        <span>
+                           菜单背景颜色
+                        </span>
+                     </template>
+                     <el-color-picker v-model="form.background" />
+                  </el-form-item>
+               </el-col>
+               <el-col :span="12">
+                  <el-form-item>
+                     <template #label>
+                        <span>
+                           菜单图标颜色
+                        </span>
+                     </template>
+                     <el-color-picker v-model="form.color" />
+                  </el-form-item>
+               </el-col>
             </el-row>
          </el-form>
          <template #footer>