feat 配置

This commit is contained in:
Ironsp
2026-09-08 16:23:17 +08:00
parent 7e81a8ca59
commit bbde4c4a66
11 changed files with 475 additions and 39 deletions

17
src/auto-imports.d.ts vendored
View File

@@ -32,12 +32,18 @@ declare global {
const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch'] const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent'] const defineComponent: typeof import('vue')['defineComponent']
const device: typeof import('./utils/device')['default']
const eagerComputed: typeof import('@vueuse/core')['eagerComputed'] const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
const effectScope: typeof import('vue')['effectScope'] const effectScope: typeof import('vue')['effectScope']
const executeSql: typeof import('./utils/sqlite')['executeSql'] const executeSql: typeof import('./utils/sqlite')['executeSql']
const extendRef: typeof import('@vueuse/core')['extendRef'] const extendRef: typeof import('@vueuse/core')['extendRef']
const getCurrentInstance: typeof import('vue')['getCurrentInstance'] const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope'] const getCurrentScope: typeof import('vue')['getCurrentScope']
const getDeviceInfoFromStorage: typeof import('./utils/device')['getDeviceInfoFromStorage']
const getDeviceTypeName: typeof import('./utils/device')['getDeviceTypeName']
const getOrInitDeviceInfo: typeof import('./utils/device')['getOrInitDeviceInfo']
const getOsTypeName: typeof import('./utils/device')['getOsTypeName']
const getSystemInfo: typeof import('./utils/device')['getSystemInfo']
const h: typeof import('vue')['h'] const h: typeof import('vue')['h']
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch'] const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
const initTables: typeof import('./utils/sqlite')['initTables'] const initTables: typeof import('./utils/sqlite')['initTables']
@@ -114,6 +120,7 @@ declare global {
const resolveComponent: typeof import('vue')['resolveComponent'] const resolveComponent: typeof import('vue')['resolveComponent']
const resolveRef: typeof import('@vueuse/core')['resolveRef'] const resolveRef: typeof import('@vueuse/core')['resolveRef']
const resolveUnref: typeof import('@vueuse/core')['resolveUnref'] const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
const saveDeviceInfo: typeof import('./utils/device')['saveDeviceInfo']
const selectSql: typeof import('./utils/sqlite')['selectSql'] const selectSql: typeof import('./utils/sqlite')['selectSql']
const shallowReactive: typeof import('vue')['shallowReactive'] const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly'] const shallowReadonly: typeof import('vue')['shallowReadonly']
@@ -328,6 +335,9 @@ declare global {
// @ts-ignore // @ts-ignore
export type { Component, Slot, Slots, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue' export type { Component, Slot, Slots, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
import('vue') import('vue')
// @ts-ignore
export type { SystemInfo } from './utils/device'
import('./utils/device')
} }
// for vue template auto import // for vue template auto import
@@ -361,12 +371,18 @@ declare module 'vue' {
readonly debouncedWatch: UnwrapRef<typeof import('@vueuse/core')['debouncedWatch']> readonly debouncedWatch: UnwrapRef<typeof import('@vueuse/core')['debouncedWatch']>
readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']> readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']> readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
readonly device: UnwrapRef<typeof import('./utils/device')['default']>
readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']> readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']>
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']> readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
readonly executeSql: UnwrapRef<typeof import('./utils/sqlite')['executeSql']> readonly executeSql: UnwrapRef<typeof import('./utils/sqlite')['executeSql']>
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']> readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']> readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']> readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
readonly getDeviceInfoFromStorage: UnwrapRef<typeof import('./utils/device')['getDeviceInfoFromStorage']>
readonly getDeviceTypeName: UnwrapRef<typeof import('./utils/device')['getDeviceTypeName']>
readonly getOrInitDeviceInfo: UnwrapRef<typeof import('./utils/device')['getOrInitDeviceInfo']>
readonly getOsTypeName: UnwrapRef<typeof import('./utils/device')['getOsTypeName']>
readonly getSystemInfo: UnwrapRef<typeof import('./utils/device')['getSystemInfo']>
readonly h: UnwrapRef<typeof import('vue')['h']> readonly h: UnwrapRef<typeof import('vue')['h']>
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']> readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
readonly initTables: UnwrapRef<typeof import('./utils/sqlite')['initTables']> readonly initTables: UnwrapRef<typeof import('./utils/sqlite')['initTables']>
@@ -443,6 +459,7 @@ declare module 'vue' {
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']> readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']> readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']> readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']>
readonly saveDeviceInfo: UnwrapRef<typeof import('./utils/device')['saveDeviceInfo']>
readonly selectSql: UnwrapRef<typeof import('./utils/sqlite')['selectSql']> readonly selectSql: UnwrapRef<typeof import('./utils/sqlite')['selectSql']>
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']> readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']> readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>

