chore: eslint 配置
This commit is contained in:
@ -4,7 +4,6 @@ import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescri
|
||||
import pluginImport from 'eslint-plugin-import-x';
|
||||
import oxlint from 'eslint-plugin-oxlint';
|
||||
import perfectionist from 'eslint-plugin-perfectionist';
|
||||
import perfectionistPlugin from 'eslint-plugin-perfectionist';
|
||||
import pluginVue from 'eslint-plugin-vue';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
@ -13,8 +12,6 @@ const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const gitignorePath = path.resolve(__dirname, '.gitignore');
|
||||
|
||||
import type { Linter } from 'eslint';
|
||||
|
||||
// To allow more languages other than `ts` in `.vue` files, uncomment the following lines:
|
||||
import { configureVueProject } from '@vue/eslint-config-typescript';
|
||||
|
||||
@ -24,13 +21,13 @@ configureVueProject({ scriptLangs: ['ts', 'tsx', 'js', 'jsx'] });
|
||||
export default defineConfigWithVueTs(
|
||||
includeIgnoreFile(gitignorePath), // oxlint . --fix -D correctness --ignore-path .gitignore
|
||||
{
|
||||
name: 'app/files-to-lint',
|
||||
files: ['**/*.{ts,mts,tsx,vue}'],
|
||||
name: 'app/files-to-lint',
|
||||
},
|
||||
|
||||
{
|
||||
name: 'app/files-to-ignore',
|
||||
ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**'],
|
||||
name: 'app/files-to-ignore',
|
||||
},
|
||||
|
||||
pluginVue.configs['flat/essential'],
|
||||
@ -48,43 +45,9 @@ export default defineConfigWithVueTs(
|
||||
oxlint.configs['flat/recommended'],
|
||||
skipFormatting,
|
||||
|
||||
importPluginConfig(),
|
||||
{
|
||||
rules: {
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'vue/block-order': [
|
||||
'error',
|
||||
{
|
||||
order: ['script', 'template', 'style'],
|
||||
},
|
||||
],
|
||||
'vue/define-macros-order': [
|
||||
'error',
|
||||
{
|
||||
order: ['defineOptions', 'defineProps', 'defineEmits', 'defineSlots'],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
// https://perfectionist.dev/guide/getting-started
|
||||
perfectionistPlugin.configs['recommended-natural'],
|
||||
[
|
||||
{
|
||||
plugins: {
|
||||
perfectionist,
|
||||
},
|
||||
rules: {
|
||||
'perfectionist/sort-imports': ['error'],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
function importPluginConfig(): Linter.Config[] {
|
||||
return [
|
||||
{
|
||||
plugins: {
|
||||
// @ts-expect-error - This is a dynamic import
|
||||
import: pluginImport,
|
||||
},
|
||||
rules: {
|
||||
@ -98,5 +61,35 @@ function importPluginConfig(): Linter.Config[] {
|
||||
// 'import/no-webpack-loader-syntax': 'error',
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
],
|
||||
|
||||
{
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'vue/block-order': [
|
||||
'error',
|
||||
{
|
||||
order: ['script', 'template', 'style'],
|
||||
},
|
||||
],
|
||||
'vue/define-macros-order': [
|
||||
'error',
|
||||
{
|
||||
order: ['defineOptions', 'defineProps', 'defineEmits', 'defineSlots'],
|
||||
},
|
||||
],
|
||||
'vue/multi-word-component-names': 'off',
|
||||
},
|
||||
},
|
||||
|
||||
// https://perfectionist.dev/guide/getting-started
|
||||
|
||||
[
|
||||
perfectionist.configs['recommended-natural'],
|
||||
{
|
||||
rules: {
|
||||
'perfectionist/sort-imports': ['error'],
|
||||
},
|
||||
},
|
||||
],
|
||||
);
|
||||
|
@ -4,14 +4,7 @@ import { defineFakeRoute } from 'vite-plugin-fake-server/client';
|
||||
let fail = !false;
|
||||
export default defineFakeRoute([
|
||||
{
|
||||
timeout: 2000,
|
||||
method: 'POST',
|
||||
url: '/fake/upload',
|
||||
response: () => {
|
||||
return {
|
||||
url: 'https://picsum.photos/200/300',
|
||||
};
|
||||
},
|
||||
rawResponse(req, res) {
|
||||
fail = !fail;
|
||||
if (fail) {
|
||||
@ -22,5 +15,12 @@ export default defineFakeRoute([
|
||||
res.end(JSON.stringify({ url: 'https://picsum.photos/200/300' }));
|
||||
}
|
||||
},
|
||||
response: () => {
|
||||
return {
|
||||
url: 'https://picsum.photos/200/300',
|
||||
};
|
||||
},
|
||||
timeout: 2000,
|
||||
url: '/fake/upload',
|
||||
},
|
||||
]);
|
||||
|
@ -5,30 +5,30 @@ import { defineFakeRoute } from 'vite-plugin-fake-server/client';
|
||||
|
||||
export default defineFakeRoute([
|
||||
{
|
||||
url: '/mock/get-user-info',
|
||||
response: () => {
|
||||
return Mock.mock({
|
||||
id: '@guid',
|
||||
username: '@first',
|
||||
email: '@email',
|
||||
avatar: '@image("200x200")',
|
||||
email: '@email',
|
||||
id: '@guid',
|
||||
role: 'admin',
|
||||
username: '@first',
|
||||
});
|
||||
},
|
||||
url: '/mock/get-user-info',
|
||||
},
|
||||
{
|
||||
url: '/fake/get-user-info',
|
||||
response: () => {
|
||||
return {
|
||||
id: faker.string.uuid(),
|
||||
avatar: faker.image.avatar(),
|
||||
birthday: faker.date.birthdate(),
|
||||
email: faker.internet.email(),
|
||||
firstName: faker.person.firstName(),
|
||||
id: faker.string.uuid(),
|
||||
lastName: faker.person.lastName(),
|
||||
sex: faker.person.sexType(),
|
||||
role: 'admin',
|
||||
sex: faker.person.sexType(),
|
||||
};
|
||||
},
|
||||
url: '/fake/get-user-info',
|
||||
},
|
||||
]);
|
||||
|
@ -12,29 +12,13 @@ import { defineConfig, devices } from '@playwright/test';
|
||||
* See https://playwright.dev/docs/test-configuration.
|
||||
*/
|
||||
export default defineConfig({
|
||||
testDir: './tests/e2e',
|
||||
/* Run tests in files in parallel */
|
||||
fullyParallel: true,
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
forbidOnly: !!process.env.CI,
|
||||
/* Retry on CI only */
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
/* Opt out of parallel tests on CI. */
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||
reporter: 'html',
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
use: {
|
||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||
baseURL: process.env.BASE_URL || 'https://vue-ts-example.oo1.dev',
|
||||
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
trace: 'on-first-retry',
|
||||
},
|
||||
expect: {
|
||||
timeout: 30 * 1000,
|
||||
},
|
||||
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
forbidOnly: !!process.env.CI,
|
||||
/* Run tests in files in parallel */
|
||||
fullyParallel: true,
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{
|
||||
@ -72,6 +56,22 @@ export default defineConfig({
|
||||
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
|
||||
// },
|
||||
],
|
||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||
reporter: 'html',
|
||||
/* Retry on CI only */
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
testDir: './tests/e2e',
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
use: {
|
||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||
baseURL: process.env.BASE_URL || 'https://vue-ts-example.oo1.dev',
|
||||
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
trace: 'on-first-retry',
|
||||
},
|
||||
|
||||
/* Opt out of parallel tests on CI. */
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
|
||||
/* Run your local dev server before starting the tests */
|
||||
// webServer: {
|
||||
|
@ -6,7 +6,7 @@ function checkIsVisible(el: Element, root: Element | null = null) {
|
||||
const elRect = el.getBoundingClientRect();
|
||||
const rootRect = root
|
||||
? root.getBoundingClientRect()
|
||||
: { top: 0, left: 0, bottom: window.innerHeight, right: window.innerWidth };
|
||||
: { bottom: window.innerHeight, left: 0, right: window.innerWidth, top: 0 };
|
||||
|
||||
return (
|
||||
elRect.bottom >= rootRect.top &&
|
||||
@ -32,26 +32,26 @@ function checkIsVisible(el: Element, root: Element | null = null) {
|
||||
*/
|
||||
|
||||
const props = defineProps<{
|
||||
loading: boolean;
|
||||
complete: boolean;
|
||||
error: boolean;
|
||||
errorText: string;
|
||||
loading: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
load: [];
|
||||
clickError: [];
|
||||
load: [];
|
||||
}>();
|
||||
|
||||
defineSlots<{
|
||||
// 加载中
|
||||
loading(): unknown;
|
||||
// 加载完成(还有更多)
|
||||
loaded(): unknown;
|
||||
// 加载完成(没有更多了)
|
||||
complete(): unknown;
|
||||
// 加载失败
|
||||
error(): unknown;
|
||||
// 加载完成(还有更多)
|
||||
loaded(): unknown;
|
||||
// 加载中
|
||||
loading(): unknown;
|
||||
}>();
|
||||
|
||||
const check = (reason?: string) => {
|
||||
|
@ -6,15 +6,15 @@ interface FileExt extends File {
|
||||
}
|
||||
|
||||
interface FileUploadInst extends FileUploadState {
|
||||
chooseDisabled?: boolean;
|
||||
files: FileExt[];
|
||||
uploadedFiles: {
|
||||
rawFile: FileExt;
|
||||
name: string;
|
||||
url: string;
|
||||
status: 'uploading' | 'uploaded' | 'failed';
|
||||
progress: number;
|
||||
rawFile: FileExt;
|
||||
status: 'failed' | 'uploaded' | 'uploading';
|
||||
url: string;
|
||||
}[];
|
||||
chooseDisabled?: boolean;
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -30,11 +30,11 @@ const onUploader = (event: FileUploadUploaderEvent) => {
|
||||
const files = event.files as FileExt[];
|
||||
for (const file of files) {
|
||||
fileUploadRef.value!.uploadedFiles.push({
|
||||
rawFile: file,
|
||||
name: file.name,
|
||||
url: '',
|
||||
status: 'uploading',
|
||||
progress: 0,
|
||||
rawFile: file,
|
||||
status: 'uploading',
|
||||
url: '',
|
||||
});
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
const { remaining: countdownTime, start: startCountdown, isActive: isCounting } = useCountdown($__DEV__ ? 3 : 60);
|
||||
const { isActive: isCounting, remaining: countdownTime, start: startCountdown } = useCountdown($__DEV__ ? 3 : 60);
|
||||
|
||||
const isSending = ref(false);
|
||||
const sendSms = async () => {
|
||||
@ -8,7 +8,7 @@ const sendSms = async () => {
|
||||
try {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
startCountdown();
|
||||
ToastService.add({ severity: 'info', summary: '提示', life: 3000, detail: '验证码发送成功' });
|
||||
ToastService.add({ detail: '验证码发送成功', life: 3000, severity: 'info', summary: '提示' });
|
||||
} finally {
|
||||
isSending.value = false;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import { ref } from 'vue';
|
||||
|
||||
import { useLayout } from './composables/layout';
|
||||
|
||||
const { layoutConfig, isDarkTheme } = useLayout();
|
||||
const { isDarkTheme, layoutConfig } = useLayout();
|
||||
const presets = {
|
||||
Aura,
|
||||
Lara,
|
||||
@ -419,12 +419,50 @@ const surfaces = ref([
|
||||
},
|
||||
]);
|
||||
|
||||
function applyTheme(type: string, color: any) {
|
||||
if (type === 'primary') {
|
||||
updatePreset(getPresetExt());
|
||||
} else if (type === 'surface') {
|
||||
updateSurfacePalette(color.palette);
|
||||
}
|
||||
}
|
||||
|
||||
function getPresetExt() {
|
||||
const color = primaryColors.value.find((c) => c.name === layoutConfig.primary)!;
|
||||
|
||||
if (color.name === 'noir') {
|
||||
return {
|
||||
semantic: {
|
||||
colorScheme: {
|
||||
dark: {
|
||||
highlight: {
|
||||
background: '{primary.50}',
|
||||
color: '{primary.950}',
|
||||
focusBackground: '{primary.300}',
|
||||
focusColor: '{primary.950}',
|
||||
},
|
||||
primary: {
|
||||
activeColor: '{primary.300}',
|
||||
color: '{primary.50}',
|
||||
contrastColor: '{primary.950}',
|
||||
hoverColor: '{primary.200}',
|
||||
},
|
||||
},
|
||||
light: {
|
||||
highlight: {
|
||||
background: '{primary.950}',
|
||||
color: '#ffffff',
|
||||
focusBackground: '{primary.700}',
|
||||
focusColor: '#ffffff',
|
||||
},
|
||||
primary: {
|
||||
activeColor: '{primary.700}',
|
||||
color: '{primary.950}',
|
||||
contrastColor: '#ffffff',
|
||||
hoverColor: '{primary.800}',
|
||||
},
|
||||
},
|
||||
},
|
||||
primary: {
|
||||
50: '{surface.50}',
|
||||
100: '{surface.100}',
|
||||
@ -438,93 +476,49 @@ function getPresetExt() {
|
||||
900: '{surface.900}',
|
||||
950: '{surface.950}',
|
||||
},
|
||||
colorScheme: {
|
||||
light: {
|
||||
primary: {
|
||||
color: '{primary.950}',
|
||||
contrastColor: '#ffffff',
|
||||
hoverColor: '{primary.800}',
|
||||
activeColor: '{primary.700}',
|
||||
},
|
||||
highlight: {
|
||||
background: '{primary.950}',
|
||||
focusBackground: '{primary.700}',
|
||||
color: '#ffffff',
|
||||
focusColor: '#ffffff',
|
||||
},
|
||||
},
|
||||
dark: {
|
||||
primary: {
|
||||
color: '{primary.50}',
|
||||
contrastColor: '{primary.950}',
|
||||
hoverColor: '{primary.200}',
|
||||
activeColor: '{primary.300}',
|
||||
},
|
||||
highlight: {
|
||||
background: '{primary.50}',
|
||||
focusBackground: '{primary.300}',
|
||||
color: '{primary.950}',
|
||||
focusColor: '{primary.950}',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
semantic: {
|
||||
primary: color.palette,
|
||||
colorScheme: {
|
||||
light: {
|
||||
primary: {
|
||||
color: '{primary.500}',
|
||||
contrastColor: '#ffffff',
|
||||
hoverColor: '{primary.600}',
|
||||
activeColor: '{primary.700}',
|
||||
},
|
||||
highlight: {
|
||||
background: '{primary.50}',
|
||||
focusBackground: '{primary.100}',
|
||||
color: '{primary.700}',
|
||||
focusColor: '{primary.800}',
|
||||
},
|
||||
},
|
||||
dark: {
|
||||
highlight: {
|
||||
background: 'color-mix(in srgb, {primary.400}, transparent 84%)',
|
||||
color: 'rgba(255,255,255,.87)',
|
||||
focusBackground: 'color-mix(in srgb, {primary.400}, transparent 76%)',
|
||||
focusColor: 'rgba(255,255,255,.87)',
|
||||
},
|
||||
primary: {
|
||||
activeColor: '{primary.200}',
|
||||
color: '{primary.400}',
|
||||
contrastColor: '{surface.900}',
|
||||
hoverColor: '{primary.300}',
|
||||
activeColor: '{primary.200}',
|
||||
},
|
||||
},
|
||||
light: {
|
||||
highlight: {
|
||||
background: 'color-mix(in srgb, {primary.400}, transparent 84%)',
|
||||
focusBackground: 'color-mix(in srgb, {primary.400}, transparent 76%)',
|
||||
color: 'rgba(255,255,255,.87)',
|
||||
focusColor: 'rgba(255,255,255,.87)',
|
||||
background: '{primary.50}',
|
||||
color: '{primary.700}',
|
||||
focusBackground: '{primary.100}',
|
||||
focusColor: '{primary.800}',
|
||||
},
|
||||
primary: {
|
||||
activeColor: '{primary.700}',
|
||||
color: '{primary.500}',
|
||||
contrastColor: '#ffffff',
|
||||
hoverColor: '{primary.600}',
|
||||
},
|
||||
},
|
||||
},
|
||||
primary: color.palette,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function updateColors(type: string, color: any) {
|
||||
if (type === 'primary') {
|
||||
layoutConfig.primary = color.name;
|
||||
} else if (type === 'surface') {
|
||||
layoutConfig.surface = color.name;
|
||||
}
|
||||
|
||||
applyTheme(type, color);
|
||||
}
|
||||
|
||||
function applyTheme(type: string, color: any) {
|
||||
if (type === 'primary') {
|
||||
updatePreset(getPresetExt());
|
||||
} else if (type === 'surface') {
|
||||
updateSurfacePalette(color.palette);
|
||||
}
|
||||
function onMenuModeChange() {
|
||||
layoutConfig.menuMode = menuMode.value;
|
||||
}
|
||||
|
||||
function onPresetChange() {
|
||||
@ -535,8 +529,14 @@ function onPresetChange() {
|
||||
$t().preset(presetValue).preset(getPresetExt()).surfacePalette(surfacePalette).use({ useDefaultOptions: true });
|
||||
}
|
||||
|
||||
function onMenuModeChange() {
|
||||
layoutConfig.menuMode = menuMode.value;
|
||||
function updateColors(type: string, color: any) {
|
||||
if (type === 'primary') {
|
||||
layoutConfig.primary = color.name;
|
||||
} else if (type === 'surface') {
|
||||
layoutConfig.surface = color.name;
|
||||
}
|
||||
|
||||
applyTheme(type, color);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -8,9 +8,9 @@ import AppSidebar from './AppSidebar.vue';
|
||||
import AppTopbar from './AppTopbar.vue';
|
||||
import { useLayout } from './composables/layout';
|
||||
|
||||
const { layoutConfig, layoutState, isSidebarActive } = useLayout();
|
||||
const { isSidebarActive, layoutConfig, layoutState } = useLayout();
|
||||
|
||||
const outsideClickListener = ref(null as Parameters<typeof document.addEventListener>[1] | null);
|
||||
const outsideClickListener = ref(null as null | Parameters<typeof document.addEventListener>[1]);
|
||||
|
||||
watch(isSidebarActive, (newVal) => {
|
||||
if (newVal) {
|
||||
@ -22,11 +22,11 @@ watch(isSidebarActive, (newVal) => {
|
||||
|
||||
const containerClass = computed(() => {
|
||||
return {
|
||||
'layout-mobile-active': layoutState.staticMenuMobileActive,
|
||||
'layout-overlay': layoutConfig.menuMode === 'overlay',
|
||||
'layout-overlay-active': layoutState.overlayMenuActive,
|
||||
'layout-static': layoutConfig.menuMode === 'static',
|
||||
'layout-static-inactive': layoutState.staticMenuDesktopInactive && layoutConfig.menuMode === 'static',
|
||||
'layout-overlay-active': layoutState.overlayMenuActive,
|
||||
'layout-mobile-active': layoutState.staticMenuMobileActive,
|
||||
};
|
||||
});
|
||||
|
||||
@ -43,13 +43,6 @@ function bindOutsideClickListener() {
|
||||
}
|
||||
}
|
||||
|
||||
function unbindOutsideClickListener() {
|
||||
if (outsideClickListener.value) {
|
||||
document.removeEventListener('click', outsideClickListener.value);
|
||||
outsideClickListener.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
function isOutsideClicked(event: Event) {
|
||||
const sidebarEl = document.querySelector('.layout-sidebar')!;
|
||||
const topbarEl = document.querySelector('.layout-menu-button')!;
|
||||
@ -61,6 +54,13 @@ function isOutsideClicked(event: Event) {
|
||||
topbarEl.contains(event.target as never)
|
||||
);
|
||||
}
|
||||
|
||||
function unbindOutsideClickListener() {
|
||||
if (outsideClickListener.value) {
|
||||
document.removeEventListener('click', outsideClickListener.value);
|
||||
outsideClickListener.value = null;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -2,7 +2,7 @@
|
||||
import AppConfigurator from './AppConfigurator.vue';
|
||||
import { useLayout } from './composables/layout';
|
||||
|
||||
const { toggleMenu, toggleDarkMode, isDarkTheme } = useLayout();
|
||||
const { isDarkTheme, toggleDarkMode, toggleMenu } = useLayout();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -1,21 +1,21 @@
|
||||
import { computed, reactive } from 'vue';
|
||||
|
||||
const layoutConfig = reactive({
|
||||
darkTheme: false,
|
||||
menuMode: 'static',
|
||||
preset: 'Aura',
|
||||
primary: 'emerald',
|
||||
surface: null,
|
||||
darkTheme: false,
|
||||
menuMode: 'static',
|
||||
});
|
||||
|
||||
const layoutState = reactive({
|
||||
staticMenuDesktopInactive: false,
|
||||
activeMenuItem: null,
|
||||
configSidebarVisible: false,
|
||||
menuHoverActive: false,
|
||||
overlayMenuActive: false,
|
||||
profileSidebarVisible: false,
|
||||
configSidebarVisible: false,
|
||||
staticMenuDesktopInactive: false,
|
||||
staticMenuMobileActive: false,
|
||||
menuHoverActive: false,
|
||||
activeMenuItem: null,
|
||||
});
|
||||
|
||||
export function useLayout() {
|
||||
@ -59,14 +59,14 @@ export function useLayout() {
|
||||
const getSurface = computed(() => layoutConfig.surface);
|
||||
|
||||
return {
|
||||
layoutConfig,
|
||||
layoutState,
|
||||
toggleMenu,
|
||||
isSidebarActive,
|
||||
isDarkTheme,
|
||||
getPrimary,
|
||||
getSurface,
|
||||
isDarkTheme,
|
||||
isSidebarActive,
|
||||
layoutConfig,
|
||||
layoutState,
|
||||
setActiveMenuItem,
|
||||
toggleDarkMode,
|
||||
toggleMenu,
|
||||
};
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import type { PopconfirmProps } from 'ant-design-vue';
|
||||
|
||||
type NotUndefined<T> = T extends undefined ? never : T;
|
||||
type PopconfirmOnConfirmParameters = Parameters<NotUndefined<PopconfirmProps['onConfirm']>>;
|
||||
export type HPopconfirmProps = {
|
||||
description: PopconfirmProps['description'];
|
||||
onConfirm?: (...args: PopconfirmOnConfirmParameters) => Promise<void>;
|
||||
title: PopconfirmProps['title'];
|
||||
};
|
||||
type NotUndefined<T> = T extends undefined ? never : T;
|
||||
type PopconfirmOnConfirmParameters = Parameters<NotUndefined<PopconfirmProps['onConfirm']>>;
|
||||
|
@ -1,18 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
import 'orbpro/style/widgets.css';
|
||||
import {
|
||||
Viewer,
|
||||
GoogleMaps,
|
||||
Math as CesiumMath,
|
||||
Cartographic,
|
||||
Cartesian3,
|
||||
viewerReferenceFrameMixin,
|
||||
TileMapServiceImageryProvider,
|
||||
ImageryLayer,
|
||||
Cartographic,
|
||||
Math as CesiumMath,
|
||||
DynamicTimeline,
|
||||
// VERSION,
|
||||
EmbeddedTileServiceImageryProvider,
|
||||
DynamicTimeline,
|
||||
GoogleMaps,
|
||||
ImageryLayer,
|
||||
SpaceEntity,
|
||||
TileMapServiceImageryProvider,
|
||||
Viewer,
|
||||
viewerReferenceFrameMixin,
|
||||
} from 'orbpro';
|
||||
|
||||
import { demoOrbitGeneration } from './fns';
|
||||
@ -21,25 +21,25 @@ let viewer: Viewer;
|
||||
|
||||
onMounted(() => {
|
||||
viewer = new Viewer('cesiumContainer', {
|
||||
// globe: false, // 地球
|
||||
baseLayerPicker: true,
|
||||
homeButton: true, // Home按钮
|
||||
fullscreenButton: !true, // 全屏按钮
|
||||
geocoder: true, // = IonGeocodeProviderType.DEFAULT] - 在使用Geocoder小部件进行搜索时使用的地理编码服务或服务。如果设置为false,则不会创建Geocoder小部件。
|
||||
infoBox: true, // InfoBox小部件。
|
||||
navigationHelpButton: !true, // 是否显示导航帮助按钮
|
||||
projectionPicker: !true, // 投影选择器
|
||||
sceneModePicker: true, // 是否显示场景模式选择器(2D/3D切换)
|
||||
animation: true, // 是否创建动画小部件
|
||||
animationContainer: !true,
|
||||
// globe: false, // 地球
|
||||
baseLayerPicker: true,
|
||||
bottomContainer: document.createElement('p'), // The DOM element or ID that will contain the bottomContainer. If not specified, the bottomContainer is added to the widget itself.
|
||||
fullscreenButton: !true, // 全屏按钮
|
||||
geocoder: true, // = IonGeocodeProviderType.DEFAULT] - 在使用Geocoder小部件进行搜索时使用的地理编码服务或服务。如果设置为false,则不会创建Geocoder小部件。
|
||||
homeButton: true, // Home按钮
|
||||
infoBox: true, // InfoBox小部件。
|
||||
navigationHelpButton: !true, // 是否显示导航帮助按钮
|
||||
orderIndependentTranslucency: false, // 顺序无关透明度
|
||||
projectionPicker: !true, // 投影选择器
|
||||
requestRenderMode: !true, // 如果为真,渲染帧将仅在场景内部发生变化时需要时发生。启用此功能可以减少应用程序的CPU/GPU使用率,并在移动设备上节省更多电量,但在此模式下需要使用{@link Scene#requestRender}显式渲染新帧。在API的其他部分对场景进行更改后,在许多情况下都需要这样做。请参阅{@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|使用显式渲染提高性能}。
|
||||
sceneModePicker: true, // 是否显示场景模式选择器(2D/3D切换)
|
||||
selectionIndicator: true,
|
||||
shadows: true, // Determines if shadows are cast by light sources.
|
||||
showRenderLoopErrors: true, // 如果为真,当发生渲染循环错误时,此小部件将自动向用户显示包含错误的HTML面板。
|
||||
timeline: !true, // If set to false, the Timeline widget will not be created.
|
||||
timelineContainer: true,
|
||||
selectionIndicator: true,
|
||||
requestRenderMode: !true, // 如果为真,渲染帧将仅在场景内部发生变化时需要时发生。启用此功能可以减少应用程序的CPU/GPU使用率,并在移动设备上节省更多电量,但在此模式下需要使用{@link Scene#requestRender}显式渲染新帧。在API的其他部分对场景进行更改后,在许多情况下都需要这样做。请参阅{@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|使用显式渲染提高性能}。
|
||||
showRenderLoopErrors: true, // 如果为真,当发生渲染循环错误时,此小部件将自动向用户显示包含错误的HTML面板。
|
||||
bottomContainer: document.createElement('p'), // The DOM element or ID that will contain the bottomContainer. If not specified, the bottomContainer is added to the widget itself.
|
||||
orderIndependentTranslucency: false, // 顺序无关透明度
|
||||
shadows: true, // Determines if shadows are cast by light sources.
|
||||
});
|
||||
viewer.scene.debugShowFramesPerSecond = true;
|
||||
|
||||
|
@ -8,8 +8,8 @@ import {
|
||||
SpaceCatalogDataSource,
|
||||
SpaceEntity,
|
||||
VerticalOrigin,
|
||||
viewerReferenceFrameMixin,
|
||||
type Viewer,
|
||||
viewerReferenceFrameMixin,
|
||||
} from 'orbpro';
|
||||
|
||||
declare global {
|
||||
@ -26,85 +26,85 @@ export async function demoOrbitGeneration(viewer: Viewer) {
|
||||
// https://spacedatastandards.org/#/standards?search=OMM
|
||||
const ISS = new SpaceEntity({
|
||||
id: '25544',
|
||||
label: {
|
||||
backgroundColor: new Color(0.1, 0.1, 0.1, 0.9),
|
||||
font: `1rem Helvetica`,
|
||||
pixelOffset: new Cartesian2(10, 0),
|
||||
pixelOffsetScaleByDistance: new NearFarScalar(1.5e2, 3.0, 1.5e7, 0.5),
|
||||
scaleByDistance: new NearFarScalar(1.5e2, 1.5, 13.0e7, 0.0),
|
||||
show: false,
|
||||
showBackground: true,
|
||||
},
|
||||
name: 'ISS',
|
||||
point: {
|
||||
pixelSize: 1,
|
||||
},
|
||||
label: {
|
||||
show: false,
|
||||
font: `1rem Helvetica`,
|
||||
showBackground: true,
|
||||
backgroundColor: new Color(0.1, 0.1, 0.1, 0.9),
|
||||
pixelOffset: new Cartesian2(10, 0),
|
||||
scaleByDistance: new NearFarScalar(1.5e2, 1.5, 13.0e7, 0.0),
|
||||
pixelOffsetScaleByDistance: new NearFarScalar(1.5e2, 3.0, 1.5e7, 0.5),
|
||||
},
|
||||
viewFrom: new Cartesian3(-1678500.7493507154, -17680994.63403464, 24667690.486357275),
|
||||
});
|
||||
|
||||
ISS.position.loadOMM({
|
||||
/* CCSDS OMM版本 */ CCSDS_OMM_VERS: 0.0,
|
||||
/* 创建日期(ISO 8601 UTC格式) */ CREATION_DATE: null,
|
||||
/* 创建者 */ ORIGINATOR: null,
|
||||
/* 卫星名称 */ OBJECT_NAME: 'ISS (ZARYA)',
|
||||
/* 国际标识符(YYYY-NNNAAA) */ OBJECT_ID: '1998-067A',
|
||||
/* 中心名称(例如:EARTH, MARS) */ CENTER_NAME: null,
|
||||
/* 参考坐标系 */ REFERENCE_FRAME: 2,
|
||||
/* 参考坐标系历元(ISO 8601 UTC格式) */ REFERENCE_FRAME_EPOCH: null,
|
||||
/* 时间系统[M, UTC] */ TIME_SYSTEM: 11,
|
||||
/* 平均元素理论 */ MEAN_ELEMENT_THEORY: 0,
|
||||
/* 注释 */ COMMENT: null,
|
||||
/* 平均开普勒根数的历元(ISO 8601 UTC格式) */ EPOCH: '2024-05-08T19:52:52.426848',
|
||||
/* 半长轴(km) */ SEMI_MAJOR_AXIS: 0,
|
||||
/* 平均运动(圈/天) */ MEAN_MOTION: 15.51025615,
|
||||
/* 偏心率(无量纲) */ ECCENTRICITY: 0.0003349,
|
||||
/* 轨道倾角(度) */ INCLINATION: 51.6355,
|
||||
/* 升交点赤经(度) */ RA_OF_ASC_NODE: 150.5366,
|
||||
/* 近地点幅角(度) */ ARG_OF_PERICENTER: 149.2285,
|
||||
/* 平近点角(度) */ MEAN_ANOMALY: 210.8902,
|
||||
/* 引力常数(km³/s²) */ GM: 0,
|
||||
/* 质量(kg) */ MASS: 0,
|
||||
/* 太阳辐射面积(m²) */ SOLAR_RAD_AREA: 0,
|
||||
/* 太阳辐射压系数(无量纲) */ SOLAR_RAD_COEFF: 0,
|
||||
/* 大气阻力面积(m²) */ DRAG_AREA: 0,
|
||||
/* 大气阻力系数(无量纲) */ DRAG_COEFF: 0,
|
||||
/* 星历类型(SGP,SGP4等) */ EPHEMERIS_TYPE: 0,
|
||||
/* 分类类型,默认'U' */ CLASSIFICATION_TYPE: 'U',
|
||||
/* NORAD编号 */ NORAD_CAT_ID: 25544,
|
||||
/* 根数组编号 */ ELEMENT_SET_NO: 999,
|
||||
/* 历元时的圈次 */ REV_AT_EPOCH: 45244,
|
||||
/* 气阻系数(1/地球半径) */ BSTAR: 0.00028217,
|
||||
/* 平均运动一阶导数(圈/天²) */ MEAN_MOTION_DOT: 0.00016275,
|
||||
/* 平均运动二阶导数(圈/天³) */ MEAN_MOTION_DDOT: 0,
|
||||
/* 协方差矩阵参考坐标系 */ COV_REFERENCE_FRAME: 23,
|
||||
/* CCSDS OMM版本 */ ARG_OF_PERICENTER: 149.2285,
|
||||
/* 创建日期(ISO 8601 UTC格式) */ BSTAR: 0.00028217,
|
||||
/* 创建者 */ CCSDS_OMM_VERS: 0.0,
|
||||
/* 卫星名称 */ CENTER_NAME: null,
|
||||
/* 国际标识符(YYYY-NNNAAA) */ CLASSIFICATION_TYPE: 'U',
|
||||
/* 中心名称(例如:EARTH, MARS) */ COMMENT: null,
|
||||
/* 参考坐标系 */ COV_REFERENCE_FRAME: 23,
|
||||
/* 参考坐标系历元(ISO 8601 UTC格式) */ CREATION_DATE: null,
|
||||
/* 时间系统[M, UTC] */ CX_DOT_X: 0,
|
||||
/* 平均元素理论 */ CX_DOT_X_DOT: 0,
|
||||
/* 注释 */ CX_DOT_Y: 0,
|
||||
/* 平均开普勒根数的历元(ISO 8601 UTC格式) */ CX_DOT_Z: 0,
|
||||
/* 半长轴(km) */ CX_X: 0,
|
||||
/* 平均运动(圈/天) */ CY_DOT_X: 0,
|
||||
/* 偏心率(无量纲) */ CY_DOT_X_DOT: 0,
|
||||
/* 轨道倾角(度) */ CY_DOT_Y: 0,
|
||||
/* 升交点赤经(度) */ CY_DOT_Y_DOT: 0,
|
||||
/* 近地点幅角(度) */ CY_DOT_Z: 0,
|
||||
/* 平近点角(度) */ CY_X: 0,
|
||||
/* 引力常数(km³/s²) */ CY_Y: 0,
|
||||
/* 质量(kg) */ CZ_DOT_X: 0,
|
||||
/* 太阳辐射面积(m²) */ CZ_DOT_X_DOT: 0,
|
||||
/* 太阳辐射压系数(无量纲) */ CZ_DOT_Y: 0,
|
||||
/* 大气阻力面积(m²) */ CZ_DOT_Y_DOT: 0,
|
||||
/* 大气阻力系数(无量纲) */ CZ_DOT_Z: 0,
|
||||
/* 星历类型(SGP,SGP4等) */ CZ_DOT_Z_DOT: 0,
|
||||
/* 分类类型,默认'U' */ CZ_X: 0,
|
||||
/* NORAD编号 */ CZ_Y: 0,
|
||||
/* 根数组编号 */ CZ_Z: 0,
|
||||
/* 历元时的圈次 */ DRAG_AREA: 0,
|
||||
/* 气阻系数(1/地球半径) */ DRAG_COEFF: 0,
|
||||
/* 平均运动一阶导数(圈/天²) */ ECCENTRICITY: 0.0003349,
|
||||
/* 平均运动二阶导数(圈/天³) */ ELEMENT_SET_NO: 999,
|
||||
/* 协方差矩阵参考坐标系 */ EPHEMERIS_TYPE: 0,
|
||||
/* --- 位置/速度协方差矩阵(6x6下三角) --- */
|
||||
/* 位置协方差矩阵元素(km²) */ CX_X: 0,
|
||||
/* 位置协方差矩阵元素(km²) */ CY_X: 0,
|
||||
/* 位置协方差矩阵元素(km²) */ CY_Y: 0,
|
||||
/* 位置协方差矩阵元素(km²) */ CZ_X: 0,
|
||||
/* 位置协方差矩阵元素(km²) */ CZ_Y: 0,
|
||||
/* 位置协方差矩阵元素(km²) */ CZ_Z: 0,
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ CX_DOT_X: 0,
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ CX_DOT_Y: 0,
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ CX_DOT_Z: 0,
|
||||
/* 速度协方差矩阵元素(km²/s²) */ CX_DOT_X_DOT: 0,
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ CY_DOT_X: 0,
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ CY_DOT_Y: 0,
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ CY_DOT_Z: 0,
|
||||
/* 速度协方差矩阵元素(km²/s²) */ CY_DOT_X_DOT: 0,
|
||||
/* 速度协方差矩阵元素(km²/s²) */ CY_DOT_Y_DOT: 0,
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ CZ_DOT_X: 0,
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ CZ_DOT_Y: 0,
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ CZ_DOT_Z: 0,
|
||||
/* 速度协方差矩阵元素(km²/s²) */ CZ_DOT_X_DOT: 0,
|
||||
/* 速度协方差矩阵元素(km²/s²) */ CZ_DOT_Y_DOT: 0,
|
||||
/* 速度协方差矩阵元素(km²/s²) */ CZ_DOT_Z_DOT: 0,
|
||||
/* 位置协方差矩阵元素(km²) */ EPOCH: '2024-05-08T19:52:52.426848',
|
||||
/* 位置协方差矩阵元素(km²) */ GM: 0,
|
||||
/* 位置协方差矩阵元素(km²) */ INCLINATION: 51.6355,
|
||||
/* 位置协方差矩阵元素(km²) */ MASS: 0,
|
||||
/* 位置协方差矩阵元素(km²) */ MEAN_ANOMALY: 210.8902,
|
||||
/* 位置协方差矩阵元素(km²) */ MEAN_ELEMENT_THEORY: 0,
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ MEAN_MOTION: 15.51025615,
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ MEAN_MOTION_DDOT: 0,
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ MEAN_MOTION_DOT: 0.00016275,
|
||||
/* 速度协方差矩阵元素(km²/s²) */ NORAD_CAT_ID: 25544,
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ OBJECT_ID: '1998-067A',
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ OBJECT_NAME: 'ISS (ZARYA)',
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ ORIGINATOR: null,
|
||||
/* 速度协方差矩阵元素(km²/s²) */ RA_OF_ASC_NODE: 150.5366,
|
||||
/* 速度协方差矩阵元素(km²/s²) */ REFERENCE_FRAME: 2,
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ REFERENCE_FRAME_EPOCH: null,
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ REV_AT_EPOCH: 45244,
|
||||
/* 速度-位置协方差矩阵元素(km²/s) */ SEMI_MAJOR_AXIS: 0,
|
||||
/* 速度协方差矩阵元素(km²/s²) */ SOLAR_RAD_AREA: 0,
|
||||
/* 速度协方差矩阵元素(km²/s²) */ SOLAR_RAD_COEFF: 0,
|
||||
/* 速度协方差矩阵元素(km²/s²) */ TIME_SYSTEM: 11,
|
||||
/* --- 用户自定义字段 --- */
|
||||
/* 用户自定义BIP-0044类型 */ USER_DEFINED_BIP_0044_TYPE: 0,
|
||||
/* 用户自定义对象标识符 */ USER_DEFINED_OBJECT_DESIGNATOR: null,
|
||||
/* 用户自定义地球模型 */ USER_DEFINED_EARTH_MODEL: null,
|
||||
/* 用户自定义历元时间戳 */ USER_DEFINED_EPOCH_TIMESTAMP: 0,
|
||||
/* 用户自定义微秒数 */ USER_DEFINED_MICROSECONDS: 0,
|
||||
/* 用户自定义对象标识符 */ USER_DEFINED_EARTH_MODEL: null,
|
||||
/* 用户自定义地球模型 */ USER_DEFINED_EPOCH_TIMESTAMP: 0,
|
||||
/* 用户自定义历元时间戳 */ USER_DEFINED_MICROSECONDS: 0,
|
||||
/* 用户自定义微秒数 */ USER_DEFINED_OBJECT_DESIGNATOR: null,
|
||||
});
|
||||
|
||||
ISS.point!.pixelSize = 10 as any;
|
||||
@ -112,8 +112,8 @@ export async function demoOrbitGeneration(viewer: Viewer) {
|
||||
|
||||
MakeBillboardLabel({
|
||||
entity: ISS,
|
||||
text: 'ISS-text',
|
||||
fontSize: 36,
|
||||
text: 'ISS-text',
|
||||
verticalOrigin: VerticalOrigin.CENTER,
|
||||
});
|
||||
|
||||
|
@ -4,10 +4,10 @@ import { createReusableTemplate } from '@vueuse/core';
|
||||
const TemplateFoo = createReusableTemplate<
|
||||
{ msg: string },
|
||||
{
|
||||
default: object;
|
||||
slotNameee: {
|
||||
slotPropName: string;
|
||||
};
|
||||
default: object;
|
||||
}
|
||||
>();
|
||||
</script>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
const baseURL = '/fake-api';
|
||||
|
||||
let fakeApiResult = $ref<Record<string, unknown> | null>(null);
|
||||
let fakeApiResult = $ref<null | Record<string, unknown>>(null);
|
||||
|
||||
fetch(`${baseURL}/mock/get-user-info`)
|
||||
.then((response) => response.json())
|
||||
|
@ -1,10 +1,12 @@
|
||||
## 配置项目
|
||||
|
||||
- https://github.dev/CesiumGS/cesium-vite-example
|
||||
- https://cesium.com/blog/2024/02/13/configuring-vite-or-webpack-for-cesiumjs/
|
||||
- https://cesium.com/learn/cesiumjs-learn/cesiumjs-quickstart/
|
||||
- vite-plugin-cesium
|
||||
|
||||
## 参考
|
||||
|
||||
- https://www.npmjs.com/package/vue-cesium
|
||||
- https://zouyaoji.top/vue-cesium/#/zh-CN/component/controls/vc-navigation
|
||||
- https://cesium.pages.dev/
|
||||
|
@ -8,64 +8,64 @@ export function cesium_init() {
|
||||
// 复写原型方法 用于timeline组件日期格式化;
|
||||
// @ts-expect-error node_modules/@cesium/widgets/Source/Timeline/Timeline.js
|
||||
Cesium.Timeline.prototype.makeLabel = function (time) {
|
||||
let minutes = 0 - new Date().getTimezoneOffset();
|
||||
let dataZone8 = Cesium.JulianDate.addMinutes(time, minutes, new Cesium.JulianDate());
|
||||
const minutes = 0 - new Date().getTimezoneOffset();
|
||||
const dataZone8 = Cesium.JulianDate.addMinutes(time, minutes, new Cesium.JulianDate());
|
||||
return Cesium.JulianDate.toIso8601(dataZone8).slice(0, 19);
|
||||
};
|
||||
|
||||
// cesium-viewer-bottom
|
||||
|
||||
const viewer = new Cesium.Viewer('cesiumContainer', {
|
||||
animation: true, // 是否创建动画小部件
|
||||
// globe: false, // 地球
|
||||
baseLayerPicker: true,
|
||||
fullscreenButton: !true, // 全屏按钮
|
||||
geocoder: true, // = IonGeocodeProviderType.DEFAULT] - 在使用Geocoder小部件进行搜索时使用的地理编码服务或服务。如果设置为false,则不会创建Geocoder小部件。
|
||||
homeButton: true, // Home按钮
|
||||
infoBox: true, // InfoBox小部件。
|
||||
navigationHelpButton: !true, // 是否显示导航帮助按钮
|
||||
orderIndependentTranslucency: false, // 顺序无关透明度
|
||||
projectionPicker: !true, // 投影选择器
|
||||
requestRenderMode: !true, // 如果为真,渲染帧将仅在场景内部发生变化时需要时发生。启用此功能可以减少应用程序的CPU/GPU使用率,并在移动设备上节省更多电量,但在此模式下需要使用{@link Scene#requestRender}显式渲染新帧。在API的其他部分对场景进行更改后,在许多情况下都需要这样做。请参阅{@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|使用显式渲染提高性能}。
|
||||
sceneModePicker: true, // 是否显示场景模式选择器(2D/3D切换)
|
||||
selectionIndicator: true,
|
||||
shadows: true, // Determines if shadows are cast by light sources.
|
||||
/* animationContainer: !true, */
|
||||
/* timelineContainer: true, */
|
||||
/* bottomContainer: document.createElement('p'), // The DOM element or ID that will contain the bottomContainer. If not specified, the bottomContainer is added to the widget itself. */
|
||||
shouldAnimate: true,
|
||||
// globe: false, // 地球
|
||||
baseLayerPicker: true,
|
||||
homeButton: true, // Home按钮
|
||||
fullscreenButton: !true, // 全屏按钮
|
||||
geocoder: true, // = IonGeocodeProviderType.DEFAULT] - 在使用Geocoder小部件进行搜索时使用的地理编码服务或服务。如果设置为false,则不会创建Geocoder小部件。
|
||||
infoBox: true, // InfoBox小部件。
|
||||
navigationHelpButton: !true, // 是否显示导航帮助按钮
|
||||
projectionPicker: !true, // 投影选择器
|
||||
sceneModePicker: true, // 是否显示场景模式选择器(2D/3D切换)
|
||||
animation: true, // 是否创建动画小部件
|
||||
timeline: true, // If set to false, the Timeline widget will not be created.
|
||||
selectionIndicator: true,
|
||||
requestRenderMode: !true, // 如果为真,渲染帧将仅在场景内部发生变化时需要时发生。启用此功能可以减少应用程序的CPU/GPU使用率,并在移动设备上节省更多电量,但在此模式下需要使用{@link Scene#requestRender}显式渲染新帧。在API的其他部分对场景进行更改后,在许多情况下都需要这样做。请参阅{@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|使用显式渲染提高性能}。
|
||||
showRenderLoopErrors: true, // 如果为真,当发生渲染循环错误时,此小部件将自动向用户显示包含错误的HTML面板。
|
||||
orderIndependentTranslucency: false, // 顺序无关透明度
|
||||
shadows: true, // Determines if shadows are cast by light sources.
|
||||
timeline: true, // If set to false, the Timeline widget will not be created.
|
||||
});
|
||||
/* if ($__DEV__) */ viewer.scene.debugShowFramesPerSecond = true;
|
||||
|
||||
// 时间格式化
|
||||
let minutes = 0 - new Date().getTimezoneOffset(); // 0 - (-480);
|
||||
const minutes = 0 - new Date().getTimezoneOffset(); // 0 - (-480);
|
||||
viewer.animation.viewModel.timeFormatter = function (date, _viewModel) {
|
||||
let dataZone8 = Cesium.JulianDate.addMinutes(date, minutes, new Cesium.JulianDate());
|
||||
const dataZone8 = Cesium.JulianDate.addMinutes(date, minutes, new Cesium.JulianDate());
|
||||
return Cesium.JulianDate.toIso8601(dataZone8).slice(11, 19);
|
||||
};
|
||||
viewer.animation.viewModel.dateFormatter = function (date, _viewModel) {
|
||||
let dataZone8 = Cesium.JulianDate.addMinutes(date, minutes, new Cesium.JulianDate());
|
||||
const dataZone8 = Cesium.JulianDate.addMinutes(date, minutes, new Cesium.JulianDate());
|
||||
return Cesium.JulianDate.toIso8601(dataZone8).slice(0, 10);
|
||||
};
|
||||
|
||||
//高德卫星地图
|
||||
let gaoDeSatelliteImgLayer = new Cesium.UrlTemplateImageryProvider({
|
||||
url: 'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
|
||||
minimumLevel: 3,
|
||||
const gaoDeSatelliteImgLayer = new Cesium.UrlTemplateImageryProvider({
|
||||
maximumLevel: 18,
|
||||
minimumLevel: 3,
|
||||
tilingScheme: new Cesium.WebMercatorTilingScheme(),
|
||||
url: 'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
|
||||
});
|
||||
|
||||
const customLayerViewModel = new Cesium.ProviderViewModel({
|
||||
name: '高德地图',
|
||||
iconUrl: 'gaodeImage.png',
|
||||
tooltip: '高德地图',
|
||||
category: 'Cesium ion', // 或 'Other 、Cesium ion'、'Bing Maps' 等
|
||||
creationFunction: function () {
|
||||
return gaoDeSatelliteImgLayer;
|
||||
},
|
||||
iconUrl: 'gaodeImage.png',
|
||||
name: '高德地图',
|
||||
tooltip: '高德地图',
|
||||
});
|
||||
// 设置高德地图为默认图层
|
||||
viewer.baseLayerPicker.viewModel.imageryProviderViewModels.unshift(customLayerViewModel);
|
||||
|
@ -1,6 +1,7 @@
|
||||
import type { Viewer } from 'cesium';
|
||||
|
||||
import * as Cesium from 'cesium';
|
||||
import { twoline2satrec, propagate, gstime, eciToEcf } from 'satellite.js';
|
||||
import { eciToEcf, gstime, propagate, twoline2satrec } from 'satellite.js';
|
||||
|
||||
export async function demoOrbitGeneration(viewer: Viewer) {
|
||||
const tle = `STARLINK-11371 [DTC]
|
||||
@ -74,36 +75,36 @@ export async function demoOrbitGeneration(viewer: Viewer) {
|
||||
viewer.entities.add({
|
||||
name: `${satelliteName} Orbit`,
|
||||
polyline: {
|
||||
material: new Cesium.PolylineGlowMaterialProperty({
|
||||
color: Cesium.Color.BLUE,
|
||||
glowPower: 0.2,
|
||||
}),
|
||||
positions: pointsArray,
|
||||
width: 2,
|
||||
material: new Cesium.PolylineGlowMaterialProperty({
|
||||
glowPower: 0.2,
|
||||
color: Cesium.Color.BLUE,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
await PromiseConfirmationService({ message: '添加卫星实体' });
|
||||
// 添加卫星实体
|
||||
const satellite = viewer.entities.add({
|
||||
label: {
|
||||
fillColor: Cesium.Color.WHITE,
|
||||
font: '14pt sans-serif',
|
||||
outlineColor: Cesium.Color.BLACK,
|
||||
outlineWidth: 2,
|
||||
pixelOffset: new Cesium.Cartesian2(0, -10),
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
text: satelliteName,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
},
|
||||
name: satelliteName,
|
||||
position: currentPosition,
|
||||
point: {
|
||||
pixelSize: 10,
|
||||
color: Cesium.Color.YELLOW,
|
||||
outlineColor: Cesium.Color.WHITE,
|
||||
outlineWidth: 2,
|
||||
pixelSize: 10,
|
||||
},
|
||||
label: {
|
||||
text: satelliteName,
|
||||
font: '14pt sans-serif',
|
||||
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
fillColor: Cesium.Color.WHITE,
|
||||
outlineColor: Cesium.Color.BLACK,
|
||||
outlineWidth: 2,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
pixelOffset: new Cesium.Cartesian2(0, -10),
|
||||
},
|
||||
position: currentPosition,
|
||||
// billboard: {
|
||||
// image: '/assets/satellite.png', // 您需要添加一个卫星图标
|
||||
// scale: 0.5,
|
||||
|
@ -3,6 +3,7 @@ import type { Viewer } from 'cesium';
|
||||
|
||||
import { cesium_init } from './cesium-helper/00.cesium-init';
|
||||
import { demoOrbitGeneration } from './cesium-helper/01.x';
|
||||
|
||||
let viewer: Viewer;
|
||||
onMounted(async () => {
|
||||
viewer = cesium_init();
|
||||
|
@ -10,8 +10,8 @@ export const usePageData = defineBasicLoader(
|
||||
return { idFromPreviousPage: route.params.id, someOtherData: 'someOtherData' };
|
||||
},
|
||||
{
|
||||
lazy: false,
|
||||
commit: 'immediate',
|
||||
lazy: false,
|
||||
// - `immediate`: the data is committed as soon as it is loaded.
|
||||
// - `after-load`: the data is committed after all non-lazy loaders have finished loading.
|
||||
// - `immediate`:数据在加载后立即提交。
|
||||
@ -28,8 +28,8 @@ definePage({
|
||||
});
|
||||
const {
|
||||
data: pageData, // the data returned by the loader
|
||||
isLoading, // a boolean indicating if the loader is fetching data
|
||||
error, // an error object if the loader failed
|
||||
isLoading, // a boolean indicating if the loader is fetching data
|
||||
reload, // a function to refetch the data without navigating
|
||||
} = usePageData();
|
||||
|
||||
|
@ -13,11 +13,11 @@ async function getUserById(userId: string, { signal }: { signal?: AbortSignal })
|
||||
}
|
||||
|
||||
export const useUserData = defineColadaLoader('DataLoadersIdSub1UserId', {
|
||||
key: (to) => ['users', to.params.userId],
|
||||
async query(to, { signal }) {
|
||||
console.debug('[defineColadaLoader] query');
|
||||
return getUserById(to.params.userId, { signal });
|
||||
},
|
||||
key: (to) => ['users', to.params.userId],
|
||||
// Keep the data "fresh" 10 seconds to avoid fetching the same data too often
|
||||
// 保持数据“新鲜”10秒,以避免过于频繁地获取相同的数据
|
||||
staleTime: 1000 * 10,
|
||||
@ -31,7 +31,7 @@ export const usePageData = defineBasicLoader('DataLoadersIdSub1UserId', async (r
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
const { data: user, status, error, isLoading, reload, refresh } = useUserData();
|
||||
const { data: user, error, isLoading, refresh, reload, status } = useUserData();
|
||||
|
||||
const route = useRoute('DataLoadersIdSub1UserId');
|
||||
</script>
|
||||
|
@ -4,13 +4,13 @@ import { routes } from 'vue-router/auto-routes';
|
||||
|
||||
definePage({ meta: { title: '首页' } });
|
||||
useHead({
|
||||
// Classes
|
||||
bodyAttrs: { class: { overflow: true } },
|
||||
// Template params
|
||||
templateParams: { separator: '|', siteName: 'My App' },
|
||||
// Titles
|
||||
title: 'Hello World',
|
||||
titleTemplate: '%s %separator %siteName',
|
||||
// Template params
|
||||
templateParams: { separator: '|', siteName: 'My App' },
|
||||
// Classes
|
||||
bodyAttrs: { class: { overflow: true } },
|
||||
// Deduping
|
||||
// script: [{ key: '123', src: '/script.js' }],
|
||||
});
|
||||
@ -21,9 +21,9 @@ const FComponent: import('vue').FunctionalComponent<{ prop: string }> = (props,
|
||||
<>
|
||||
<a
|
||||
class="green"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="https://cn.vuejs.org/guide/extras/render-function#typing-functional-components"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
函数式组件: https://cn.vuejs.org/guide/extras/render-function#typing-functional-components
|
||||
</a>
|
||||
|
@ -2,11 +2,11 @@
|
||||
const structuredClone = window.structuredClone || ((obj) => JSON.parse(JSON.stringify(obj)));
|
||||
|
||||
const K_INITIAL_STATE = deepFreeze({
|
||||
list: [] as Record<string, never>[],
|
||||
page: 0,
|
||||
loading: false,
|
||||
complete: false,
|
||||
error: null as unknown,
|
||||
list: [] as Record<string, never>[],
|
||||
loading: false,
|
||||
page: 0,
|
||||
});
|
||||
|
||||
let page3ShouldError = true;
|
||||
@ -33,6 +33,8 @@ const refresh = () => {
|
||||
loadMore();
|
||||
};
|
||||
|
||||
type CurrentUse = 'use-intersection-observer-infinite-loading' | 'van-list';
|
||||
|
||||
async function loadMore() {
|
||||
if (state.loading) return;
|
||||
|
||||
@ -59,8 +61,6 @@ async function loadMore() {
|
||||
state.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
type CurrentUse = 'van-list' | 'use-intersection-observer-infinite-loading';
|
||||
const currentUse = ref<CurrentUse>((sessionStorage.getItem('currentUse') as CurrentUse) || 'van-list');
|
||||
watchEffect(() => {
|
||||
sessionStorage.setItem('currentUse', currentUse.value);
|
||||
|
@ -3,8 +3,8 @@ import dialogContent from './__dialog-content.vue';
|
||||
const dynamicComponent = defineComponent({
|
||||
props: {
|
||||
'defining-props': {
|
||||
type: Object as PropType<Record<string, unknown>>,
|
||||
default: () => ({}),
|
||||
type: Object as PropType<Record<string, unknown>>,
|
||||
},
|
||||
},
|
||||
setup(props, ctx) {
|
||||
@ -24,12 +24,6 @@ const dynamicComponent = defineComponent({
|
||||
// https://primevue.org/dynamicdialog/
|
||||
export const openDialog = async () => {
|
||||
const dialog1 = DialogService.open(dynamicComponent, {
|
||||
props: {
|
||||
header: '对话框1 可以拖动',
|
||||
position: 'bottomleft',
|
||||
draggable: true,
|
||||
pt: { mask: { class: 'backdrop-blur-sm' } }, // 相当于: pt:mask:class="backdrop-blur-sm"
|
||||
},
|
||||
data: {
|
||||
用inject接收: '通过 DynamicDialogOptions.data 传递的数据',
|
||||
},
|
||||
@ -39,8 +33,14 @@ export const openDialog = async () => {
|
||||
'defining-props': {
|
||||
'用-props-接收': '定义在-DynamicDialogOptions.emits-的数据',
|
||||
},
|
||||
绑定给组件的attrs: '定义在-DynamicDialogOptions.emits-的数据,',
|
||||
onClose: () => dialog1.close(),
|
||||
绑定给组件的attrs: '定义在-DynamicDialogOptions.emits-的数据,',
|
||||
},
|
||||
props: {
|
||||
draggable: true,
|
||||
header: '对话框1 可以拖动',
|
||||
position: 'bottomleft',
|
||||
pt: { mask: { class: 'backdrop-blur-sm' } }, // 相当于: pt:mask:class="backdrop-blur-sm"
|
||||
},
|
||||
});
|
||||
|
||||
@ -58,17 +58,17 @@ export const openDialog = async () => {
|
||||
|
||||
export const openConfirm = async () => {
|
||||
ConfirmationService.require({
|
||||
message: '确定要继续吗?',
|
||||
header: '确认',
|
||||
icon: 'pi pi-exclamation-triangle',
|
||||
rejectProps: { label: '取消', severity: 'secondary', outlined: true },
|
||||
accept: () => {
|
||||
ToastService.add({ detail: '您已同意操作', life: 3000, severity: 'info', summary: '已确认' });
|
||||
},
|
||||
// rejectProps: { style: { display: 'none' } },
|
||||
acceptProps: { label: '确定' },
|
||||
accept: () => {
|
||||
ToastService.add({ severity: 'info', summary: '已确认', life: 3000, detail: '您已同意操作' });
|
||||
},
|
||||
header: '确认',
|
||||
icon: 'pi pi-exclamation-triangle',
|
||||
message: '确定要继续吗?',
|
||||
reject: () => {
|
||||
ToastService.add({ severity: 'error', summary: '已取消', life: 3000, detail: '您已取消操作' });
|
||||
ToastService.add({ detail: '您已取消操作', life: 3000, severity: 'error', summary: '已取消' });
|
||||
},
|
||||
rejectProps: { label: '取消', outlined: true, severity: 'secondary' },
|
||||
});
|
||||
};
|
||||
|
@ -2,10 +2,10 @@
|
||||
import { $enum } from 'ts-enum-util';
|
||||
|
||||
enum Direction {
|
||||
Up = 'UP',
|
||||
Down = 'DOWN',
|
||||
Left = 'LEFT',
|
||||
Right = 'RIGHT',
|
||||
Up = 'UP',
|
||||
}
|
||||
|
||||
enum TestEnum {
|
||||
@ -15,25 +15,25 @@ enum TestEnum {
|
||||
|
||||
const visitValue = (value: Direction | null | undefined) => {
|
||||
$enum.visitValue(value).with({
|
||||
[Direction.Up]: () => {},
|
||||
[Direction.Down]: () => {},
|
||||
[Direction.Left]: () => {},
|
||||
[Direction.Right]: () => {},
|
||||
[$enum.handleNull]: () => {},
|
||||
[$enum.handleUndefined]: () => {},
|
||||
[$enum.handleUnexpected]: () => {},
|
||||
[Direction.Down]: () => {},
|
||||
[Direction.Left]: () => {},
|
||||
[Direction.Right]: () => {},
|
||||
[Direction.Up]: () => {},
|
||||
});
|
||||
};
|
||||
|
||||
const mapValue = (value: Direction | null | undefined) => {
|
||||
return $enum.mapValue(value).with({
|
||||
[Direction.Up]: 'Up',
|
||||
[Direction.Down]: 'Down',
|
||||
[Direction.Left]: 'Left',
|
||||
[Direction.Right]: 'Right',
|
||||
[$enum.handleNull]: 'Null',
|
||||
[$enum.handleUndefined]: 'Undefined',
|
||||
[$enum.handleUnexpected]: 'Unexpected',
|
||||
[Direction.Down]: 'Down',
|
||||
[Direction.Left]: 'Left',
|
||||
[Direction.Right]: 'Right',
|
||||
[Direction.Up]: 'Up',
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
@ -1,7 +1,7 @@
|
||||
type AutoInstallModule = { [K: string]: unknown; install?: UserPlugin };
|
||||
type UserPlugin = (ctx: UserPluginContext) => void;
|
||||
// https://github.com/antfu-collective/vitesse/blob/47618e72dfba76c77b9b85b94784d739e35c492b/src/modules/README.md
|
||||
type UserPluginContext = { app: import('vue').App<Element> };
|
||||
type UserPlugin = (ctx: UserPluginContext) => void;
|
||||
type AutoInstallModule = { install?: UserPlugin; [K: string]: unknown };
|
||||
|
||||
export function setupPlugins(app: import('vue').App, modules: AutoInstallModule | Record<string, unknown>) {
|
||||
console.group('🔌 Plugins');
|
||||
|
@ -12,17 +12,17 @@ export function install({ app }: { app: import('vue').App<Element> }) {
|
||||
app.use(PrimeVue, {
|
||||
locale: {
|
||||
...zhCN['zh-CN'],
|
||||
completed: '已上传',
|
||||
noFileChosenMessage: '未选择文件',
|
||||
pending: '待上传',
|
||||
completed: '已上传',
|
||||
}, // usePrimeVue().config.locale
|
||||
theme: {
|
||||
preset: Aura,
|
||||
options: {
|
||||
prefix: 'p',
|
||||
darkModeSelector: '.app-dark' /* 'system' */,
|
||||
cssLayer: false,
|
||||
darkModeSelector: '.app-dark' /* 'system' */,
|
||||
prefix: 'p',
|
||||
},
|
||||
preset: Aura,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ const setupLayoutsResult = setupLayouts(routes);
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes: /* routes ?? */ setupLayoutsResult,
|
||||
strict: true,
|
||||
scrollBehavior: (_to, _from, savedPosition) => {
|
||||
if (savedPosition) {
|
||||
return savedPosition;
|
||||
@ -16,6 +15,7 @@ const router = createRouter({
|
||||
return { left: 0, top: 0 };
|
||||
}
|
||||
},
|
||||
strict: true,
|
||||
});
|
||||
if (import.meta.hot) handleHotUpdate(router);
|
||||
if ($__DEV__) Object.assign(window, { router });
|
||||
@ -23,7 +23,7 @@ router.onError((error) => {
|
||||
console.debug('🚨 [router error]: ', error);
|
||||
});
|
||||
|
||||
export { router, setupLayoutsResult, createGetRoutes };
|
||||
export { createGetRoutes, router, setupLayoutsResult };
|
||||
export function install({ app }: { app: import('vue').App<Element> }) {
|
||||
app
|
||||
// Register the plugin before the router
|
||||
|
@ -14,7 +14,7 @@
|
||||
declare module 'vue' {
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
interface HTMLAttributes
|
||||
extends Partial<Record<import('@unocss/preset-attributify').AttributifyNames, string | boolean>> {}
|
||||
extends Partial<Record<import('@unocss/preset-attributify').AttributifyNames, boolean | string>> {}
|
||||
}
|
||||
|
||||
export {};
|
||||
|
@ -1,11 +1,11 @@
|
||||
export async function PromiseConfirmationService({ message }: { message: string }) {
|
||||
return await new Promise<boolean>((reslove) => {
|
||||
ConfirmationService.require({
|
||||
position: 'bottomright',
|
||||
modal: false,
|
||||
accept: () => reslove(true),
|
||||
header: '提示',
|
||||
message: message,
|
||||
accept: () => reslove(true),
|
||||
modal: false,
|
||||
position: 'bottomright',
|
||||
reject: () => reslove(false),
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
test('接口请求页面', async ({ page }) => {
|
||||
await page.goto('/api');
|
||||
|
@ -3,52 +3,6 @@ import { defineConfig, presetAttributify, presetWind3, transformerDirectives, tr
|
||||
// import presetChinese, { chineseTypography } from 'unocss-preset-chinese';
|
||||
|
||||
export default defineConfig({
|
||||
theme: {
|
||||
// https://unocss.dev/presets/wind#differences-from-tailwind-css
|
||||
// https://www.npmjs.com/package/unocss-preset-animations
|
||||
// https://github.com/whatnickcodes/unocss-preset-tailwindcss-motion
|
||||
animation: {
|
||||
keyframes: {
|
||||
scalein: '{0% { opacity: 0; transform: scaleY(0.8); } 100% { opacity: 1; transform: scaleY(1); }}',
|
||||
fadeout: '{0% { opacity: 1; } 100% { opacity: 0; }}',
|
||||
},
|
||||
durations: {
|
||||
scalein: '0.15s',
|
||||
fadeout: '0.15s',
|
||||
},
|
||||
timingFns: {
|
||||
scalein: 'linear',
|
||||
fadeout: 'linear',
|
||||
},
|
||||
properties: {
|
||||
scalein: {
|
||||
transition: 'transform 0.12s cubic-bezier(0, 0, 0.2, 1), opacity 0.12s cubic-bezier(0, 0, 0.2, 1)',
|
||||
},
|
||||
fadeout: {},
|
||||
},
|
||||
counts: {
|
||||
scalein: '1',
|
||||
fadeout: '1',
|
||||
},
|
||||
},
|
||||
|
||||
// https://unocss.dev/config/theme#usage
|
||||
colors: {
|
||||
'surface-0': 'var(--p-surface-0)', // text-surface-0
|
||||
'surface-900': 'var(--p-surface-900)', // text-surface-900
|
||||
},
|
||||
},
|
||||
|
||||
shortcuts: [
|
||||
{
|
||||
'logo-transform': 'i-icon:pacman w-6em h-6em transform transition-800',
|
||||
pacman: 'i-icon:pacman text-(pink 36)',
|
||||
},
|
||||
{
|
||||
// https://github.com/primefaces/tailwindcss-primeui/blob/d5e903377e015b7c63cb5edf42490b9d6954ef04/src/utils/preset.js
|
||||
'text-muted-color': 'text-[var(--p-text-muted-color)]',
|
||||
},
|
||||
],
|
||||
presets: [
|
||||
presetWind3({
|
||||
/* prefix: "u-", */
|
||||
@ -64,6 +18,52 @@ export default defineConfig({
|
||||
// https://unocss.dev/presets/attributify
|
||||
presetAttributify(),
|
||||
],
|
||||
|
||||
shortcuts: [
|
||||
{
|
||||
'logo-transform': 'i-icon:pacman w-6em h-6em transform transition-800',
|
||||
pacman: 'i-icon:pacman text-(pink 36)',
|
||||
},
|
||||
{
|
||||
// https://github.com/primefaces/tailwindcss-primeui/blob/d5e903377e015b7c63cb5edf42490b9d6954ef04/src/utils/preset.js
|
||||
'text-muted-color': 'text-[var(--p-text-muted-color)]',
|
||||
},
|
||||
],
|
||||
theme: {
|
||||
// https://unocss.dev/presets/wind#differences-from-tailwind-css
|
||||
// https://www.npmjs.com/package/unocss-preset-animations
|
||||
// https://github.com/whatnickcodes/unocss-preset-tailwindcss-motion
|
||||
animation: {
|
||||
counts: {
|
||||
fadeout: '1',
|
||||
scalein: '1',
|
||||
},
|
||||
durations: {
|
||||
fadeout: '0.15s',
|
||||
scalein: '0.15s',
|
||||
},
|
||||
keyframes: {
|
||||
fadeout: '{0% { opacity: 1; } 100% { opacity: 0; }}',
|
||||
scalein: '{0% { opacity: 0; transform: scaleY(0.8); } 100% { opacity: 1; transform: scaleY(1); }}',
|
||||
},
|
||||
properties: {
|
||||
fadeout: {},
|
||||
scalein: {
|
||||
transition: 'transform 0.12s cubic-bezier(0, 0, 0.2, 1), opacity 0.12s cubic-bezier(0, 0, 0.2, 1)',
|
||||
},
|
||||
},
|
||||
timingFns: {
|
||||
fadeout: 'linear',
|
||||
scalein: 'linear',
|
||||
},
|
||||
},
|
||||
|
||||
// https://unocss.dev/config/theme#usage
|
||||
colors: {
|
||||
'surface-0': 'var(--p-surface-0)', // text-surface-0
|
||||
'surface-900': 'var(--p-surface-900)', // text-surface-900
|
||||
},
|
||||
},
|
||||
transformers: [
|
||||
//https://unocss.dev/transformers/variant-group
|
||||
transformerVariantGroup(),
|
||||
|
@ -3,7 +3,6 @@
|
||||
* https://github.com/vue-macros/vue-macros/blob/main/playground/vue3/vite.config.ts
|
||||
*/
|
||||
|
||||
import { viteStaticCopy } from 'vite-plugin-static-copy';
|
||||
import VueI18n from '@intlify/unplugin-vue-i18n/vite';
|
||||
import { PrimeVueResolver } from '@primevue/auto-import-resolver';
|
||||
import { unheadVueComposablesImports } from '@unhead/vue';
|
||||
@ -26,6 +25,7 @@ import { createUtils4uAutoImports } from 'utils4u/auto-imports';
|
||||
import { PluginOption } from 'vite';
|
||||
import cdnImport from 'vite-plugin-cdn-import';
|
||||
import { vitePluginFakeServer } from 'vite-plugin-fake-server';
|
||||
import { viteStaticCopy } from 'vite-plugin-static-copy';
|
||||
import VueDevTools from 'vite-plugin-vue-devtools';
|
||||
import Layouts from 'vite-plugin-vue-layouts';
|
||||
import MetaLayouts from 'vite-plugin-vue-meta-layouts';
|
||||
@ -42,22 +42,22 @@ export function Plugins() {
|
||||
plugins.push(
|
||||
VueMacros({
|
||||
plugins: {
|
||||
vue: Vue({ include: [/\.vue$/, /\.md$/] }),
|
||||
vueJsx: VueJsx(), // 如有需要
|
||||
// https://uvr.esm.is/guide/configuration.html
|
||||
// https://github.com/posva/unplugin-vue-router
|
||||
vueRouter: VueRouter({
|
||||
routesFolder: 'src/pages',
|
||||
exclude: ['**/__*', '**/__*/**/*'],
|
||||
extensions: ['.page.vue', '.page.md'],
|
||||
getRouteName: (routeNode) => getPascalCaseRouteName(routeNode),
|
||||
logs: false,
|
||||
extensions: ['.page.vue', '.page.md'],
|
||||
routesFolder: 'src/pages',
|
||||
}),
|
||||
vue: Vue({ include: [/\.vue$/, /\.md$/] }),
|
||||
vueJsx: VueJsx(), // 如有需要
|
||||
},
|
||||
}), // https://vue-macros.dev/zh-CN/guide/bundler-integration.html
|
||||
|
||||
// https://github.com/JohnCampionJr/vite-plugin-vue-layouts?tab=readme-ov-file#configuration
|
||||
Layouts({ pagesDirs: [], defaultLayout: 'sakai-vue/AppLayout' }),
|
||||
Layouts({ defaultLayout: 'sakai-vue/AppLayout', pagesDirs: [] }),
|
||||
|
||||
// https://github.com/dishait/vite-plugin-vue-meta-layouts
|
||||
MetaLayouts({
|
||||
@ -76,7 +76,11 @@ export function Plugins() {
|
||||
|
||||
// https://github.com/antfu/unplugin-auto-import
|
||||
AutoImport({
|
||||
resolvers: [TDesignResolver({ library: 'mobile-vue', esm: true }), VantResolver({ importStyle: true })],
|
||||
dirs: [
|
||||
// 'src/composables',
|
||||
'src/stores',
|
||||
'src/utils',
|
||||
],
|
||||
imports: [
|
||||
'vue',
|
||||
'vue-i18n',
|
||||
@ -95,37 +99,33 @@ export function Plugins() {
|
||||
},
|
||||
),
|
||||
{
|
||||
'consola/browser': ['consola'],
|
||||
// add any other imports you were relying on
|
||||
'vue-router/auto': ['useLink'],
|
||||
'consola/browser': ['consola'],
|
||||
},
|
||||
],
|
||||
dirs: [
|
||||
// 'src/composables',
|
||||
'src/stores',
|
||||
'src/utils',
|
||||
],
|
||||
resolvers: [TDesignResolver({ esm: true, library: 'mobile-vue' }), VantResolver({ importStyle: true })],
|
||||
vueTemplate: true,
|
||||
}),
|
||||
|
||||
// https://github.com/antfu/unplugin-vue-components
|
||||
Components({
|
||||
// __开头的
|
||||
excludeNames: [/^__/],
|
||||
// allow auto load markdown components under `./src/components/`
|
||||
extensions: ['vue', 'md'],
|
||||
// allow auto import and register components used in markdown
|
||||
include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
|
||||
// __开头的
|
||||
excludeNames: [/^__/],
|
||||
resolvers: [
|
||||
AntDesignVueResolver({
|
||||
importStyle: false, // css in js
|
||||
resolveIcons: true,
|
||||
}),
|
||||
IconsResolver({
|
||||
prefix: 'icon',
|
||||
customCollections: ['svg'],
|
||||
prefix: 'icon',
|
||||
}), // https://github.com/unplugin/unplugin-icons?tab=readme-ov-file#auto-importing
|
||||
TDesignResolver({ library: 'mobile-vue', esm: true }),
|
||||
TDesignResolver({ esm: true, library: 'mobile-vue' }),
|
||||
VantResolver({ importStyle: true }),
|
||||
PrimeVueResolver(/* { components: { prefix: 'P' } } */),
|
||||
],
|
||||
@ -166,9 +166,9 @@ export function Plugins() {
|
||||
|
||||
// https://github.com/condorheroblog/vite-plugin-fake-server?tab=readme-ov-file#usage
|
||||
vitePluginFakeServer({
|
||||
include: 'fake',
|
||||
basename: 'fake-api',
|
||||
enableProd: true,
|
||||
include: 'fake',
|
||||
}),
|
||||
|
||||
viteStaticCopy({
|
||||
@ -195,9 +195,9 @@ export function Plugins() {
|
||||
// https://github.com/mmf-fe/vite-plugin-cdn-import/blob/HEAD/README.zh-CN.md
|
||||
// 会对 Components 插件的自动导入产生影响。
|
||||
cdnImport({
|
||||
enableInDevMode: true,
|
||||
modules: ['vue'],
|
||||
prodUrl: '//fastly.jsdelivr.net/npm/{name}@{version}/{path}',
|
||||
enableInDevMode: true,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
@ -7,29 +7,14 @@ import { defineConfig, loadEnv } from 'vite';
|
||||
import { cesiumBaseUrl, Plugins } from './vite.config.plugins';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(({ mode, command }) => {
|
||||
export default defineConfig(({ command, mode }) => {
|
||||
const isBuild = command === 'build';
|
||||
const env = loadEnv(mode, process.cwd());
|
||||
|
||||
return {
|
||||
base: env.VITE_BASE,
|
||||
plugins: Plugins(),
|
||||
define: {
|
||||
$__DEV__: JSON.stringify(!isBuild),
|
||||
CESIUM_BASE_URL: JSON.stringify(`/${cesiumBaseUrl}`),
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||
},
|
||||
},
|
||||
server: {
|
||||
proxy: createViteProxy(),
|
||||
allowedHosts: ['.nwct.dev'],
|
||||
},
|
||||
build: {
|
||||
minify: 'terser',
|
||||
sourcemap: mode !== 'production' || env.VITE_SOURCE_MAP === 'true',
|
||||
rollupOptions: {
|
||||
onwarn: (warning, warn) => {
|
||||
if (warning.code === 'EMPTY_BUNDLE') return;
|
||||
@ -54,6 +39,21 @@ export default defineConfig(({ mode, command }) => {
|
||||
// },
|
||||
},
|
||||
},
|
||||
sourcemap: mode !== 'production' || env.VITE_SOURCE_MAP === 'true',
|
||||
},
|
||||
define: {
|
||||
$__DEV__: JSON.stringify(!isBuild),
|
||||
CESIUM_BASE_URL: JSON.stringify(`/${cesiumBaseUrl}`),
|
||||
},
|
||||
plugins: Plugins(),
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||
},
|
||||
},
|
||||
server: {
|
||||
allowedHosts: ['.nwct.dev'],
|
||||
proxy: createViteProxy(),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
Reference in New Issue
Block a user