2026-02-26 23:37:06 +08:00
|
|
|
<template>
|
|
|
|
|
<div class="index">
|
|
|
|
|
<div class="form">
|
|
|
|
|
<div class="form_button">
|
|
|
|
|
<el-button type="primary" :icon="Plus" @click="addOpen">创建子账号</el-button>
|
|
|
|
|
<el-button @click="addImport">批量导入</el-button>
|
|
|
|
|
<el-button @click="exportExcel">导出</el-button>
|
|
|
|
|
<el-button @click="clearForm">清空条件</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
<el-form class="form_content"
|
|
|
|
|
><el-form-item>
|
2026-02-27 15:13:45 +08:00
|
|
|
<el-input v-model="formData.mobile" placeholder="请输入账号手机号" @keydown.enter="getData">
|
2026-02-26 23:37:06 +08:00
|
|
|
<template #append>
|
|
|
|
|
<el-button icon="Search" @click="getData" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-input>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item>
|
|
|
|
|
<el-input v-model="formData.companyName" placeholder="请输入企业名称" @keydown.enter="getData">
|
|
|
|
|
<template #append>
|
|
|
|
|
<el-button icon="Search" @click="getData" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-input>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item>
|
|
|
|
|
<el-select v-model="formData.accountType" placeholder="账号类型(全部)" class="input" clearable @change="getData">
|
|
|
|
|
<el-option v-for="item of ACCOUNTTYPE_CONST" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
|
|
</el-select>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item>
|
2026-02-27 15:13:45 +08:00
|
|
|
<el-select v-model="formData.status" placeholder="账号状态(全部)" class="input" clearable @change="getData">
|
2026-02-26 23:37:06 +08:00
|
|
|
<el-option v-for="item of STATUS_CONST" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
|
|
</el-select>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-form>
|
|
|
|
|
</div>
|
|
|
|
|
<tableComponents :tableData="tableData" :tableLoading="loading" :hadExpand="false">
|
|
|
|
|
<el-table-column prop="name" label="姓名" align="center" />
|
2026-02-27 15:13:45 +08:00
|
|
|
<el-table-column prop="mobile" label="手机号" align="center" />
|
2026-02-26 23:37:06 +08:00
|
|
|
<el-table-column prop="companyName" label="企业名称" align="center" />
|
|
|
|
|
<el-table-column prop="accountType" label="账号类型" align="center">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
{{ ACCOUNTTYPE_CONST[scope.row.accountType]?.label }}
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column prop="createTime" label="创建时间" align="center" />
|
|
|
|
|
<el-table-column prop="updateTime" label="变更时间" align="center" />
|
2026-02-27 15:13:45 +08:00
|
|
|
<el-table-column prop="status" label="账号状态" align="center">
|
2026-02-26 23:37:06 +08:00
|
|
|
<template #default="scope">
|
|
|
|
|
<div style="display: flex; align-items: center; justify-content: center">
|
2026-02-27 15:13:45 +08:00
|
|
|
<div class="r_point" v-if="scope.row.status === 0">
|
2026-02-26 23:37:06 +08:00
|
|
|
<div class="point" style="background-color: #2dc74c"></div>
|
2026-02-27 15:13:45 +08:00
|
|
|
<text style="color: #2dc74c; white-space: nowrap">{{ STATUS_CONST[scope.row.status]?.label }}</text>
|
2026-02-26 23:37:06 +08:00
|
|
|
</div>
|
|
|
|
|
<div class="r_point" v-else>
|
|
|
|
|
<div class="point" style="background-color: #eb1c5d"></div>
|
2026-02-27 15:13:45 +08:00
|
|
|
<text style="color: #eb1c5d; white-space: nowrap">{{ STATUS_CONST[scope.row.status]?.label }}</text>
|
2026-02-26 23:37:06 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="操作" align="center">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<el-button type="text" @click="addOpen(scope.row)">编辑</el-button>
|
2026-02-27 15:13:45 +08:00
|
|
|
<el-button type="text" v-if="scope.row.status === 1" @click="doUpdateStatus(scope.row)">启用</el-button>
|
2026-02-26 23:37:06 +08:00
|
|
|
<el-button type="text" v-else @click="doUpdateStatus(scope.row)">禁用</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
</tableComponents>
|
|
|
|
|
|
|
|
|
|
<addDialog ref="addDialogRef" @close="getData"></addDialog>
|
|
|
|
|
<importDialog ref="importDialogRef" @close="getData"></importDialog>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts" name="tenant">
|
|
|
|
|
import { onMounted, ref, reactive } from 'vue';
|
|
|
|
|
import { NextLoading } from '/@/utils/loading';
|
|
|
|
|
import tableComponents from '/@/components/tableComponents/index.vue';
|
|
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
|
|
|
import addDialog from './add.vue';
|
|
|
|
|
import importDialog from './import.vue';
|
|
|
|
|
import { Plus } from '@element-plus/icons-vue';
|
|
|
|
|
import { disableTenantUser, enableTenantUser, exportTenantUser, getTenantUserList } from '/@/api/tenant';
|
|
|
|
|
import { ACCOUNTTYPE_CONST, STATUS_CONST } from '/@/views/pages/tenant/constant';
|
|
|
|
|
|
|
|
|
|
type FormData = {
|
2026-02-27 15:13:45 +08:00
|
|
|
mobile: string;
|
2026-02-26 23:37:06 +08:00
|
|
|
companyName: string;
|
|
|
|
|
accountType: number | undefined;
|
2026-02-27 15:13:45 +08:00
|
|
|
status: number | undefined;
|
2026-02-26 23:37:06 +08:00
|
|
|
};
|
|
|
|
|
type IData = {
|
|
|
|
|
id: number;
|
|
|
|
|
companyName: string;
|
|
|
|
|
accountType: number;
|
2026-02-27 15:13:45 +08:00
|
|
|
mobile: string;
|
2026-02-26 23:37:06 +08:00
|
|
|
name: string;
|
|
|
|
|
createTime: string;
|
|
|
|
|
updateTime: string;
|
2026-02-27 15:13:45 +08:00
|
|
|
status: number;
|
2026-02-26 23:37:06 +08:00
|
|
|
};
|
|
|
|
|
type TableData = {
|
|
|
|
|
data: IData[];
|
|
|
|
|
total: number;
|
|
|
|
|
page: number;
|
|
|
|
|
size: number;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const formData = reactive<FormData>({
|
2026-02-27 15:13:45 +08:00
|
|
|
mobile: '',
|
2026-02-26 23:37:06 +08:00
|
|
|
companyName: '',
|
|
|
|
|
accountType: undefined,
|
2026-02-27 15:13:45 +08:00
|
|
|
status: undefined,
|
2026-02-26 23:37:06 +08:00
|
|
|
});
|
|
|
|
|
const tableData = reactive<TableData>({
|
|
|
|
|
data: [],
|
|
|
|
|
total: 0,
|
|
|
|
|
page: 1,
|
|
|
|
|
size: 20,
|
|
|
|
|
});
|
|
|
|
|
const loading = ref(false);
|
|
|
|
|
|
|
|
|
|
// 获取数据
|
|
|
|
|
async function getData() {
|
|
|
|
|
loading.value = true;
|
|
|
|
|
let { code, data, total } = await getTenantUserList({
|
|
|
|
|
page: tableData.page,
|
|
|
|
|
size: tableData.size,
|
|
|
|
|
...formData,
|
|
|
|
|
});
|
|
|
|
|
loading.value = false;
|
|
|
|
|
if (code == 200) {
|
|
|
|
|
tableData.data = data;
|
|
|
|
|
tableData.total = total;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 启用禁用
|
|
|
|
|
async function doUpdateStatus(row: IData) {
|
2026-02-27 15:13:45 +08:00
|
|
|
ElMessageBox.confirm('确定' + (row.status === 1 ? '启用' : '禁用') + '该账号吗?', '提示', {
|
2026-02-26 23:37:06 +08:00
|
|
|
type: 'warning',
|
|
|
|
|
}).then(async () => {
|
|
|
|
|
// 启用或禁用
|
2026-02-27 15:13:45 +08:00
|
|
|
const updateStatus = row.status === 1 ? enableTenantUser : disableTenantUser;
|
2026-02-26 23:37:06 +08:00
|
|
|
|
|
|
|
|
let { code, data } = await updateStatus({
|
|
|
|
|
id: row.id,
|
|
|
|
|
});
|
|
|
|
|
if (code == 200) {
|
|
|
|
|
ElMessage.success('操作成功');
|
|
|
|
|
getData();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const addDialogRef = ref();
|
|
|
|
|
// 新增弹窗打开
|
|
|
|
|
function addOpen(data?: IData) {
|
|
|
|
|
addDialogRef.value.open(data);
|
|
|
|
|
}
|
|
|
|
|
const importDialogRef = ref();
|
|
|
|
|
function addImport(data?: any) {
|
|
|
|
|
importDialogRef.value.open(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 导出
|
|
|
|
|
function exportExcel() {
|
|
|
|
|
ElMessageBox.confirm('确定导出吗?', '提示', {
|
|
|
|
|
type: 'warning',
|
|
|
|
|
}).then(async () => {
|
2026-02-27 15:13:45 +08:00
|
|
|
try {
|
|
|
|
|
// 导出
|
|
|
|
|
const response = await exportTenantUser({
|
|
|
|
|
page: tableData.page,
|
|
|
|
|
size: tableData.size,
|
|
|
|
|
...formData,
|
|
|
|
|
});
|
2026-02-26 23:37:06 +08:00
|
|
|
|
2026-02-27 15:13:45 +08:00
|
|
|
const filename = '租户子账号导出.xlsx'; // 默认文件名
|
|
|
|
|
// 创建 Blob URL
|
|
|
|
|
const blob = new Blob([response]); // response 已经是 Blob 对象
|
|
|
|
|
const downloadUrl = window.URL.createObjectURL(blob);
|
|
|
|
|
const link = document.createElement('a');
|
|
|
|
|
link.href = downloadUrl;
|
|
|
|
|
link.download = filename; // 设置下载文件名
|
|
|
|
|
document.body.appendChild(link);
|
|
|
|
|
link.click();
|
|
|
|
|
document.body.removeChild(link);
|
|
|
|
|
// 释放 Blob URL
|
|
|
|
|
window.URL.revokeObjectURL(downloadUrl);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
ElMessage.error('导出失败');
|
2026-02-26 23:37:06 +08:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function clearForm() {
|
2026-02-27 15:13:45 +08:00
|
|
|
formData.mobile = '';
|
2026-02-26 23:37:06 +08:00
|
|
|
formData.companyName = '';
|
|
|
|
|
formData.accountType = undefined;
|
2026-02-27 15:13:45 +08:00
|
|
|
formData.status = undefined;
|
2026-02-26 23:37:06 +08:00
|
|
|
getData();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 页面加载时
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
NextLoading.done();
|
|
|
|
|
getData();
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
.index {
|
|
|
|
|
background-color: white;
|
|
|
|
|
padding: 30px;
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form {
|
|
|
|
|
// display: flex;
|
|
|
|
|
// justify-content: space-between;
|
|
|
|
|
margin-bottom: 30px;
|
|
|
|
|
|
|
|
|
|
.input {
|
|
|
|
|
width: 200px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form_content {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 20px;
|
|
|
|
|
align-items: center;
|
|
|
|
|
padding: 20px;
|
|
|
|
|
border: 1px solid #f0f0f0;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
background-color: #fafafa;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(.el-form-item--large) {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(.el-form-item--label-right .el-form-item__label) {
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
color: #3e3e3e;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form_button {
|
|
|
|
|
display: flex;
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.r_point {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 3px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.point {
|
|
|
|
|
width: 8px;
|
|
|
|
|
height: 8px;
|
|
|
|
|
border-radius: 100px;
|
|
|
|
|
// color: #ffaa48;
|
|
|
|
|
}
|
|
|
|
|
</style>
|