This commit is contained in:
Zzc 2025-10-31 15:40:24 +08:00
commit 7442465435
11 changed files with 878 additions and 9 deletions

View File

@ -25,10 +25,14 @@
"pnpm": ">=8.0.0" "pnpm": ">=8.0.0"
}, },
"dependencies": { "dependencies": {
"@vueuse/core": "^14.0.0",
"dayjs": "^1.11.18", "dayjs": "^1.11.18",
"element-plus": "^2.11.5",
"vant": "^4.9.21" "vant": "^4.9.21"
}, },
"devDependencies": { "devDependencies": {
"@vant/auto-import-resolver": "^1.3.0" "@vant/auto-import-resolver": "^1.3.0",
"unplugin-auto-import": "^0.17.0",
"unplugin-vue-components": "^0.26.0"
} }
} }

View File

@ -0,0 +1,78 @@
<template>
<div v-if="buttons.length" class="dynamic-table-toolbar" :style="toolbarStyle">
<el-space :size="8">
<el-button
v-for="(btn, idx) in buttons"
:key="btn.key || idx"
:type="btn.type"
:icon="btn.icon"
:loading="btn.loading"
:disabled="btn.disabled || (btn.needsSelection && !selectedKeys.length)"
@click="handleClick(btn)"
>
{{ btn.text }}
</el-button>
</el-space>
</div>
</template>
<script setup>
import { computed } from 'vue'
import { ElMessage } from 'element-plus'
const props = defineProps({
/**
* 按钮列表
*/
buttons: {
type: Array,
default: () => []
},
/**
* 已选中的行 key 数组
*/
selectedKeys: {
type: Array,
default: () => []
},
/**
* 数据源传递给按钮 onClick
*/
dataSource: {
type: Array,
default: () => []
},
/**
* 工具栏对齐方式
*/
align: {
type: String,
default: 'left',
validator: (v) => ['left', 'center', 'right'].includes(v)
}
})
const toolbarStyle = computed(() => ({
justifyContent: props.align === 'left' ? 'flex-start'
: props.align === 'right' ? 'flex-end'
: 'center'
}))
const handleClick = (button) => {
//
if (button.needsSelection && !props.selectedKeys.length) {
ElMessage.warning(button.selectionMessage || '请选择要操作的数据')
return
}
// onClick
button.onClick?.(props.selectedKeys, props.dataSource)
}
</script>
<style scoped>
.dynamic-table-toolbar {
display: flex;
margin-bottom: 16px;
}
</style>

View File

@ -0,0 +1,6 @@
/**
* DynamicTable 组件导出
*/
import DynamicTable from './index.vue'
export default DynamicTable

View File

