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