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

BIN
public/favicon.ico


+ 0 - 17
public/report.rdlx-json

@@ -1,17 +0,0 @@
-{
-  "Name": "Report",
-  "Body": {
-    "ReportItems": [
-      {
-        "Type": "textbox",
-        "Name": "TextBox1",
-        "Value": "Hello, ActiveReportsJS Viewer",
-        "Style": {
-          "FontSize": "18pt"
-        },
-        "Width": "8.5in",
-        "Height": "0.5in"
-      }
-    ]
-  }
-}

BIN
src/assets/images/login-img.png


+ 48 - 0
src/assets/styles/element-ui.scss

@@ -93,4 +93,52 @@
 
 .el-dropdown .el-dropdown-link{
   color: var(--el-color-primary) !important;
+}
+
+
+.el-form .el-form-item__label{
+	font-weight: 400!important;
+}
+.el-dialog{
+	background: #EEEEEE!important;
+}
+.el-dialog__header{
+	background: #EEEEEE;
+	padding-bottom: 14px;
+}
+.el-dialog__body{
+	background: #fff;
+  padding: 20px 30px!important;
+}
+.el-dialog__footer{
+	background: #fff;
+	text-align: center!important;
+	padding: 40px 0;
+}
+
+.el-loading-mask{
+  z-index: 1000!important;
+}
+
+.el-form-item{
+  padding: 0 10px!important;
+}
+
+.el-form-item__label{
+  height: 22px!important;
+}
+
+.el-tree-node__content{
+  height: 40px !important;
+  font-size: 12px!important;
+  color: #666!important;
+}
+
+.el-tree-node:focus>.el-tree-node__content{
+  background-color: #EFF6FF!important;
+  
+}
+
+.is-current{
+  background-color: #EFF6FF!important;
 }

+ 20 - 0
src/assets/styles/index.scss