@ -0,0 +1,220 @@
<template>
<div
ref="containerRef"
class="dynamic-table-container"
:class="{ 'auto-height-enabled': autoHeight }"
>
<!-- 工具栏 -->
<TableToolbar
v-if="toolbar"
:buttons="toolbar.buttons"
:selected-keys="selectedRowKeys"
:data-source="dataSource"
:align="toolbar.align"
/>
<!-- 表格 - 直接透传所有原生属性 -->
<el-table
ref="tableRef"
:data="dataSource"
:height="computedHeight"
v-bind="$attrs"
@selection-change="handleSelectionChange"
>
<!-- 渲染列 -->
<el-table-column
v-for="(col, idx) in processedColumns"
:key="col.prop || col.label || idx"
v-bind="getColumnProps(col)"
>
<!-- 自定义渲染render slot -->
<template v-if="col.render || col.slot" #default="scope">
<component
v-if="col.render"
:is="col.render(scope.row, scope.column, scope.$index)"
/>
<slot v-else-if="col.slot" :name="col.slot" v-bind="scope" />
</template>
</el-table-column>
<!-- 透传所有插槽 -->
<template v-for="name in Object.keys($slots)" #[name]="scope">
<slot :name="name" v-bind="typeof scope === 'object' ? scope : {}" />
</template>
</el-table>
<!-- 分页 -->
<el-pagination
v-if="pagination"
:current-page="pagination.current"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="pagination.pageSizes || [10, 20, 50, 100]"
:layout="pagination.layout || 'total, sizes, prev, pager, next, jumper'"
@current-change="handlePageChange"
@size-change="handleSizeChange"
/>
</div>
</template>
<script setup>
import { ref, computed } from "vue";
import TableToolbar from "./TableToolbar.vue";
import { useAutoHeight } from "./useAutoHeight";
defineOptions({
name: "DynamicTable",
inheritAttrs: false, //
});
const props = defineProps({
/**
* 数据源
*/
dataSource: {
type: Array,
default: () => [],
},
/**
* 列配置
*/
columns: {
type: Array,
default: () => [],
},
/**
* 工具栏配置
*/
toolbar: {
type: Object,
default: null,
},
/**
* 是否启用自适应高度
*/
autoHeight: {
type: Boolean,
default: false,
},
/**
* 分页配置false 表示不分页
*/
pagination: {
type: [Object, Boolean],
default: false,
},
});
const emit = defineEmits(["selection-change"]);
const containerRef = ref(null);
const tableRef = ref(null);
const selectedRowKeys = ref([]);
// ==================== ====================
const { tableHeight } = useAutoHeight(containerRef, {
enabled: props.autoHeight,
minHeight: 200,
});
const computedHeight = computed(() => {
return props.autoHeight ? tableHeight.value : undefined;
});
// ==================== ====================
/**
* 处理列配置,设置合理的默认值
* 原则: 仅设置默认值,不改变结构,用户配置优先
*/
const processedColumns = computed(() => {
return props.columns.map((col) => {
// (selection/index/expand),
if (col.type) return col;
//
return {
showOverflowTooltip: true, //
align: "center", //
minWidth: col.width ? undefined : 100, //
...col, //
};
});
});
/**
* 获取列的 props用于 v-bind
* 过滤掉自定义属性 (render, slot)
*/
const getColumnProps = (col) => {
const { render, slot, ...restProps } = col;
return restProps;
};
// ==================== ====================
/**
* 处理行选择改变
*/
const handleSelectionChange = (selection) => {
// key
const rowKey = props.$attrs?.rowKey || props.$attrs?.["row-key"] || "id";
selectedRowKeys.value = selection.map((row) =>
typeof rowKey === "function" ? rowKey(row) : row[rowKey]
);
emit("selection-change", selection);
};
/**
* 处理分页页码改变
*/
const handlePageChange = (page) => {
props.pagination?.onChange?.(page, props.pagination.pageSize);
};
/**
* 处理每页条数改变
*/
const handleSizeChange = (size) => {
// ,
props.pagination?.onChange?.(1, size);
};
// ==================== ====================
defineExpose({
/**
* el-table 实例引用
*/
tableRef,
/**
* 已选中的行 key 数组
*/
selectedRowKeys,
/**
* 手动重新计算表格高度
*/
recalculate: () => {
if (props.autoHeight) {
setTimeout(() => {
tableHeight.recalculate?.();
}, 100);
}
},
});
</script>
<style scoped>
.dynamic-table-container {
display: flex;
flex-direction: column;
height: 100%;
}
.auto-height-enabled {
overflow: hidden;
}
.el-pagination {
margin-top: 16px;
justify-content: flex-end;
}
</style>

View File

