feat(system): add Excel export for tenant, role, post and site lists
Reuse list filters with ids/columns support and ListExportDropdown UX. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
5c7210facc
commit
82d8cb7f64
10 files changed
+356
-6
No files matched your search
@@ -37,6 +37,7 @@ from app.schemas.menu_favorite import (
|
||||
)
|
||||
from app.services.web_auth_roles import _map_role_name_to_web
|
||||
from app.utils.excel_export import (
|
||||
EXPORT_MAX_ROWS,
|
||||
ExportColumn,
|
||||
ExportValidationError,
|
||||
export_rows_to_xlsx_response,
|
||||
@@ -174,6 +175,55 @@ def list_tenants(
|
||||
)
|
||||
|
||||
|
||||
|
||||
TENANT_EXPORT_COLUMNS = [
|
||||
ExportColumn(title="租户编号", field="tenantNo"),
|
||||
ExportColumn(title="租户名称", field="tenantName"),
|
||||
ExportColumn(title="联系人", field="contactName"),
|
||||
ExportColumn(title="联系电话", field="contactPhone"),
|
||||
ExportColumn(title="创建时间", field="createTime"),
|
||||
]
|
||||
|
||||
|
||||
class TenantExportBody(BaseModel):
|
||||
keyword: Optional[str] = None
|
||||
ids: Optional[List[str]] = None
|
||||
columns: Optional[List[str]] = None
|
||||
|
||||
|
||||
@router.post("/tenants/export")
|
||||
def export_tenants(
|
||||
body: TenantExportBody,
|
||||
_user: dict = Depends(require_admin_or_super_admin),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""导出租户列表(当前筛选全量,或 ids 已选)。"""
|
||||
try:
|
||||
items, _ = tenant_svc.list_tenants(
|
||||
db,
|
||||
page=1,
|
||||
page_size=EXPORT_MAX_ROWS,
|
||||
keyword=body.keyword,
|
||||
ids=body.ids,
|
||||
max_page_size=EXPORT_MAX_ROWS,
|
||||
user_info=_user,
|
||||
)
|
||||
cols = filter_export_columns(TENANT_EXPORT_COLUMNS, body.columns)
|
||||
date_str = datetime.now().strftime("%Y%m%d")
|
||||
return export_rows_to_xlsx_response(
|
||||
db,
|
||||
tenant_no=None,
|
||||
sheet_title="租户列表",
|
||||
columns=cols,
|
||||
rows=items,
|
||||
filename_stem=f"租户列表_{date_str}",
|
||||
)
|
||||
except ExportValidationError as e:
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(500, str(e))
|
||||
|
||||
|
||||
@router.post("/tenants")
|
||||
def create_tenant(
|
||||
body: TenantCreateBody,
|
||||
@@ -1001,6 +1051,60 @@ def list_sites(
|
||||
return success_response({"list": items, "total": total, "page": page, "pageSize": pageSize, "totalPages": tp})
|
||||
|
||||
|
||||
|
||||
SITE_EXPORT_COLUMNS = [
|
||||
ExportColumn(title="站点名称", field="siteName"),
|
||||
ExportColumn(title="站点编码", field="siteCode"),
|
||||
ExportColumn(title="站点类型", field="siteType"),
|
||||
ExportColumn(title="状态", field="status", dict_type="sys_status"),
|
||||
ExportColumn(title="地址", field="address"),
|
||||
ExportColumn(title="联系人", field="contactName"),
|
||||
ExportColumn(title="联系电话", field="contactPhone"),
|
||||
ExportColumn(title="创建时间", field="createTime"),
|
||||
]
|
||||
|
||||
|
||||
class SiteExportBody(BaseModel):
|
||||
keyword: Optional[str] = None
|
||||
ids: Optional[List[str]] = None
|
||||
columns: Optional[List[str]] = None
|
||||
|
||||
|
||||
@router.post("/sites/export")
|
||||
def export_sites(
|
||||
body: SiteExportBody,
|
||||
user: dict = Depends(require_menu_code("system:site:list")),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""导出站点列表(当前筛选全量,或 ids 已选)。"""
|
||||
try:
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
items, _ = site_svc.list_sites(
|
||||
db,
|
||||
page=1,
|
||||
page_size=EXPORT_MAX_ROWS,
|
||||
keyword=body.keyword,
|
||||
tenant_no=tenant_no,
|
||||
ids=body.ids,
|
||||
max_page_size=EXPORT_MAX_ROWS,
|
||||
user_info=user,
|
||||
)
|
||||
cols = filter_export_columns(SITE_EXPORT_COLUMNS, body.columns)
|
||||
date_str = datetime.now().strftime("%Y%m%d")
|
||||
return export_rows_to_xlsx_response(
|
||||
db,
|
||||
tenant_no=tenant_no,
|
||||
sheet_title="站点列表",
|
||||
columns=cols,
|
||||
rows=items,
|
||||
filename_stem=f"站点列表_{date_str}",
|
||||
)
|
||||
except ExportValidationError as e:
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(500, str(e))
|
||||
|
||||
|
||||
@router.post("/sites")
|
||||
def create_site(
|
||||
body: SiteCreateBody,
|
||||
@@ -1110,6 +1214,56 @@ def list_posts(
|
||||
return success_response({"list": items, "total": total, "page": page, "pageSize": pageSize, "totalPages": tp})
|
||||
|
||||
|
||||
|
||||
POST_EXPORT_COLUMNS = [
|
||||
ExportColumn(title="职位名称", field="postName"),
|
||||
ExportColumn(title="职位编码", field="postCode"),
|
||||
ExportColumn(title="状态", field="status", dict_type="sys_status"),
|
||||
ExportColumn(title="创建时间", field="createTime"),
|
||||
]
|
||||
|
||||
|
||||
class PostExportBody(BaseModel):
|
||||
keyword: Optional[str] = None
|
||||
ids: Optional[List[str]] = None
|
||||
columns: Optional[List[str]] = None
|
||||
|
||||
|
||||
@router.post("/posts/export")
|
||||
def export_posts(
|
||||
body: PostExportBody,
|
||||
user: dict = Depends(require_menu_code("system:post:list")),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""导出职位列表(当前筛选全量,或 ids 已选)。"""
|
||||
try:
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
items, _ = post_svc.list_posts(
|
||||
db,
|
||||
page=1,
|
||||
page_size=EXPORT_MAX_ROWS,
|
||||
keyword=body.keyword,
|
||||
tenant_no=tenant_no,
|
||||
ids=body.ids,
|
||||
max_page_size=EXPORT_MAX_ROWS,
|
||||
user_info=user,
|
||||
)
|
||||
cols = filter_export_columns(POST_EXPORT_COLUMNS, body.columns)
|
||||
date_str = datetime.now().strftime("%Y%m%d")
|
||||
return export_rows_to_xlsx_response(
|
||||
db,
|
||||
tenant_no=tenant_no,
|
||||
sheet_title="职位列表",
|
||||
columns=cols,
|
||||
rows=items,
|
||||
filename_stem=f"职位列表_{date_str}",
|
||||
)
|
||||
except ExportValidationError as e:
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(500, str(e))
|
||||
|
||||
|
||||
@router.post("/posts")
|
||||
def create_post(
|
||||
body: PostCreateBody,
|
||||
@@ -1380,6 +1534,56 @@ def list_role_management(
|
||||
return success_response({"list": items, "total": total, "page": page, "pageSize": pageSize, "totalPages": tp})
|
||||
|
||||
|
||||
|
||||
ROLE_EXPORT_COLUMNS = [
|
||||
ExportColumn(title="角色名称", field="roleName"),
|
||||
ExportColumn(title="数据权限", field="dataScope", dict_type="sys_data_scope"),
|
||||
ExportColumn(title="状态", field="status", dict_type="sys_status"),
|
||||
ExportColumn(title="创建时间", field="createTime"),
|
||||
]
|
||||
|
||||
|
||||
class RoleExportBody(BaseModel):
|
||||
keyword: Optional[str] = None
|
||||
ids: Optional[List[str]] = None
|
||||
columns: Optional[List[str]] = None
|
||||
|
||||
|
||||
@router.post("/role-management/export")
|
||||
def export_role_management(
|
||||
body: RoleExportBody,
|
||||
user: dict = Depends(require_menu_code("system:role:list")),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""导出角色列表(当前筛选全量,或 ids 已选)。"""
|
||||
try:
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
items, _ = role_svc.list_roles(
|
||||
db,
|
||||
page=1,
|
||||
page_size=EXPORT_MAX_ROWS,
|
||||
keyword=body.keyword,
|
||||
tenant_no=tenant_no,
|
||||
ids=body.ids,
|
||||
max_page_size=EXPORT_MAX_ROWS,
|
||||
user_info=user,
|
||||
)
|
||||
cols = filter_export_columns(ROLE_EXPORT_COLUMNS, body.columns)
|
||||
date_str = datetime.now().strftime("%Y%m%d")
|
||||
return export_rows_to_xlsx_response(
|
||||
db,
|
||||
tenant_no=tenant_no,
|
||||
sheet_title="角色列表",
|
||||
columns=cols,
|
||||
rows=items,
|
||||
filename_stem=f"角色列表_{date_str}",
|
||||
)
|
||||
except ExportValidationError as e:
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(500, str(e))
|
||||
|
||||
|
||||
@router.post("/role-management")
|
||||
def create_role_management(
|
||||
body: RoleCreateBody,
|
||||
|
||||
@@ -35,6 +35,8 @@ def list_posts(
|
||||
page_size: int = 10,
|
||||
keyword: Optional[str] = None,
|
||||
tenant_no: Optional[str] = None,
|
||||
ids: Optional[List[str]] = None,
|
||||
max_page_size: Optional[int] = None,
|
||||
user_info=None,
|
||||
) -> Tuple[List[Dict[str, Any]], int]:
|
||||
def _filtered():
|
||||
@@ -45,12 +47,15 @@ def list_posts(
|
||||
if kw:
|
||||
like = f"%{kw}%"
|
||||
q0 = q0.filter(or_(SysPost.post_name.like(like), SysPost.post_code.like(like)))
|
||||
if ids:
|
||||
q0 = q0.filter(SysPost.id.in_(ids))
|
||||
# 职位为租户主数据,不做 create_by 数据范围过滤
|
||||
return q0
|
||||
|
||||
total = _filtered().order_by(None).with_entities(func.count(SysPost.id)).scalar() or 0
|
||||
page = max(1, page)
|
||||
page_size = min(max(1, page_size), 500)
|
||||
cap = int(max_page_size) if max_page_size else 500
|
||||
page_size = min(max(1, page_size), cap)
|
||||
rows = (
|
||||
_filtered()
|
||||
.order_by(SysPost.create_time.desc())
|
||||
|
||||
@@ -51,6 +51,8 @@ def list_roles(
|
||||
page_size: int = 10,
|
||||
keyword: Optional[str] = None,
|
||||
tenant_no: Optional[str] = None,
|
||||
ids: Optional[List[str]] = None,
|
||||
max_page_size: Optional[int] = None,
|
||||
user_info=None,
|
||||
) -> Tuple[List[Dict[str, Any]], int]:
|
||||
def _filtered():
|
||||
@@ -61,6 +63,8 @@ def list_roles(
|
||||
if kw:
|
||||
like = f"%{kw}%"
|
||||
q0 = q0.filter(SysRole.role_name.like(like))
|
||||
if ids:
|
||||
q0 = q0.filter(SysRole.id.in_(ids))
|
||||
if user_info:
|
||||
from app.core.data_scope import apply_data_scope
|
||||
q0 = apply_data_scope(q0, SysRole, user_info, db, tenant_no)
|
||||
@@ -68,7 +72,8 @@ def list_roles(
|
||||
|
||||
total = _filtered().order_by(None).with_entities(func.count(SysRole.id)).scalar() or 0
|
||||
page = max(1, page)
|
||||
page_size = min(max(1, page_size), 500)
|
||||
cap = int(max_page_size) if max_page_size else 500
|
||||
page_size = min(max(1, page_size), cap)
|
||||
rows = (
|
||||
_filtered()
|
||||
.order_by(SysRole.create_time.desc())
|
||||
|
||||
@@ -40,6 +40,8 @@ def list_sites(
|
||||
page_size: int = 10,
|
||||
keyword: Optional[str] = None,
|
||||
tenant_no: Optional[str] = None,
|
||||
ids: Optional[List[str]] = None,
|
||||
max_page_size: Optional[int] = None,
|
||||
user_info=None,
|
||||
) -> Tuple[List[Dict[str, Any]], int]:
|
||||
def _filtered():
|
||||
@@ -50,12 +52,15 @@ def list_sites(
|
||||
if kw:
|
||||
like = f"%{kw}%"
|
||||
q0 = q0.filter(or_(SysSite.site_name.like(like), SysSite.site_code.like(like)))
|
||||
if ids:
|
||||
q0 = q0.filter(SysSite.id.in_(ids))
|
||||
# 站点为租户主数据,不做 create_by 数据范围过滤
|
||||
return q0
|
||||
|
||||
total = _filtered().order_by(None).with_entities(func.count(SysSite.id)).scalar() or 0
|
||||
page = max(1, page)
|
||||
page_size = min(max(1, page_size), 500)
|
||||
cap = int(max_page_size) if max_page_size else 500
|
||||
page_size = min(max(1, page_size), cap)
|
||||
rows = (
|
||||
_filtered()
|
||||
.order_by(SysSite.create_time.desc())
|
||||
|
||||
@@ -35,6 +35,8 @@ def list_tenants(
|
||||
page: int = 1,
|
||||
page_size: int = 10,
|
||||
keyword: Optional[str] = None,
|
||||
ids: Optional[List[str]] = None,
|
||||
max_page_size: Optional[int] = None,
|
||||
user_info=None,
|
||||
) -> Tuple[List[Dict[str, Any]], int]:
|
||||
def _filtered():
|
||||
@@ -43,6 +45,8 @@ def list_tenants(
|
||||
if kw:
|
||||
like = f"%{kw}%"
|
||||
q0 = q0.filter(or_(SysTenant.tenant_no.like(like), SysTenant.tenant_name.like(like)))
|
||||
if ids:
|
||||
q0 = q0.filter(SysTenant.id.in_(ids))
|
||||
if user_info:
|
||||
from app.core.data_scope import apply_data_scope
|
||||
q0 = apply_data_scope(q0, SysTenant, user_info, db)
|
||||
@@ -50,7 +54,8 @@ def list_tenants(
|
||||
|
||||
total = _filtered().order_by(None).with_entities(func.count(SysTenant.id)).scalar() or 0
|
||||
page = max(1, page)
|
||||
page_size = min(max(1, page_size), 500)
|
||||
cap = int(max_page_size) if max_page_size else 500
|
||||
page_size = min(max(1, page_size), cap)
|
||||
rows = (
|
||||
_filtered()
|
||||
.order_by(SysTenant.create_time.desc())
|
||||
|
||||
@@ -52,6 +52,15 @@ export function fetchTenantList(params?: { page?: number; pageSize?: number; key
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function fetchExportTenants(data: Record<string, any>) {
|
||||
return request.post({
|
||||
url: '/web/admin/tenants/export',
|
||||
data,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
export function fetchCreateTenant(data: {
|
||||
tenantNo: string
|
||||
tenantName: string
|
||||
@@ -374,6 +383,15 @@ export function fetchSiteList(params?: { page?: number; pageSize?: number; keywo
|
||||
totalPages: number
|
||||
}>({ url: '/web/admin/sites', params })
|
||||
}
|
||||
|
||||
|
||||
export function fetchExportSites(data: Record<string, any>) {
|
||||
return request.post({
|
||||
url: '/web/admin/sites/export',
|
||||
data,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
export function fetchCreateSite(data: {
|
||||
siteName: string
|
||||
siteCode: string
|
||||
@@ -422,6 +440,15 @@ export function fetchPostList(params?: { page?: number; pageSize?: number; keywo
|
||||
totalPages: number
|
||||
}>({ url: '/web/admin/posts', params })
|
||||
}
|
||||
|
||||
|
||||
export function fetchExportPosts(data: Record<string, any>) {
|
||||
return request.post({
|
||||
url: '/web/admin/posts/export',
|
||||
data,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
export function fetchCreatePost(data: {
|
||||
postName: string
|
||||
postCode: string
|
||||
@@ -522,6 +549,15 @@ export function fetchRoleList(params?: { page?: number; pageSize?: number; keywo
|
||||
totalPages: number
|
||||
}>({ url: '/web/admin/role-management', params })
|
||||
}
|
||||
|
||||
|
||||
export function fetchExportRoles(data: Record<string, any>) {
|
||||
return request.post({
|
||||
url: '/web/admin/role-management/export',
|
||||
data,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
export function fetchRoleDetail(id: string) {
|
||||
return request.get<Api.Role.RoleItem>({ url: `/web/admin/role-management/${id}` })
|
||||
}
|
||||
|
||||
@@ -73,6 +73,15 @@
|
||||
批量删除
|
||||
</el-button>
|
||||
|
||||
<ListExportDropdown
|
||||
:export-fn="fetchExportPosts"
|
||||
:get-filter-params="getPostExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="selectedRows.map((r) => r.id)"
|
||||
:visible-columns="postExportColumns"
|
||||
filename="职位列表.xlsx"
|
||||
/>
|
||||
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
:column-defs="listColumnDefs"
|
||||
@@ -353,6 +362,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
|
||||
@@ -377,6 +387,7 @@ import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import {
|
||||
fetchPostList,
|
||||
fetchExportPosts,
|
||||
fetchCreatePost,
|
||||
fetchUpdatePost,
|
||||
fetchDeletePost,
|
||||
@@ -411,6 +422,20 @@ import { useDictStore } from '@/store/modules/dict'
|
||||
const selectedRows = ref<Api.Post.PostItem[]>([])
|
||||
const loading = ref(false)
|
||||
const pagination = reactive({ page: 1, pageSize: 20, total: 0 })
|
||||
|
||||
function getPostExportFilterParams() {
|
||||
const quickKeyword = quickSearchKeyword.value?.trim()
|
||||
return {
|
||||
keyword: quickKeyword || searchForm.keyword || undefined
|
||||
}
|
||||
}
|
||||
|
||||
const postExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
if (!cols.includes('postName')) cols.unshift('postName')
|
||||
return cols
|
||||
})
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const dialogTitle = ref('新增职位')
|
||||
const isEdit = ref(false)
|
||||
|
||||
@@ -85,6 +85,15 @@
|
||||
批量删除
|
||||
</el-button>
|
||||
|
||||
<ListExportDropdown
|
||||
:export-fn="fetchExportRoles"
|
||||
:get-filter-params="getRoleExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="selectedRows.map((r) => r.id)"
|
||||
:visible-columns="roleExportColumns"
|
||||
filename="角色列表.xlsx"
|
||||
/>
|
||||
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
:column-defs="listColumnDefs"
|
||||
@@ -189,10 +198,11 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
|
||||
import RoleManageDialogs from '@/components/business/role-manage-dialogs/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ref, reactive, onMounted, computed } from 'vue'
|
||||
import {
|
||||
canDeleteByCreator,
|
||||
filterDeletableByCreator,
|
||||
@@ -211,7 +221,7 @@
|
||||
} from '@element-plus/icons-vue'
|
||||
import { withFullscreenLoading, fullscreenLoadingText } from '@/utils/fullscreen-loading'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import { fetchRoleList, fetchDeleteRole } from '@/api/admin'
|
||||
import { fetchRoleList, fetchExportRoles, fetchDeleteRole } from '@/api/admin'
|
||||
|
||||
defineOptions({ name: 'SystemRole' })
|
||||
|
||||
@@ -235,6 +245,19 @@
|
||||
const pagination = reactive({ page: 1, pageSize: 20, total: 0 })
|
||||
const roleDialogsRef = ref<InstanceType<typeof RoleManageDialogs> | null>(null)
|
||||
|
||||
function getRoleExportFilterParams() {
|
||||
const quickKeyword = quickSearchKeyword.value?.trim()
|
||||
return {
|
||||
keyword: quickKeyword || searchForm.keyword || undefined
|
||||
}
|
||||
}
|
||||
|
||||
const roleExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
if (!cols.includes('roleName')) cols.unshift('roleName')
|
||||
return cols
|
||||
})
|
||||
|
||||
const handleSelectionChange = (rows: Api.Role.RoleItem[]) => {
|
||||
selectedRows.value = rows
|
||||
}
|
||||
|
||||
@@ -41,6 +41,14 @@
|
||||
批量删除
|
||||
</el-button>
|
||||
|
||||
<ListExportDropdown
|
||||
:export-fn="fetchExportSites"
|
||||
:get-filter-params="getSiteExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="selectedRows.map((r) => r.id)"
|
||||
filename="站点列表.xlsx"
|
||||
/>
|
||||
|
||||
<ListToolbarEndActions :loading="loading" @refresh="loadData" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -302,6 +310,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
|
||||
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
@@ -311,6 +320,7 @@ import { useDictStore } from '@/store/modules/dict'
|
||||
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
|
||||
import {
|
||||
fetchSiteList,
|
||||
fetchExportSites,
|
||||
fetchCreateSite,
|
||||
fetchUpdateSite,
|
||||
fetchDeleteSite,
|
||||
@@ -377,6 +387,13 @@ const dictStore = useDictStore()
|
||||
const selectedRows = ref<Api.Site.SiteItem[]>([])
|
||||
const loading = ref(false)
|
||||
const pagination = reactive({ page: 1, pageSize: 20, total: 0 })
|
||||
|
||||
function getSiteExportFilterParams() {
|
||||
return {
|
||||
keyword: searchForm.keyword || undefined
|
||||
}
|
||||
}
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const dialogTitle = ref('新增站点')
|
||||
const isEdit = ref(false)
|
||||
|
||||
@@ -75,6 +75,15 @@
|
||||
批量删除
|
||||
</el-button>
|
||||
|
||||
<ListExportDropdown
|
||||
:export-fn="fetchExportTenants"
|
||||
:get-filter-params="getTenantExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="selectedRows.map((r) => r.id)"
|
||||
:visible-columns="tenantExportColumns"
|
||||
filename="租户列表.xlsx"
|
||||
/>
|
||||
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
:column-defs="listColumnDefs"
|
||||
@@ -274,6 +283,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
import { ref, reactive, onMounted, computed } from 'vue'
|
||||
@@ -294,6 +304,7 @@ import { syncViewRowFromFlatList } from '@/utils/view-dialog-refresh'
|
||||
import { withFullscreenLoading, fullscreenLoadingText } from '@/utils/fullscreen-loading'
|
||||
import {
|
||||
fetchTenantList,
|
||||
fetchExportTenants,
|
||||
fetchCreateTenant,
|
||||
fetchUpdateTenant,
|
||||
fetchDeleteTenant
|
||||
@@ -325,6 +336,20 @@ import { syncViewRowFromFlatList } from '@/utils/view-dialog-refresh'
|
||||
const selectedRows = ref<Api.Tenant.TenantItem[]>([])
|
||||
const loading = ref(false)
|
||||
const pagination = reactive({ page: 1, pageSize: 20, total: 0 })
|
||||
|
||||
function getTenantExportFilterParams() {
|
||||
const quickKeyword = quickSearchKeyword.value?.trim()
|
||||
return {
|
||||
keyword: quickKeyword || searchForm.keyword || undefined
|
||||
}
|
||||
}
|
||||
|
||||
const tenantExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
if (!cols.includes('tenantName')) cols.unshift('tenantName')
|
||||
return cols
|
||||
})
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const dialogTitle = ref('新增租户')
|
||||
const isEdit = ref(false)
|
||||
|
||||
Reference in new issue
Block a user