feat 接口api

This commit is contained in:
Ironsp
2026-09-23 10:52:28 +08:00
parent 59379dff79
commit 4ff3e92049
9 changed files with 198 additions and 33 deletions

7
.gitignore vendored
View File

@@ -6,12 +6,19 @@ yarn-debug.log*
yarn-error.log* yarn-error.log*
pnpm-debug.log* pnpm-debug.log*
lerna-debug.log* lerna-debug.log*
doc
node_modules node_modules
.DS_Store .DS_Store
dist dist
*.local *.local
.omo .omo
.clinerules
CLAUDE.md
.github
.vscode
.claude
.rtk
# Editor directories and files # Editor directories and files
.idea .idea

View File

@@ -90,6 +90,6 @@
"pre-commit": "pnpm lint-staged" "pre-commit": "pnpm lint-staged"
}, },
"lint-staged": { "lint-staged": {
"*": "eslint --fix" "*.{js,jsx,ts,tsx,mjs,cjs,mts,cts,vue}": "eslint --fix"
} }
} }

53
src/api/device/index.ts Normal file
View File

@@ -0,0 +1,53 @@
import type { ApiResult, AuthStatus } from '../types'
import { request } from '../request'
export interface DeviceAuthStatus {
deviceId: string
deviceName: string
authStatus: AuthStatus | string
startDate: string
endDate: string
remainingDays: number
}
export interface ActivateDeviceResult extends ApiResult {
endDate: string
deviceId: string
}
export interface RenewDeviceParams {
activationCode: string
deviceId: string
}
export interface RenewDeviceResult extends ApiResult {
endDate: string
deviceId: string
}
/** POST /api/device/activate 激活设备 */
export function activateDevice(params: { activationCode?: string, deviceId?: string }) {
return request<ActivateDeviceResult>({
url: '/api/device/activate',
method: 'POST',
params,
})
}
/** GET /api/device/status 查询设备授权状态 */
export function getDeviceStatus(deviceId?: string) {
return request<ApiResult<DeviceAuthStatus>>({
url: '/api/device/status',
method: 'GET',
params: deviceId ? { deviceId } : undefined,
})
}
/** POST /api/device/renew 续期 */
export function renewDevice(data: RenewDeviceParams) {
return request<RenewDeviceResult>({
url: '/api/device/renew',
method: 'POST',
data,
})
}

View File

98
src/api/report/index.ts Normal file
View File

@@ -0,0 +1,98 @@
import type { ApiResult, PageResult, ReportStatus } from '../types'
import { request } from '../request'
export interface ReportItem {
reportId: number
reportNo: string
deviceId: string
projectId: number
projectName: string
constructionSection: string
compactArea: number
qualificationRate: number
reportStatus: ReportStatus | string
workStartTime: string
workEndTime: string
workDuration?: number | null
avgAmplitude?: number | null
avgCompaction?: number | null
avgFrequency?: number | null
avgSpeed?: number | null
avgTemperature?: number | null
passCount?: number | null
exceptionCount?: number | null
conclusion?: string | null
filePath?: string | null
generateTime?: string | null
createBy?: string | null
createTime?: string | null
updateBy?: string | null
updateTime?: string | null
remark?: string | null
}
export interface UploadReportParams {
/** 本地文件路径(uni.uploadFile) */
filePath: string
deviceId: string
projectId: string
reportNo: string
workStartTime: string
workEndTime: string
compactArea: string
qualificationRate: string
constructionSection: string
}
/** GET /api/report/list 报告列表 */
export function getReportList(params?: Record<string, unknown>) {
return request<PageResult<ReportItem>>({
url: '/api/report/list',
method: 'GET',
params,
})
}
/** GET /api/report/{reportId} 报告详情 */
export function getReportDetail(reportId: number | string) {
return request<ApiResult<ReportItem>>({
url: `/api/report/${reportId}`,
method: 'GET',
})
}
/**
* POST /api/report/upload 上传报告文件
* 使用 uni.uploadFile,适用于 App / 小程序本地文件路径
*/
export function uploadReport(data: UploadReportParams) {
const baseURL = import.meta.env.VITE_API_BASE_URL || 'https://api.example.com'
return new Promise<ApiResult>((resolve, reject) => {
uni.uploadFile({
url: `${baseURL}/api/report/upload`,
filePath: data.filePath,
name: 'file',
formData: {
deviceId: data.deviceId,
projectId: data.projectId,
reportNo: data.reportNo,
workStartTime: data.workStartTime,
workEndTime: data.workEndTime,
compactArea: data.compactArea,
qualificationRate: data.qualificationRate,
constructionSection: data.constructionSection,
},
success: (res) => {
try {
const result = typeof res.data === 'string' ? JSON.parse(res.data) : res.data
resolve(result)
}
catch (e) {
reject(e)
}
},
fail: reject,
})
})
}