@ -0,0 +1,129 @@
/**
* 自适应高度 Hook
* 根据父容器和兄弟元素动态计算表格高度
*
* @param {Ref} containerRef - 容器 DOM 引用
* @param {Object} options - 配置选项
* @param {boolean} options.enabled - 是否启用自适应高度
* @param {number} options.minHeight - 最小高度
* @param {number} options.offset - 额外的高度偏移
* @param {number} options.debounce - 防抖延迟
* @returns {{tableHeight: Ref<number>, recalculate: Function}}
*/
import { ref, onMounted, onUnmounted } from 'vue'
import { useResizeObserver } from '@vueuse/core'
export function useAutoHeight(containerRef, options = {}) {
const {
enabled = true,
minHeight = 200,
offset = 0,
debounce = 100
} = options
const tableHeight = ref(400)
let debounceTimer = null
/**
* 计算表格可用高度
* 逻辑: 父容器高度 - 兄弟元素高度 - 工具栏 - 表头 - 分页器
*/
const calculateHeight = () => {
if (!enabled || !containerRef.value) return
const container = containerRef.value
const parentElement = container.parentElement
if (!parentElement) return
// 1. 获取父容器可用高度
const parentRect = parentElement.getBoundingClientRect()
const parentStyle = window.getComputedStyle(parentElement)
const parentPaddingTop = parseFloat(parentStyle.paddingTop) || 0
const parentPaddingBottom = parseFloat(parentStyle.paddingBottom) || 0
// 2. 计算兄弟元素占用的高度
let siblingsHeight = 0
Array.from(parentElement.children).forEach(child => {
if (child !== container) {
const childRect = child.getBoundingClientRect()
const childStyle = window.getComputedStyle(child)
const marginTop = parseFloat(childStyle.marginTop) || 0
const marginBottom = parseFloat(childStyle.marginBottom) || 0
siblingsHeight += childRect.height + marginTop + marginBottom
}
})
let availableHeight = parentRect.height - parentPaddingTop - parentPaddingBottom - siblingsHeight
// 3. 减去容器内部组件高度
// 工具栏
const toolbar = container.querySelector('.dynamic-table-toolbar')
if (toolbar) {
const toolbarRect = toolbar.getBoundingClientRect()
const toolbarStyle = window.getComputedStyle(toolbar)
const marginBottom = parseFloat(toolbarStyle.marginBottom) || 0
availableHeight -= (toolbarRect.height + marginBottom)
}
// 表头
const thead = container.querySelector('.el-table__header-wrapper')
if (thead) {
availableHeight -= thead.getBoundingClientRect().height
}
// 分页器
const pagination = container.querySelector('.el-pagination')
if (pagination) {
const paginationRect = pagination.getBoundingClientRect()
const paginationStyle = window.getComputedStyle(pagination)
const marginTop = parseFloat(paginationStyle.marginTop) || 0
const marginBottom = parseFloat(paginationStyle.marginBottom) || 0
availableHeight -= (paginationRect.height + marginTop + marginBottom)
}
// 4. 应用偏移和最小高度限制
const finalHeight = Math.max(availableHeight - offset, minHeight)
tableHeight.value = finalHeight
}
/**
* 防抖包装
*/
const debouncedCalculate = () => {
if (debounceTimer) clearTimeout(debounceTimer)
debounceTimer = setTimeout(calculateHeight, debounce)
}
// 监听容器尺寸变化
useResizeObserver(containerRef, debouncedCalculate)
// 组件挂载后初始化
onMounted(() => {
if (!enabled || !containerRef.value) return
// 监听父容器尺寸变化
const parentElement = containerRef.value.parentElement
if (parentElement) {
useResizeObserver(parentElement, debouncedCalculate)
}
// 初始计算(延迟确保 DOM 渲染完成)
setTimeout(calculateHeight, 100)
// 监听窗口尺寸变化(兜底)
window.addEventListener('resize', debouncedCalculate)
})
// 清理
onUnmounted(() => {
window.removeEventListener('resize', debouncedCalculate)
if (debounceTimer) clearTimeout(debounceTimer)
})
return {
tableHeight,
recalculate: calculateHeight
}
}

View File

@ -3,10 +3,12 @@ import { createPinia } from 'pinia'
import router from './router' import router from './router'
import App from './App.vue' import App from './App.vue'
import './styles/index.scss' import './styles/index.scss'
import ElementPlus from 'element-plus'
const app = createApp(App) const app = createApp(App)
app.use(createPinia()) app.use(createPinia())
app.use(ElementPlus)
app.use(router) app.use(router)
app.mount('#app') app.mount('#app')

View File

@ -1,3 +1,4 @@
import component from 'element-plus/es/components/tree-select/src/tree-select-option.mjs'
import { createRouter, createWebHistory } from 'vue-router' import { createRouter, createWebHistory } from 'vue-router'
const routes = [ const routes = [
@ -10,6 +11,11 @@ const routes = [
path: '/cockpit', path: '/cockpit',
name: 'Cockpit', name: 'Cockpit',
component: () => import('../views/cockpit/index.vue') component: () => import('../views/cockpit/index.vue')
},
{
path: '/test',
name: 'test',
component: () => import('../views/ServiceStationManagePage/index.vue')
} }
] ]

View File

@ -0,0 +1,16 @@
import axios from 'axios'
const service = axios.create({
baseURL: '',
timeout: 10000
})
export async function request(config) {
const res = await service(config)
if (res === null || res === undefined) {
return res
}
if (Object.prototype.hasOwnProperty.call(res, 'data')) {
return res.data
}
}

View File

