Files
smartDriveEEFront/src/views/lb-business/department-user/index.vue
2026-04-26 11:52:04 +08:00

611 lines
20 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<el-card class="filter-container" shadow="never">
<el-form :model="queryParams" :inline="true" label-width="100px">
<el-form-item label="租户ID">
<el-input v-model="queryParams.tenantId" clearable placeholder="请输入租户ID" style="width: 180px" />
</el-form-item>
<el-form-item label="用户ID">
<el-input v-model="queryParams.userId" clearable placeholder="请输入用户ID" style="width: 180px" />
</el-form-item>
<el-form-item label="父级ID">
<el-input v-model="queryParams.parentId" clearable placeholder="请输入父级ID" style="width: 180px" />
</el-form-item>
<el-form-item label="姓名">
<el-input v-model="queryParams.name" clearable placeholder="请输入姓名" style="width: 180px" />
</el-form-item>
<el-form-item label="电话">
<el-input v-model="queryParams.phone" clearable placeholder="请输入电话" style="width: 180px" />
</el-form-item>
<el-form-item label="行业">
<el-input v-model="queryParams.industry" clearable placeholder="请输入行业" style="width: 180px" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
<el-button icon="el-icon-delete" @click="resetQuery">清空</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="action-container" shadow="never">
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">新增</el-button>
</el-card>
<el-card class="table-container" shadow="never">
<el-table v-loading="loading" :data="list" style="width: 100%">
<el-table-column label="租户ID" prop="tenantId" min-width="140" show-overflow-tooltip />
<el-table-column label="用户ID" prop="userId" min-width="140" show-overflow-tooltip />
<el-table-column label="父级ID" prop="parentId" min-width="140" show-overflow-tooltip />
<el-table-column label="姓名" prop="name" min-width="120" />
<el-table-column label="电话" prop="phone" min-width="120" />
<el-table-column label="地址" prop="address" min-width="160" show-overflow-tooltip />
<el-table-column label="行业" prop="industry" min-width="120" />
<el-table-column label="加入日期" prop="joinDate" min-width="120" />
<el-table-column label="创建时间" prop="createTime" min-width="170">
<template slot-scope="scope">
{{ formatDateTime(scope.row.createTime) }}
</template>
</el-table-column>
<el-table-column label="更新时间" prop="updateTime" min-width="170">
<template slot-scope="scope">
{{ formatDateTime(scope.row.updateTime) }}
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="220">
<template slot-scope="scope">
<el-button type="text" @click="handleEdit(scope.row)">编辑</el-button>
<el-button type="text" @click="handleFindParent(scope.row)">找上级</el-button>
<el-button type="text" style="color:#F56C6C;" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
:current-page="queryParams.current"
:page-size="queryParams.size"
:page-sizes="[10, 20, 50, 100]"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</el-card>
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="760px" @close="resetForm">
<el-form ref="dataForm" :model="form" :rules="formRules" label-width="120px">
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="租户ID" prop="tenantId">
<el-input v-model="form.tenantId" placeholder="请输入租户ID" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="用户ID" prop="userId">
<el-input v-model="form.userId" placeholder="请输入用户ID" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="父级ID" prop="parentId">
<el-input v-model="form.parentId" placeholder="请输入父级ID" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="姓名" prop="name">
<el-input v-model="form.name" placeholder="请输入姓名" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="电话" prop="phone">
<el-input v-model="form.phone" placeholder="请输入电话" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="行业" prop="industry">
<el-input v-model="form.industry" placeholder="请输入行业" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="地址" prop="address">
<el-input v-model="form.address" type="textarea" :rows="2" placeholder="请输入地址" />
</el-form-item>
<el-form-item label="加入日期" prop="joinDate">
<el-date-picker
v-model="form.joinDate"
type="date"
clearable
value-format="yyyy-MM-dd"
placeholder="请选择加入日期"
style="width: 100%"
/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">确定</el-button>
</div>
</el-dialog>
<el-dialog title="找上级 - 人员列表" :visible.sync="parentDialogVisible" width="980px" @close="resetParentDialog">
<el-form :model="parentQueryParams" :inline="true" label-width="70px">
<el-form-item label="姓名">
<el-input v-model="parentQueryParams.name" clearable placeholder="请输入姓名" style="width: 160px" />
</el-form-item>
<el-form-item label="电话">
<el-input v-model="parentQueryParams.phone" clearable placeholder="请输入电话" style="width: 160px" />
</el-form-item>
<el-form-item label="行业">
<el-input v-model="parentQueryParams.industry" clearable placeholder="请输入行业" style="width: 160px" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleParentQuery">查询</el-button>
<el-button icon="el-icon-delete" @click="resetParentQuery">清空</el-button>
</el-form-item>
</el-form>
<el-alert
v-if="currentParentTarget && currentParentTarget.name"
:title="`当前记录:${currentParentTarget.name}${currentParentTarget.id || '-'}`"
type="info"
:closable="false"
show-icon
class="parent-alert"
/>
<el-table
ref="parentTable"
v-loading="parentLoading"
:data="parentList"
row-key="id"
style="width: 100%"
@selection-change="handleParentSelectionChange"
>
<el-table-column type="selection" width="35" />
<el-table-column label="用户ID" prop="userId" min-width="180" show-overflow-tooltip />
<el-table-column label="姓名" prop="name" min-width="120" />
<el-table-column label="电话" prop="phone" min-width="120" />
</el-table>
<el-pagination
:current-page="parentQueryParams.current"
:page-size="parentQueryParams.size"
:page-sizes="[10, 20, 50, 100]"
:total="parentTotal"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleParentSizeChange"
@current-change="handleParentCurrentChange"
/>
<div slot="footer" class="dialog-footer">
<span class="selected-tip">已选 {{ parentSelectedRows.length }} </span>
<el-button @click="parentDialogVisible = false">关闭</el-button>
<el-button type="primary" :loading="parentBindLoading" @click="confirmParentSelection">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
addLbDepartmentUser,
bindLbDepartmentUserParent,
deleteLbDepartmentUser,
getLbDepartmentUserList,
updateLbDepartmentUser
} from '@/api/lb-department-user'
export default {
name: 'LbDepartmentUser',
data() {
return {
loading: false,
submitLoading: false,
parentBindLoading: false,
list: [],
total: 0,
dialogVisible: false,
parentDialogVisible: false,
parentLoading: false,
dialogTitle: '',
isEdit: false,
currentParentTarget: null,
parentList: [],
parentTotal: 0,
parentSelectedRows: [],
lastSelectedParentRow: null,
queryParams: {
current: 1,
size: 10,
tenantId: '',
userId: '',
parentId: '',
name: '',
phone: '',
industry: ''
},
parentQueryParams: {
current: 1,
size: 10,
tenantId: '',
userId: '',
parentId: '',
name: '',
phone: '',
industry: ''
},
form: {
id: '',
tenantId: '',
userId: '',
parentId: '',
name: '',
phone: '',
address: '',
industry: '',
joinDate: ''
},
formRules: {
tenantId: [{ required: true, message: '请输入租户ID', trigger: 'blur' }],
userId: [{ required: true, message: '请输入用户ID', trigger: 'blur' }],
parentId: [{ required: true, message: '请输入父级ID', trigger: 'blur' }],
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }]
}
}
},
created() {
this.fetchList()
},
methods: {
fetchList() {
this.loading = true
getLbDepartmentUserList(this.buildListParams())
.then((res) => {
if (res && (res.code === 20000 || res.code === 200 || res.success === true)) {
this.list = Array.isArray(res.data) ? res.data : []
this.total = typeof res.total === 'number'
? res.total
: (res.page && typeof res.page.total === 'number' ? res.page.total : this.list.length)
} else {
this.list = []
this.total = 0
}
})
.catch(() => {
this.list = []
this.total = 0
})
.finally(() => {
this.loading = false
})
},
buildListParams() {
const params = {
current: this.queryParams.current,
size: this.queryParams.size,
tenantId: this.queryParams.tenantId || undefined,
userId: this.queryParams.userId || undefined,
parentId: this.queryParams.parentId || undefined,
name: this.queryParams.name || undefined,
phone: this.queryParams.phone || undefined,
industry: this.queryParams.industry || undefined
}
Object.keys(params).forEach((key) => {
if (params[key] === undefined || params[key] === '') delete params[key]
})
return params
},
handleQuery() {
this.queryParams.current = 1
this.fetchList()
},
resetQuery() {
this.queryParams = {
current: 1,
size: 10,
tenantId: '',
userId: '',
parentId: '',
name: '',
phone: '',
industry: ''
}
this.fetchList()
},
handleSizeChange(size) {
this.queryParams.size = size
this.fetchList()
},
handleCurrentChange(current) {
this.queryParams.current = current
this.fetchList()
},
handleAdd() {
this.dialogTitle = '新增部门人员'
this.isEdit = false
this.resetFormData()
this.dialogVisible = true
this.$nextTick(() => {
this.$refs.dataForm && this.$refs.dataForm.clearValidate()
})
},
handleEdit(row) {
this.dialogTitle = '编辑部门人员'
this.isEdit = true
this.form = {
id: row.id || '',
tenantId: row.tenantId || '',
userId: row.userId || '',
parentId: row.parentId || '',
name: row.name || '',
phone: row.phone || '',
address: row.address || '',
industry: row.industry || '',
joinDate: row.joinDate || ''
}
this.dialogVisible = true
this.$nextTick(() => {
this.$refs.dataForm && this.$refs.dataForm.clearValidate()
})
},
handleDelete(row) {
this.$confirm('确定删除这条部门人员记录吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
return deleteLbDepartmentUser(row.id)
}).then((res) => {
this.$message.success((res && res.message) || '删除成功')
this.fetchList()
}).catch(() => {})
},
handleFindParent(row) {
this.currentParentTarget = row
this.parentDialogVisible = true
this.parentSelectedRows = []
this.parentQueryParams = {
current: 1,
size: 10,
tenantId: row.tenantId || '',
userId: '',
parentId: '',
name: '',
phone: '',
industry: ''
}
this.fetchParentList()
},
fetchParentList() {
this.parentLoading = true
const params = this.buildParentListParams()
getLbDepartmentUserList(params)
.then((res) => {
if (res && (res.code === 20000 || res.code === 200 || res.success === true)) {
this.parentList = Array.isArray(res.data) ? res.data : []
this.parentTotal = typeof res.total === 'number'
? res.total
: (res.page && typeof res.page.total === 'number' ? res.page.total : this.parentList.length)
} else {
this.parentList = []
this.parentTotal = 0
}
})
.catch(() => {
this.parentList = []
this.parentTotal = 0
})
.finally(() => {
this.parentLoading = false
})
},
buildParentListParams() {
const params = {
current: this.parentQueryParams.current,
size: this.parentQueryParams.size,
tenantId: this.parentQueryParams.tenantId || undefined,
userId: this.parentQueryParams.userId || undefined,
parentId: this.parentQueryParams.parentId || undefined,
name: this.parentQueryParams.name || undefined,
phone: this.parentQueryParams.phone || undefined,
industry: this.parentQueryParams.industry || undefined
}
Object.keys(params).forEach((key) => {
if (params[key] === undefined || params[key] === '') delete params[key]
})
return params
},
handleParentSelectionChange(selection) {
if (!selection.length) {
this.parentSelectedRows = []
this.lastSelectedParentRow = null
return
}
const latestSelected = selection[selection.length - 1]
if (selection.length > 1 && this.$refs.parentTable) {
this.$refs.parentTable.clearSelection()
this.$refs.parentTable.toggleRowSelection(latestSelected, true)
}
this.parentSelectedRows = [latestSelected]
this.lastSelectedParentRow = latestSelected
},
handleParentQuery() {
this.parentQueryParams.current = 1
this.fetchParentList()
},
resetParentQuery() {
this.parentQueryParams = {
current: 1,
size: 10,
tenantId: (this.currentParentTarget && this.currentParentTarget.tenantId) || '',
userId: '',
parentId: '',
name: '',
phone: '',
industry: ''
}
this.fetchParentList()
},
handleParentSizeChange(size) {
this.parentQueryParams.size = size
this.fetchParentList()
},
handleParentCurrentChange(current) {
this.parentQueryParams.current = current
this.fetchParentList()
},
confirmParentSelection() {
if (!this.parentSelectedRows.length) {
this.$message.warning('请先勾选上级人员')
return
}
if (this.parentSelectedRows.length > 1) {
this.$message.warning('一次只能选择 1 位上级人员')
return
}
if (!this.currentParentTarget || !this.currentParentTarget.userId) {
this.$message.error('未获取到当前子用户信息,请重新打开弹框后重试')
return
}
const selectedParent = this.parentSelectedRows[0]
if (!selectedParent || !selectedParent.userId) {
this.$message.error('未获取到上级用户ID请重新选择')
return
}
const tenantId = this.currentParentTarget.tenantId || selectedParent.tenantId || ''
if (!tenantId) {
this.$message.error('未获取到租户ID无法绑定')
return
}
this.parentBindLoading = true
bindLbDepartmentUserParent({
parentUserId: selectedParent.userId,
parentUserName: selectedParent.name || undefined,
childUserId: this.currentParentTarget.userId,
childUserName: this.currentParentTarget.name || undefined,
tenantId
}).then((res) => {
this.$message.success((res && res.message) || '绑定上级成功')
this.parentDialogVisible = false
this.fetchList()
}).finally(() => {
this.parentBindLoading = false
})
},
resetParentDialog() {
this.parentList = []
this.parentTotal = 0
this.parentSelectedRows = []
this.lastSelectedParentRow = null
this.parentBindLoading = false
this.currentParentTarget = null
this.parentQueryParams = {
current: 1,
size: 10,
tenantId: '',
userId: '',
parentId: '',
name: '',
phone: '',
industry: ''
}
},
handleSubmit() {
this.$refs.dataForm.validate((valid) => {
if (!valid) return
const payload = this.buildPayload()
this.submitLoading = true
const req = this.isEdit ? updateLbDepartmentUser(payload) : addLbDepartmentUser(payload)
req.then((res) => {
this.$message.success((res && res.message) || (this.isEdit ? '更新成功' : '新增成功'))
this.dialogVisible = false
this.fetchList()
}).finally(() => {
this.submitLoading = false
})
})
},
buildPayload() {
const payload = {
tenantId: this.form.tenantId,
userId: this.form.userId,
parentId: this.form.parentId,
name: this.form.name,
phone: this.form.phone || undefined,
address: this.form.address || undefined,
industry: this.form.industry || undefined,
joinDate: this.form.joinDate || undefined
}
if (this.isEdit) payload.id = this.form.id
Object.keys(payload).forEach((key) => {
if (payload[key] === undefined || payload[key] === '') delete payload[key]
})
return payload
},
resetForm() {
this.$refs.dataForm && this.$refs.dataForm.resetFields()
this.resetFormData()
},
resetFormData() {
this.form = {
id: '',
tenantId: '',
userId: '',
parentId: '',
name: '',
phone: '',
address: '',
industry: '',
joinDate: ''
}
},
formatDateTime(dateTime) {
if (!dateTime) return '-'
const date = new Date(String(dateTime).replace('T', ' '))
if (Number.isNaN(date.getTime())) return String(dateTime)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}
}
}
</script>
<style lang="scss" scoped>
.app-container {
.filter-container {
margin-bottom: 20px;
}
.action-container {
margin-bottom: 20px;
}
.table-container {
.el-pagination {
margin-top: 20px;
text-align: right;
}
}
.parent-alert {
margin-bottom: 12px;
}
.selected-tip {
float: left;
color: #606266;
}
}
</style>