feat 联调项目表

This commit is contained in:
Ironsp
2026-09-17 10:41:07 +08:00
parent e803ffa38c
commit 0399e8ede4
12 changed files with 127 additions and 60 deletions

View File

@@ -4,21 +4,27 @@ import { useCurrentProject } from '@/composables/useCurrentProject'
import { useDbStore } from '@/store/modules/db' import { useDbStore } from '@/store/modules/db'
const db = useDbStore() const db = useDbStore()
const { hasCurrentProject } = useCurrentProject() const { hasCurrentProject, currentProjectId } = useCurrentProject()
const now = new Date() const now = new Date()
const dateStr = `${now.getFullYear()}年${now.getMonth() + 1}月${now.getDate()}日` const dateStr = `${now.getFullYear()}年${now.getMonth() + 1}月${now.getDate()}日`
const projectWorkRecords = computed(() => {
if (!hasCurrentProject.value || currentProjectId.value == null)
return []
return (db.work_record || []).filter(item => item.project_id === currentProjectId.value)
})
const totalCompactionArea = computed(() => { const totalCompactionArea = computed(() => {
if (!hasCurrentProject.value) if (!hasCurrentProject.value)
return null return null
return (db.work_record || []).reduce((sum, item) => sum + (item.compaction_area ?? 0), 0) return projectWorkRecords.value.reduce((sum, item) => sum + (item.compaction_area ?? 0), 0)
}) })
const totalDuration = computed(() => { const totalDuration = computed(() => {
if (!hasCurrentProject.value) if (!hasCurrentProject.value)
return null return null
return (db.work_record || []).reduce((sum, item) => sum + (item.duration ?? 0), 0) return projectWorkRecords.value.reduce((sum, item) => sum + (item.duration ?? 0), 0)
}) })
const onlineCount = computed(() => { const onlineCount = computed(() => {
@@ -40,8 +46,9 @@ function formatCount(value: number | null) {
} }
onMounted(async () => { onMounted(async () => {
if (!db.work_record?.length) if (!hasCurrentProject.value || currentProjectId.value == null)
await db.loadAll() return
await db.loadByProject(currentProjectId.value)
}) })
</script> </script>

View File

@@ -5,18 +5,14 @@ import { calcUncompactedArea } from '@/service/project'
import { useDbStore } from '@/store/modules/db' import { useDbStore } from '@/store/modules/db'
const db = useDbStore() const db = useDbStore()
const { currentProject: storedProject, hasCurrentProject } = useCurrentProject() const { hasCurrentProject, currentProjectId } = useCurrentProject()
const currentProject = computed(() => { const currentProject = computed(() => {
if (!hasCurrentProject.value) if (!hasCurrentProject.value || currentProjectId.value == null)
return null return null
const list = db.project || [] const list = db.project || []
const storedId = storedProject.value?.id return list.find(item => item.id === currentProjectId.value) || null
if (storedId == null)
return null
return list.find(item => item.id === storedId) || null
}) })
const progressPercent = computed(() => { const progressPercent = computed(() => {
@@ -84,8 +80,9 @@ function formatPercent(value: number | null) {
} }
onMounted(async () => { onMounted(async () => {
if (!db.project?.length) if (!hasCurrentProject.value || currentProjectId.value == null)
await db.loadAll() return
await db.loadByProject(currentProjectId.value)
}) })
</script> </script>

View File

@@ -1,18 +1,12 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Project } from '@/service/project' import type { Project } from '@/service/project'
import { computed, onMounted } from 'vue' import { computed, onMounted } from 'vue'
import { useCurrentProject } from '@/composables/useCurrentProject'
import { useDbStore } from '@/store/modules/db' import { useDbStore } from '@/store/modules/db'
const db = useDbStore() const db = useDbStore()
const { hasCurrentProject } = useCurrentProject()
/** 首页只展示最近几条 */ /** 首页展示最近 2 条,按 id 倒序 */
const list = computed(() => { const list = computed(() => (db.project || []).slice().sort((a, b) => (b.id ?? 0) - (a.id ?? 0)).slice(0, 2))
if (!hasCurrentProject.value)
return []
return (db.project || []).slice(0, 2)
})
onMounted(async () => { onMounted(async () => {
if (!db.project?.length) if (!db.project?.length)
@@ -45,10 +39,7 @@ function goToDetail(item: Project) {
</wd-button> </wd-button>
</view> </view>
<view class="card-body"> <view class="card-body">
<view v-if="!hasCurrentProject" class="empty-tip"> <view v-if="!list.length" class="empty-tip">
--
</view>
<view v-else-if="!list.length" class="empty-tip">
暂无项目 暂无项目
</view> </view>
<home-list <home-list

View File

@@ -37,7 +37,7 @@ function goToWork() {
</view> </view>
</view> </view>
<view class="status-params"> <view class="status-params">
<view class="param"> <!-- <view class="param">
<text class="param-label"> <text class="param-label">
振动频率 振动频率
</text> </text>
@@ -52,7 +52,7 @@ function goToWork() {
<text class="param-value"> <text class="param-value">
8939mm 8939mm
</text> </text>
</view> </view> -->
<view class="param"> <view class="param">
<text class="param-label"> <text class="param-label">
行驶速度 行驶速度

View File

@@ -5,21 +5,21 @@ import { useCurrentProject } from '@/composables/useCurrentProject'
import { useDbStore } from '@/store/modules/db' import { useDbStore } from '@/store/modules/db'
const db = useDbStore() const db = useDbStore()
const { hasCurrentProject, currentProject } = useCurrentProject() const { hasCurrentProject, currentProjectId } = useCurrentProject()
/** 首页只展示当前项目最近几条 */ /** 首页只展示当前项目最近几条 */
const list = computed(() => { const list = computed(() => {
if (!hasCurrentProject.value) if (!hasCurrentProject.value || currentProjectId.value == null)
return [] return []
const projectId = currentProject.value?.id
return (db.warning_record || []) return (db.warning_record || [])
.filter(item => projectId == null || item.project_id === projectId) .filter(item => item.project_id === currentProjectId.value)
.slice(0, 3) .slice(0, 3)
}) })
onMounted(async () => { onMounted(async () => {
if (!db.warning_record?.length) if (!hasCurrentProject.value || currentProjectId.value == null)
await db.loadAll() return
await db.loadByProject(currentProjectId.value)
}) })
function goToWarningList() { function goToWarningList() {

View File

@@ -1,13 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { useCurrentProject } from '@/composables/useCurrentProject'
import { projectService } from '@/service' import { projectService } from '@/service'
import storage from '@/utils/storage' import { useDbStore } from '@/store/modules/db'
const PROJECT_KEY = 'current_project' const db = useDbStore()
const currentProject = storage.get(PROJECT_KEY) const { setCurrentProject, currentProjectId } = useCurrentProject()
const projectName = ref(currentProject?.project_name || '') const projectName = ref('')
const startEndStation = ref(currentProject?.stake_range || '') const startEndStation = ref('')
const totalArea = ref(currentProject?.total_area ? String(currentProject.total_area) : '') const totalArea = ref('')
async function handleSave() { async function handleSave() {
if (!projectName.value) { if (!projectName.value) {
@@ -16,21 +17,30 @@ async function handleSave() {
} }
try { try {
const id = await projectService.insert({ const payload = {
project_name: projectName.value, project_name: projectName.value,
stake_range: startEndStation.value, stake_range: startEndStation.value,
total_area: Number(totalArea.value) || 0, total_area: Number(totalArea.value) || 0,
status: 0, status: 0 as const,
}) }
// 保存到 storage // 始终新建项目,写入数据库
storage.set(PROJECT_KEY, { const id = await projectService.insert(payload)
id, if (!id) {
project_name: projectName.value, uni.showToast({ title: '保存失败:未获取到项目ID', icon: 'none' })
stake_range: startEndStation.value, return
total_area: Number(totalArea.value) || 0, }
status: 0,
}) // 写入 storage,后续业务按该项目 id 查询
const project = await projectService.selectById(id)
if (!project) {
uni.showToast({ title: '保存失败:项目不存在', icon: 'none' })
return
}
setCurrentProject(project)
await db.loadByProject(id)
console.log('id22222', id, 'currentProjectId.value', currentProjectId.value)
uni.showToast({ title: '保存成功', icon: 'success' }) uni.showToast({ title: '保存成功', icon: 'success' })
} }

View File

@@ -1,28 +1,49 @@
import type { Project } from '@/service/project'
import { onShow } from '@dcloudio/uni-app' import { onShow } from '@dcloudio/uni-app'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import storage from '@/utils/storage' import storage from '@/utils/storage'
const PROJECT_KEY = 'current_project' const PROJECT_KEY = 'current_project'
/** 模块级共享,保证各页面读到同一当前项目 */
const currentProject = ref<Partial<Project> | undefined>(storage.get(PROJECT_KEY))
/** /**
* 读取本地当前项目;无项目时首页/压实作业数据统一展示为 `--` * 读取本地当前项目;无项目时首页/压实作业数据统一展示为 `--`
* 有项目时,业务查询应以 currentProjectId 为条件
*/ */
export function useCurrentProject() { export function useCurrentProject() {
const currentProject = ref(storage.get(PROJECT_KEY)) const currentProjectId = computed(() => {
const id = currentProject.value?.id
return id == null ? null : Number(id)
})
const hasCurrentProject = computed(() => currentProject.value?.id != null) const hasCurrentProject = computed(() => currentProjectId.value != null && currentProjectId.value > 0)
function refreshCurrentProject() { function refreshCurrentProject() {
currentProject.value = storage.get(PROJECT_KEY) currentProject.value = storage.get(PROJECT_KEY)
} }
/** 写入 storage 并同步内存中的当前项目 */
function setCurrentProject(project: Partial<Project> | null | undefined) {
if (!project?.id) {
storage.remove(PROJECT_KEY)
currentProject.value = undefined
return
}
storage.set(PROJECT_KEY, project)
currentProject.value = project
}
onShow(() => { onShow(() => {
refreshCurrentProject() refreshCurrentProject()
}) })
return { return {
currentProject, currentProject,
currentProjectId,
hasCurrentProject, hasCurrentProject,
setCurrentProject,
refreshCurrentProject, refreshCurrentProject,
} }
} }

View File

@@ -38,6 +38,8 @@ const projects = computed(() => {
} }
return true return true
}) })
.slice()
.reverse()
.map(mapProjectItem) .map(mapProjectItem)
}) })

View File

@@ -68,14 +68,23 @@ export async function selectByStatus(status: 0 | 1): Promise<Project[]> {
return DB.selectByField(TABLE, 'status', status) return DB.selectByField(TABLE, 'status', status)
} }
/** 新增项目 */ /** 新增项目,返回新记录 id */
export async function insert(data: Omit<Project, 'id'>): Promise<number> { export async function insert(data: Omit<Project, 'id'>): Promise<number> {
await DB.insert(TABLE, { await DB.insert(TABLE, {
...data, ...data,
uncompacted_area: calcUncompactedArea(data.total_area, data.total_compaction_area), uncompacted_area: calcUncompactedArea(data.total_area, data.total_compaction_area),
}) })
const result = await DB.selectSql('SELECT last_insert_rowid() as id') const result = await DB.selectSql('SELECT last_insert_rowid() as id')
return result?.[0]?.id || 0 let id = Number(result?.[0]?.id) || 0
// 部分端上 last_insert_rowid 不稳定,回退取最新一条
if (!id) {
const latest = await DB.select(TABLE, '*', undefined, 'id DESC', 1)
id = Number(latest?.[0]?.id) || 0
}
return id
} }
/** 更新项目;标记为已完成(status=1)时清除该项目的作业记录与 RTK 轨迹 */ /** 更新项目;标记为已完成(status=1)时清除该项目的作业记录与 RTK 轨迹 */

View File

@@ -46,6 +46,15 @@ export async function selectByWorkRecordId(workRecordId: number): Promise<RtkTra
return DB.selectByField(TABLE, 'work_record_id', workRecordId) return DB.selectByField(TABLE, 'work_record_id', workRecordId)
} }
/** 按项目 ID 查询(通过 work_record 关联) */
export async function selectByProjectId(projectId: number): Promise<RtkTrack[]> {
return DB.selectSql(
`SELECT t.* FROM ${TABLE} t
INNER JOIN work_record w ON t.work_record_id = w.id
WHERE w.project_id = ${projectId}`,
)
}
/** 新增轨迹点 */ /** 新增轨迹点 */
export async function insert(data: RtkTrack): Promise<any> { export async function insert(data: RtkTrack): Promise<any> {
return DB.insert(TABLE, data) return DB.insert(TABLE, data)

View File

@@ -1,4 +1,4 @@
// 当日工作记录表 // 工作记录表
import DB from '@/utils/sqlite' import DB from '@/utils/sqlite'
const TABLE = 'work_record' const TABLE = 'work_record'

View File

@@ -20,6 +20,7 @@ import {
* import { useDbStore } from '@/store/modules/db' * import { useDbStore } from '@/store/modules/db'
* const db = useDbStore() * const db = useDbStore()
* await db.loadAll() * await db.loadAll()
* await db.loadByProject(projectId) // 按当前项目加载关联数据
* *
* db.project // 项目表 * db.project // 项目表
* db.work_record // 作业记录表 * db.work_record // 作业记录表
@@ -50,6 +51,25 @@ export const useDbStore = defineStore('db', () => {
history_report.value = historyReports history_report.value = historyReports
} }
/**
* 按项目加载关联数据(作业 / 轨迹 / 告警)
* 项目列表、历史报告始终全量加载,不按项目 id 过滤
*/
async function loadByProject(projectId: number) {
const [projects, workRecords, rtkTracks, warningRecords, historyReports] = await Promise.all([
projectService.selectAll(),
workRecordService.selectByProjectId(projectId),
rtkTrackService.selectByProjectId(projectId),
warningRecordService.selectByProjectId(projectId),
historyReportService.selectAll(),
])
project.value = projects
work_record.value = workRecords
rtk_track.value = rtkTracks
warning_record.value = warningRecords
history_report.value = historyReports
}
/** 按项目筛选作业记录 */ /** 按项目筛选作业记录 */
async function loadWorkRecordByProject(projectId: number) { async function loadWorkRecordByProject(projectId: number) {
work_record.value = await workRecordService.selectByProjectId(projectId) work_record.value = await workRecordService.selectByProjectId(projectId)
@@ -65,9 +85,9 @@ export const useDbStore = defineStore('db', () => {
warning_record.value = await warningRecordService.selectByProjectId(projectId) warning_record.value = await warningRecordService.selectByProjectId(projectId)
} }
/** 按项目筛选历史报告 */ /** 加载全部历史报告(不按项目过滤) */
async function loadHistoryReportByProject(projectId: number) { async function loadHistoryReportAll() {
history_report.value = await historyReportService.selectByProjectId(projectId) history_report.value = await historyReportService.selectAll()
} }
return { return {
@@ -77,9 +97,10 @@ export const useDbStore = defineStore('db', () => {
warning_record, warning_record,
history_report, history_report,
loadAll, loadAll,
loadByProject,
loadWorkRecordByProject, loadWorkRecordByProject,
loadRtkTrackByWorkRecord, loadRtkTrackByWorkRecord,
loadWarningByProject, loadWarningByProject,
loadHistoryReportByProject, loadHistoryReportAll,
} }
}) })