@ -0,0 +1,204 @@
<template>
<DynamicTable
:dataSource="tableData"
:columns="columns"
:toolbar="toolbar"
:autoHeight="true"
:pagination="pagination"
></DynamicTable>
</template>
<script lang="ts" setup>
import DynamicTable from "../../component/DynamicTable";
import { h, ref, onMounted, reactive } from "vue";
import { request } from "@/utils/request";
const tableData = ref([
{
county: "潼南",
road_code: "G319线",
mile_code: "2654+000",
level: "国道",
monthly_traffic: "5625",
tec_level: "二级",
name: "三汇停车区",
service_station_address: "交通公路部门",
},
{
county: "潼南",
road_code: "G319线",
mile_code: "2654+000",
level: "国道",
monthly_traffic: "5625",
tec_level: "二级",
name: "三汇停车区",
service_station_address: "交通公路部门",
},
{
county: "潼南",
road_code: "G319线",
mile_code: "2654+000",
level: "国道",
monthly_traffic: "5625",
tec_level: "二级",
name: "三汇停车区",
service_station_address: "交通公路部门",
},
{
county: "潼南",
road_code: "G319线",
mile_code: "2654+000",
level: "国道",
monthly_traffic: "5625",
tec_level: "二级",
name: "三汇停车区",
service_station_address: "交通公路部门",
},
{
county: "潼南",
road_code: "G319线",
mile_code: "2654+000",
level: "国道",
monthly_traffic: "5625",
tec_level: "二级",
name: "三汇停车区",
service_station_address: "交通公路部门",
},
{
county: "潼南",
road_code: "G319线",
mile_code: "2654+000",
level: "国道",
monthly_traffic: "5625",
tec_level: "二级",
name: "三汇停车区",
service_station_address: "交通公路部门",
},
{
county: "潼南",
road_code: "G319线",
mile_code: "2654+000",
level: "国道",
monthly_traffic: "5625",
tec_level: "二级",
name: "三汇停车区",
service_station_address: "交通公路部门",
},
{
county: "潼南",
road_code: "G319线",
mile_code: "2654+000",
level: "国道",
monthly_traffic: "5625",
tec_level: "二级",
name: "三汇停车区",
service_station_address: "交通公路部门",
},
{
county: "潼南",
road_code: "G319线",
mile_code: "2654+000",
level: "国道",
monthly_traffic: "5625",
tec_level: "二级",
name: "三汇停车区",
service_station_address: "交通公路部门",
},
{
county: "潼南",
road_code: "G319线",
mile_code: "2654+000",
level: "国道",
monthly_traffic: "5625",
tec_level: "二级",
name: "三汇停车区",
service_station_address: "交通公路部门",
},
]);
const getTableData = async () => {
try {
const params = {
pageNum: pagination.current,
pageSize: pagination.pageSize,
};
const res = await request({
url: "/api/yhz/list",
method: "GET",
params: params,
});
} catch (error) {}
};
onMounted(() => {
getTableData();
});
const columns = [
{
prop: "county",
label: "区县",
},
{
prop: "road_code",
label: "路线编码",
// minWidth: 160,
},
{
prop: "mile_code",
label: "里程桩号",
},
{
prop: "level",
label: "行政等级(仅划分:国道、省道、农村公路三类)",
},
{
prop: "monthly_traffic",
label: "机动车月交通流量",
},
{
prop: "tec_level",
label: "技术等级",
},
{
prop: "name",
label: "服务保障点具体名称",
},
{
prop: "type",
label: "类型",
},
{
label: "操作",
fixed: "right",
width: 100,
render: (row) => () =>
h(
ElButton,
{
type: "text",
onClick: () => {
console.log(row);
},
},
() => "详情"
),
},
];
const pagination = reactive({
current: 1,
pageSize: 10,
total: 0,
pageSizes: [10, 20, 50],
layout: "prev, pager, next, jumper",
onChange: (page: number, pageSize: number) => {
pagination.current = page;
pagination.pageSize = pageSize;
getTableData();
},
});
</script>
<style lang="scss" scoped>
</style>

View File