@@ -192,3 +192,23 @@ aside {
 .multiselect--active {
   z-index: 1000 !important;
 }
+
+.commons-title{
+  font-size: 14px;
+  font-weight: 500;
+  margin-bottom: 20px;
+  padding-left: 20px;
+  position: relative;
+}
+
+.commons-title::before{
+  content: '';
+  display: inline-block;
+  width: 4px;
+  height: 14px;
+  background: #409eff;
+  margin-right: 10px;
+  position: absolute;
+  left: 0;
+  top:3px;
+}

+ 7 - 0
src/components/byForm/demo.vue

@@ -42,9 +42,15 @@ const formConfig = computed (() => {
                 width:"100px",
             },
             isLoad:{
+                //链接
                 url:"/getRouters",
+                //返回数据的路径默认返回data
                 resUrl:"",
+                //参数
+                req:{},
+                //返回数据的key
                 labelKey:"name",
+                //返回数据的value
                 labelVal:"path"
             },
         },
@@ -54,6 +60,7 @@ const formConfig = computed (() => {
             label:'时间',
             itemType:'datetimerange',
         },
+        //如果想隐藏label 打两个空格
         {
             type:"radio",
             prop:"radio",

+ 83 - 21
src/components/byForm/index.vue

@@ -5,6 +5,7 @@
 			:label-width="formOption.labelWidth"
 			:inline="formOption.inline || false"
 			:rules="rules"
+			:labelPosition="formOption.labelPosition || 'top'"
 			ref="byForm"
 		>
 			<el-form-item
@@ -13,13 +14,15 @@
 				:key="i.model"
 				:prop="i.prop"
 				:style="
-					i.itemWidth
+					i.type == 'title' ? 'width:100%' :
+						i.itemWidth
 						? 'width:' + i.itemWidth + '%'
 						: formOption.itemWidth
 						? 'width:' + formOption.itemWidth + '%'
-						: ''
+						: '100%'
 				"
 			>
+				
 				<el-input
 					v-if="i.type == 'input'"
 					v-model="formData[i.prop]"
@@ -37,8 +40,19 @@
 					:disabled="i.disabled ? i.disabled : false"
 					:style="i.style"
 				>
-					<el-option :label="j.name" :value="j.id" v-for="j in i.data" :key="j.id" />
+					<el-option :label="j.title || j.name" :value="j.id || j.value" v-for="j in i.data" :key="j.id">
+						
+					</el-option>
 				</el-select>
+				<el-tree-select
+					v-model="formData[i.prop]"
+					v-else-if="i.type == 'treeSelect'"
+					:data="i.data"
+					:props="{ value: 'id', label: 'label', children: 'children' }"
+					value-key="id"
+					:placeholder="i.placeholder || '请选择'"
+					check-strictly
+				/>
 				<el-date-picker
 					v-model="formData[i.prop]"
 					v-else-if="i.type == 'date'"
@@ -68,18 +82,50 @@
 					v-else-if="i.type == 'radio'"
 					v-model="formData[i.prop]"
 					:disabled="i.disabled ? i.disabled : false"
+					
 				>
-					<el-radio label="Sponsor" />
-					<el-radio label="Venue" />
+					<el-radio 
+						:border="i.border ? i.border : false"
+						v-for="j in i.data" :key="j.id || j.value" :label="j.id  || j.value" name="type"
+					>
+						{{ j.name || j.label }}
+					</el-radio>
 				</el-radio-group>
+				<el-input-number
+					v-else-if="i.type == 'number'"
+					v-model="formData[i.prop]"
+					:placeholder="i.placeholder || '请输入'"
+					@input="commonsEmit"
+					:disabled="i.disabled ? i.disabled : false"
+					:min="i.min ? i.min : 0"
+					:max="i.max ? i.max : 100"
+					:step="i.step ? i.step : 1">
+				</el-input-number>
+				<el-tree
+					v-else-if="i.type == 'tree'"
+					:data="i.data"
+					:props="i.props"
+					:show-checkbox="i.showCheckbox || true"
+				>
+				</el-tree>
+				<el-cascader
+					v-else-if="i.type == 'cascader'"
+					:options="i.data"
+					:props="i.props"
+					:placeholder="i.placeholder || '请选择'"
+					@change="commonsEmit"
+					:disabled="i.disabled ? i.disabled : false"
+					:style="i.style">
+				</el-cascader>
+				<div class="form-title" v-else-if="i.type == 'title'">
+					{{ i.title }}
+				</div>
 				<slot 
                     :name="i.slotName" 
                     v-else-if="i.type == 'slot'">
                     {{i.slotName}}插槽占位符
                 </slot>
 			</el-form-item>
-			<el-button @click="resetForm">qingkong</el-button>
-			
 		</el-form>
 	</div>
 </template>
@@ -109,23 +155,17 @@ defineProps({
 		default: false,
 	},
 })
+
 const isInit = ref(false)
 const { proxy } = getCurrentInstance()
 const emit = defineEmits(['update:modelValue'])
 const formData = computed(() => {
-	return proxy.modelValue
-	if(isInit.value) {
-	}else{
-		return formDataInit()
-	}
-	
+	return proxy.modelValue	
 })
 const formDataReset = ref({...proxy.modelValue})
-const onSubmit = () => {}
 const commonsEmit = (prop) => {
 	emit('update:modelValue', formData.value)
 }
-
 const loadInit = () => {
 	const v = this
 	for (let i = 0; i < proxy.formConfig.length; i++) {
@@ -135,11 +175,6 @@ const loadInit = () => {
 		}
 	}
 }
-
-const resetForm = (() => {
-	proxy.resetForm("byForm");
-})
-
 const dateFormatInit = ((itemType) => {
 	const formatObj = {
 		year:"YYYY",
@@ -180,7 +215,7 @@ const commonRecursive = (arr, labelKey, labelVal, childrenName) => {
 
 //请求form表单所需数据字典
 const commonGetdata = (isLoad,i) => {
-	proxy.get('/getRouters').then(message=>{
+	proxy[isLoad.method](isLoad.url,isLoad.req).then(message=>{
 		if (getFormat(isLoad.resUrl, message) == undefined) {
 			console.log('请查看isLoad配置是否正确url:' + isLoad.url)
 			return
@@ -197,6 +232,7 @@ const commonGetdata = (isLoad,i) => {
 	})
 }
 
+
 //根据resurl获取数据
 const getFormat = (formatStr, props) => {
 	if(!formatStr)  return props
@@ -224,6 +260,8 @@ const formDataInit = () => {
 		Solt: null,
 		Transfer: [],
 		Upload: { path: null, id: null, name: null },
+		password:'',
+		treeSelect:'',
 	}
 	const formDataCopy = { ...formData.value }
 	for (let i = 0; i < proxy.formConfig.length; i++) {
@@ -241,18 +279,42 @@ const formDataInit = () => {
 	emit('update:modelValue', formData.value)
 }
 
+const handleSubmit = (onSubmit) => {
+	proxy.$refs['byForm'].validate((valid) => {
+		if (valid) {
+			onSubmit()
+		} else {
+			ElMessage({
+				message: '请检查表单',
+				type: 'warning',
+			})
+		}
+	})
+}
+const byform = ref(null) // 延迟使用,因为还没有返回跟挂载
 onMounted(()=>{
 	
 })
+defineExpose({
+	handleSubmit,
+})
 formDataInit()
 loadInit()
 </script>
 
 <style>
 
+.form-title {
+	font-size: 14px;
+	font-weight: bold;
+	margin-top: 22px;
+	color: #333333;
+}
 .by-form .el-form--inline .el-form-item {
 	margin-right: 0px;
 	padding-right: 32px;
 	box-sizing: border-box;
 }
+
+
 </style>

+ 11 - 3
src/components/byTable/demo.vue

@@ -14,7 +14,8 @@
 				:table-events="{
 					//element talbe事件都能传
 					'row-click': handleRowClick,
-					'cell-contextmenu':handleRowClick
+					'cell-contextmenu':handleRowClick.apply,
+					'select-all':select
 				}"
 				:action-list="[
 					{
@@ -84,6 +85,7 @@ const selectConfig = computed(() => {
 		{
 			label: '合同状态1',
 			prop: 'tdaProductId',
+			
 			data: [
 				{
 					label: '已关闭',
@@ -106,6 +108,7 @@ const selectConfig = computed(() => {
 const config = computed(() => {
 	return [
 		{
+			type:"selection",
 			attrs: {
 				label: '角色名称',
 				prop: 'remark',
@@ -115,7 +118,6 @@ const config = computed(() => {
 			attrs: {
 				label: '权限字符',
 				prop: 'roleKey',
-				width: 100,
 			},
 		},
 		{
@@ -322,6 +324,13 @@ const getList = async (res) => {
 const openModal = () => {
 	dialogVisible.value = true
 }
+const select = (row, column, cell) => {
+	ElMessage({
+		dangerouslyUseHTMLString: true, // Be careful :)
+		message: `点了全选`,
+	})
+
+}
 const handleRowClick = (row, column, cell) => {
 	ElMessage({
 		dangerouslyUseHTMLString: true, // Be careful :)
@@ -372,7 +381,6 @@ getList()
 .box-container {
 	.content {
 		position: relative;
-
 		margin: 0 auto;
 	}
 }

+ 18 - 13
src/components/byTable/index.vue

@@ -8,6 +8,7 @@
         		:plain="item.plain || false"
 				v-bind="getHeaderActions(item)"
 				@click="item.action"
+				:disabled="item.disabled || false"
 			>
 				{{ item.text }}
 			</el-button>
@@ -67,22 +68,21 @@
 				style="width: 100%"
 				v-bind="$attrs"
 				v-on="tableEvents"
+				
 			>
 				<el-table-column
 					v-for="(item, index) in config"
 					:key="index"
 					v-bind="getAttrsValue(item)"
+					:type="item.type || ''"
 				>
-					<template #default="scope" v-if="item.attrs.slot">
-						
-						<slot :name="item.attrs.slot" :item="scope.row">
+					
+					
+					<template #default="scope" v-if="!item.type">
+						<slot :name="item.attrs.slot" :item="scope.row"  v-if="item.attrs.slot">
 							插槽占位符
 						</slot>
-					</template>
-					
-					<template #default="scope" v-else>
-						
-						<div v-if="isFunction(getValue(scope, item))">
+						<div v-else-if="isFunction(getValue(scope, item))">
 							
 
 							<component
@@ -120,7 +120,7 @@
 				<el-pagination
 					background
 					layout="total, sizes, prev, pager, next, jumper"
-					:current-page="getPagination.currentPage"
+					:current-page="getPagination.pageNum"
 					:page-size="getPagination.pageSize"
 					:total="getPagination.total"
 					@size-change="handleSizeChange"
@@ -226,7 +226,7 @@ export default defineComponent({
 			default() {
 				return {}
 			},
-		},
+		}
 	},
 	setup(props) {
 		
@@ -262,7 +262,7 @@ export default defineComponent({
 		})
 		const getPagination = computed(() => {
 			const params = {
-				currentPage: 1,
+				pageNum: 1,
 				pageSize: 10,
 				total: 0,
 			}
@@ -320,7 +320,7 @@ export default defineComponent({
 		const handlePageChange = (val) => {
 			proxy.$emit(
 				'getList',
-				Object.assign(props.filterParams, { page: val })
+				Object.assign(props.filterParams, { pageNum: val })
 			)
 		}
 		const handleSizeChange = (val) => {
@@ -393,8 +393,13 @@ export default defineComponent({
 .table-list-container th {
 	color: #333 !important;
 }
-.by-table .el-table-fixed-column--right .el-button{
+.by-table td .el-button+.el-button{
+	margin-left: 0!important;
+}
+.by-table td .el-button{
 	background: none!important;
+	margin: 0!important;
+	padding:8px 6px!important;
 }
 </style>
   <style lang="scss" scoped>

+ 185 - 119
src/components/headerBar/header-bar.vue

@@ -4,7 +4,7 @@
 			<ul class="nav">
 				<div class="logo">GrandStar</div>
 				<li class="header-bar-hover-warp nav-li">
-					<div @click="isChildMenu = !isChildMenu" class="menu-modal">
+					<div @click="isChildMenu = !isChildMenu" class="menu-modal" style="font-size: 12px;">
 						功能导览
 						<i class="el-icon-arrow-down el-icon--right"></i>
 					</div>
@@ -15,27 +15,64 @@
 				<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">
-							<ul class="menu-warp">
-								<li
-									v-for="(i, index) in sidebarRouters"
-									:key="index"
-									class="menu-ul"
-								>
-									<div class="menu-title">
-										{{ i.meta.title }}
-									</div>
-									<ul style="background: #fff">
+							<div class="left-banner">
+								<div class="first-order">
+									<el-icon size="16" color="#0084FF">
+										<edit />
+									</el-icon>
+									常用功能
+								</div>
+								<div class="first-order">
+									<el-icon size="16" color="#0084FF">
+										<edit />
+									</el-icon>
+									订购服务
+								</div>
+								<ul>
+									<li>外贸ERP</li>
+									<li>云仓</li>
+									<li>办公OA</li>
+									<li>供应链</li>
+									<li>产品库</li>
+								</ul>
+								<div class="first-order">
+									<el-icon size="16" color="#0084FF">
+										<edit /> 
+									</el-icon>
+									推荐服务
+								</div>
+							</div>
+							<div class="menu-warp">
+								<div class="first-order-title">
+									外贸ERP
+								</div>
+								<ul class="second-level">
+									<div v-for="(i, index) in sidebarRouters"
+											:key="index">
+										<li
+											v-if="i.isNone"
+											class="menu-ul"
+											style="cursor: auto;"
+										></li>
+										<li class="menu-title" v-else-if="i.isTitle">
+											<el-icon size="16" color="#0084FF">
+												<edit />
+											</el-icon>
+											{{ i.meta.title }}
+										</li>
 										<li
-											@click="routerPush(i, j)"
+											v-else
+											class="menu-ul"
+											@click="routerPush(i)"
 											style="cursor: pointer"
-											v-for="(j, jindex) in i.children"
-											:key="jindex"
 										>
-											{{ j.meta.title }}
+											{{ i.meta.title }}
 										</li>
-									</ul>
-								</li>
-							</ul>
+									</div>
+									
+								</ul>
+								
+							</div>
 						</div>
 					</div>
 				</div>
@@ -99,14 +136,51 @@ const router = useRouter()
 const userStore = useUserStore()
 const permissionStore = usePermissionStore()
 
-const sidebarRouters = computed(() => permissionStore.addRoutes)
-console.log(sidebarRouters)
-
+const sidebarRouters = ref([])
 const input1 = ref('')
 const isChildMenu = ref(false)
 const menuData = ref([])
 const barData = ref([])
 const userData = ref(Cookies.get('username') || '')
+
+const routerInit = (() => {
+	//二维转一维
+	const arr = []
+	for (let i = 0; i < permissionStore.addRoutes.length; i++) {
+		const element = permissionStore.addRoutes[i];
+		element.isTitle = true
+		arr.push(element)
+		if(element.children && element.children.length > 0){
+			for (let j = 0; j < element.children.length; j++) {
+				const jelement = element.children[j];
+				jelement.isTitle = false
+				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 % 10 + element.children.length + 1 > 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++
+					}
+				}
+			}
+			num ++ 
+		}else{
+			num ++ 
+		}
+	}
+	sidebarRouters.value = arr
+})
 function handleCommand(command) {
 	switch (command) {
 		case 'setLayout':
@@ -134,11 +208,16 @@ function logout() {
 		.catch(() => {})
 }
 //拼接url跳转
-function routerPush(i, j) {
-	router.push(i.path + '/' + j.path)
+function routerPush(i) {
+	router.push(i.fatherPath + '/' + i.path)
 	this.isChildMenu = false
 }
-function getData() {}
+
+onMounted(()=>{
+	routerInit()
+})
+
+
 </script>
   
 <style  lang="scss">
@@ -150,6 +229,7 @@ function getData() {}
 	bottom: 0;
 	background: rgba(0, 0, 0, 0.5);
 	z-index: 1100;
+	
 }
 .header-bar {
 	background: #20222a;
@@ -158,12 +238,17 @@ function getData() {}
 	left: 0;
 	right: 0;
 	z-index: 1100;
-
+	ul,li{
+		list-style: none;
+		padding: 0;
+	}
 	.avatar-wrapper {
 		margin-top: 10px;
 	}
 	.menu-modal {
 		cursor: pointer;
+		font-size: 12px;
+		font-weight: 300;
 	}
 	.header-bar-hover {
 		position: fixed;
@@ -171,13 +256,40 @@ function getData() {}
 		top: 50px;
 		left: 0px;
 		right: 0;
-		display: flex;
 		background: #fff;
 		box-shadow: 0px 3px 10px 1px rgba(0, 0, 0, 0.1);
 		height: 500px;
+
 		.header-bar-hover-content {
-			margin: 32px 20px;
+			display: flex;
 			text-align: left;
+			.left-banner{
+				width: 230px;
+				ul{
+					background: #F1F1F1;
+					li{
+						height: 50px;
+						line-height: 50px;
+						padding: 0 50px;
+						font-size: 12px;
+						cursor: pointer;
+					}
+				}
+				.first-order{
+					height: 50px;
+					padding: 0 20px;
+					line-height: 50px;
+					font-size: 14px;
+					font-weight: bold;
+					background: #F9F9F9;
+					cursor: pointer;
+					i{
+						position: relative;
+						top: 3px;
+						margin-right: 5px;
+					}
+				}
+			}
 			.el-alert {
 				line-height: 20px;
 				text-align: center;
@@ -189,106 +301,60 @@ function getData() {}
 					color: #46a6ff;
 				}
 			}
-			.fun-lists {
-				width: 700px;
-				overflow: hidden;
-				.fun-list {
-					width: 120px;
-					height: 40px;
-					margin: 20px 20px 0 0;
-					background: #f1f1f1;
-					border-radius: 4px 4px 4px 4px;
-					line-height: 40px;
-					color: #333333;
-					font-size: 12px;
-					float: left;
-					text-align: center;
-					cursor: pointer;
-					span {
-						margin-left: 10px;
-					}
-				}
-				.fun-list.active {
-					border: 1px solid #46a6ff;
-					background: #fff;
-					color: #46a6ff;
-					box-sizing: border-box;
-					i {
-						color: #46a6ff;
-					}
-				}
-			}
 		}
-
-		ul {
-			padding: 0 20px;
-			margin: 0;
-			width: 230px;
-			background: #f1f1f1;
-			text-align: left;
-
-			li {
+		.menu-warp {
+			width: calc(100vw - 230px);
+			background: #fff;
+			overflow: hidden;
+			box-sizing: border-box;
+			padding: 0 40px;
+			height: 500px;
+			overflow-y: auto;
+			.first-order-title{
+				height: 70px;
+				line-height: 70px;
 				color: #333333;
-				list-style: none;
-				margin: 0;
-				position: relative;
-				.text {
-					margin-left: 10px;
-					font-size: 14px;
-					font-weight: bold;
-				}
-				.el-icon-arrow-down {
-					position: absolute;
-					right: 0;
-					top: 20px;
-				}
-				.child-menu {
-					margin-left: 24px;
-					font-size: 12px;
-					font-weight: 400;
-				}
+				font-size: 15px;
+				font-weight: bold;
 			}
-			.active-warp {
-				cursor: pointer;
+			.second-level{
+				overflow: hidden;
+				height:420px;
+				display: flex;
+				flex-wrap:wrap;
+				flex-direction:column;
+				flex-grow:0;
+				flex-basis:auto;
 			}
-
-			.active-warp:hover {
-				color: #0084ff;
-				i {
-					color: #0084ff;
+			.menu-title {
+				font-weight: 600;
+				color: #0084FF;
+				height: 40px;
+				line-height: 40px;
+				border-bottom: 1px solid #ddd;
+				font-size: 14px;
+				width: 140px;
+				margin: 0 100px 0 0;
+				i{
+					position: relative;
+					top:3px;
+					margin-right: 5px;
 				}
 			}
-		}
-		.menu-warp {
-			width: 100vw;
-			background: #fff;
-			overflow: hidden;
 			.menu-ul {
 				float: left;
-				width: 100px;
-				margin-right: 80px;
-				.menu-title {
-					font-weight: bold;
-					color: #333333;
-					height: 40px;
-					line-height: 40px;
-					border-bottom: 1px solid #ddd;
-				}
-				ul {
-					li {
-						list-style: none;
-						margin: 0;
-						padding: 0;
-						height: 34px;
-						line-height: 34px;
-						font-size: 12px;
-						font-weight: 400;
-						cursor: pointer;
-					}
-					li:hover {
-						color: #0084ff;
-					}
-				}
+				width: 140px;
+				list-style: none;
+				margin: 0 100px 0 0;
+				padding: 0;
+				height: 36px;
+				line-height: 36px;
+				font-size: 12px;
+				font-weight: 400;
+				cursor: pointer;
+			}
+			.menu-ul:hover{
+				color: #0084ff;
 			}
 		}
 	}

+ 87 - 0
src/components/treeList/index.vue

@@ -0,0 +1,87 @@
+<!--treeList组件封装-->
+<template>
+	<div class="treeList">
+		<div class="title commons-title">
+			{{title}}
+		</div>
+		<div class="search">
+			<el-input
+				v-model="search"
+				placeholder="请输入搜索内容"
+				clearable
+				@clear="search = ''"
+				@keyup.enter="searchChange"
+			></el-input>
+			<el-button type="primary" @click="searchChange">搜索</el-button>
+		</div>
+		<el-tree
+			:data="data"
+			ref="tree"
+			:node-key="['node-key']"
+			@node-click="treeChange"
+			:filter-node-method="filterNode"
+		>
+		</el-tree>
+	</div>
+</template>
+<script setup>
+defineProps({
+	title: {
+		type: String,
+		default: '租户列表',
+	},
+	type: {
+		type: String,
+		default: 'radio',
+	},
+	data: {
+		type: Array,
+		default: () => [],
+	},
+	modelValue: {
+		type: Array || String,
+	},
+	'node-key': {
+		type: String,
+		default: 'id',
+	},
+})
+const search = ref('')
+const emit = defineEmits(['update:modelValue'])
+const { proxy } = getCurrentInstance()
+const treeChange = (e, data) => {
+	if (proxy.type == 'radio') {
+		emit('update:modelValue', e.id)
+		emit('change', e)
+	} else {
+		emit('change', e)
+	}
+}
+
+const filterNode = (value, data,node) => {
+	if (!value) return true
+	return data.label.indexOf(value) !== -1
+}
+
+const searchChange = () => {
+	proxy.$refs.tree.filter(search.value)
+}
+</script>
+
+<style lang="scss">
+.treeList {
+	display: block;
+	height: 100%;
+	background: #fff;
+	padding: 20px;
+	.search {
+		margin-bottom: 20px;
+		.el-input {
+			width: calc(100% - 70px);
+			margin-right: 10px;
+			text-align: center;
+		}
+	}
+}
+
+</style>

+ 10 - 12
src/utils/request.js

@@ -37,6 +37,7 @@ service.interceptors.request.use(config => {
     config.url = url;
   }
   if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
+    
     const requestObj = {
       url: config.url,
       data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
@@ -102,7 +103,6 @@ service.interceptors.response.use(res => {
     }
   },
   error => {
-    console.log('err' + error)
     let { message } = error;
     if (message == "Network Error") {
       message = "后端接口连接异常";
@@ -115,7 +115,6 @@ service.interceptors.response.use(res => {
     return Promise.reject(error)
   }
 )
-
 // 通用下载方法
 export function download(url, params, filename, config) {
   downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)", })
@@ -165,18 +164,17 @@ export function get(url, params = {}) {
 * @returns {Promise}
 */
 
-export function post(url, data = {},params,headers) {
+export function post(url, data = {},method) {
   return new Promise((resolve, reject) => {
-      
-      service.post(url, data = {},{
+      console.log(method)
+      service({
+        method: method || 'post',
+        url:url,
+        data: data,
+      }).then(res=>{
+        resolve(res.data);
       })
-          .then(response => {
-              setTimeout(() => {
-              }, 500)
-              resolve(response.data);
-          }, err => {
-              reject(err)
-          })
+      
   })
 }
 

+ 9 - 0
src/views/login.vue

@@ -15,6 +15,7 @@
 								<el-input
 									placeholder="请输入租户号"
 									prefix-icon="user"
+									@keyup.enter="handleLogin"
 									v-model="loginForm.tenantId">
 									
 								</el-input>
@@ -23,6 +24,7 @@
 								<el-input
 									placeholder="请输入账号"
 									prefix-icon="UserFilled"
+									@keyup.enter="handleLogin"
 									v-model="loginForm.username">
 								</el-input>
 							</el-form-item>
@@ -72,6 +74,7 @@ const loginForm = ref({
 	username: 'admin',
 	password: 'admin123',
 	rememberMe: false,
+	tenantId:'000000',
 	code: '',
 	uuid: '',
 })
@@ -99,6 +102,9 @@ function handleLogin() {
 				Cookies.set('username', loginForm.value.username, {
 					expires: 30,
 				})
+				Cookies.set('tenantId', loginForm.value.tenantId, {
+					expires: 30,
+				})
 				Cookies.set('password', encrypt(loginForm.value.password), {
 					expires: 30,
 				})
@@ -107,6 +113,7 @@ function handleLogin() {
 				})
 			} else {
 				// 否则移除
+				Cookies.remove('tenantId')
 				Cookies.remove('username')
 				Cookies.remove('password')
 				Cookies.remove('rememberMe')
@@ -143,6 +150,7 @@ function getCookie() {
 	const username = Cookies.get('username')
 	const password = Cookies.get('password')
 	const rememberMe = Cookies.get('rememberMe')
+	const tenantId = Cookies.get('tenantId')
 	loginForm.value = {
 		username: username === undefined ? loginForm.value.username : username,
 		password:
@@ -150,6 +158,7 @@ function getCookie() {
 				? loginForm.value.password
 				: decrypt(password),
 		rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
+		tenantId: tenantId === undefined ? loginForm.value.tenantId : tenantId,
 	}
 }
 

+ 368 - 0
src/views/system/role2/index.vue

@@ -0,0 +1,368 @@
+<template>
+	<div class="role">
+        <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"
+				:table-events="{
+					//element talbe事件都能传
+					'select': select,
+				}"
+				:action-list="[
+					{
+						text: '权限配置',
+						plain: true,
+						//type: 'warning',
+						action: () => openRoomModal(),
+						disabled:selection.data.length != 1,
+					},
+					{
+						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"
+			>
+				
+			</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="roomDialogVisible"
+			width="500"
+			:before-close="handleClose"
+			v-loading="loading">
+				
+				<el-tree
+					:data="treeData"
+					:show-checkbox="true"
+					v-model="formData.treeData"
+					ref="tree"
+					node-key="id"
+				>
+				</el-tree>
+			<template #footer>
+				<el-button @click="roomDialogVisible = false" size="large"
+					>取 消</el-button
+				>
+				<el-button
+					type="primary"
+					@click="submitTree('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 treeList from '@/components/treeList/index'
+import { computed, defineComponent, ref } from 'vue'
+const loading = ref(false)
+const submitLoading = 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({
+	tenantId: [{ required: true, message: '请输入活动名称', trigger: 'blur' }],
+})
+const { proxy } = getCurrentInstance()
+const selectConfig = computed(() => {
+	return [
+	]
+})
+const config = computed(() => {
+	return [
+        {
+			type: 'selection',
+			attrs: {
+				label: '多选',
+				prop: 'remark',
+			},
+		},
+		{
+			attrs: {
+				label: '角色编码',
+				prop: 'roleKey',
+			},
+		},
+		{
+			attrs: {
+				label: '角色名称',
+				prop: 'roleName',
+				align: 'left',
+			},
+		},
+		{
+			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: '删除',
+							type: 'danger',
+							text: true,
+						},
+						el: 'button',
+						click() {
+							// 弹窗提示是否删除
+							ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', {
+								confirmButtonText: '确定',
+								cancelButtonText: '取消',
+								type: 'warning',
+							})
+								.then(() => {
+									// 删除
+									proxy.post('/tenantRole/' + row.tenantId, {
+										id: row.id,
+									},'delete').then((res) => {
+										ElMessage({
+											message: '删除成功',
+											type: 'success',
+										})
+										proxy.getList()
+									})
+								})
+						},
+					},
+				]
+			},
+		},
+	]
+})
+
+let formData = reactive({
+	data:{},
+	treeData:[],
+})
+const formOption = reactive({
+	inline: true,
+	labelWidth: 100,
+	itemWidth: 100,
+	rules: [],
+})
+const byform = ref(null)
+const treeData = ref([])
+const treeListData = ref([])
+const formConfig = computed(() => {
+	return [
+        
+		{
+			type: 'input',
+			prop: 'roleKey',
+			label: '角色编码',
+			required: true,
+			itemWidth: 100,
+			//disabled:true,
+			itemType: 'text',
+		},
+		{
+			type: 'input',
+			prop: 'roleName',
+			label: '角色名称',
+			required: true,
+			itemWidth: 100,
+			//disabled:true,
+			itemType: 'text',
+		},
+	]
+})
+const getTreeList = () => {
+    proxy.post('/tenantInfo/list').then((message) => {
+        message.map((item) => {
+            item.label = item.enterpriseName
+            item.id = item.tenantId
+            item.children = []
+        })
+        treeListData.value = message
+        console.log(treeListData.value)
+    })
+}
+const getList = async (req) => {
+	sourceList.value.pagination = { ...sourceList.value.pagination, ...req }
+	loading.value = true
+	proxy.get('/tenantRole/list',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 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 = {}
+	
+}
+const TreetenantId = ref('')
+const selection = ref({
+	data:[],
+})
+const select = (_selection, row) => {
+	selection.value.data = _selection
+	console.log(_selection.length)
+}
+const openRoomModal = () => {
+	roomDialogVisible.value = true
+	proxy.get('/tenantInfo/roleMenuTreeSelect/' + selection.value.data[0].tenantId).then((res) => {
+		if(res.code == 200){
+			treeData.value = res.menus
+			formData.treeData = res.checkedKeys
+			tree.value.setCheckedKeys(res.checkedKeys)
+		}
+	})
+	
+}
+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 = () => {
+	
+	byform.value.handleSubmit((valid) => {
+		const method = modalType.value == 'add' ? 'POST' : 'PUT'
+		console.log(method)
+		proxy.post(
+				'/tenantRole',
+				{...formData.data,
+					tenantId:sourceList.value.pagination.tenantId,
+					roleSort:1,
+					status:"0"},
+					method
+				).then((res) => {
+			ElMessage({
+				message: modalType.value == 'add' ? '添加成功' : '编辑成功',
+				type: 'success',  
+			})
+			dialogVisible.value = false
+			getList()
+		})
+	})
+}
+
+const getDtl = (row) => {
+	formData.data = {...row}
+	
+	modalType.value = 'edit'
+	console.log(modalType.value)
+	dialogVisible.value = true
+}
+getTreeList()
+getList()
+</script>
+  
+<style lang="scss" scoped>
+.role {
+	padding: 20px;
+    display: flex;
+    justify-content: space-between;
+    .tree{
+        width: 300px;
+    }
+    .content{
+        width:calc(100% - 320px);
+    }
+}
+</style>

+ 404 - 0
src/views/system/tenant/index.vue

@@ -0,0 +1,404 @@
+<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: '权限配置',
+						plain: true,
+						//type: 'warning',
+						action: () => openRoomModal(),
+						disabled:selection.data.length != 1,
+					},
+					{
+						text: '添加租户',
+						action: () => openModal('add'),
+					},
+				]"
+				@get-list="getList"
+			>
+				<template #slotName="{ item }">
+					{{ item.createTime }}
+				</template>
+			</byTable>
+		</div>
+		<el-dialog
+			:title="modalType == 'add' ? '新增' : '编辑'"
+			v-model="dialogVisible"
+			width="800"
+			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>
+		<el-dialog
+			title="权限配置"
+			v-model="roomDialogVisible"
+			width="500"
+			:before-close="handleClose"
+			v-loading="loading">
+				
+				<el-tree
+					:data="treeData"
+					:show-checkbox="true"
+					v-model="formData.treeData"
+					ref="tree"
+					node-key="id"
+				>
+				</el-tree>
+			<template #footer>
+				<el-button @click="roomDialogVisible = false" size="large"
+					>取 消</el-button
+				>
+				<el-button
+					type="primary"
+					@click="submitTree('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 } from 'vue'
+const loading = ref(false)
+const submitLoading = 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({
+	tenantId: [{ required: true, message: '请输入活动名称', trigger: 'blur' }],
+})
+const { proxy } = getCurrentInstance()
+const selectConfig = computed(() => {
+	return [
+		{
+			label: '审核状态',
+			prop: 'flowStatus',
+			data: [
+				{
+					label: '审核中',
+					value: '1',
+				},
+				{
+					label: '审核通过',
+					value: '2',
+				},
+				{
+					label: '审核不通过',
+					value: '3',
+				},
+			],
+		},
+		{
+			label: '启用状态',
+			prop: 'status',
+			data: [
+				{
+					label: '启用',
+					value: '1',
+				},
+				{
+					label: '禁用',
+					value: '0',
+				},
+			],
+		},
+	]
+})
+const config = computed(() => {
+	return [
+		{
+			type: 'selection',
+			attrs: {
+				label: '多选',
+				prop: 'remark',
+			},
+		},
+		{
+			attrs: {
+				label: '企业名称',
+				prop: 'enterpriseName',
+			},
+		},
+		{
+			attrs: {
+				label: '租户id',
+				prop: 'tenantId',
+				align: 'center',
+			},
+		},
+		{
+			attrs: {
+				label: '已创建账号数',
+				prop: 'accountCount',
+				align: 'center',
+			},
+		},
+		{
+			attrs: {
+				label: '审核状态',
+				width: 100,
+				prop: 'flowStatus',
+			},
+			render(flowStatus) {
+				//1审核中 2审核通过 3审核不通过
+				return flowStatus == 1
+					? '审核中'
+					: flowStatus == 2
+					? '审核通过'
+					: '审核不通过'
+			},
+		},
+		{
+			attrs: {
+				label: '启用状态',
+				prop: 'createTime',
+			},
+			render(status) {
+				return status ? '启用' : '禁用'
+			},
+		},
+		{
+			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: 'danger',
+							text: true,
+						},
+						el: 'button',
+						click() {
+							// 弹窗提示是否删除
+							ElMessageBox.confirm('此操作将永久删除该数据, 是否继续?', '提示', {
+								confirmButtonText: '确定',
+								cancelButtonText: '取消',
+								type: 'warning',
+							})
+								.then(() => {
+									// 删除
+									proxy.post('/tenantInfo/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: 'tenantId',
+			label: '租户id',
+			required: true,
+			itemWidth: 100,
+			//disabled:true,
+			itemType: 'text',
+		},
+		{
+			type: 'input',
+			prop: 'enterpriseName',
+			label: '企业名称',
+		},
+		{
+			type: 'radio',
+			prop: 'status',
+			label: '启用状态',
+			border: true,
+			data: [
+				{
+					label: '启用',
+					value: 1,
+				},
+				{
+					label: '禁用',
+					value: 0,
+				},
+			],
+		},
+		{
+			type: 'title',
+			title: '管理员信息',
+		},
+		{
+			type: 'input',
+			itemType: 'password',
+			prop: 'password',
+			label: '密码',
+		},
+	]
+})
+const getList = async (req) => {
+	sourceList.value.pagination = { ...sourceList.value.pagination, ...req }
+	loading.value = true
+	proxy.post('/tenantInfo/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 selection = ref({
+	data:[],
+})
+const select = (_selection, row) => {
+	selection.value.data = _selection
+	console.log(_selection.length)
+}
+const openRoomModal = () => {
+	
+	roomDialogVisible.value = true
+	
+	proxy.get('/tenantInfo/roleMenuTreeSelect/' + selection.value.data[0].tenantId).then((res) => {
+		if(res.code == 200){
+			treeData.value = res.menus
+			formData.treeData = res.checkedKeys
+			tree.value.setCheckedKeys(res.checkedKeys)
+		}
+	})
+	
+}
+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)
+		dialogVisible.value = true
+	})
+}
+
+getList()
+</script>
+  
+<style lang="scss" scoped>
+.tenant {
+	padding: 20px;
+}
+</style>

+ 427 - 0
src/views/system/user2/index.vue

@@ -0,0 +1,427 @@
+<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"
+				: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="roomDialogVisible"
+			width="500"
+			:before-close="handleClose"
+			v-loading="loading"
+		>
+			<template #footer>
+				<el-button @click="roomDialogVisible = false" size="large"
+					>取 消</el-button
+				>
+				<el-button
+					type="primary"
+					@click="submitTree('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 treeList from '@/components/treeList/index'
+import { computed, defineComponent, ref } from 'vue'
+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({
+	roleKey: [{ required: true, message: '请选择部门', trigger: 'blur' }],
+    nickName: [{ required: true, message: '姓名不能为空', trigger: 'blur' }],
+    userName:[{ required: true, message: '用户名不能为空', trigger: 'blur' }],
+})
+const { proxy } = getCurrentInstance()
+const selectConfig = computed(() => {
+	return []
+})
+const config = computed(() => {
+	return [
+		{
+			attrs: {
+				label: '部门',
+				prop: 'deptName',
+			},
+		},
+		{
+			attrs: {
+				label: '姓名',
+				prop: 'userName',
+				align: 'left',
+			},
+		},
+		{
+			attrs: {
+				label: '用户名',
+				prop: 'nickName',
+			},
+		},
+		{
+			attrs: {
+				label: '系统用户',
+				prop: 'remark',
+			},
+		},
+		{
+			attrs: {
+				label: '手机号',
+				prop: 'phonenumber',
+			},
+		},
+		{
+			attrs: {
+				label: '工号',
+				prop: 'jobNumber',
+			},
+		},
+		{
+			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: 'danger',
+							text: true,
+						},
+						el: 'button',
+						click() {
+							// 弹窗提示是否删除
+							ElMessageBox.confirm(
+								'此操作将永久删除该数据, 是否继续?',
+								'提示',
+								{
+									confirmButtonText: '确定',
+									cancelButtonText: '取消',
+									type: 'warning',
+								}
+							).then(() => {
+								// 删除
+								proxy
+									.post(
+										'/tenantUser/' + row.userId,
+										{
+											id: row.userId,
+										},
+										'delete'
+									)
+									.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: 'treeSelect',
+			prop: 'deptId',
+			label: '部门名称',
+			data: [],
+		},
+		{
+			type: 'input',
+			prop: 'nickName',
+			label: '姓名',
+			required: true,
+			itemWidth: 50,
+			//disabled:true,
+			itemType: 'text',
+		},
+        {
+            type: 'slot',
+            prop: 'userName',
+            slotName: 'account',
+            label:"账户信息"
+        },
+		{
+			type: 'radio',
+			prop: 'userType',
+			label: '系统用户',
+			required: true,
+			border: true,
+			data: [
+				{
+					label: '是',
+					id: 1,
+				},
+				{
+					label: '否',
+					id: 0,
+				},
+			],
+		},
+		{
+			type: 'select',
+			label: '角色',
+			prop: 'roleIds',
+            multiple: true,
+			isLoad: {
+				url: '/tenantRole/list?pageNum=1&pageSize=10000',
+				labelKey: 'roleName',
+				labelVal: 'roleId',
+				method: 'get',
+				resUrl: 'rows',
+			},
+		},
+		{
+			type: 'input',
+			prop: 'phonenumber',
+			label: '手机号',
+			required: true,
+			itemWidth: 50,
+			//disabled:true,
+			itemType: 'text',
+		},
+		{
+			type: 'input',
+			prop: 'jobNumber',
+			label: '工号',
+			required: true,
+			itemWidth: 50,
+			//disabled:true,
+			itemType: 'text',
+		},
+	]
+})
+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 getTreeList = () => {
+	proxy.post('/tenantInfo/list').then((message) => {
+		message.map((item) => {
+			item.label = item.enterpriseName
+			item.id = item.tenantId
+			item.children = []
+		})
+		
+		treeListData.value = message
+		console.log(treeListData.value)
+	})
+
+}
+const getList = async (req) => {
+	sourceList.value.pagination = { ...sourceList.value.pagination, ...req }
+	loading.value = true
+	proxy
+		.get('/tenantUser/list', sourceList.value.pagination)
+		.then((message) => {
+			message.rows.map((item) => {
+				item.deptName = item.dept ? item.dept.deptName : item.dept
+			})
+			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 = {}
+}
+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) => {
+		const method = modalType.value == 'add' ? 'POST' : 'PUT'
+		console.log(method)
+		proxy
+			.post(
+				'/tenantUser',
+				{
+					...formData.data,
+					tenantId: sourceList.value.pagination.tenantId,
+				},
+				method
+			)
+			.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()
+getList()
+getDept()
+</script>
+  
+<style lang="scss" scoped>
+.user {
+	padding: 20px;
+	display: flex;
+	justify-content: space-between;
+	.tree {
+		width: 300px;
+	}
+	.content {
+		width: calc(100% - 320px);
+	}
+}
+</style>