View File

@@ -2,47 +2,26 @@ import type { AxiosRequestConfig, AxiosResponse } from 'axios'
import { createUniAppAxiosAdapter } from '@uni-helper/axios-adapter' import { createUniAppAxiosAdapter } from '@uni-helper/axios-adapter'
import axios from 'axios' import axios from 'axios'
// 创建自定义实例
const instance = axios.create({ const instance = axios.create({
baseURL: 'https://api.example.com', // 你的基础域名 baseURL: import.meta.env.VITE_API_BASE_URL || 'https://api.example.com',
timeout: 10000, timeout: 10000,
adapter: createUniAppAxiosAdapter(), // 指定 uniapp 适配器 adapter: createUniAppAxiosAdapter(),
}) })
// 请求拦截器(守卫)
instance.interceptors.request.use(
(config) => {
// 例如:在这里统一添加 Token
// const token = uni.getStorageSync('token');
// if (token) config.headers.Authorization = `Bearer ${token}`;
return config
},
error => Promise.reject(error),
)
// 响应拦截器(守卫)
instance.interceptors.response.use( instance.interceptors.response.use(
(response: AxiosResponse) => { (response: AxiosResponse) => {
// 直接返回解包后的 data,这样调用时就不需要写 res.data.data 了
return response.data return response.data
}, },
// (error) => {
// // 统一错误处理
// uni.showToast({ title: error.message || '请求失败', icon: 'none' })
// return Promise.reject(error)
// },
(error: any) => { (error: any) => {
let { message } = error let { message } = error
if (message === 'Network Error') { if (message === 'Network Error')
message = '后端接口连接异常' message = '后端接口连接异常'
} else if (message?.includes('timeout'))
else if (message.includes('timeout')) {
message = '系统接口请求超时' message = '系统接口请求超时'
} else if (message?.includes('Request failed with status code'))
else if (message.includes('Request failed with status code')) {
message = `系统接口${message.substr(message.length - 3)}异常` message = `系统接口${message.substr(message.length - 3)}异常`
}
ElMessage({ message, type: 'error', duration: 5 * 1000 }) uni.showToast({ title: message || '请求失败', icon: 'none', duration: 3000 })
return Promise.reject(error) return Promise.reject(error)
}, },
) )

20
src/api/types.ts Normal file
View File

@@ -0,0 +1,20 @@
/** 通用接口响应 */
export interface ApiResult<T = unknown> {
code: number
msg: string
data?: T
}
/** 分页列表响应 */
export interface PageResult<T = unknown> {
code: number
msg: string
total: number
rows: T[]
}
/** 授权状态:0=未激活,1=已激活,2=已过期,3=已禁用 */
export type AuthStatus = '0' | '1' | '2' | '3'
/** 报告状态:0=已完成,1=有异常 */
export type ReportStatus = '0' | '1'

View File

@@ -23,22 +23,22 @@ defineProps<{
{{ avgSpeed }} {{ avgSpeed }}
</text> </text>
</view> </view>
<view class="detail-row"> <!-- <view class="detail-row">
<text class="detail-label"> <text class="detail-label">
平均振动频率 平均振动频率
</text> </text>
<text class="detail-value"> <text class="detail-value">
{{ avgFrequency }} {{ avgFrequency }}
</text> </text>
</view> </view> -->
<view class="detail-row"> <!-- <view class="detail-row">
<text class="detail-label"> <text class="detail-label">
平均振幅 平均振幅
</text> </text>
<text class="detail-value"> <text class="detail-value">
{{ avgAmplitude }} {{ avgAmplitude }}
</text> </text>
</view> </view> -->
<view class="detail-row"> <view class="detail-row">
<text class="detail-label"> <text class="detail-label">
平均摊铺温度 平均摊铺温度

8
src/env.d.ts vendored
View File

@@ -1 +1,9 @@
/// <reference types="vite/client" /> /// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_BASE_URL?: string
}
interface ImportMeta {
readonly env: ImportMetaEnv
}