@ -1,9 +1,20 @@
import { defineConfig } from 'vite' import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import { resolve } from 'path' import { resolve } from 'path'
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
resolve: { resolve: {
alias: { alias: {
'@': resolve(__dirname, 'src'), '@': resolve(__dirname, 'src'),
@ -13,7 +24,13 @@ export default defineConfig({
server: { server: {
port: 3000, port: 3000,
open: true, open: true,
cors: true cors: true,
proxy: {
'/api': {
target: '',
changeOrigin: true,
},
}
}, },
build: { build: {
outDir: 'dist', outDir: 'dist',

199
pnpm-lock.yaml generated
View File

@ -8,9 +8,15 @@ importers:
.: .:
dependencies: dependencies:
'@vueuse/core':
specifier: ^14.0.0
version: 14.0.0(vue@3.5.22)
dayjs: dayjs:
specifier: ^1.11.18 specifier: ^1.11.18
version: 1.11.18 version: 1.11.18
element-plus:
specifier: ^2.11.5
version: 2.11.5(vue@3.5.22)
vant: vant:
specifier: ^4.9.21 specifier: ^4.9.21
version: 4.9.21(vue@3.5.22) version: 4.9.21(vue@3.5.22)
@ -18,6 +24,12 @@ importers:
'@vant/auto-import-resolver': '@vant/auto-import-resolver':
specifier: ^1.3.0 specifier: ^1.3.0
version: 1.3.0 version: 1.3.0
unplugin-auto-import:
specifier: ^0.17.0
version: 0.17.8(@vueuse/core@14.0.0(vue@3.5.22))(rollup@4.52.4)
unplugin-vue-components:
specifier: ^0.26.0
version: 0.26.0(@babel/parser@7.28.4)(rollup@4.52.4)(vue@3.5.22)
packages/mobile: packages/mobile:
dependencies: dependencies:
@ -45,7 +57,7 @@ importers:
version: 1.93.2 version: 1.93.2
unplugin-auto-import: unplugin-auto-import:
specifier: ^0.17.0 specifier: ^0.17.0
version: 0.17.8(rollup@4.52.4) version: 0.17.8(@vueuse/core@14.0.0(vue@3.5.22))(rollup@4.52.4)
unplugin-vue-components: unplugin-vue-components:
specifier: ^0.26.0 specifier: ^0.26.0
version: 0.26.0(@babel/parser@7.28.4)(rollup@4.52.4)(vue@3.5.22) version: 0.26.0(@babel/parser@7.28.4)(rollup@4.52.4)(vue@3.5.22)
@ -115,6 +127,15 @@ packages:
resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
'@ctrl/tinycolor@3.6.1':
resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==}
engines: {node: '>=10'}
'@element-plus/icons-vue@2.3.2':
resolution: {integrity: sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==}
peerDependencies:
vue: ^3.2.0
'@esbuild/aix-ppc64@0.21.5': '@esbuild/aix-ppc64@0.21.5':
resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -253,6 +274,15 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@floating-ui/core@1.7.3':
resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==}
'@floating-ui/dom@1.7.4':
resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==}
'@floating-ui/utils@0.2.10':
resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
'@jridgewell/gen-mapping@0.3.13': '@jridgewell/gen-mapping@0.3.13':
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
@ -482,9 +512,24 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@sxzz/popperjs-es@2.11.7':
resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==}
'@types/estree@1.0.8': '@types/estree@1.0.8':
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
'@types/lodash-es@4.17.12':
resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
'@types/lodash@4.17.20':
resolution: {integrity: sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==}
'@types/web-bluetooth@0.0.16':
resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==}
'@types/web-bluetooth@0.0.21':
resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==}
'@vant/auto-import-resolver@1.3.0': '@vant/auto-import-resolver@1.3.0':
resolution: {integrity: sha512-lJyWtCyFizR4bHZvMiNMF3w+WTFTUWAvka1eqTnPK9ticUcKTCOx6qEmHcm8JPb3g1t3GaD2W3MnHkBp/nHamw==} resolution: {integrity: sha512-lJyWtCyFizR4bHZvMiNMF3w+WTFTUWAvka1eqTnPK9ticUcKTCOx6qEmHcm8JPb3g1t3GaD2W3MnHkBp/nHamw==}
@ -535,6 +580,28 @@ packages:
'@vue/shared@3.5.22': '@vue/shared@3.5.22':
resolution: {integrity: sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==} resolution: {integrity: sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==}
'@vueuse/core@14.0.0':
resolution: {integrity: sha512-d6tKRWkZE8IQElX2aHBxXOMD478fHIYV+Dzm2y9Ag122ICBpNKtGICiXKOhWU3L1kKdttDD9dCMS4bGP3jhCTQ==}
peerDependencies:
vue: ^3.5.0
'@vueuse/core@9.13.0':
resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==}
'@vueuse/metadata@14.0.0':
resolution: {integrity: sha512-6yoGqbJcMldVCevkFiHDBTB1V5Hq+G/haPlGIuaFZHpXC0HADB0EN1ryQAAceiW+ryS3niUwvdFbGiqHqBrfVA==}
'@vueuse/metadata@9.13.0':
resolution: {integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==}
'@vueuse/shared@14.0.0':
resolution: {integrity: sha512-mTCA0uczBgurRlwVaQHfG0Ja7UdGe4g9mwffiJmvLiTtp1G4AQyIjej6si/k8c8pUwTfVpNufck+23gXptPAkw==}
peerDependencies:
vue: ^3.5.0
'@vueuse/shared@9.13.0':
resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==}
acorn@8.15.0: acorn@8.15.0:
resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
@ -544,6 +611,9 @@ packages:
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
async-validator@4.2.5:
resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==}
asynckit@0.4.0: asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
@ -626,6 +696,11 @@ packages:
echarts@5.6.0: echarts@5.6.0:
resolution: {integrity: sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==} resolution: {integrity: sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==}
element-plus@2.11.5:
resolution: {integrity: sha512-O+bIVHQCjUDm4GiIznDXRoS8ar2TpWLwfOGnN/Aam0VXf5kbuc4SxdKKJdovWNxmxeqbcwjsSZPKgtXNcqys4A==}
peerDependencies:
vue: ^3.2.0
entities@4.5.0: entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'} engines: {node: '>=0.12'}
@ -786,6 +861,19 @@ packages:
resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==} resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==}
engines: {node: '>=14'} engines: {node: '>=14'}
lodash-es@4.17.21:
resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
lodash-unified@1.0.3:
resolution: {integrity: sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==}
peerDependencies:
'@types/lodash-es': '*'
lodash: '*'
lodash-es: '*'
lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
magic-string@0.30.19: magic-string@0.30.19:
resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==}
@ -797,6 +885,9 @@ packages:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
memoize-one@6.0.0:
resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==}
merge2@1.4.1: merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@ -845,9 +936,8 @@ packages:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
parse-node-version@1.0.1: normalize-wheel-es@1.2.0:
resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==}
engines: {node: '>= 0.10'}
path-parse@1.0.7: path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
@ -1119,6 +1209,12 @@ snapshots:
'@babel/helper-string-parser': 7.27.1 '@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.27.1 '@babel/helper-validator-identifier': 7.27.1
'@ctrl/tinycolor@3.6.1': {}
'@element-plus/icons-vue@2.3.2(vue@3.5.22)':
dependencies:
vue: 3.5.22
'@esbuild/aix-ppc64@0.21.5': '@esbuild/aix-ppc64@0.21.5':
optional: true optional: true
@ -1188,6 +1284,17 @@ snapshots:
'@esbuild/win32-x64@0.21.5': '@esbuild/win32-x64@0.21.5':
optional: true optional: true
'@floating-ui/core@1.7.3':
dependencies:
'@floating-ui/utils': 0.2.10
'@floating-ui/dom@1.7.4':
dependencies:
'@floating-ui/core': 1.7.3
'@floating-ui/utils': 0.2.10
'@floating-ui/utils@0.2.10': {}
'@jridgewell/gen-mapping@0.3.13': '@jridgewell/gen-mapping@0.3.13':
dependencies: dependencies:
'@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/sourcemap-codec': 1.5.5
@ -1358,8 +1465,20 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.52.4': '@rollup/rollup-win32-x64-msvc@4.52.4':
optional: true optional: true
'@sxzz/popperjs-es@2.11.7': {}
'@types/estree@1.0.8': {} '@types/estree@1.0.8': {}
'@types/lodash-es@4.17.12':
dependencies:
'@types/lodash': 4.17.20
'@types/lodash@4.17.20': {}
'@types/web-bluetooth@0.0.16': {}
'@types/web-bluetooth@0.0.21': {}
'@vant/auto-import-resolver@1.3.0': {} '@vant/auto-import-resolver@1.3.0': {}
'@vant/popperjs@1.3.0': {} '@vant/popperjs@1.3.0': {}
@ -1429,6 +1548,38 @@ snapshots:
'@vue/shared@3.5.22': {} '@vue/shared@3.5.22': {}
'@vueuse/core@14.0.0(vue@3.5.22)':
dependencies:
'@types/web-bluetooth': 0.0.21
'@vueuse/metadata': 14.0.0
'@vueuse/shared': 14.0.0(vue@3.5.22)
vue: 3.5.22
'@vueuse/core@9.13.0(vue@3.5.22)':
dependencies:
'@types/web-bluetooth': 0.0.16
'@vueuse/metadata': 9.13.0
'@vueuse/shared': 9.13.0(vue@3.5.22)
vue-demi: 0.14.10(vue@3.5.22)
transitivePeerDependencies:
- '@vue/composition-api'
- vue
'@vueuse/metadata@14.0.0': {}
'@vueuse/metadata@9.13.0': {}
'@vueuse/shared@14.0.0(vue@3.5.22)':
dependencies:
vue: 3.5.22
'@vueuse/shared@9.13.0(vue@3.5.22)':
dependencies:
vue-demi: 0.14.10(vue@3.5.22)
transitivePeerDependencies:
- '@vue/composition-api'
- vue
acorn@8.15.0: {} acorn@8.15.0: {}
anymatch@3.1.3: anymatch@3.1.3:
@ -1436,6 +1587,8 @@ snapshots:
normalize-path: 3.0.0 normalize-path: 3.0.0
picomatch: 2.3.1 picomatch: 2.3.1
async-validator@4.2.5: {}
asynckit@0.4.0: {} asynckit@0.4.0: {}
axios@1.12.2: axios@1.12.2:
@ -1521,6 +1674,26 @@ snapshots:
tslib: 2.3.0 tslib: 2.3.0
zrender: 5.6.1 zrender: 5.6.1
element-plus@2.11.5(vue@3.5.22):
dependencies:
'@ctrl/tinycolor': 3.6.1
'@element-plus/icons-vue': 2.3.2(vue@3.5.22)
'@floating-ui/dom': 1.7.4
'@popperjs/core': '@sxzz/popperjs-es@2.11.7'
'@types/lodash': 4.17.20
'@types/lodash-es': 4.17.12
'@vueuse/core': 9.13.0(vue@3.5.22)
async-validator: 4.2.5
dayjs: 1.11.18
lodash: 4.17.21
lodash-es: 4.17.21
lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21)
memoize-one: 6.0.0
normalize-wheel-es: 1.2.0
vue: 3.5.22
transitivePeerDependencies:
- '@vue/composition-api'
entities@4.5.0: {} entities@4.5.0: {}
errno@0.1.8: errno@0.1.8:
@ -1704,6 +1877,16 @@ snapshots:
pkg-types: 2.3.0 pkg-types: 2.3.0
quansync: 0.2.11 quansync: 0.2.11
lodash-es@4.17.21: {}
lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21):
dependencies:
'@types/lodash-es': 4.17.12
lodash: 4.17.21
lodash-es: 4.17.21
lodash@4.17.21: {}
magic-string@0.30.19: magic-string@0.30.19:
dependencies: dependencies:
'@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/sourcemap-codec': 1.5.5
@ -1716,6 +1899,8 @@ snapshots:
math-intrinsics@1.1.0: {} math-intrinsics@1.1.0: {}
memoize-one@6.0.0: {}
merge2@1.4.1: {} merge2@1.4.1: {}
micromatch@4.0.8: micromatch@4.0.8:
@ -1758,7 +1943,7 @@ snapshots:
normalize-path@3.0.0: {} normalize-path@3.0.0: {}
parse-node-version@1.0.1: {} normalize-wheel-es@1.2.0: {}
path-parse@1.0.7: {} path-parse@1.0.7: {}
@ -1927,7 +2112,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- rollup - rollup
unplugin-auto-import@0.17.8(rollup@4.52.4): unplugin-auto-import@0.17.8(@vueuse/core@14.0.0(vue@3.5.22))(rollup@4.52.4):
dependencies: dependencies:
'@antfu/utils': 0.7.10 '@antfu/utils': 0.7.10
'@rollup/pluginutils': 5.3.0(rollup@4.52.4) '@rollup/pluginutils': 5.3.0(rollup@4.52.4)
@ -1937,6 +2122,8 @@ snapshots:
minimatch: 9.0.5 minimatch: 9.0.5
unimport: 3.14.6(rollup@4.52.4) unimport: 3.14.6(rollup@4.52.4)
unplugin: 1.16.1 unplugin: 1.16.1
optionalDependencies:
'@vueuse/core': 14.0.0(vue@3.5.22)
transitivePeerDependencies: transitivePeerDependencies:
- rollup - rollup