fix: 修复管理端前端 lint 与构建问题

- 收敛 easyflow-ui-admin 的 lint、格式和类型问题

- 修正 demo 页面与管理端前端构建失败点

- 验证 pnpm lint 与 pnpm build 均已通过
This commit is contained in:
2026-04-05 21:39:13 +08:00
parent bb72e19c84
commit 7e7c236c2a
240 changed files with 5151 additions and 4701 deletions

View File

@@ -76,7 +76,9 @@ function clearSelectedFile() {
async function downloadTemplate() {
downloadLoading.value = true;
try {
const blob = await api.download('/api/v1/sysAccount/downloadImportTemplate');
const blob = await api.download(
'/api/v1/sysAccount/downloadImportTemplate',
);
downloadFileFromBlob({
fileName: 'user_import_template.xlsx',
source: blob,
@@ -136,7 +138,9 @@ async function handleImport() {
<ElIcon class="text-4xl text-[var(--el-text-color-secondary)]">
<UploadFilled />
</ElIcon>
<div class="text-[15px] font-semibold text-[var(--el-text-color-primary)]">
<div
class="text-[15px] font-semibold text-[var(--el-text-color-primary)]"
>
{{ $t('sysAccount.importUploadTitle') }}
</div>
<div class="text-[13px] text-[var(--el-text-color-secondary)]">
@@ -182,17 +186,23 @@ async function handleImport() {
</div>
<div class="result-stats">
<div class="stat-item">
<div class="stat-label">{{ $t('sysAccount.importTotalCount') }}</div>
<div class="stat-label">
{{ $t('sysAccount.importTotalCount') }}
</div>
<div class="stat-value">{{ importResult.totalCount || 0 }}</div>
</div>
<div class="stat-item">
<div class="stat-label">{{ $t('sysAccount.importSuccessCount') }}</div>
<div class="stat-label">
{{ $t('sysAccount.importSuccessCount') }}
</div>
<div class="stat-value success-text">
{{ importResult.successCount || 0 }}
</div>
</div>
<div class="stat-item">
<div class="stat-label">{{ $t('sysAccount.importErrorCount') }}</div>
<div class="stat-label">
{{ $t('sysAccount.importErrorCount') }}
</div>
<div class="stat-value" :class="hasErrors ? 'danger-text' : ''">
{{ importResult.errorCount || 0 }}
</div>
@@ -267,25 +277,25 @@ async function handleImport() {
}
.sys-account-upload-area :deep(.el-upload-dragger) {
background: hsl(var(--surface) / 72%);
border-color: hsl(var(--border) / 68%);
border-radius: 18px;
border-color: hsl(var(--border) / 0.68);
background: hsl(var(--surface) / 0.72);
}
.selected-file-card {
display: flex;
align-items: center;
justify-content: space-between;
border: 1px solid hsl(var(--border) / 0.72);
border-radius: 16px;
padding: 12px 16px;
background: hsl(var(--surface-subtle) / 0.95);
background: hsl(var(--surface-subtle) / 95%);
border: 1px solid hsl(var(--border) / 72%);
border-radius: 16px;
}
.selected-file-main {
display: flex;
align-items: center;
gap: 10px;
align-items: center;
min-width: 0;
}
@@ -296,15 +306,15 @@ async function handleImport() {
.selected-file-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--el-text-color-primary);
white-space: nowrap;
}
.result-wrap {
border: 1px solid hsl(var(--border) / 0.72);
border-radius: 18px;
padding: 18px;
background: hsl(var(--surface-subtle) / 0.94);
background: hsl(var(--surface-subtle) / 94%);
border: 1px solid hsl(var(--border) / 72%);
border-radius: 18px;
}
.result-head {
@@ -313,8 +323,8 @@ async function handleImport() {
.result-title-wrap {
display: flex;
align-items: center;
gap: 8px;
align-items: center;
font-weight: 600;
color: var(--el-text-color-primary);
}
@@ -327,9 +337,9 @@ async function handleImport() {
}
.stat-item {
border-radius: 14px;
padding: 14px 16px;
background: hsl(var(--surface) / 0.95);
background: hsl(var(--surface) / 95%);
border-radius: 14px;
}
.stat-label {
@@ -354,9 +364,9 @@ async function handleImport() {
.dialog-footer {
display: flex;
gap: 12px;
align-items: center;
justify-content: flex-end;
gap: 12px;
width: 100%;
}
</style>

View File

@@ -270,7 +270,9 @@ function isAdmin(data: any) {
<template #middle>
<div v-if="selectedCount > 0" class="sys-account-batch-inline">
<span class="sys-account-batch-inline__count">
{{ $t('sysAccount.batchSelectedCount', { count: selectedCount }) }}
{{
$t('sysAccount.batchSelectedCount', { count: selectedCount })
}}
</span>
<div class="sys-account-batch-inline__actions">
<div v-access:code="'/api/v1/sysAccount/save'">
@@ -427,9 +429,9 @@ function isAdmin(data: any) {
<style scoped>
.sys-account-batch-inline {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
gap: 10px;
align-items: center;
}
.sys-account-batch-inline__count {
@@ -444,9 +446,9 @@ function isAdmin(data: any) {
.sys-account-batch-inline__actions {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
.sys-account-batch-inline__actions :deep(.el-button) {
@@ -464,8 +466,8 @@ function isAdmin(data: any) {
:deep(.sys-account-batch-inline__button:not(.is-disabled):hover),
:deep(.sys-account-batch-inline__button:not(.is-disabled):focus-visible) {
color: hsl(var(--primary));
background: hsl(var(--primary) / 0.08);
border-color: hsl(var(--primary) / 0.16);
background: hsl(var(--primary) / 8%);
border-color: hsl(var(--primary) / 16%);
}
:deep(.sys-account-batch-inline__button.is-danger) {
@@ -473,10 +475,12 @@ function isAdmin(data: any) {
}
:deep(.sys-account-batch-inline__button.is-danger:not(.is-disabled):hover),
:deep(.sys-account-batch-inline__button.is-danger:not(.is-disabled):focus-visible) {
:deep(
.sys-account-batch-inline__button.is-danger:not(.is-disabled):focus-visible
) {
color: hsl(var(--destructive));
background: hsl(var(--destructive) / 0.08);
border-color: hsl(var(--destructive) / 0.16);
background: hsl(var(--destructive) / 8%);
border-color: hsl(var(--destructive) / 16%);
}
@media (max-width: 640px) {

View File

@@ -153,10 +153,7 @@ function closeDialog() {
:label="$t('sysAccount.password')"
>
<div class="w-full">
<EasyFlowInputPassword
v-model="entity.password"
password-strength
/>
<EasyFlowInputPassword v-model="entity.password" password-strength />
<div class="mt-2 text-xs text-[var(--el-text-color-secondary)]">
{{ $t('sysAccount.passwordStrongTip') }}
</div>

View File

@@ -190,7 +190,7 @@ function getTree() {
<style scoped>
.search-input {
border-radius: 4px;
width: 300px;
border-radius: 4px;
}
</style>

View File

@@ -5,12 +5,7 @@ import { computed, ref } from 'vue';
import { EasyFlowFormModal } from '@easyflow/common-ui';
import {
ElForm,
ElFormItem,
ElInput,
ElMessage,
} from 'element-plus';
import { ElForm, ElFormItem, ElInput, ElMessage } from 'element-plus';
import { api } from '#/api/request';
import DictSelect from '#/components/dict/DictSelect.vue';
@@ -41,14 +36,16 @@ interface CategoryPermissionTreeNode {
label: string;
}
const RESOURCE_SCOPE_GROUPS: Array<{ label: string; resourceType: ResourceType }> =
[
{ resourceType: 'BOT', label: $t('bot.chatAssistant') },
{ resourceType: 'PLUGIN', label: $t('menus.ai.plugin') },
{ resourceType: 'WORKFLOW', label: $t('menus.ai.workflow') },
{ resourceType: 'KNOWLEDGE', label: $t('menus.ai.documentCollection') },
{ resourceType: 'RESOURCE', label: $t('menus.ai.resources') },
];
const RESOURCE_SCOPE_GROUPS: Array<{
label: string;
resourceType: ResourceType;
}> = [
{ resourceType: 'BOT', label: $t('bot.chatAssistant') },
{ resourceType: 'PLUGIN', label: $t('menus.ai.plugin') },
{ resourceType: 'WORKFLOW', label: $t('menus.ai.workflow') },
{ resourceType: 'KNOWLEDGE', label: $t('menus.ai.documentCollection') },
{ resourceType: 'RESOURCE', label: $t('menus.ai.resources') },
];
const saveForm = ref<FormInstance>();
const dialogVisible = ref(false);
@@ -270,29 +267,31 @@ function buildScopeItemsFromTree(): CategoryScopeItem[] {
}
function getCategoryScopeDetail(roleId: number | string) {
api.get('/api/v1/sysRoleCategoryScope/detail', {
params: { roleId },
}).then((res) => {
if (res.errorCode !== 0) {
categoryScopeEditable.value = false;
api
.get('/api/v1/sysRoleCategoryScope/detail', {
params: { roleId },
})
.then((res) => {
if (res.errorCode !== 0) {
categoryScopeEditable.value = false;
categoryScopeDetail.value = {
roleId,
scopes: buildDefaultScopes(),
};
syncCategoryTreeCheckedKeys(categoryScopeDetail.value.scopes);
return;
}
categoryScopeEditable.value = !!res.data?.editable;
categoryScopeDetail.value = {
roleId,
scopes: buildDefaultScopes(),
scopes: (res.data?.scopes || buildDefaultScopes()).map((item: any) => ({
categoryIds: item.categoryIds || [],
resourceType: item.resourceType,
scopeMode: item.scopeMode || 'CUSTOM',
})),
};
syncCategoryTreeCheckedKeys(categoryScopeDetail.value.scopes);
return;
}
categoryScopeEditable.value = !!res.data?.editable;
categoryScopeDetail.value = {
roleId,
scopes: (res.data?.scopes || buildDefaultScopes()).map((item: any) => ({
categoryIds: item.categoryIds || [],
resourceType: item.resourceType,
scopeMode: item.scopeMode || 'CUSTOM',
})),
};
syncCategoryTreeCheckedKeys(categoryScopeDetail.value.scopes);
});
});
}
async function saveCategoryScope(roleId: number | string) {
@@ -375,9 +374,9 @@ async function saveCategoryScope(roleId: number | string) {
<style scoped>
.role-category-scope-panel {
display: flex;
width: 100%;
flex-direction: column;
gap: 12px;
width: 100%;
}
.role-category-scope-group {
@@ -385,16 +384,16 @@ async function saveCategoryScope(roleId: number | string) {
flex-direction: column;
gap: 8px;
padding: 12px;
background: var(--el-fill-color-extra-light);
border: 1px solid var(--el-border-color-lighter);
border-radius: 10px;
background: var(--el-fill-color-extra-light);
}
.role-category-scope-head {
display: flex;
gap: 16px;
align-items: center;
justify-content: space-between;
gap: 16px;
}
.role-category-scope-title {