fix: 修复管理端前端 lint 与构建问题
- 收敛 easyflow-ui-admin 的 lint、格式和类型问题 - 修正 demo 页面与管理端前端构建失败点 - 验证 pnpm lint 与 pnpm build 均已通过
This commit is contained in:
@@ -7,7 +7,12 @@ import { computed, nextTick, ref, unref, useAttrs, watch } from 'vue';
|
||||
|
||||
import { LoaderCircle } from '@easyflow/icons';
|
||||
|
||||
import { cloneDeep, get, isEqual, isFunction } from '@easyflow-core/shared/utils';
|
||||
import {
|
||||
cloneDeep,
|
||||
get,
|
||||
isEqual,
|
||||
isFunction,
|
||||
} from '@easyflow-core/shared/utils';
|
||||
|
||||
import { objectOmit } from '@vueuse/core';
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
|
||||
import type { ChatThinkingBlockProps } from './types';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
defineOptions({
|
||||
name: 'ChatThinkingBlock',
|
||||
});
|
||||
@@ -24,8 +24,8 @@ const emit = defineEmits<{
|
||||
|
||||
const normalizedContent = computed(() =>
|
||||
String(props.content || '')
|
||||
.replace(/\r\n/g, '\n')
|
||||
.replace(/^\s*\n+/, '')
|
||||
.replaceAll('\r\n', '\n')
|
||||
.replace(/^\s*\n/, '')
|
||||
.trimEnd(),
|
||||
);
|
||||
|
||||
@@ -131,27 +131,26 @@ function toggleExpanded() {
|
||||
|
||||
<style scoped>
|
||||
.chat-thinking-block {
|
||||
border: 1px solid hsl(var(--divider-faint) / 0.18);
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
hsl(var(--glass-tint) / 48%) 0%,
|
||||
hsl(var(--surface-panel) / 74%) 100%
|
||||
);
|
||||
border: 1px solid hsl(var(--divider-faint) / 18%);
|
||||
border-radius: 16px;
|
||||
background:
|
||||
linear-gradient(
|
||||
180deg,
|
||||
hsl(var(--glass-tint) / 0.48) 0%,
|
||||
hsl(var(--surface-panel) / 0.74) 100%
|
||||
);
|
||||
box-shadow:
|
||||
inset 0 1px 0 hsl(var(--glass-border) / 0.24),
|
||||
0 10px 24px -24px hsl(var(--foreground) / 0.18);
|
||||
inset 0 1px 0 hsl(var(--glass-border) / 24%),
|
||||
0 10px 24px -24px hsl(var(--foreground) / 18%);
|
||||
backdrop-filter: blur(12px);
|
||||
}
|
||||
|
||||
.chat-thinking-block__trigger {
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr) auto;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
grid-template-columns: auto minmax(0, 1fr) auto;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 9px 12px;
|
||||
color: inherit;
|
||||
text-align: left;
|
||||
@@ -166,7 +165,7 @@ function toggleExpanded() {
|
||||
}
|
||||
|
||||
.chat-thinking-block__trigger:not(:disabled):hover {
|
||||
background: hsl(var(--surface-contrast-soft) / 0.34);
|
||||
background: hsl(var(--surface-contrast-soft) / 34%);
|
||||
}
|
||||
|
||||
.chat-thinking-block__trigger:disabled {
|
||||
@@ -175,9 +174,9 @@ function toggleExpanded() {
|
||||
|
||||
.chat-thinking-block__leading {
|
||||
display: inline-flex;
|
||||
min-width: 0;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.chat-thinking-block__indicator {
|
||||
@@ -185,19 +184,19 @@ function toggleExpanded() {
|
||||
flex: 0 0 auto;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: hsl(var(--text-muted) / 74%);
|
||||
border-radius: 999px;
|
||||
background: hsl(var(--text-muted) / 0.74);
|
||||
}
|
||||
|
||||
.chat-thinking-block.is-thinking .chat-thinking-block__indicator {
|
||||
background: hsl(var(--primary) / 0.82);
|
||||
box-shadow: 0 0 0 4px hsl(var(--primary) / 0.12);
|
||||
background: hsl(var(--primary) / 82%);
|
||||
box-shadow: 0 0 0 4px hsl(var(--primary) / 12%);
|
||||
animation: chat-thinking-pulse 1.8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.chat-thinking-block.is-error .chat-thinking-block__indicator {
|
||||
background: hsl(var(--destructive) / 0.86);
|
||||
box-shadow: 0 0 0 4px hsl(var(--destructive) / 0.1);
|
||||
background: hsl(var(--destructive) / 86%);
|
||||
box-shadow: 0 0 0 4px hsl(var(--destructive) / 10%);
|
||||
}
|
||||
|
||||
.chat-thinking-block__label {
|
||||
@@ -211,10 +210,10 @@ function toggleExpanded() {
|
||||
.chat-thinking-block__summary {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 12px;
|
||||
line-height: 1.3;
|
||||
color: hsl(var(--text-muted));
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@@ -236,15 +235,15 @@ function toggleExpanded() {
|
||||
}
|
||||
|
||||
.chat-thinking-block__content {
|
||||
margin: 0;
|
||||
padding: 10px 12px;
|
||||
border-radius: 12px;
|
||||
background: hsl(var(--surface-panel) / 0.72);
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
line-height: 1.68;
|
||||
color: hsl(var(--text-secondary));
|
||||
overflow-wrap: anywhere;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
background: hsl(var(--surface-panel) / 72%);
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.chat-thinking-block.is-disabled {
|
||||
@@ -267,12 +266,12 @@ function toggleExpanded() {
|
||||
@keyframes chat-thinking-pulse {
|
||||
0%,
|
||||
100% {
|
||||
box-shadow: 0 0 0 4px hsl(var(--primary) / 0.12);
|
||||
box-shadow: 0 0 0 4px hsl(var(--primary) / 12%);
|
||||
opacity: 0.92;
|
||||
}
|
||||
|
||||
50% {
|
||||
box-shadow: 0 0 0 7px hsl(var(--primary) / 0.04);
|
||||
box-shadow: 0 0 0 7px hsl(var(--primary) / 4%);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,2 @@
|
||||
export { default as ChatThinkingBlock } from './ChatThinkingBlock.vue';
|
||||
export type {
|
||||
ChatThinkingBlockProps,
|
||||
ChatThinkingBlockStatus,
|
||||
} from './types';
|
||||
export type { ChatThinkingBlockProps, ChatThinkingBlockStatus } from './types';
|
||||
|
||||
@@ -8,10 +8,10 @@ import { EmptyIcon, Grip, listIcons } from '@easyflow/icons';
|
||||
import { $t } from '@easyflow/locales';
|
||||
|
||||
import {
|
||||
Button,
|
||||
EasyFlowIcon,
|
||||
EasyFlowIconButton,
|
||||
EasyFlowPopover,
|
||||
Button,
|
||||
Input,
|
||||
Pagination,
|
||||
PaginationEllipsis,
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { TreeProps } from '@easyflow-core/shadcn-ui';
|
||||
import { Inbox } from '@easyflow/icons';
|
||||
import { $t } from '@easyflow/locales';
|
||||
|
||||
import { treePropsDefaults, EasyFlowTree } from '@easyflow-core/shadcn-ui';
|
||||
import { EasyFlowTree, treePropsDefaults } from '@easyflow-core/shadcn-ui';
|
||||
|
||||
const props = withDefaults(defineProps<TreeProps>(), treePropsDefaults());
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import {mount} from '@vue/test-utils';
|
||||
import {nextTick} from 'vue';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import {beforeEach, describe, expect, it, vi} from 'vitest';
|
||||
import AuthenticationLogin from '../login.vue';
|
||||
|
||||
const { formApi, routerPush } = vi.hoisted(() => ({
|
||||
@@ -41,7 +42,8 @@ vi.mock('@easyflow-core/form-ui', async () => {
|
||||
|
||||
vi.mock('@easyflow-core/shadcn-ui', async (importOriginal) => {
|
||||
const vue = await import('vue');
|
||||
const actual = await importOriginal<typeof import('@easyflow-core/shadcn-ui')>();
|
||||
const actual =
|
||||
await importOriginal<typeof import('@easyflow-core/shadcn-ui')>();
|
||||
|
||||
return {
|
||||
...actual,
|
||||
@@ -102,7 +104,7 @@ vi.mock('@easyflow-core/shadcn-ui', async (importOriginal) => {
|
||||
};
|
||||
});
|
||||
|
||||
describe('AuthenticationLogin', () => {
|
||||
describe('authenticationLogin', () => {
|
||||
const rememberKey = `REMEMBER_ME_ACCOUNT_${location.hostname}`;
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
<slot></slot>
|
||||
</h2>
|
||||
|
||||
<p class="text-muted-foreground max-w-[34rem] text-[0.97rem] leading-7 sm:text-[1rem]">
|
||||
<p
|
||||
class="text-muted-foreground max-w-[34rem] text-[0.97rem] leading-7 sm:text-[1rem]"
|
||||
>
|
||||
<slot name="desc"></slot>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import type {Recordable} from '@easyflow/types';
|
||||
import type { Recordable } from '@easyflow/types';
|
||||
|
||||
import type {EasyFlowFormSchema} from '@easyflow-core/form-ui';
|
||||
import {useEasyFlowForm} from '@easyflow-core/form-ui';
|
||||
import type { EasyFlowFormSchema } from '@easyflow-core/form-ui';
|
||||
|
||||
import {computed, reactive} from 'vue';
|
||||
import {useRouter} from 'vue-router';
|
||||
import { computed, reactive } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import {$t} from '@easyflow/locales';
|
||||
import {EasyFlowButton} from '@easyflow-core/shadcn-ui';
|
||||
import { $t } from '@easyflow/locales';
|
||||
|
||||
import { useEasyFlowForm } from '@easyflow-core/form-ui';
|
||||
import { EasyFlowButton } from '@easyflow-core/shadcn-ui';
|
||||
|
||||
import Title from './auth-title.vue';
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import type {EasyFlowFormSchema} from '@easyflow-core/form-ui';
|
||||
import {useEasyFlowForm} from '@easyflow-core/form-ui';
|
||||
import type { EasyFlowFormSchema } from '@easyflow-core/form-ui';
|
||||
|
||||
import {computed, reactive} from 'vue';
|
||||
import {useRouter} from 'vue-router';
|
||||
import { computed, reactive } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import {$t} from '@easyflow/locales';
|
||||
import {EasyFlowButton} from '@easyflow-core/shadcn-ui';
|
||||
import { $t } from '@easyflow/locales';
|
||||
|
||||
import { useEasyFlowForm } from '@easyflow-core/form-ui';
|
||||
import { EasyFlowButton } from '@easyflow-core/shadcn-ui';
|
||||
|
||||
import Title from './auth-title.vue';
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { computed, watch } from 'vue';
|
||||
import { $t } from '@easyflow/locales';
|
||||
|
||||
import { useEasyFlowModal } from '@easyflow-core/popup-ui';
|
||||
import { Slot, EasyFlowAvatar } from '@easyflow-core/shadcn-ui';
|
||||
import { EasyFlowAvatar, Slot } from '@easyflow-core/shadcn-ui';
|
||||
|
||||
interface Props extends AuthenticationProps {
|
||||
avatar?: string;
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
import type {Recordable} from '@easyflow/types';
|
||||
import type { Recordable } from '@easyflow/types';
|
||||
|
||||
import type {EasyFlowFormSchema} from '@easyflow-core/form-ui';
|
||||
import {useEasyFlowForm} from '@easyflow-core/form-ui';
|
||||
import type { EasyFlowFormSchema } from '@easyflow-core/form-ui';
|
||||
|
||||
import type {AuthenticationProps} from './types';
|
||||
import type { AuthenticationProps } from './types';
|
||||
|
||||
import {computed, onMounted, reactive, ref} from 'vue';
|
||||
import {useRouter} from 'vue-router';
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import {$t} from '@easyflow/locales';
|
||||
import {EasyFlowButton, EasyFlowCheckbox} from '@easyflow-core/shadcn-ui';
|
||||
import { $t } from '@easyflow/locales';
|
||||
|
||||
import { useEasyFlowForm } from '@easyflow-core/form-ui';
|
||||
import { EasyFlowButton, EasyFlowCheckbox } from '@easyflow-core/shadcn-ui';
|
||||
|
||||
import Title from './auth-title.vue';
|
||||
import ThirdPartyLogin from './third-party-login.vue';
|
||||
@@ -174,7 +175,10 @@ defineExpose({
|
||||
</slot>
|
||||
|
||||
<slot name="to-register">
|
||||
<div v-if="showRegister" class="auth-footer-copy mt-5 text-center text-sm">
|
||||
<div
|
||||
v-if="showRegister"
|
||||
class="auth-footer-copy mt-5 text-center text-sm"
|
||||
>
|
||||
{{ $t('authentication.accountTip') }}
|
||||
<button
|
||||
class="auth-inline-action"
|
||||
@@ -198,8 +202,8 @@ defineExpose({
|
||||
}
|
||||
|
||||
.auth-form-group :deep(.easyflow-form-ui .text-destructive) {
|
||||
font-size: 0.84rem;
|
||||
margin-top: 0.45rem;
|
||||
font-size: 0.84rem;
|
||||
}
|
||||
|
||||
.auth-login-options {
|
||||
@@ -207,14 +211,14 @@ defineExpose({
|
||||
}
|
||||
|
||||
.auth-checkbox {
|
||||
color: hsl(var(--text-muted));
|
||||
font-size: 0.92rem;
|
||||
color: hsl(var(--text-muted));
|
||||
}
|
||||
|
||||
.auth-inline-action {
|
||||
color: hsl(var(--nav-item-active-foreground));
|
||||
font-size: 0.92rem;
|
||||
font-weight: 500;
|
||||
color: hsl(var(--nav-item-active-foreground));
|
||||
transition: opacity 0.18s ease;
|
||||
}
|
||||
|
||||
@@ -228,20 +232,19 @@ defineExpose({
|
||||
}
|
||||
|
||||
.auth-brand-submit {
|
||||
background:
|
||||
linear-gradient(
|
||||
120deg,
|
||||
rgb(11 111 211) 0%,
|
||||
rgb(22 159 200) 38%,
|
||||
rgb(38 199 193) 62%,
|
||||
rgb(11 111 211) 100%
|
||||
);
|
||||
color: rgb(255 255 255);
|
||||
background: linear-gradient(
|
||||
120deg,
|
||||
rgb(11 111 211) 0%,
|
||||
rgb(22 159 200) 38%,
|
||||
rgb(38 199 193) 62%,
|
||||
rgb(11 111 211) 100%
|
||||
);
|
||||
background-size: 200% 200%;
|
||||
border: none;
|
||||
box-shadow:
|
||||
0 22px 34px -22px rgb(11 111 211 / 0.56),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.24);
|
||||
color: rgb(255 255 255);
|
||||
0 22px 34px -22px rgb(11 111 211 / 56%),
|
||||
inset 0 1px 0 rgb(255 255 255 / 24%);
|
||||
transition:
|
||||
transform 180ms ease,
|
||||
box-shadow 180ms ease,
|
||||
@@ -251,8 +254,8 @@ defineExpose({
|
||||
|
||||
.auth-brand-submit:hover {
|
||||
box-shadow:
|
||||
0 24px 38px -22px rgb(11 111 211 / 0.62),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.28);
|
||||
0 24px 38px -22px rgb(11 111 211 / 62%),
|
||||
inset 0 1px 0 rgb(255 255 255 / 28%);
|
||||
filter: saturate(1.04);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
@@ -262,7 +265,7 @@ defineExpose({
|
||||
}
|
||||
|
||||
.auth-brand-submit:focus-visible {
|
||||
outline: 2px solid rgb(78 176 255 / 0.8);
|
||||
outline: 2px solid rgb(78 176 255 / 80%);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import {ref} from 'vue';
|
||||
import {useRouter} from 'vue-router';
|
||||
import { ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import {$t} from '@easyflow/locales';
|
||||
import { $t } from '@easyflow/locales';
|
||||
|
||||
import {EasyFlowButton} from '@easyflow-core/shadcn-ui';
|
||||
import { EasyFlowButton } from '@easyflow-core/shadcn-ui';
|
||||
|
||||
import {useQRCode} from '@vueuse/integrations/useQRCode';
|
||||
import { useQRCode } from '@vueuse/integrations/useQRCode';
|
||||
|
||||
import Title from './auth-title.vue';
|
||||
|
||||
@@ -112,25 +112,29 @@ function goToLogin() {
|
||||
}
|
||||
|
||||
.auth-qrcode-frame {
|
||||
align-items: center;
|
||||
background: linear-gradient(180deg, rgb(255 255 255 / 0.92), rgb(244 249 255 / 0.96));
|
||||
border: 1px solid hsl(var(--line-subtle));
|
||||
border-radius: 1.5rem;
|
||||
box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.6);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto;
|
||||
max-width: 17rem;
|
||||
padding: 1rem;
|
||||
margin: 0 auto;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgb(255 255 255 / 92%),
|
||||
rgb(244 249 255 / 96%)
|
||||
);
|
||||
border: 1px solid hsl(var(--line-subtle));
|
||||
border-radius: 1.5rem;
|
||||
box-shadow: inset 0 1px 0 rgb(255 255 255 / 60%);
|
||||
}
|
||||
|
||||
.auth-qrcode-image {
|
||||
width: min(100%, 13rem);
|
||||
aspect-ratio: 1;
|
||||
border-radius: 1rem;
|
||||
width: min(100%, 13rem);
|
||||
}
|
||||
|
||||
.dark .auth-qrcode-frame {
|
||||
background: linear-gradient(180deg, rgb(14 22 36 / 0.92), rgb(11 19 31 / 0.96));
|
||||
background: linear-gradient(180deg, rgb(14 22 36 / 92%), rgb(11 19 31 / 96%));
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import type {Recordable} from '@easyflow/types';
|
||||
import type { Recordable } from '@easyflow/types';
|
||||
|
||||
import type {EasyFlowFormSchema} from '@easyflow-core/form-ui';
|
||||
import {useEasyFlowForm} from '@easyflow-core/form-ui';
|
||||
import type { EasyFlowFormSchema } from '@easyflow-core/form-ui';
|
||||
|
||||
import {computed, reactive} from 'vue';
|
||||
import {useRouter} from 'vue-router';
|
||||
import { computed, reactive } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import {$t} from '@easyflow/locales';
|
||||
import {EasyFlowButton} from '@easyflow-core/shadcn-ui';
|
||||
import { $t } from '@easyflow/locales';
|
||||
|
||||
import { useEasyFlowForm } from '@easyflow-core/form-ui';
|
||||
import { EasyFlowButton } from '@easyflow-core/shadcn-ui';
|
||||
|
||||
import Title from './auth-title.vue';
|
||||
|
||||
@@ -127,9 +128,9 @@ defineExpose({
|
||||
}
|
||||
|
||||
.auth-inline-action {
|
||||
color: hsl(var(--nav-item-active-foreground));
|
||||
font-size: 0.92rem;
|
||||
font-weight: 500;
|
||||
color: hsl(var(--nav-item-active-foreground));
|
||||
transition: opacity 0.18s ease;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@easyflow-core/shadcn-ui';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@easyflow-core/shadcn-ui';
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
|
||||
@@ -3,7 +3,12 @@ import type { TabOption } from '@easyflow/types';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@easyflow-core/shadcn-ui';
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from '@easyflow-core/shadcn-ui';
|
||||
|
||||
interface Props {
|
||||
tabs?: TabOption[];
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import type {ToolbarType} from './types';
|
||||
import type { ToolbarType } from './types';
|
||||
|
||||
import {computed, onBeforeUnmount, onMounted, ref} from 'vue';
|
||||
import {useRoute} from 'vue-router';
|
||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import {$t} from '@easyflow/locales';
|
||||
import {preferences, usePreferences} from '@easyflow/preferences';
|
||||
import { $t } from '@easyflow/locales';
|
||||
import { preferences, usePreferences } from '@easyflow/preferences';
|
||||
|
||||
import {Copyright} from '../basic/copyright';
|
||||
import { Copyright } from '../basic/copyright';
|
||||
import AuthenticationFormView from './form.vue';
|
||||
import Toolbar from './toolbar.vue';
|
||||
|
||||
@@ -107,7 +107,9 @@ onBeforeUnmount(() => {
|
||||
class="absolute left-0 top-0 z-20 flex flex-1"
|
||||
@click="clickLogo"
|
||||
>
|
||||
<div class="auth-brand-chip text-foreground ml-4 mt-4 flex items-center sm:ml-6 sm:mt-6">
|
||||
<div
|
||||
class="auth-brand-chip text-foreground ml-4 mt-4 flex items-center sm:ml-6 sm:mt-6"
|
||||
>
|
||||
<img
|
||||
v-if="logoSrc"
|
||||
:key="logoSrc"
|
||||
@@ -121,8 +123,12 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
</slot>
|
||||
|
||||
<main class="auth-stage relative z-10 flex min-h-full w-full items-center justify-center px-6 pb-10 pt-28 sm:px-10 sm:pt-32">
|
||||
<div class="auth-stage-inner mx-auto flex w-full max-w-[1080px] flex-col items-center">
|
||||
<main
|
||||
class="auth-stage relative z-10 flex min-h-full w-full items-center justify-center px-6 pb-10 pt-28 sm:px-10 sm:pt-32"
|
||||
>
|
||||
<div
|
||||
class="auth-stage-inner mx-auto flex w-full max-w-[1080px] flex-col items-center"
|
||||
>
|
||||
<div
|
||||
v-if="isLoginRoute"
|
||||
class="auth-stage-copy w-full max-w-[780px] text-center"
|
||||
@@ -130,7 +136,10 @@ onBeforeUnmount(() => {
|
||||
<h1 class="auth-page-title text-foreground">
|
||||
{{ stageGreeting }}
|
||||
</h1>
|
||||
<div class="auth-stage-switcher text-muted-foreground" aria-label="同一入口能力切换">
|
||||
<div
|
||||
class="auth-stage-switcher text-muted-foreground"
|
||||
aria-label="同一入口能力切换"
|
||||
>
|
||||
<span class="auth-stage-switcher-label">在同一入口管理</span>
|
||||
<span class="auth-stage-pill" aria-live="polite">
|
||||
<Transition mode="out-in" name="auth-pill">
|
||||
@@ -146,8 +155,8 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
|
||||
<AuthenticationFormView
|
||||
class="auth-window-host w-full"
|
||||
:class="[
|
||||
'auth-window-host w-full',
|
||||
isLoginRoute ? 'max-w-[25rem] sm:max-w-[26rem]' : 'max-w-[31rem]',
|
||||
isLoginRoute ? 'mt-8 sm:mt-10' : 'mt-0 sm:mt-4',
|
||||
]"
|
||||
@@ -170,69 +179,100 @@ onBeforeUnmount(() => {
|
||||
<style scoped>
|
||||
.auth-shell {
|
||||
background:
|
||||
radial-gradient(circle at top, rgb(255 255 255 / 78%), rgb(255 255 255 / 0) 36%),
|
||||
radial-gradient(
|
||||
circle at top,
|
||||
rgb(255 255 255 / 78%),
|
||||
rgb(255 255 255 / 0%) 36%
|
||||
),
|
||||
linear-gradient(180deg, #f7faff 0%, #eef4fd 55%, #edf3fb 100%);
|
||||
}
|
||||
|
||||
.auth-shell-grid {
|
||||
background-image:
|
||||
linear-gradient(rgb(13 74 160 / 0.06) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgb(13 74 160 / 0.06) 1px, transparent 1px);
|
||||
linear-gradient(rgb(13 74 160 / 6%) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgb(13 74 160 / 6%) 1px, transparent 1px);
|
||||
background-position: center center;
|
||||
background-size: 120px 120px;
|
||||
mask-image: linear-gradient(180deg, rgb(0 0 0 / 0.28), transparent 75%);
|
||||
opacity: 0.42;
|
||||
mask-image: linear-gradient(180deg, rgb(0 0 0 / 28%), transparent 75%);
|
||||
}
|
||||
|
||||
.auth-shell-noise {
|
||||
background-image:
|
||||
radial-gradient(circle at 20% 20%, rgb(255 255 255 / 0.35) 0 0.9px, transparent 1.2px),
|
||||
radial-gradient(circle at 80% 30%, rgb(255 255 255 / 0.22) 0 1px, transparent 1.3px),
|
||||
radial-gradient(circle at 40% 70%, rgb(11 111 211 / 0.08) 0 1px, transparent 1.4px);
|
||||
background-size: 180px 180px, 240px 240px, 200px 200px;
|
||||
radial-gradient(
|
||||
circle at 20% 20%,
|
||||
rgb(255 255 255 / 35%) 0 0.9px,
|
||||
transparent 1.2px
|
||||
),
|
||||
radial-gradient(
|
||||
circle at 80% 30%,
|
||||
rgb(255 255 255 / 22%) 0 1px,
|
||||
transparent 1.3px
|
||||
),
|
||||
radial-gradient(
|
||||
circle at 40% 70%,
|
||||
rgb(11 111 211 / 8%) 0 1px,
|
||||
transparent 1.4px
|
||||
);
|
||||
background-size:
|
||||
180px 180px,
|
||||
240px 240px,
|
||||
200px 200px;
|
||||
mix-blend-mode: soft-light;
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
.auth-glow {
|
||||
border-radius: 9999px;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
border-radius: 9999px;
|
||||
}
|
||||
|
||||
.auth-glow-primary {
|
||||
background: radial-gradient(circle, rgb(87 150 255 / 0.24) 0%, rgb(87 150 255 / 0) 68%);
|
||||
height: 26rem;
|
||||
left: 50%;
|
||||
top: 4rem;
|
||||
transform: translateX(-50%);
|
||||
left: 50%;
|
||||
width: 26rem;
|
||||
height: 26rem;
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgb(87 150 255 / 24%) 0%,
|
||||
rgb(87 150 255 / 0%) 68%
|
||||
);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.auth-glow-secondary {
|
||||
background: radial-gradient(circle, rgb(36 189 211 / 0.18) 0%, rgb(36 189 211 / 0) 72%);
|
||||
height: 20rem;
|
||||
left: 14%;
|
||||
top: 46%;
|
||||
left: 14%;
|
||||
width: 20rem;
|
||||
height: 20rem;
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgb(36 189 211 / 18%) 0%,
|
||||
rgb(36 189 211 / 0%) 72%
|
||||
);
|
||||
}
|
||||
|
||||
.auth-glow-tertiary {
|
||||
background: radial-gradient(circle, rgb(66 116 255 / 0.14) 0%, rgb(66 116 255 / 0) 74%);
|
||||
bottom: 8%;
|
||||
height: 22rem;
|
||||
right: 10%;
|
||||
bottom: 8%;
|
||||
width: 22rem;
|
||||
height: 22rem;
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgb(66 116 255 / 14%) 0%,
|
||||
rgb(66 116 255 / 0%) 74%
|
||||
);
|
||||
}
|
||||
|
||||
.auth-brand-chip {
|
||||
backdrop-filter: blur(12px);
|
||||
background: rgb(255 255 255 / 0.72);
|
||||
border: 1px solid rgb(255 255 255 / 0.84);
|
||||
border-radius: 9999px;
|
||||
box-shadow: 0 20px 44px -32px rgb(11 59 132 / 0.26);
|
||||
min-height: 3rem;
|
||||
padding: 0.45rem 0.95rem;
|
||||
background: rgb(255 255 255 / 72%);
|
||||
border: 1px solid rgb(255 255 255 / 84%);
|
||||
border-radius: 9999px;
|
||||
box-shadow: 0 20px 44px -32px rgb(11 59 132 / 26%);
|
||||
backdrop-filter: blur(12px);
|
||||
}
|
||||
|
||||
.auth-brand-name {
|
||||
@@ -242,19 +282,19 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
|
||||
.auth-page-title {
|
||||
max-width: 16ch;
|
||||
margin: 0 auto;
|
||||
font-size: clamp(2.1rem, 4vw, 3.7rem);
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.04em;
|
||||
line-height: 1.05;
|
||||
margin: 0 auto;
|
||||
max-width: 16ch;
|
||||
letter-spacing: -0.04em;
|
||||
}
|
||||
|
||||
.auth-stage-switcher {
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.7rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
@@ -265,19 +305,19 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
|
||||
.auth-stage-pill {
|
||||
align-items: center;
|
||||
backdrop-filter: blur(10px);
|
||||
background: rgb(255 255 255 / 0.74);
|
||||
border: 1px solid rgb(255 255 255 / 0.9);
|
||||
border-radius: 9999px;
|
||||
box-shadow: 0 18px 34px -28px rgb(14 61 132 / 0.3);
|
||||
color: hsl(var(--nav-item-active-foreground));
|
||||
display: inline-flex;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 6.5rem;
|
||||
padding: 0.55rem 1rem;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
color: hsl(var(--nav-item-active-foreground));
|
||||
background: rgb(255 255 255 / 74%);
|
||||
border: 1px solid rgb(255 255 255 / 90%);
|
||||
border-radius: 9999px;
|
||||
box-shadow: 0 18px 34px -28px rgb(14 61 132 / 30%);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.auth-stage-pill-text {
|
||||
@@ -310,13 +350,17 @@ onBeforeUnmount(() => {
|
||||
|
||||
.dark.auth-shell {
|
||||
background:
|
||||
radial-gradient(circle at top, rgb(35 66 114 / 0.32), rgb(15 22 35 / 0) 40%),
|
||||
radial-gradient(
|
||||
circle at top,
|
||||
rgb(35 66 114 / 32%),
|
||||
rgb(15 22 35 / 0%) 40%
|
||||
),
|
||||
linear-gradient(180deg, #06101b 0%, #08111d 52%, #09131f 100%);
|
||||
|
||||
.auth-shell-grid {
|
||||
background-image:
|
||||
linear-gradient(rgb(118 160 241 / 0.08) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgb(118 160 241 / 0.08) 1px, transparent 1px);
|
||||
linear-gradient(rgb(118 160 241 / 8%) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgb(118 160 241 / 8%) 1px, transparent 1px);
|
||||
opacity: 0.36;
|
||||
}
|
||||
|
||||
@@ -325,32 +369,44 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
|
||||
.auth-brand-chip {
|
||||
background: rgb(11 19 31 / 0.68);
|
||||
border-color: rgb(138 174 255 / 0.18);
|
||||
box-shadow: 0 24px 48px -34px rgb(0 0 0 / 0.52);
|
||||
background: rgb(11 19 31 / 68%);
|
||||
border-color: rgb(138 174 255 / 18%);
|
||||
box-shadow: 0 24px 48px -34px rgb(0 0 0 / 52%);
|
||||
}
|
||||
|
||||
.auth-stage-switcher-label {
|
||||
color: rgb(195 206 230 / 0.8);
|
||||
color: rgb(195 206 230 / 80%);
|
||||
}
|
||||
|
||||
.auth-stage-pill {
|
||||
background: rgb(11 19 31 / 0.7);
|
||||
border-color: rgb(138 174 255 / 0.18);
|
||||
box-shadow: 0 18px 34px -28px rgb(0 0 0 / 0.46);
|
||||
color: rgb(144 196 255 / 0.92);
|
||||
color: rgb(144 196 255 / 92%);
|
||||
background: rgb(11 19 31 / 70%);
|
||||
border-color: rgb(138 174 255 / 18%);
|
||||
box-shadow: 0 18px 34px -28px rgb(0 0 0 / 46%);
|
||||
}
|
||||
|
||||
.auth-glow-primary {
|
||||
background: radial-gradient(circle, rgb(70 120 255 / 0.26) 0%, rgb(70 120 255 / 0) 70%);
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgb(70 120 255 / 26%) 0%,
|
||||
rgb(70 120 255 / 0%) 70%
|
||||
);
|
||||
}
|
||||
|
||||
.auth-glow-secondary {
|
||||
background: radial-gradient(circle, rgb(41 170 201 / 0.18) 0%, rgb(41 170 201 / 0) 72%);
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgb(41 170 201 / 18%) 0%,
|
||||
rgb(41 170 201 / 0%) 72%
|
||||
);
|
||||
}
|
||||
|
||||
.auth-glow-tertiary {
|
||||
background: radial-gradient(circle, rgb(95 128 255 / 0.16) 0%, rgb(95 128 255 / 0) 74%);
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgb(95 128 255 / 16%) 0%,
|
||||
rgb(95 128 255 / 0%) 74%
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,9 +426,9 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
|
||||
.auth-page-title {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
max-width: none;
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.auth-stage-switcher {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import {computed} from 'vue';
|
||||
import {useRoute} from 'vue-router';
|
||||
import { computed } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
defineOptions({
|
||||
name: 'AuthenticationFormView',
|
||||
@@ -15,22 +15,23 @@ const isLoginRoute = computed(() => route.path === '/auth/login');
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="auth-form-wrap relative min-h-full"
|
||||
>
|
||||
<div :class="['auth-window-shell', { 'auth-window-shell-plain': isLoginRoute }]">
|
||||
<div class="auth-form-wrap relative min-h-full">
|
||||
<div
|
||||
class="auth-window-shell"
|
||||
:class="[{ 'auth-window-shell-plain': isLoginRoute }]"
|
||||
>
|
||||
<template v-if="!isLoginRoute">
|
||||
<div class="auth-window-edge auth-window-edge-top"></div>
|
||||
<div class="auth-window-edge auth-window-edge-bottom"></div>
|
||||
</template>
|
||||
<slot></slot>
|
||||
|
||||
<RouterView v-slot="{ Component, route }">
|
||||
<RouterView v-slot="{ Component, route: currentRoute }">
|
||||
<Transition appear mode="out-in" name="slide-right">
|
||||
<KeepAlive :include="['Login']">
|
||||
<component
|
||||
:is="Component"
|
||||
:key="route.fullPath"
|
||||
:key="currentRoute.fullPath"
|
||||
class="side-content w-full"
|
||||
:data-side="dataSide"
|
||||
/>
|
||||
@@ -53,49 +54,60 @@ const isLoginRoute = computed(() => route.path === '/auth/login');
|
||||
}
|
||||
|
||||
.auth-window-shell {
|
||||
backdrop-filter: blur(22px);
|
||||
background:
|
||||
linear-gradient(180deg, rgb(255 255 255 / 0.96) 0%, rgb(248 251 255 / 0.98) 100%);
|
||||
border: 1px solid rgb(255 255 255 / 0.82);
|
||||
position: relative;
|
||||
padding: 1.25rem;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgb(255 255 255 / 96%) 0%,
|
||||
rgb(248 251 255 / 98%) 100%
|
||||
);
|
||||
border: 1px solid rgb(255 255 255 / 82%);
|
||||
border-radius: 2rem;
|
||||
box-shadow:
|
||||
0 40px 80px -48px rgb(13 61 132 / 0.38),
|
||||
0 18px 36px -26px rgb(13 61 132 / 0.18);
|
||||
overflow: hidden;
|
||||
padding: 1.25rem;
|
||||
position: relative;
|
||||
0 40px 80px -48px rgb(13 61 132 / 38%),
|
||||
0 18px 36px -26px rgb(13 61 132 / 18%);
|
||||
backdrop-filter: blur(22px);
|
||||
}
|
||||
|
||||
.auth-window-shell-plain {
|
||||
backdrop-filter: none;
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
overflow: visible;
|
||||
padding: 0;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
|
||||
.auth-window-edge {
|
||||
border-radius: 9999px;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
border-radius: 9999px;
|
||||
}
|
||||
|
||||
.auth-window-edge-top {
|
||||
background: linear-gradient(90deg, rgb(11 111 211 / 0.18), rgb(22 159 200 / 0.08));
|
||||
height: 10rem;
|
||||
left: -4rem;
|
||||
top: -6rem;
|
||||
left: -4rem;
|
||||
width: 14rem;
|
||||
height: 10rem;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgb(11 111 211 / 18%),
|
||||
rgb(22 159 200 / 8%)
|
||||
);
|
||||
}
|
||||
|
||||
.auth-window-edge-bottom {
|
||||
background: radial-gradient(circle, rgb(84 132 255 / 0.14) 0%, rgb(84 132 255 / 0) 72%);
|
||||
bottom: -4rem;
|
||||
height: 11rem;
|
||||
right: -4rem;
|
||||
bottom: -4rem;
|
||||
width: 11rem;
|
||||
height: 11rem;
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgb(84 132 255 / 14%) 0%,
|
||||
rgb(84 132 255 / 0%) 72%
|
||||
);
|
||||
}
|
||||
|
||||
.auth-copyright {
|
||||
@@ -104,12 +116,15 @@ const isLoginRoute = computed(() => route.path === '/auth/login');
|
||||
}
|
||||
|
||||
.dark .auth-window-shell {
|
||||
background:
|
||||
linear-gradient(180deg, rgb(10 18 30 / 0.92) 0%, rgb(9 17 29 / 0.96) 100%);
|
||||
border-color: rgb(136 168 235 / 0.16);
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgb(10 18 30 / 92%) 0%,
|
||||
rgb(9 17 29 / 96%) 100%
|
||||
);
|
||||
border-color: rgb(136 168 235 / 16%);
|
||||
box-shadow:
|
||||
0 42px 84px -50px rgb(0 0 0 / 0.64),
|
||||
0 18px 36px -28px rgb(0 0 0 / 0.42);
|
||||
0 42px 84px -50px rgb(0 0 0 / 64%),
|
||||
0 18px 36px -28px rgb(0 0 0 / 42%);
|
||||
}
|
||||
|
||||
.dark .auth-window-shell-plain {
|
||||
@@ -119,11 +134,19 @@ const isLoginRoute = computed(() => route.path === '/auth/login');
|
||||
}
|
||||
|
||||
.dark .auth-window-edge-top {
|
||||
background: linear-gradient(90deg, rgb(69 120 255 / 0.22), rgb(28 155 197 / 0.08));
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgb(69 120 255 / 22%),
|
||||
rgb(28 155 197 / 8%)
|
||||
);
|
||||
}
|
||||
|
||||
.dark .auth-window-edge-bottom {
|
||||
background: radial-gradient(circle, rgb(92 136 255 / 0.16) 0%, rgb(92 136 255 / 0) 72%);
|
||||
background: radial-gradient(
|
||||
circle,
|
||||
rgb(92 136 255 / 16%) 0%,
|
||||
rgb(92 136 255 / 0%) 72%
|
||||
);
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
@@ -132,8 +155,8 @@ const isLoginRoute = computed(() => route.path === '/auth/login');
|
||||
}
|
||||
|
||||
.auth-window-shell {
|
||||
border-radius: 1.6rem;
|
||||
padding: 1rem;
|
||||
border-radius: 1.6rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import type {ToolbarType} from './types';
|
||||
import type { ToolbarType } from './types';
|
||||
|
||||
import {computed} from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import {preferences} from '@easyflow/preferences';
|
||||
import { preferences } from '@easyflow/preferences';
|
||||
|
||||
import {
|
||||
AuthenticationColorToggle,
|
||||
@@ -48,17 +48,17 @@ const showTheme = computed(() => props.toolbarList.includes('theme'));
|
||||
|
||||
<style scoped>
|
||||
.auth-toolbar {
|
||||
backdrop-filter: blur(10px);
|
||||
background: rgb(255 255 255 / 0.72);
|
||||
border: 1px solid rgb(255 255 255 / 0.78);
|
||||
border-radius: 9999px;
|
||||
box-shadow: 0 20px 42px -30px rgb(14 55 124 / 0.28);
|
||||
padding: 0.25rem 0.58rem;
|
||||
background: rgb(255 255 255 / 72%);
|
||||
border: 1px solid rgb(255 255 255 / 78%);
|
||||
border-radius: 9999px;
|
||||
box-shadow: 0 20px 42px -30px rgb(14 55 124 / 28%);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
:deep(.dark) .auth-toolbar {
|
||||
background: rgb(11 19 34 / 66%);
|
||||
border-color: rgb(122 167 255 / 18%);
|
||||
box-shadow: 0 20px 40px -28px rgb(0 0 0 / 0.46);
|
||||
box-shadow: 0 20px 40px -28px rgb(0 0 0 / 46%);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
<script lang="ts" setup>
|
||||
import type {VNode} from 'vue';
|
||||
import {computed} from 'vue';
|
||||
import type { VNode } from 'vue';
|
||||
import type {
|
||||
RouteLocationNormalizedLoaded,
|
||||
RouteLocationNormalizedLoadedGeneric,
|
||||
} from 'vue-router';
|
||||
import {RouterView} from 'vue-router';
|
||||
|
||||
import {preferences, usePreferences} from '@easyflow/preferences';
|
||||
import {getTabKey, storeToRefs, useTabbarStore} from '@easyflow/stores';
|
||||
import { computed } from 'vue';
|
||||
import { RouterView } from 'vue-router';
|
||||
|
||||
import {IFrameRouterView} from '../../iframe';
|
||||
import { preferences, usePreferences } from '@easyflow/preferences';
|
||||
import { getTabKey, storeToRefs, useTabbarStore } from '@easyflow/stores';
|
||||
|
||||
import { IFrameRouterView } from '../../iframe';
|
||||
|
||||
defineOptions({ name: 'LayoutContent' });
|
||||
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
<script lang="ts" setup>
|
||||
import type {CSSProperties} from 'vue';
|
||||
import {computed, useSlots} from 'vue';
|
||||
import type { CSSProperties } from 'vue';
|
||||
|
||||
import {useRefresh} from '@easyflow/hooks';
|
||||
import {RotateCw} from '@easyflow/icons';
|
||||
import {preferences, usePreferences} from '@easyflow/preferences';
|
||||
import {useAccessStore} from '@easyflow/stores';
|
||||
import { computed, useSlots } from 'vue';
|
||||
|
||||
import {EasyFlowFullScreen, EasyFlowIconButton} from '@easyflow-core/shadcn-ui';
|
||||
import { useRefresh } from '@easyflow/hooks';
|
||||
import { RotateCw } from '@easyflow/icons';
|
||||
import { preferences, usePreferences } from '@easyflow/preferences';
|
||||
import { useAccessStore } from '@easyflow/stores';
|
||||
|
||||
import {
|
||||
EasyFlowFullScreen,
|
||||
EasyFlowIconButton,
|
||||
} from '@easyflow-core/shadcn-ui';
|
||||
|
||||
import {
|
||||
GlobalSearch,
|
||||
@@ -174,16 +178,28 @@ function clearPreferencesAndLogout() {
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="slot.name === 'theme-toggle'">
|
||||
<ThemeToggle :class="toolbarButtonClass" :style="toolbarButtonStyle" />
|
||||
<ThemeToggle
|
||||
:class="toolbarButtonClass"
|
||||
:style="toolbarButtonStyle"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="slot.name === 'language-toggle'">
|
||||
<LanguageToggle :class="toolbarButtonClass" :style="toolbarButtonStyle" />
|
||||
<LanguageToggle
|
||||
:class="toolbarButtonClass"
|
||||
:style="toolbarButtonStyle"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="slot.name === 'fullscreen'">
|
||||
<EasyFlowFullScreen :class="toolbarButtonClass" :style="toolbarButtonStyle" />
|
||||
<EasyFlowFullScreen
|
||||
:class="toolbarButtonClass"
|
||||
:style="toolbarButtonStyle"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="slot.name === 'timezone'">
|
||||
<TimezoneButton :class="toolbarButtonClass" :style="toolbarButtonStyle" />
|
||||
<TimezoneButton
|
||||
:class="toolbarButtonClass"
|
||||
:style="toolbarButtonStyle"
|
||||
/>
|
||||
</template>
|
||||
</slot>
|
||||
</template>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import type {MenuRecordRaw} from '@easyflow/types';
|
||||
import type { MenuRecordRaw } from '@easyflow/types';
|
||||
|
||||
import {computed, onBeforeMount, ref, watch} from 'vue';
|
||||
import {useRoute} from 'vue-router';
|
||||
import { computed, onBeforeMount, ref, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import {preferences, usePreferences} from '@easyflow/preferences';
|
||||
import {useAccessStore} from '@easyflow/stores';
|
||||
import {findRootMenuByPath} from '@easyflow/utils';
|
||||
import { preferences, usePreferences } from '@easyflow/preferences';
|
||||
import { useAccessStore } from '@easyflow/stores';
|
||||
import { findRootMenuByPath } from '@easyflow/utils';
|
||||
|
||||
import {useNavigation} from './use-navigation';
|
||||
import { useNavigation } from './use-navigation';
|
||||
|
||||
function useMixedMenu() {
|
||||
const { navigation, prefetch, willOpenedByWindow } = useNavigation();
|
||||
|
||||
@@ -237,10 +237,7 @@ onMounted(() => {
|
||||
class="block truncate text-sm font-medium leading-6 text-[hsl(var(--text-strong))]"
|
||||
>
|
||||
<template
|
||||
v-for="chunk in getHighlightedChunks(
|
||||
item.name || '',
|
||||
keyword,
|
||||
)"
|
||||
v-for="chunk in getHighlightedChunks(item.name || '', keyword)"
|
||||
:key="`${item.path}-${chunk.text}-${chunk.matched}`"
|
||||
>
|
||||
<span
|
||||
|
||||
@@ -6,7 +6,10 @@ import { Languages } from '@easyflow/icons';
|
||||
import { loadLocaleMessages } from '@easyflow/locales';
|
||||
import { preferences, updatePreferences } from '@easyflow/preferences';
|
||||
|
||||
import { EasyFlowDropdownRadioMenu, EasyFlowIconButton } from '@easyflow-core/shadcn-ui';
|
||||
import {
|
||||
EasyFlowDropdownRadioMenu,
|
||||
EasyFlowIconButton,
|
||||
} from '@easyflow-core/shadcn-ui';
|
||||
|
||||
defineOptions({
|
||||
name: 'LanguageToggle',
|
||||
|
||||
@@ -13,7 +13,10 @@ import {
|
||||
usePreferences,
|
||||
} from '@easyflow/preferences';
|
||||
|
||||
import { EasyFlowDropdownRadioMenu, EasyFlowIconButton } from '@easyflow-core/shadcn-ui';
|
||||
import {
|
||||
EasyFlowDropdownRadioMenu,
|
||||
EasyFlowIconButton,
|
||||
} from '@easyflow-core/shadcn-ui';
|
||||
|
||||
defineOptions({
|
||||
name: 'AuthenticationLayoutToggle',
|
||||
|
||||
@@ -5,7 +5,10 @@ import { useSlots } from 'vue';
|
||||
|
||||
import { CircleHelp } from '@easyflow/icons';
|
||||
|
||||
import { EasyFlowCheckButtonGroup, EasyFlowTooltip } from '@easyflow-core/shadcn-ui';
|
||||
import {
|
||||
EasyFlowCheckButtonGroup,
|
||||
EasyFlowTooltip,
|
||||
} from '@easyflow-core/shadcn-ui';
|
||||
|
||||
defineOptions({
|
||||
name: 'PreferenceCheckboxItem',
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useSlots } from 'vue';
|
||||
|
||||
import { CircleHelp, CircleX } from '@easyflow/icons';
|
||||
|
||||
import { Input, EasyFlowTooltip } from '@easyflow-core/shadcn-ui';
|
||||
import { EasyFlowTooltip, Input } from '@easyflow-core/shadcn-ui';
|
||||
|
||||
defineOptions({
|
||||
name: 'PreferenceSelectItem',
|
||||
|
||||
@@ -6,12 +6,12 @@ import { useSlots } from 'vue';
|
||||
import { CircleHelp } from '@easyflow/icons';
|
||||
|
||||
import {
|
||||
EasyFlowTooltip,
|
||||
NumberField,
|
||||
NumberFieldContent,
|
||||
NumberFieldDecrement,
|
||||
NumberFieldIncrement,
|
||||
NumberFieldInput,
|
||||
EasyFlowTooltip,
|
||||
} from '@easyflow-core/shadcn-ui';
|
||||
|
||||
defineOptions({
|
||||
|
||||
@@ -6,12 +6,12 @@ import { useSlots } from 'vue';
|
||||
import { CircleHelp } from '@easyflow/icons';
|
||||
|
||||
import {
|
||||
EasyFlowTooltip,
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
EasyFlowTooltip,
|
||||
} from '@easyflow-core/shadcn-ui';
|
||||
|
||||
defineOptions({
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useSlots } from 'vue';
|
||||
|
||||
import { CircleHelp } from '@easyflow/icons';
|
||||
|
||||
import { Switch, EasyFlowTooltip } from '@easyflow-core/shadcn-ui';
|
||||
import { EasyFlowTooltip, Switch } from '@easyflow-core/shadcn-ui';
|
||||
|
||||
defineOptions({
|
||||
name: 'PreferenceSwitchItem',
|
||||
|
||||
@@ -10,9 +10,9 @@ import {
|
||||
} from '@easyflow/preferences';
|
||||
|
||||
import {
|
||||
EasyFlowTooltip,
|
||||
ToggleGroup,
|
||||
ToggleGroupItem,
|
||||
EasyFlowTooltip,
|
||||
} from '@easyflow-core/shadcn-ui';
|
||||
|
||||
import ThemeButton from './theme-button.vue';
|
||||
|
||||
@@ -7,9 +7,9 @@ import { useTimezoneStore } from '@easyflow/stores';
|
||||
|
||||
import { useEasyFlowModal } from '@easyflow-core/popup-ui';
|
||||
import {
|
||||
EasyFlowIconButton,
|
||||
RadioGroup,
|
||||
RadioGroupItem,
|
||||
EasyFlowIconButton,
|
||||
} from '@easyflow-core/shadcn-ui';
|
||||
|
||||
const TimezoneIcon = createIconifyIcon('fluent-mdl2:world-clock');
|
||||
|
||||
@@ -9,7 +9,10 @@ import type { Ref } from 'vue';
|
||||
|
||||
import type { ClassType, DeepPartial } from '@easyflow/types';
|
||||
|
||||
import type { BaseFormComponentType, EasyFlowFormProps } from '@easyflow-core/form-ui';
|
||||
import type {
|
||||
BaseFormComponentType,
|
||||
EasyFlowFormProps,
|
||||
} from '@easyflow-core/form-ui';
|
||||
|
||||
import type { VxeGridApi } from './api';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user