1
src/components.d.ts vendored
View File

@@ -13,6 +13,7 @@ declare module 'vue' {
DeviceInfo: typeof import('./components/deviceInfo.vue')['default'] DeviceInfo: typeof import('./components/deviceInfo.vue')['default']
FullscreenNav: typeof import('./components/FullscreenNav.vue')['default'] FullscreenNav: typeof import('./components/FullscreenNav.vue')['default']
HomeConstruction: typeof import('./components/home/construction.vue')['default'] HomeConstruction: typeof import('./components/home/construction.vue')['default']
HomeDeviceFooter: typeof import('./components/home/deviceFooter.vue')['default']
HomeHomeNav: typeof import('./components/home/homeNav.vue')['default'] HomeHomeNav: typeof import('./components/home/homeNav.vue')['default']
HomeList: typeof import('./components/home/list.vue')['default'] HomeList: typeof import('./components/home/list.vue')['default']
HomeOverview: typeof import('./components/home/overview.vue')['default'] HomeOverview: typeof import('./components/home/overview.vue')['default']

View File

@@ -0,0 +1,183 @@
<script setup lang="ts">
import { onMounted } from 'vue'
import { useDeviceStore } from '@/store/modules/home'
const deviceStore = useDeviceStore()
onMounted(() => {
console.log('组件挂载时 初始化设备信息')
deviceStore.initDevice()
})
</script>
<template>
<view v-if="deviceStore.currentDevice" class="device-footer">
<view class="device-info">
<view class="device-main">
<view class="device-icon">
<wd-icon name="settings" size="20px" color="#3b82f6" />
</view>
<view class="device-detail">
<text class="device-name">
{{ deviceStore.currentDevice.brand }} {{ deviceStore.currentDevice.model }}
</text>
<text class="device-model">
{{ deviceStore.osTypeName }} · {{ deviceStore.deviceTypeName }}
</text>
</view>
</view>
<view class="device-status">
<view class="status-indicator status-online" />
<text class="status-text">
已连接
</text>
</view>
</view>
<view class="device-metrics">
<view class="metric-item">
<text class="metric-label">
屏幕
</text>
<text class="metric-value">
{{ deviceStore.currentDevice.windowWidth }} x {{ deviceStore.currentDevice.windowHeight }}
</text>
</view>
<view class="metric-item">
<text class="metric-label">
平台
</text>
<text class="metric-value">
{{ deviceStore.currentDevice.platform }}
</text>
</view>
</view>
<view class="device-id">
<text class="id-label">
设备ID:
</text>
<text class="id-value">
{{ deviceStore.currentDevice.deviceId }}
</text>
</view>
</view>
</template>
<style scoped>
.device-footer {
background: #fff;
border-radius: 12px;
padding: 16px;
margin-top: 12px;
}
.device-info {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.device-main {
display: flex;
align-items: center;
gap: 12px;
}
.device-icon {
width: 40px;
height: 40px;
border-radius: 10px;
background: #eff6ff;
display: flex;
align-items: center;
justify-content: center;
}
.device-detail {
display: flex;
flex-direction: column;
gap: 2px;
}
.device-name {
font-size: 16px;
font-weight: 600;
color: #333;
}
.device-model {
font-size: 12px;
color: #999;
}
.device-status {
display: flex;
align-items: center;
gap: 6px;
}
.status-indicator {
width: 8px;
height: 8px;
border-radius: 50%;
}
.status-online {
background: #22c55e;
}
.status-text {
font-size: 12px;
color: #666;
}
.device-metrics {
display: flex;
gap: 16px;
}
.metric-item {
flex: 1;
display: flex;
align-items: center;
gap: 8px;
}
.metric-label {
font-size: 12px;
color: #999;
width: 35px;
}
.metric-value {
font-size: 12px;
color: #666;
}
.device-id {
display: flex;
align-items: center;
gap: 6px;
margin-top: 12px;
padding-top: 12px;
border-top: 1px solid #f0f0f0;
}
.id-label {
font-size: 11px;
color: #999;
}
.id-value {
font-size: 11px;
color: #666;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>

View File

@@ -1,9 +1,11 @@
import { createSSRApp } from 'vue' import { createSSRApp } from 'vue'
import App from './App.vue' import App from './App.vue'
import store from './store'
import 'uno.css' import 'uno.css'
export function createApp() { export function createApp() {
const app = createSSRApp(App) const app = createSSRApp(App)
app.use(store)
return { return {
app, app,
} }

View File

@@ -24,6 +24,9 @@ definePage({
<home-warning /> <home-warning />
</view> </view>
</view> </view>
<!-- 当前设备信息 -->
<home-deviceFooter />
</view> </view>
</view> </view>
</template> </template>

View File

@@ -1,30 +0,0 @@
import { defineStore } from 'pinia'
// import { computed, ref } from 'vue'
// import { getDevicetList } from '@/api/equipmentList/index'
export const useDeviceStore = defineStore('devices', () => {
// --- State (状态) ---
// 相当于 Vuex 中的 state,用 ref 或 reactive 定义
// const deviceList = ref();
// --- Getters (计算属性) ---
// 相当于 Vuex 中的 getters,直接用 computed 定义
// --- Actions (动作) ---
// 相当于 Vuex 中的 actions/mutations,直接写同步或异步函数
// async function getdeviceList(query?: any) {
// try {
// const response = await getDevicetList(query);
// console.log('获取设备列表:', response);
// deviceList.value = response.rows;
// } catch (error) {
// console.error('获取设备列表失败', error);
// }
// }
// ⚠️ 核心点:必须把需要暴露出去的变量和方法 return 出去!
return {
// deviceList,
// getdeviceList
}
})

5
src/store/index.ts Normal file
View File

@@ -0,0 +1,5 @@
import { createPinia } from 'pinia'
const store = createPinia()
export default store

53
src/store/modules/home.ts Normal file
View File

@@ -0,0 +1,53 @@
import type { SystemInfo } from '@/utils/device'
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import { getDeviceTypeName, getOrInitDeviceInfo, getOsTypeName } from '@/utils/device'
export const useDeviceStore = defineStore('device', () => {
// --- State ---
const currentDevice = ref<SystemInfo | null>(null)
// --- Getters ---
const deviceTypeName = computed(() => {
return currentDevice.value ? getDeviceTypeName(currentDevice.value.deviceType) : '未知'
})
const osTypeName = computed(() => {
return currentDevice.value ? getOsTypeName(currentDevice.value.osType) : '未知'
})
const isPhone = computed(() => currentDevice.value?.deviceType === 'phone')
const isTablet = computed(() => currentDevice.value?.deviceType === 'tablet')
const isPC = computed(() => currentDevice.value?.deviceType === 'pc')
// --- Actions ---
/**
* 初始化设备信息
* 从本地存储读取或重新获取当前设备信息,并写入 state
*/
function initDevice() {
currentDevice.value = getOrInitDeviceInfo()
console.log('初始化设备信息11111111111111', currentDevice.value)
}
function getDevice() {
if (!currentDevice.value) {
initDevice()
}
return currentDevice.value
}
return {
// State
currentDevice,
// Getters
deviceTypeName,
osTypeName,
isPhone,
isTablet,
isPC,
// Actions
initDevice,
getDevice,
}
})

1
src/uni-pages.d.ts vendored
View File

@@ -6,7 +6,6 @@
type _LocationUrl = type _LocationUrl =
"/pages/Ahome/index" | "/pages/Ahome/index" |
"/pages/bluetooth/index" | "/pages/bluetooth/index" |
"/pages/demo/sqlite" |
"/pages/heatmap/index" | "/pages/heatmap/index" |
"/pages/message/index" | "/pages/message/index" |
"/pages/project/index" | "/pages/project/index" |

203
src/utils/device.ts Normal file
View File

@@ -0,0 +1,203 @@
/**
* 设备信息工具类
* 获取当前运行设备的信息(手机、平板、电脑)
*/
import storage from './storage'
export interface SystemInfo {
brand: string
model: string
system: string
platform: string
screenWidth: number
screenHeight: number
windowWidth: number
windowHeight: number
statusBarHeight?: number
deviceType: 'phone' | 'tablet' | 'pc'
osType: 'android' | 'ios' | 'windows' | 'mac' | 'linux' | 'unknown'
deviceId: string
}
const STORAGE_KEY = 'device_info'
const DEVICE_ID_KEY = 'device_unique_id'
/**
* 获取设备类型
*/
function getDeviceType(info: UniApp.GetSystemInfoResult): SystemInfo['deviceType'] {
const platform = info.platform?.toLowerCase() || ''
if (platform === 'windows' || platform === 'mac' || platform === 'linux') {
return 'pc'
}
const screenWidth = info.screenWidth || 0
const screenHeight = info.screenHeight || 0
const minSize = Math.min(screenWidth, screenHeight)
if (minSize >= 600) {
return 'tablet'
}
return 'phone'
}
/**
* 获取操作系统类型
*/
function getOsType(info: UniApp.GetSystemInfoResult): SystemInfo['osType'] {
const system = info.system?.toLowerCase() || ''
const platform = info.platform?.toLowerCase() || ''
if (system.includes('android') || platform === 'android') {
return 'android'
}
if (system.includes('ios') || platform === 'ios') {
return 'ios'
}
if (platform === 'windows') {
return 'windows'
}
if (platform === 'mac') {
return 'mac'
}
if (platform === 'linux') {
return 'linux'
}
return 'unknown'
}
/**
* 生成 UUID v4
*/
function generateUUID(): string {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0
const v = c === 'x' ? r : (r & 0x3) | 0x8
return v.toString(16)
})
}
/**
* 获取设备唯一标识
*/
function getDeviceId(): string {
// 从存储获取
const storedId = storage.get<string>(DEVICE_ID_KEY)
if (storedId) {
console.log('设备ID (已存储):', storedId)
return storedId
}
// 尝试使用系统 deviceId
try {
const deviceInfo = uni.getDeviceInfo()
if (deviceInfo.deviceId) {
storage.set(DEVICE_ID_KEY, deviceInfo.deviceId)
console.log('设备ID (系统):', deviceInfo.deviceId)
return deviceInfo.deviceId
}
}
catch {
// 忽略
}
// 生成新的 UUID
const newId = generateUUID()
storage.set(DEVICE_ID_KEY, newId)
console.log('设备ID (新生成):', newId)
return newId
}
/**
* 获取完整系统信息
*/
export function getSystemInfo(): SystemInfo {
const info = uni.getSystemInfoSync()
return {
brand: info.brand || 'unknown',
model: info.model || 'unknown',
system: info.system || 'unknown',
platform: info.platform || 'unknown',
screenWidth: info.screenWidth || 0,
screenHeight: info.screenHeight || 0,
windowWidth: info.windowWidth || 0,
windowHeight: info.windowHeight || 0,
statusBarHeight: info.statusBarHeight,
deviceType: getDeviceType(info),
osType: getOsType(info),
deviceId: getDeviceId(),
}
}
/**
* 获取设备类型中文名
*/
export function getDeviceTypeName(type: SystemInfo['deviceType']): string {
const typeMap: Record<SystemInfo['deviceType'], string> = {
phone: '手机',
tablet: '平板',
pc: '电脑',
}
return typeMap[type] || '未知'
}
/**
* 获取操作系统中文名
*/
export function getOsTypeName(type: SystemInfo['osType']): string {
const typeMap: Record<SystemInfo['osType'], string> = {
android: 'Android',
ios: 'iOS',
windows: 'Windows',
mac: 'macOS',
linux: 'Linux',
unknown: '未知',
}
return typeMap[type] || '未知'
}
/**
* 保存设备信息到本地存储
*/
export function saveDeviceInfo(info: SystemInfo): void {
storage.set(STORAGE_KEY, info)
}
/**
* 从本地存储获取设备信息
*/
export function getDeviceInfoFromStorage(): SystemInfo | null {
return storage.get<SystemInfo>(STORAGE_KEY) || null
}
/**
* 获取设备信息(优先从存储读取,没有则获取并保存)
*/
export function getOrInitDeviceInfo(): SystemInfo {
let deviceInfo = getDeviceInfoFromStorage()
if (!deviceInfo) {
deviceInfo = getSystemInfo()
saveDeviceInfo(deviceInfo)
}
else if (!deviceInfo.deviceId) {
// 旧数据没有 deviceId,补充生成
deviceInfo.deviceId = getDeviceId()
saveDeviceInfo(deviceInfo)
}
return deviceInfo
}
export default {
getSystemInfo,
getDeviceTypeName,
getOsTypeName,
saveDeviceInfo,
getDeviceInfoFromStorage,
getOrInitDeviceInfo,
}

View File

@@ -399,11 +399,11 @@ class DB {
*/ */
export async function initTables() { export async function initTables() {
const sqls = [ const sqls = [
// 设备信息表 // 项目信息表
`CREATE TABLE IF NOT EXISTS device ( `CREATE TABLE IF NOT EXISTS project (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
device_name TEXT NOT NULL, project_name TEXT NOT NULL,
device_type TEXT, project_type TEXT,
status TEXT DEFAULT 'offline', status TEXT DEFAULT 'offline',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP, created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
@@ -411,7 +411,7 @@ export async function initTables() {
// 作业记录表 // 作业记录表
`CREATE TABLE IF NOT EXISTS work_record ( `CREATE TABLE IF NOT EXISTS work_record (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
device_id INTEGER, project_id INTEGER,
start_time DATETIME, start_time DATETIME,
end_time DATETIME, end_time DATETIME,
speed REAL, speed REAL,
@@ -421,7 +421,7 @@ export async function initTables() {
gps_lat REAL, gps_lat REAL,
gps_lng REAL, gps_lng REAL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP, created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (device_id) REFERENCES device(id) FOREIGN KEY (project_id) REFERENCES project(id)
)`, )`,
// RTK 轨迹数据表 // RTK 轨迹数据表
`CREATE TABLE IF NOT EXISTS rtk_track ( `CREATE TABLE IF NOT EXISTS rtk_track (
@@ -439,13 +439,13 @@ export async function initTables() {
// 告警记录表 // 告警记录表
`CREATE TABLE IF NOT EXISTS warning_record ( `CREATE TABLE IF NOT EXISTS warning_record (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
device_id INTEGER, project_id INTEGER,
warning_type TEXT, warning_type TEXT,
warning_level TEXT, warning_level TEXT,
message TEXT, message TEXT,
is_read INTEGER DEFAULT 0, is_read INTEGER DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP, created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (device_id) REFERENCES device(id) FOREIGN KEY (project_id) REFERENCES project(id)
)`, )`,
] ]