chore: eslint 配置
This commit is contained in:
@ -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),
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user