fix: 修复管理端前端 lint 与构建问题
- 收敛 easyflow-ui-admin 的 lint、格式和类型问题 - 修正 demo 页面与管理端前端构建失败点 - 验证 pnpm lint 与 pnpm build 均已通过
This commit is contained in:
@@ -84,14 +84,25 @@ const resolvedPrimaryAction = computed(() => {
|
||||
return props.primaryAction;
|
||||
});
|
||||
|
||||
function resolveActionPlacement(
|
||||
action: ActionButton,
|
||||
index: number,
|
||||
): ActionPlacement {
|
||||
if (action.placement) {
|
||||
return action.placement;
|
||||
}
|
||||
if (resolvedPrimaryAction.value) {
|
||||
return 'menu';
|
||||
}
|
||||
return index < 3 ? 'inline' : 'menu';
|
||||
}
|
||||
|
||||
const resolvedActions = computed<ResolvedActionButton[]>(() => {
|
||||
return props.actions
|
||||
.filter((action) => hasPermission(action.permission))
|
||||
.map((action, index) => ({
|
||||
...action,
|
||||
placement:
|
||||
action.placement ||
|
||||
(resolvedPrimaryAction.value ? 'menu' : index < 3 ? 'inline' : 'menu'),
|
||||
placement: resolveActionPlacement(action, index),
|
||||
tone:
|
||||
action.tone ||
|
||||
(action.className?.includes('danger') ? 'danger' : 'default'),
|
||||
@@ -111,8 +122,8 @@ const menuActions = computed(() => {
|
||||
const showFooter = computed(() => {
|
||||
return Boolean(
|
||||
resolvedPrimaryAction.value ||
|
||||
inlineActions.value.length ||
|
||||
menuActions.value.length,
|
||||
inlineActions.value.length > 0 ||
|
||||
menuActions.value.length > 0,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -132,10 +143,8 @@ function handleActionClick(event: Event, action: ActionButton, item: any) {
|
||||
v-for="(item, index) in props.data"
|
||||
:key="item.id ?? index"
|
||||
shadow="never"
|
||||
:class="[
|
||||
'card-item',
|
||||
{ 'card-item--interactive': resolvedPrimaryAction },
|
||||
]"
|
||||
class="card-item"
|
||||
:class="[{ 'card-item--interactive': resolvedPrimaryAction }]"
|
||||
:role="resolvedPrimaryAction ? 'button' : undefined"
|
||||
:tabindex="resolvedPrimaryAction ? 0 : undefined"
|
||||
@click="handlePrimaryAction(item)"
|
||||
@@ -201,7 +210,7 @@ function handleActionClick(event: Event, action: ActionButton, item: any) {
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="inlineActions.length || menuActions.length"
|
||||
v-if="inlineActions.length > 0 || menuActions.length > 0"
|
||||
class="card-actions"
|
||||
@click.stop
|
||||
>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import type {CSSProperties} from 'vue';
|
||||
import {computed, useSlots} from 'vue';
|
||||
import type { CSSProperties } from 'vue';
|
||||
|
||||
import { computed, useSlots } from 'vue';
|
||||
|
||||
interface Props {
|
||||
contentPadding?: number | string;
|
||||
@@ -67,8 +68,8 @@ const contentStyle = computed((): CSSProperties => {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
gap: 16px;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.list-page-shell.is-dense {
|
||||
@@ -78,9 +79,9 @@ const contentStyle = computed((): CSSProperties => {
|
||||
.list-page-shell__toolbar {
|
||||
position: relative;
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 8px 6px 2px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
@@ -92,8 +93,8 @@ const contentStyle = computed((): CSSProperties => {
|
||||
top: 12px;
|
||||
z-index: 5;
|
||||
padding: 10px 10px 6px;
|
||||
background: hsl(var(--glass-tint) / 0.7);
|
||||
border: 1px solid hsl(var(--glass-border) / 0.44);
|
||||
background: hsl(var(--glass-tint) / 70%);
|
||||
border: 1px solid hsl(var(--glass-border) / 44%);
|
||||
border-radius: 20px;
|
||||
box-shadow: var(--shadow-toolbar);
|
||||
backdrop-filter: blur(var(--glass-blur)) saturate(155%);
|
||||
@@ -110,40 +111,41 @@ const contentStyle = computed((): CSSProperties => {
|
||||
|
||||
.list-page-shell__content {
|
||||
--list-page-shell-content-padding: 0px;
|
||||
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding: var(--list-page-shell-content-padding);
|
||||
overflow: hidden;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
hsl(var(--glass-border) / 0.84) 0%,
|
||||
hsl(var(--surface-panel) / 0.94) 28%,
|
||||
hsl(var(--surface-panel) / 0.97) 100%
|
||||
hsl(var(--glass-border) / 84%) 0%,
|
||||
hsl(var(--surface-panel) / 94%) 28%,
|
||||
hsl(var(--surface-panel) / 97%) 100%
|
||||
);
|
||||
border: 1px solid hsl(var(--glass-border) / 0.58);
|
||||
border: 1px solid hsl(var(--glass-border) / 58%);
|
||||
border-radius: 24px;
|
||||
box-shadow:
|
||||
inset 0 1px 0 hsl(var(--glass-border) / 0.72),
|
||||
0 24px 54px -42px hsl(var(--primary) / 0.22),
|
||||
0 18px 42px -34px hsl(var(--foreground) / 0.1);
|
||||
inset 0 1px 0 hsl(var(--glass-border) / 72%),
|
||||
0 24px 54px -42px hsl(var(--primary) / 22%),
|
||||
0 18px 42px -34px hsl(var(--foreground) / 10%);
|
||||
backdrop-filter: blur(calc(var(--glass-blur) * 0.7)) saturate(145%);
|
||||
}
|
||||
|
||||
.list-page-shell.is-subtle .list-page-shell__content {
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
hsl(var(--glass-tint) / 0.84) 0%,
|
||||
hsl(var(--surface-contrast-soft) / 0.94) 100%
|
||||
hsl(var(--glass-tint) / 84%) 0%,
|
||||
hsl(var(--surface-contrast-soft) / 94%) 100%
|
||||
);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.list-page-shell.is-plain .list-page-shell__content {
|
||||
background: hsl(var(--surface-panel) / 0.96);
|
||||
border: 1px solid hsl(var(--divider-faint) / 0.58);
|
||||
background: hsl(var(--surface-panel) / 96%);
|
||||
border: 1px solid hsl(var(--divider-faint) / 58%);
|
||||
border-radius: 20px;
|
||||
box-shadow: none;
|
||||
backdrop-filter: none;
|
||||
@@ -162,14 +164,10 @@ const contentStyle = computed((): CSSProperties => {
|
||||
background:
|
||||
radial-gradient(
|
||||
ellipse 84% 72% at 10% 0%,
|
||||
hsl(var(--nav-ambient) / 0.18) 0%,
|
||||
hsl(var(--nav-ambient) / 18%) 0%,
|
||||
transparent 68%
|
||||
),
|
||||
linear-gradient(
|
||||
180deg,
|
||||
hsl(var(--nav-flow-trace) / 0.08) 0%,
|
||||
transparent 78%
|
||||
);
|
||||
linear-gradient(180deg, hsl(var(--nav-flow-trace) / 8%) 0%, transparent 78%);
|
||||
}
|
||||
|
||||
.list-page-shell__content > * {
|
||||
@@ -195,6 +193,7 @@ const contentStyle = computed((): CSSProperties => {
|
||||
--el-table-border-color: hsl(var(--table-row-border));
|
||||
--el-table-current-row-bg-color: hsl(var(--table-row-hover));
|
||||
--el-fill-color-blank: transparent;
|
||||
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
@@ -216,8 +215,8 @@ const contentStyle = computed((): CSSProperties => {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: hsl(var(--text-strong));
|
||||
background: hsl(var(--table-header-bg) / 0.86);
|
||||
border-bottom: 1px solid hsl(var(--divider-faint) / 0.38);
|
||||
background: hsl(var(--table-header-bg) / 86%);
|
||||
border-bottom: 1px solid hsl(var(--divider-faint) / 38%);
|
||||
}
|
||||
|
||||
.list-page-shell__content :deep(.el-table th.el-table__cell:first-child) {
|
||||
@@ -232,7 +231,7 @@ const contentStyle = computed((): CSSProperties => {
|
||||
.list-page-shell__content :deep(.el-table--border .el-table__cell) {
|
||||
padding: 14px 0;
|
||||
border-right: none;
|
||||
border-bottom: 1px solid hsl(var(--divider-faint) / 0.46);
|
||||
border-bottom: 1px solid hsl(var(--divider-faint) / 46%);
|
||||
}
|
||||
|
||||
.list-page-shell__content :deep(.el-table__row:hover > td.el-table__cell) {
|
||||
|
||||
@@ -138,7 +138,7 @@ onMounted(() => {
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
padding: 18px 20px 18px;
|
||||
padding: 18px 20px;
|
||||
}
|
||||
|
||||
.page-data-container__body {
|
||||
|
||||
@@ -114,6 +114,7 @@ const isSvgString = (icon: any) => {
|
||||
v-if="item.icon"
|
||||
class="ml-[-3px] flex items-center justify-center"
|
||||
>
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<div
|
||||
v-if="isSvgString(item.icon)"
|
||||
v-html="item.icon"
|
||||
@@ -127,6 +128,7 @@ const isSvgString = (icon: any) => {
|
||||
}"
|
||||
class="svg-container"
|
||||
></div>
|
||||
<!-- eslint-enable vue/no-v-html -->
|
||||
<img
|
||||
v-else-if="
|
||||
typeof item.icon === 'string' && !isComponent(item.icon)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {mount} from '@vue/test-utils';
|
||||
import { mount } from '@vue/test-utils';
|
||||
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import {describe, expect, it, vi} from 'vitest';
|
||||
import CardList from '../CardList.vue';
|
||||
|
||||
const { hasAccessByCodes } = vi.hoisted(() => ({
|
||||
@@ -13,7 +14,7 @@ vi.mock('@easyflow/access', () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('CardList', () => {
|
||||
describe('cardList', () => {
|
||||
function mountCardList(props: Record<string, unknown>) {
|
||||
return mount(CardList, {
|
||||
props: {
|
||||
|
||||
Reference in New Issue
Block a user