瀏覽代碼

检验任务添加拍照点逻辑

zhangxike 1 周之前
父節點
當前提交
c7925d7066

+ 124 - 47
api/work.uts

@@ -1,5 +1,5 @@
 // #ifdef APP-ANDROID
-import { selectTableData, insertTableData, updateTableData, selectJoinTableData, selectRecordData, selectRecordInfo, selectLatestInfoData, deleteTableData, selectTaskInfo, selectLatestTaskData, selectTaskId } from '@/utils/sqlite'
+import { selectTableData, insertTableData, updateTableData, selectJoinTableData, selectRecordData, selectRecordInfo, selectLatestInfoData, deleteTableData, selectTaskInfo, selectLatestTaskData, selectTaskId, selectTaskDetail, selectTableDataByOrder } from '@/utils/sqlite'
 // #endif
 
 export type Download = {
@@ -69,11 +69,11 @@ export type RecordCalculate = {
 
 //检验任务
 export type TaskInfo = {
-	gxid : string, 
-	itemTitle: string,
+	gxid : string,
+	itemTitle : string,
 	photoitemStep : number,
-	photoitemTotal: number,
-	photoitemStatus: string,
+	photoitemTotal : number,
+	photoitemStatus : string,
 	recordStep : number,
 	recordTotal : number,
 	recordStatus : string,
@@ -101,6 +101,57 @@ export type TaskDownload = {
 	uploadflag : number
 }
 
+export type TaskDetail = {
+	pdid: string,
+	gxno: string,
+	photoTotal: number,
+	photoCount: number,
+	photoStatus: string,
+	keyTotal: number,
+	keyCount: number,
+	keyStatus: string,
+	recordTotal: number,
+	recordCount: number,
+	recordStatus: string,
+}
+
+export type TaskPhoto = {
+	sxid : number,
+	pdid : number,
+	senum: number,
+	photographpoint : string,
+	photographdescription : string,
+	photourl : string,
+	photourlSpl : string[],
+	imgname : string[],
+	exampleurl : string,
+	exampleurlSpl : string[],
+	photoname : string,
+	fk_qcRecord : string,
+	fk_prodcode : string,
+	prodno : string,
+	processStep ?: string,
+}
+
+export type TaskJoinRecord = {
+	sxid : number,
+	pdid : number,
+	photographpoint : string,
+	photographdescription : string,
+	photourl ?: string,
+	photourlSpl ?: string[],
+	imgname : string,
+	exampleurl ?: string,
+	exampleurlSpl ?: string[],
+	photoname ?: string,
+	fk_qcRecord ?: string,
+	fk_prodcode ?: string,
+	prodno ?: string,
+	processStep ?: string,
+	workorder : string,
+	invname : string,
+}
+
 export function offlineData(data : UTSJSONObject) : Promise<UTSJSONObject> {
 	return new Promise((resolve, reject) => {
 		let result = JSON.parseObject(JSON.stringify(data)) as UTSJSONObject
@@ -111,7 +162,7 @@ export function offlineData(data : UTSJSONObject) : Promise<UTSJSONObject> {
 export const statusDict = { '1': '未执行', '2': '执行中', '3': '已执行', '4': '执行错误', '5': '已取消' }
 export const recordStatusDict = { '1': '未拍照', '2': '拍照中', '3': '拍照完成', '4': '检验不清晰', '5': '拍照取消' }
 export const taskType = { '1': '检测任务', '2': '关键工序任务' }
-export const funcType = {'1': '新增', '2': '更新', '3': '删除'}
+export const funcType = { '1': '新增', '2': '更新', '3': '删除' }
 //export const moduleType = {'1': '声像记录', '2':'检验任务', '3':'关键工序','4': '系统管理','5':'其它'}
 
 export async function getList(tableName : string, condition ?: string | null, value ?: string | null, condition2 ?: string | null, value2 ?: string | null, initData ?: UTSJSONObject | null) : Promise<UTSJSONObject> {
@@ -143,7 +194,7 @@ export async function updateData(tableName : string, data : string, lname ?: str
 	// #ifdef APP-ANDROID
 	const result = await updateTableData(tableName, data, lname, lvalue);
 	console.log(result);
-	addLog({module:tableName,dataid:lvalue,content:'更新数据',status:result?.['errMsg']==='ok'?1:0,params:data})
+	addLog({ module: tableName, dataid: lvalue, content: '更新数据', status: result?.['errMsg'] === 'ok' ? 1 : 0, params: data })
 	return result;
 	// #endif
 }
@@ -195,11 +246,11 @@ export async function saveMediaInfo(data ?: UTSJSONObject | null) : Promise<UTSJ
 		// 调用sqlite的插入方法
 		const result = await insertTableData(tableName, values, fields);
 		console.log('保存app_media_info成功:', result);
-		addLog({module:tableName,dataid:0,content:'保存媒体信息',status:1,params:values})
+		addLog({ module: tableName, dataid: 0, content: '保存媒体信息', status: 1, params: values })
 		return result;
 	} catch (error) {
 		console.error('保存app_media_info失败:', error);
-		addLog({module:tableName,dataid:0,content:'保存媒体信息失败',status:0,params:values})	
+		addLog({ module: tableName, dataid: 0, content: '保存媒体信息失败', status: 0, params: values })
 		return { errMsg: '保存失败', data: [] as any[] } as UTSJSONObject;
 	}
 	// #endif
@@ -226,11 +277,11 @@ export async function saveMediaRecord(values : string) : Promise<UTSJSONObject>
 		// 调用sqlite的插入方法
 		const result = await insertTableData(tableName, values, fields);
 		console.log('保存app_media_record成功:', result);
-		addLog({module:tableName,dataid:0,content:'保存媒体记录',status:1,params:values})
+		addLog({ module: tableName, dataid: 0, content: '保存媒体记录', status: 1, params: values })
 		return result;
 	} catch (error) {
 		console.error('保存app_media_record失败:', error);
-		addLog({module:tableName,dataid:0,content:'保存媒体记录失败',status:0,params:values})		
+		addLog({ module: tableName, dataid: 0, content: '保存媒体记录失败', status: 0, params: values })
 		return { errMsg: '保存失败', data: [] as any[] } as UTSJSONObject;
 	}
 	// #endif
@@ -241,7 +292,7 @@ export async function saveMediaRecord(values : string) : Promise<UTSJSONObject>
 }
 
 
-export async function getLatestRecord(productNo:string , initData ?: UTSJSONObject | null) : Promise<UTSJSONObject> {
+export async function getLatestRecord(productNo : string, initData ?: UTSJSONObject | null) : Promise<UTSJSONObject> {
 	// #ifdef APP-ANDROID
 	const result = await selectLatestInfoData(productNo);
 	console.log(result);
@@ -253,18 +304,18 @@ export async function getLatestRecord(productNo:string , initData ?: UTSJSONObje
 	// #endif
 }
 
-export async function removeTableData(tableName:string, field: string, value: string) : Promise<UTSJSONObject> {
+export async function removeTableData(tableName : string, field : string, value : string) : Promise<UTSJSONObject> {
 	// #ifdef APP-ANDROID
 
 	try {
 		// 调用sqlite的删除方法
 		const result = await deleteTableData(tableName, field, value);
 		console.log('删除数据成功:', result);
-		addLog({module:tableName,dataid:1,content:'删除数据成功',status:1,params:value})		
+		addLog({ module: tableName, dataid: 1, content: '删除数据成功', status: 1, params: value })
 		return result;
 	} catch (error) {
 		console.error('删除数据失败:', error);
-		addLog({module:tableName,dataid:1,content:'删除数据失败',status:0,params:value})
+		addLog({ module: tableName, dataid: 1, content: '删除数据失败', status: 0, params: value })
 		return { errMsg: '删除失败', data: [] as any[] } as UTSJSONObject;
 	}
 	// #endif
@@ -275,24 +326,24 @@ export async function removeTableData(tableName:string, field: string, value: st
 }
 
 
-export async function removeInfoAndRecord(value:string) : Promise<UTSJSONObject> {
+export async function removeInfoAndRecord(value : string) : Promise<UTSJSONObject> {
 	// #ifdef APP-ANDROID
-	
+
 	try {
 		// 调用sqlite的删除方法
 		const result = await deleteTableData('app_media_record', 'pid', value);
-		addLog({module:'app_media_record',dataid:1,content:'删除数据成功',status:1,params:value,updatetime: "strftime('%Y-%m-%d %H:%M:%S', 'now')"})
-		
+		addLog({ module: 'app_media_record', dataid: 1, content: '删除数据成功', status: 1, params: value, updatetime: "strftime('%Y-%m-%d %H:%M:%S', 'now')" })
+
 		const result2 = await deleteTableData('app_media_info', 'pdid', value);
-		addLog({module:'app_media_info',dataid:1,content:'删除数据成功',status:1,params:value})
+		addLog({ module: 'app_media_info', dataid: 1, content: '删除数据成功', status: 1, params: value })
 		return result;
 	} catch (error) {
 		console.error('删除数据失败:', error);
-		addLog({module:'app_media_record',dataid:1,content:'删除数据失败',status:0,params:value})
+		addLog({ module: 'app_media_record', dataid: 1, content: '删除数据失败', status: 0, params: value })
 		return { errMsg: '删除失败', data: [] as any[] } as UTSJSONObject;
 	}
 	// #endif
-	
+
 	// #ifdef H5
 	return offlineData({ success: true, data: [] } as UTSJSONObject);
 	// #endif
@@ -303,16 +354,16 @@ export async function addLog(data ?: UTSJSONObject | null) : Promise<UTSJSONObje
 	// #ifdef APP-ANDROID
 	const params = data?.getString('params')?.replace(/['"]/g, '')
 	const dataid = data?.getNumber('dataid') ?? 0
-	let fields = 'module,dataid,content,status,params';	
+	let fields = 'module,dataid,content,status,params';
 	let values = `'${data?.getString('module') ?? ''}',${data?.getNumber('dataid') ?? 0},'${data?.getString('content') ?? ''}',${data?.getNumber('status') ?? 0},'${params}'`;
-	if(dataid === 0){
+	if (dataid === 0) {
 		fields = fields + ",createuser,createtime"
 		values = values + `,'${data?.getString('createuser') ?? 0}',strftime('%Y-%m-%d %H:%M:%S', 'now')`
-	}else{
+	} else {
 		fields = fields + ",updateuser,updatetime"
 		values = values + `,'${data?.getString('updateuser') ?? 0}',strftime('%Y-%m-%d %H:%M:%S', 'now')`
 	}
-	
+
 	const result = await insertTableData(tableName, values, fields);
 	console.log(result);
 	return result;
@@ -338,11 +389,11 @@ export async function saveTaskInfo(data ?: UTSJSONObject | null) : Promise<UTSJS
 		// 调用sqlite的插入方法
 		const result = await insertTableData(tableName, values, fields);
 		console.log('保存app_task_info成功:', result);
-		addLog({module:tableName,dataid:0,content:'保存检验任务信息成功',status:1,params:values})
+		addLog({ module: tableName, dataid: 0, content: '保存检验任务信息成功', status: 1, params: values })
 		return result;
 	} catch (error) {
 		console.error('保存app_task_info失败:', error);
-		addLog({module:tableName,dataid:0,content:'保存检验任务信息失败',status:0,params:values})	
+		addLog({ module: tableName, dataid: 0, content: '保存检验任务信息失败', status: 0, params: values })
 		return { errMsg: '保存失败', data: [] as any[] } as UTSJSONObject;
 	}
 	// #endif
@@ -370,11 +421,11 @@ export async function saveTaskPhoto(values : string) : Promise<UTSJSONObject> {
 		// 调用sqlite的插入方法
 		const result = await insertTableData(tableName, values, fields);
 		console.log('保存app_task_photo成功:', result);
-		addLog({module:tableName,dataid:0,content:'保存任务图像记录',status:1,params:values})
+		addLog({ module: tableName, dataid: 0, content: '保存任务图像记录', status: 1, params: values })
 		return result;
 	} catch (error) {
 		console.error('保存app_task_photo失败:', error);
-		addLog({module:tableName,dataid:0,content:'保存任务图像记录失败',status:0,params:values})		
+		addLog({ module: tableName, dataid: 0, content: '保存任务图像记录失败', status: 0, params: values })
 		return { errMsg: '保存失败', data: [] as any[] } as UTSJSONObject;
 	}
 	// #endif
@@ -414,11 +465,11 @@ export async function saveTaskKeyProcess(data ?: UTSJSONObject | null) : Promise
 		// 调用sqlite的插入方法
 		const result = await insertTableData(tableName, values, fields);
 		console.log('保存app_task_info成功:', result);
-		addLog({module:tableName,dataid:0,content:'保存检验任务信息成功',status:1,params:values})
+		addLog({ module: tableName, dataid: 0, content: '保存检验任务信息成功', status: 1, params: values })
 		return result;
 	} catch (error) {
 		console.error('保存app_task_info失败:', error);
-		addLog({module:tableName,dataid:0,content:'保存检验任务信息失败',status:0,params:values})	
+		addLog({ module: tableName, dataid: 0, content: '保存检验任务信息失败', status: 0, params: values })
 		return { errMsg: '保存失败', data: [] as any[] } as UTSJSONObject;
 	}
 	// #endif
@@ -444,11 +495,11 @@ export async function saveTaskRecord(data ?: UTSJSONObject | null) : Promise<UTS
 		// 调用sqlite的插入方法
 		const result = await insertTableData(tableName, values, fields);
 		console.log('保存app_task_record成功:', result);
-		addLog({module:tableName,dataid:0,content:'保存检验任务记录信息成功',status:1,params:values})
+		addLog({ module: tableName, dataid: 0, content: '保存检验任务记录信息成功', status: 1, params: values })
 		return result;
 	} catch (error) {
 		console.error('保存app_task_record失败:', error);
-		addLog({module:tableName,dataid:0,content:'保存检验任务记录信息失败',status:0,params:values})	
+		addLog({ module: tableName, dataid: 0, content: '保存检验任务记录信息失败', status: 0, params: values })
 		return { errMsg: '保存失败', data: [] as any[] } as UTSJSONObject;
 	}
 	// #endif
@@ -475,11 +526,11 @@ export async function saveTaskRecordItem(data ?: UTSJSONObject | null) : Promise
 		// 调用sqlite的插入方法
 		const result = await insertTableData(tableName, values, fields);
 		console.log('保存app_task_record_item成功:', result);
-		addLog({module:tableName,dataid:0,content:'保存检验任务项目信息成功',status:1,params:values})
+		addLog({ module: tableName, dataid: 0, content: '保存检验任务项目信息成功', status: 1, params: values })
 		return result;
 	} catch (error) {
 		console.error('保存app_task_record_item失败:', error);
-		addLog({module:tableName,dataid:0,content:'保存检验任务项目信息失败',status:0,params:values})	
+		addLog({ module: tableName, dataid: 0, content: '保存检验任务项目信息失败', status: 0, params: values })
 		return { errMsg: '保存失败', data: [] as any[] } as UTSJSONObject;
 	}
 	// #endif
@@ -490,7 +541,7 @@ export async function saveTaskRecordItem(data ?: UTSJSONObject | null) : Promise
 }
 
 
-export async function getLatestTask(productNo:string, initData ?: UTSJSONObject | null) : Promise<UTSJSONObject> {
+export async function getLatestTask(productNo : string, initData ?: UTSJSONObject | null) : Promise<UTSJSONObject> {
 	// #ifdef APP-ANDROID
 	const result = await selectLatestTaskData(productNo);
 	console.log(result);
@@ -502,33 +553,59 @@ export async function getLatestTask(productNo:string, initData ?: UTSJSONObject
 	// #endif
 }
 
-export async function removeTaskAndRecord(value:string) : Promise<UTSJSONObject> {
+export async function removeTaskAndRecord(value : string) : Promise<UTSJSONObject> {
 	// #ifdef APP-ANDROID
-	
+
 	try {
 		// 调用sqlite的删除方法
 		const taskId = await selectTaskId('app_task_info', 'pdid', 'gxpk', value);
 		const result = await deleteTableData('app_task_info', 'pdid', taskId);
-		addLog({module:'app_task_info',dataid:1,content:'删除数据成功',status:1,params:value,updatetime: "strftime('%Y-%m-%d %H:%M:%S', 'now')"})
-		
+		addLog({ module: 'app_task_info', dataid: 1, content: '删除数据成功', status: 1, params: value, updatetime: "strftime('%Y-%m-%d %H:%M:%S', 'now')" })
+
 		const result2 = await deleteTableData('app_task_photo', 'pdid', taskId);
-		addLog({module:'app_task_photo',dataid:1,content:'删除数据成功',status:1,params:value})
+		addLog({ module: 'app_task_photo', dataid: 1, content: '删除数据成功', status: 1, params: value })
 
 		const recordId = await selectTaskId('app_task_record', 'sxid', 'pdid', taskId);
 		const result3 = await deleteTableData('app_task_record_item', 'psxid', recordId);
-		addLog({module:'app_task_record_item',dataid:1,content:'删除数据成功',status:1,params:value})
-		
+		addLog({ module: 'app_task_record_item', dataid: 1, content: '删除数据成功', status: 1, params: value })
+
 		const result4 = await deleteTableData('app_task_record', 'sxid', recordId);
-		addLog({module:'app_task_record',dataid:1,content:'删除数据成功',status:1,params:value})
+		addLog({ module: 'app_task_record', dataid: 1, content: '删除数据成功', status: 1, params: value })
 		return {};
 	} catch (error) {
 		console.error('删除数据失败:', error);
-		addLog({module:'app_media_record',dataid:1,content:'删除数据失败',status:0,params:value})
+		addLog({ module: 'app_media_record', dataid: 1, content: '删除数据失败', status: 0, params: value })
 		return { errMsg: '删除失败', data: [] as any[] } as UTSJSONObject;
 	}
 	// #endif
-	
+
 	// #ifdef H5
 	return offlineData({ success: true, data: [] } as UTSJSONObject);
 	// #endif
+}
+
+export async function getTaskDetail(field ?: string | null, value ?: string | null) : Promise<UTSJSONObject> {
+
+	// #ifdef APP-ANDROID
+	const result = await selectTaskDetail(field, value);
+	console.log(result);
+	return result;
+	// #endif
+
+	// #ifdef H5
+	return offlineData({ success: true, data: [] } as UTSJSONObject)
+	// #endif
+}
+
+export async function getListByOrder(tableName : string, condition ?: string | null, value ?: string | null, order ?:string | null, initData ?: UTSJSONObject | null) : Promise<UTSJSONObject> {
+
+	// #ifdef APP-ANDROID
+	const result = await selectTableDataByOrder(tableName, condition, value, null, null, order);
+	console.log(result);
+	return result;
+	// #endif
+
+	// #ifdef H5
+	return offlineData(initData)
+	// #endif
 }

+ 47 - 87
pages/work/download/DownloadDetail.uvue

@@ -15,24 +15,24 @@
 		</view>
 
 		<view class="section">
-			<uni-table v-for="(item,index) in demoData" :key="index">
+			<uni-table v-for="(item,index) in taskProcessList" :key="index">
 				<uni-tr>
-					<uni-td class="grid-text">{{item.itemTitle}}</uni-td>
+					<uni-td class="grid-text">{{item.gxno}}</uni-td>
 				</uni-tr>
-				<uni-tr class="section-title" @click="enterItem(item.gxid, 0)">
+				<uni-tr class="section-title" @click="enterItem(item.pdid, 0)">
 					<uni-td class="grid-text">拍照点</uni-td>
-					<uni-td class="grid-text">{{item.photoitemStep}} / {{item.photoitemTotal}}</uni-td>
-					<uni-td class="grid-text">{{item.photoitemStatus}}</uni-td>
+					<uni-td class="grid-text">{{item.photoCount}} / {{item.photoTotal}}</uni-td>
+					<uni-td class="grid-text">{{item.photoStatus}}</uni-td>
 				</uni-tr>
-				<uni-tr class="section-title" @click="enterItem(item.gxid, 1)">
+				<uni-tr class="section-title" @click="enterItem(item.pdid, 1)">
 					<uni-td class="grid-text">检验记录</uni-td>
-					<uni-td class="grid-text">{{item.recordStep}} / {{item.recordTotal}}</uni-td>
+					<uni-td class="grid-text">{{item.recordCount}} / {{item.recordTotal}}</uni-td>
 					<uni-td class="grid-text">{{item.recordStatus}}</uni-td>
 				</uni-tr>
-				<uni-tr class="section-title" @click="enterItem(item.gxid, 2)">
+				<uni-tr class="section-title" @click="enterItem(item.pdid, 2)">
 					<uni-td class="grid-text">关键工序记录</uni-td>
-					<uni-td class="grid-text">{{item.keypointStep}} / {{item.keypointTotal}}</uni-td>
-					<uni-td class="grid-text">{{item.keypointStatus}}</uni-td>
+					<uni-td class="grid-text">{{item.keyCount}} / {{item.keyTotal}}</uni-td>
+					<uni-td class="grid-text">{{item.keyStatus}}</uni-td>
 				</uni-tr>
 			</uni-table>
 		</view>
@@ -47,71 +47,32 @@
 		ref,
 		onMounted
 	} from 'vue'
-	import { getList, TaskDownload, TaskProcess, getRecordCalculate, RecordCalculate, statusDict, TaskInfo } from '@/api/work';
+	import { getList, TaskDownload, statusDict, TaskInfo, getTaskDetail, TaskDetail } from '@/api/work';
+	
+	//自定义返回行为,覆盖系统默认返回按钮
+	const backPressOptions = reactive({
+		from: 'backbutton'
+	} as OnBackPressOptions)
+	
+	onBackPress((options : OnBackPressOptions) : boolean | null => {
+		console.log('onBackPress', options)
+		uni.navigateTo({
+			url: `/pages/work/download/DownloadList`,
+			// 修改动画方向为从左到右退回
+			animationType: 'slide-in-left', // 使用从左到右滑出的动画效果
+			animationDuration: 300 // 动画持续时间,单位ms
+		})
+		// 返回true表示拦截默认返回行为
+		return true
+	})
 
 	const titleList = [{
 		title1: "部位", title2: "进度", title3: "状态"
 	}];
-	var taskProcessList = ref<RecordCalculate[]>([]);
-	var initTasks = [] as RecordCalculate[]
+	var taskProcessList = ref<TaskDetail[]>([]);
+	var initTasks = [] as TaskDetail[]
 	//const statusMap = ref(new Map<number, string>([[1,'未执行'],[2,'执行中'],[3,'执行完'],[4,'检验失败']]))
 	
-	var demoData = ref<TaskInfo[]>([]);
-	demoData.value = [
-		{
-			gxid: '1',
-			itemTitle : '20-检验',
-			photoitemStep : 10,
-			photoitemTotal: 10,
-			photoitemStatus : '',
-			recordStep : 5,
-			recordTotal : 5,
-			recordStatus : '不合格',
-			keypointStep : 4,
-			keypointTotal : 4,
-			keypointStatus : ''
-		} as TaskInfo,
-		{
-			gxid: '2',
-			itemTitle : '50-检验',
-			photoitemStep : 2,
-			photoitemTotal: 5,
-			photoitemStatus : '',
-			recordStep : 2,
-			recordTotal : 11,
-			recordStatus : '',
-			keypointStep : 3,
-			keypointTotal : 4,
-			keypointStatus : ''
-		} as TaskInfo,
-		{
-			gxid: '3',
-			itemTitle : '80-检验',
-			photoitemStep : 2,
-			photoitemTotal: 5,
-			photoitemStatus : '',
-			recordStep : 2,
-			recordTotal : 11,
-			recordStatus : '',
-			keypointStep : 3,
-			keypointTotal : 4,
-			keypointStatus : ''
-		} as TaskInfo,
-		{
-			gxid: '4',
-			itemTitle: '100-总检',
-			photoitemStep: 0,
-			photoitemTotal: 5,
-			photoitemStatus: '',
-			recordStep: 0,
-			recordTotal: 13,
-			recordStatus: '',
-			keypointStep: 0,
-			keypointTotal: 4,
-			keypointStatus: ''
-		} as TaskInfo
-	]
-	
 	const download = ref<TaskDownload>({
 		pdid : 0,
 		gxpk : '',
@@ -149,23 +110,22 @@
          				} 
          	 })
 			 
-			 // //获取下载产品任务数据
-			 // getRecordCalculate('app_product_points', downloadId, null).then((res:UTSJSONObject) => {
-			 //  		console.log(res)
-			 // 			let dataList = res?.['data'] as UTSJSONObject[] ?? Array<UTSJSONObject>()
-			 // 			if(dataList!=null && dataList.length>0){							
-			 // 				dataList.forEach(item =>{
-			 // 					if(item!=null){
-			 // 						let task = JSON.parse<RecordCalculate>(item.toJSONString());
-			 // 						if(task!=null){
-			 // 							initTasks.push(task)
-			 // 						}
-			 // 					}
-			 // 				});
-			 // 			} 
-				//    console.log(initTasks)
-				//    taskProcessList.value = initTasks
-			 //  })
+			 //获取下载产品任务数据
+			 getTaskDetail('pdid', downloadId).then((res:UTSJSONObject) => {
+			  		console.log(res)
+			 			let dataList = res?.['data'] as UTSJSONObject[] ?? Array<UTSJSONObject>()
+			 			if(dataList!=null && dataList.length>0){							
+			 				dataList.forEach(item =>{
+			 					if(item!=null){
+			 						let task = JSON.parse<TaskDetail>(item.toJSONString());
+			 						if(task!=null){
+			 							initTasks.push(task)
+			 						}
+			 					}
+			 				});
+			 			} 
+				   taskProcessList.value = initTasks
+			  })
 			 
         // #endif
 	})
@@ -177,7 +137,7 @@
 	const enterItem = (id : string, type : number) => {
 		let url = ''
 	  if (type == 0) {
-		  url = `/pages/work/download/PhotoRecord`
+		  url = `/pages/work/download/PhotoRecord?pdid=${id}`
 	  }	else if (type == 1) {
 		  url = `/pages/work/report/InspectionList`
 	  } else if (type == 2) {

+ 55 - 116
pages/work/download/PhotoRecord.uvue

@@ -4,10 +4,8 @@
 			<view class="tag-circle" v-for="(item, index) in initRecords" :key="index" @click="tabsClick(item.senum)"
 				:class="{'checked-tag' : item.senum == current}">
 				<text class="circle" :class="{
-								'bg-green': item.status == 3,
-								'bg-yellow': item.status == 2,
-								'bg-red': item.status == 4,
-								'bg-black': item.status == 1
+								'bg-green': item.photourlSpl.length > 0,
+								'bg-black': item.photourlSpl.length == 0
 							  }">{{item.senum}}</text>
 			</view>
 		</view>
@@ -21,54 +19,43 @@
 			<view class="header-row">
 				<text class="label">序号:</text>
 				<text class="value">{{ item.senum }}</text>
-				<text class="status"
-					:class="{'status-cancelled': item.status === 5, 'bg-red': item.status == 4}">{{ recordStatusDict[item.status.toString()] }}</text>
+				<text class="status"></text>
 			</view>
 
 			<view class="info-row">
 				<text class="label">产品码:</text>
-				<text class="value">{{ item.productno }}</text>
+				<text class="value">{{ item.prodno }}</text>
 			</view>
 
 			<view class="info-row">
 				<text class="label">拍照点:</text>
-				<text class="value">{{ item.part }}</text>
+				<text class="value">{{ item.processStep }}</text>
 			</view>
 
 			<view class="info-row">
 				<text class="label">拍照位置:</text>
-				<text class="value">{{ item.photoitem }}</text>
+				<text class="value">{{ item.photographpoint }}</text>
 			</view>
 
 			<view class="info-row">
 				<text class="label">描述:</text>
-				<text class="value">{{ item.descb }}</text>
+				<text class="value">{{ item.photographdescription }}</text>
 			</view>
 
-			<view class="info-row">
-				<text class="label">位置编号:</text>
-				<text class="value">{{ item.partno }}</text>
-			</view>
-
-			<view class="info-row">
-				<text class="label">数量:</text>
-				<text class="value">{{ item.num }}</text>
-			</view>
-
-			<button class="cancel-btn" v-if="item.status == 1 || item.status == 2" @click="cancel(item.sxid, item.num)">
+			<button class="cancel-btn" @click="cancel(item.sxid)">
 				拍照
 			</button>
 
-			<view class="tag-banner" style="">
-				<view class="tag-banner" v-for="(tag,index) in item.imgname" :key="index" v-if="item.imgname.length>0">
-					<text class="img-banner" v-if="item.imgname[index]!=''&& closeTags[index]"
+			<view class="tag-banner" style="" v-if="item.imgname.length > 0">
+				<view class="tag-banner" v-for="(tag,index) in item.imgname" :key="index" >
+					<text class="img-banner" v-if="item.imgname.length > 0 && closeTags[index]"
 						@click="closeTag(index)">{{tag}}</text>
 				</view>
 
 			</view>
 			<view class="my-page">
-				<swiper class="swiper-box my-swiper" :current="0" :indicator-dots="true" v-if="item.urlpdt.length>0">
-					<swiper-item v-for="(url, index) in item.urlpdt" :key="index" @tap="preview(uni.env.USER_DATA_PATH+url)">
+				<swiper class="swiper-box my-swiper" :current="0" :indicator-dots="true" v-if="item.photourlSpl.length>0">
+					<swiper-item v-for="(url, index) in item.photourlSpl" :key="index" @tap="preview(uni.env.USER_DATA_PATH+url)">
 						<view class="swiper-item ">
 							<image class="my-image" :src="uni.env.USER_DATA_PATH+url" mode="aspectFill" />
 						</view>
@@ -79,15 +66,15 @@
 				</swiper>
 
 				<swiper class="swiper-box my-swiper mg-top" :current="0" :indicator-dots="true"
-					v-if="item.urlspl.length>0">
-					<swiper-item v-for="(url, index) in item.urlspl" :key="index" @tap="preview(url)">
+					v-if="item.exampleurlSpl.length>0">
+					<swiper-item v-for="(url, index) in item.exampleurlSpl" :key="index" @tap="preview(url)">
 						<view class="swiper-item ">
 							<image class="my-image" :src="url" mode="aspectFill" />
 						</view>
 					</swiper-item>
 				</swiper>
 
-				<view v-if="item.urlspl">
+				<view v-if="item.exampleurl">
 					<text class="demo-view-label">样张</text>
 				</view>
 			</view>
@@ -112,7 +99,7 @@
 	import {
 		ref
 	} from 'vue'
-	import { getList, Record, recordStatusDict, updateData } from '@/api/work';
+	import { getListByOrder, TaskPhoto, recordStatusDict, updateData } from '@/api/work';
 
 	// 存储页面参数
 	let photoitem = "";
@@ -127,7 +114,7 @@
 	onBackPress((options : OnBackPressOptions) : boolean | null => {
 		console.log('onBackPress', options)
 		uni.navigateTo({
-			url: `/pages/work/record/InfoDetail?id=${pid}`,
+			url: `/pages/work/download/DownloadDetail?id=${pid}`,
 			// 修改动画方向为从左到右退回
 			animationType: 'slide-in-left', // 使用从左到右滑出的动画效果
 			animationDuration: 300 // 动画持续时间,单位ms
@@ -139,50 +126,55 @@
 	//检查项目最大数量
 	var maxcount = 5
 	var current = ref(1)
-	var records = ref<Record[]>([]);
+	var records = ref<TaskPhoto[]>([]);
 	const closeTags = ref<boolean[]>([]);
-	var initRecords = [] as Record[]
+	var initRecords = [] as TaskPhoto[]
 
 	// 定义数据刷新函数
 	const refreshRecords = (index : number) => {
 		// 清空现有数据
 		initRecords = [];
 		closeTags.value = [];
-
+		console.log(pid)
 		// #ifdef APP-ANDROID
-		getList('app_media_record', 'photoitem', photoitem, 'pid', pid, null).then((res : UTSJSONObject) => {
+		getListByOrder('app_task_photo', 'pdid', pid, ' order by sxid desc', null).then((res : UTSJSONObject) => {
 			let dataList = res?.['data'] as UTSJSONObject[] ?? Array<UTSJSONObject>()
 			if (dataList != null && dataList.length > 0) {
+				console.log(dataList);
+				let index = 1
 				dataList.forEach(item => {
 					if (item != null) {
 						const imgnameStr = item?.['imgname'] as string ?? ''
-						const urlpdtStr = item?.['urlpdt'] as string ?? ''
-						const urlsplStr = item?.['urlspl'] as string ?? ''
+						const photourlStr = item?.['photourl'] as string ?? ''
+						const exampleurlStr = item?.['exampleurl'] as string ?? ''
 						const imgnameArr = imgnameStr.indexOf(",") > -1 ? imgnameStr.split(",") : (imgnameStr != '' ? [imgnameStr] : [])
-						const urlpdtArr = urlpdtStr.indexOf(",") > -1 ? urlpdtStr.split(",") : (urlpdtStr != '' ? [urlpdtStr] : [])
-						const urlsplArr = urlsplStr.indexOf(",") > -1 ? urlsplStr.split(",") : (urlsplStr != '' ? [urlsplStr] : [])
+						const photourlArr = photourlStr.indexOf(",") > -1 ? photourlStr.split(",") : (photourlStr != '' ? [photourlStr] : [])
+						const exampleurlArr = exampleurlStr.indexOf(",") > -1 ? exampleurlStr.split(",") : (exampleurlStr != '' ? [exampleurlStr] : [])
 						item['imgname'] = imgnameArr
-						item['urlpdt'] = urlpdtArr
-						item['urlspl'] = urlsplArr
-						let record = JSON.parse<Record>(item.toJSONString());
+						item['photourlSpl'] = photourlArr
+						item['exampleurlSpl'] = exampleurlArr
+						item['senum'] = index
+						let record = JSON.parse<TaskPhoto>(item.toJSONString());
 						if (record != null) {
-							for (let i : Int = 0; i < record.num; i++) {
-								closeTags.value.push(true)
-							}
 							initRecords.push(record)
+							// 为每个图片初始化closeTags值为true,表示默认显示
+							if (record.imgname != null && record.imgname.length > 0) {
+								for (let i = 0; i < record.imgname.length; i++) {
+									closeTags.value.push(true);
+								}
+							}
+							index++
 						}
 					}
 				});
+				maxcount = index-1;
 			}
 			if (initRecords.length > 0) {
-				console.log(initRecords)
-				console.log(index)
 				if (index > 0) {
 					current.value = index
 				} else {
 					current.value = initRecords[0].senum
 				}
-				console.log(current.value)
 				records.value = initRecords.filter(item => item['senum'] == current.value)
 				console.log(records)
 			}
@@ -194,64 +186,20 @@
 
 	onLoad((options) => {
 		photoitem = options?.photoitem ?? ""
-		const num = options?.num ?? "1"
-		pid = options?.pid ?? "1"
+		pid = options?.pdid ?? "1"
 		senum = options?.senum ?? "1"
-		maxcount = parseInt(num)
-
+		
 		// 加载初始数据
 		refreshRecords(parseInt(senum));
 	});
 
-
-	// #ifdef H5
-	initRecords = [{
-		sxid: 1,
-		senum: 1,
-		photoitem: '前底-外侧',
-		productno: 'YH0001',
-		part: '角焊缝',
-		descb: '角片角焊缝',
-		date: '2025-06-05',
-		partno: 'TD10-01',
-		num: 2,
-		status: '未执行',
-		urlspl: ['/static/images/demo.png'],
-		imgname: ['1.jpg', '2.jpg'],
-		urlpdt: ['/static/images/demo.png', '/static/images/demo.png']
-	},
-	{
-		sxid: 2,
-		senum: 2,
-		photoitem: '后底-外侧',
-		productno: 'YH0002',
-		part: '角焊缝',
-		descb: '角片角焊缝',
-		date: '2025-06-05',
-		partno: 'TD10-02',
-		num: 3,
-		status: '未执行',
-		urlspl: ['/static/images/demo.png'],
-		imgname: ['1.jpg', '2.jpg', '3.jpg'],
-		urlpdt: ['/static/images/demo.png', '/static/images/demo.png', '/static/images/demo.png']
-	}] as Record[];
-	records.value = initRecords.filter(item => item['senum'] == current.value)
-	// #endif
-
 	const tabsClick = (obj : number) => {
 		current.value = obj
 		records.value = initRecords.filter(item => item['senum'] == current.value)
 	}
+	
 	const closeTag = (index : number) => {
 		let record = records.value[0]
-		// if(record.status==3){
-		// 	uni.showToast({
-		// 	  title: '拍照任务已完成',
-		// 	  icon: 'error', 
-		// 	  duration: 2000 
-		// 	});
-		// 	return;
-		// }
 
 		uni.showModal({
 			title: '系统提示',
@@ -262,7 +210,7 @@
 				if (res.confirm) {
 					closeTags.value[index] = false
 					let imgname = record.imgname.filter((img, i) => i != index)
-					let urlpdt = record.urlpdt.filter((url, i) => i != index)
+					let urlpdt = record.photourlSpl.filter((url, i) => i != index)
 					let updatedData = ''
 					if (imgname.length != urlpdt.length) {
 						uni.showToast({
@@ -272,24 +220,15 @@
 						});
 						return;
 					}
-					console.log(urlpdt)
 					if (imgname.length == 0 && urlpdt.length == 0) {
-						updatedData = "imgname='',urlpdt=''"
+						updatedData = "imgname='',photourl=''"
 					} else if (imgname.length == 1 && urlpdt.length == 1) {
-						updatedData = "imgname='" + imgname[0] + "',urlpdt='" + urlpdt[0] + "'"
+						updatedData = "imgname='" + imgname[0] + "',photourl='" + urlpdt[0] + "'"
 					} else {
-						updatedData = "imgname='" + imgname.join(",") + "',urlpdt='" + urlpdt.join(",") + "'"
-					}
-
-					if (imgname.length == 0) {
-						updatedData += ',status=1  '
-					} else if (imgname.length < record.num) {
-						updatedData += ',status=2 '
-					} else if (imgname.length + 1 == record.num){
-						updatedData += ',status=3 '
+						updatedData = "imgname='" + imgname.join(",") + "',photourl='" + urlpdt.join(",") + "'"
 					}
 
-					updateData('app_media_record', updatedData, 'sxid', record.sxid.toString()).then((res : UTSJSONObject) => {
+					updateData('app_task_photo', updatedData, 'sxid', record.sxid.toString()).then((res : UTSJSONObject) => {
 						let dataRes = res?.['data'] as boolean ?? false
 						if (dataRes) {
 							uni.showToast({
@@ -313,9 +252,9 @@
 		});
 	}
 
-	const cancel = (id : number, num : number) => {
+	const cancel = (id : number) => {
 		uni.navigateTo({
-			url: `/pages/work/record/Camera?id=${id}&num=${num}`
+			url: `/pages/work/download/TaskCamera?id=${id}&num=${current.value}`
 		})
 	}
 	defineExpose({
@@ -418,11 +357,10 @@
 	}
 
 	.value {
-		flex: 1;
-		white-space: nowrap;
-		overflow: hidden;
-		text-overflow: ellipsis;
-	}
+	flex: 1;
+	word-break: break-all;
+	word-wrap: break-word;
+}
 
 	.fee {
 		color: #fa541c;
@@ -439,6 +377,7 @@
 		padding: 5rpx 30rpx;
 		font-size: 28rpx;
 		font-weight: 700;
+		margin-top: 20rpx;
 	}
 
 	.cancel-btn:hover {

+ 423 - 0
pages/work/download/TaskCamera-scan-code.uvue

@@ -0,0 +1,423 @@
+<template>
+	<!-- #ifdef APP -->
+	<scroll-view style="flex:1">
+	<!-- #endif -->
+		<!--
+    <camera style="width: 100%; height: 300px;" :resolution="'high'" :mode="'scanCode'" @scancode="handleScanCode">
+    </camera> -->
+	<view class="my-page">
+		<swiper class="swiper-box my-swiper" :current="swiperDotIndex" :indicator-dots="true">
+			<swiper-item v-for="item in data">
+				<view class="swiper-item" @tap="previewSingleImage(item.image)">
+					<image class="my-image" :src="item.image" mode="aspectFill" />
+				</view>
+				<view>
+					<text class="demo-view-label">{{ item?.name ?? ''}}</text>
+				</view>
+			</swiper-item>
+		</swiper>
+	
+
+		<view class="camera-scan-code-back-wrap" v-show="false">
+			<button class="btn block bg-blue lg round" @click="chooseImage">
+				浏览相册
+			</button>
+		</view>
+
+		<view class="camera-scan-code-table">
+			<view class="camera-scan-code-table-pair" v-if="joinRecord.imgname!=''">
+				<view class="camera-scan-code-table-pair-label">
+					<text>已存图片</text>
+				</view>
+				<view class="camera-scan-code-table-pair-value" v-for="itemName in joinRecord.imgname.split(',')"   >					
+					<text class="txt">{{ itemName }}</text>
+				</view>
+			</view>
+
+			<view class="camera-scan-code-table-pair">
+				<view class="camera-scan-code-table-pair-label">
+					<text>待存图片</text>
+				</view>
+				<view class="camera-scan-code-table-pair-value">					
+					<text class="txt">{{ dyImgName+"-"+minAvailableNumber+".jpg"}}</text>
+				</view>
+			</view>
+		</view>
+
+
+		<view class="camera-scan-code-back-wrap">
+			<button class="btn block bg-blue lg round" @click="saveImage" style="min-width: 250px;">
+				保存图片
+			</button>
+		</view>
+
+		<view class="camera-scan-code-back-wrap">
+			<button type="default" class="btn bg-blue round" @click="navigateBack">返回拍照</button>
+		    <button type="default" class="btn bg-blue round" @click="navigateExit">退出拍照</button>
+		    
+		</view>
+    </view>	
+	<!-- #ifdef APP -->
+	</scroll-view>
+	<!-- #endif -->
+</template>
+
+<script lang="uts">
+	type CameraScanCodeResult = {
+		type : string | null;
+		result : string | null;
+	}
+	type ImageItem = {
+		image : string,
+		name : string,
+		checked : boolean
+	}
+	import { getJoinList, TaskJoinRecord, updateData } from '@/api/work';
+	export default {
+		data() {
+			return {
+				result: null as CameraScanCodeResult | null,
+				swiperDotIndex: 0 as number,
+				path: '',
+				recordId: 0,
+				imgArrLen: 0,
+				joinRecord: {
+					sxid : 0,
+					pdid : 0,
+					photographpoint : '',
+					photographdescription : '',
+					photourl : '',
+					photourlSpl : [],
+					imgname : '',
+					exampleurl : '',
+					exampleurlSpl : [],
+					photoname : '',
+					fk_qcRecord : '',
+					fk_prodcode : '',
+					prodno : '',
+					processStep : '',
+					workorder:'',
+					invname: '',
+				} as TaskJoinRecord,
+				num: 0,
+				maxcount: 0,
+				dyImgName: '',
+				minAvailableNumber: 1,
+				data: [{
+					image: '/static/images/banner/banner01.png',
+					name: 'banner01.png',
+					checked: true
+				}] as ImageItem[]
+			}
+		},
+		onBackPress() {
+			console.log(this.recordId, this.num, this.joinRecord.pdid);
+			// 覆盖系统默认的返回行为,返回到指定页面
+			//PhotoRecord?pdid=
+			uni.navigateTo({
+				url: `/pages/work/download/PhotoRecord?pdid=${this.joinRecord.pdid}&senum=${this.num}`,
+				// 修改动画方向为从左到右退回
+				animationType: 'slide-in-left', // 使用从左到右滑出的动画效果
+				animationDuration: 300 // 动画持续时间,单位ms
+			})
+			// 返回true表示拦截默认返回行为
+			return true
+		},
+		onLoad(options) {
+			this.path = options?.['path'] ?? ''
+			let recordId = options?.['recordId'] ?? ''
+			let num = options?.['num'] ?? ''
+			if (num != '') {
+				this.num = parseInt(num);
+			}
+			let maxcount = options?.['maxcount'] ?? ''
+			if (this.path != '') {
+				this.data = []
+				this.data.push({ image: this.path, name: '', checked: true })
+			}
+			if (recordId != '') {
+				this.recordId = parseInt(recordId)
+				getJoinList('app_task_photo as r', 'app_task_info as i', 'r.*,i.*', 'r.pdid=i.pdid', 'sxid', recordId, null).then((res : UTSJSONObject) => {
+					let dataList = res?.['data'] as UTSJSONObject[] ?? Array<UTSJSONObject>()
+					if (dataList != null && dataList.length > 0) {
+						dataList.forEach(item => {
+							if (item != null) {
+								let record = JSON.parse<TaskJoinRecord>(item.toJSONString());
+								console.log(record);
+								if (record != null) {
+									this.dyImgName = record.workorder + record.invname;
+									this.joinRecord = record
+									this.imgArrLen = record.imgname.indexOf(",") > -1 ? record.imgname.split(",").length : (record.imgname != '' ? 1 : 0)
+									// 计算最小可用编号
+									this.calculateMinAvailableNumber();
+
+								}
+							}
+						});
+					}
+				});
+			}
+			if (num != '') {
+				this.num = parseInt(num)
+			}
+			if (maxcount != '') {
+				this.maxcount = parseInt(maxcount)
+			}
+		},
+		methods: {
+			navigateBack() {
+				//uni.navigateBack()
+				uni.navigateTo({
+					url: `/pages/work/download/TaskCamera?id=${this.recordId}&num=${this.num}`
+				})
+			},
+			navigateExit() {
+				uni.navigateTo({
+					url: `/pages/work/download/DownloadDetail?id=${this.joinRecord.pdid}`
+				})
+			},
+			checkboxChange() {
+				console.log("选择图片名称")
+			},
+			chooseImage() {
+				uni.chooseImage({
+					sourceType: ['album'],
+					success: (res) => {
+						//this.data = res.tempFilePaths; // 获取选中的图片路径
+						this.data = []
+						for (let i = 0; i < res.tempFilePaths.length; i++) {
+							this.data.push({ image: res.tempFilePaths[i], name: '', checked: true })
+						}
+					},
+					fail: (err) => {
+						console.error('选择图片失败', err);
+					}
+				});
+			},
+			saveImage() {
+				//保存图片进入相册文件
+				if (this.path == '') {
+					uni.showToast({
+						title: '没有拍照文件',
+						icon: 'error',
+						duration: 2000
+					});
+					return;
+				}
+				let updateImgs = ''
+				let updateNames = ''
+
+				// 动态生成最小的可用图片编号
+				const getMinAvailableNumber = () => {
+					if (this.imgArrLen === 0) return 1;
+
+					// 从已有的图片名称中提取编号
+					const existingNumbers = new Set<number>();
+					const imgNames = this.joinRecord.imgname.split(',');
+
+					imgNames.forEach((name : string) => {
+						if (name != '') {
+							// 提取图片名称中的数字部分
+							const match = name.match(/-(\d+)\.jpg$/);
+							if (match != null && match[1] != null) {
+								const numStr = match[1] as string;
+								existingNumbers.add(parseInt(numStr));
+							}
+						}
+					});
+
+					// 查找1到所需图片数量之间最小的未使用编号
+					for (let i = 1; i <= 10; i++) {
+						if (!existingNumbers.has(i)) {
+							return i;
+						}
+					}
+
+					// 如果1到所需数量都被使用了,则使用当前数量+1
+					return this.imgArrLen + 1;
+				};
+
+				const minAvailableNumber = getMinAvailableNumber();
+				const newImgName = this.dyImgName + "-" + minAvailableNumber + ".jpg";				
+				const relativePath = `/uploadImgs/${newImgName}`
+
+				if (this.imgArrLen == 0) {
+					updateImgs = relativePath
+					updateNames = newImgName;
+				} else {
+					updateImgs = this.joinRecord.photourl + "," + relativePath
+					updateNames = this.joinRecord.imgname + "," + newImgName;
+				}
+
+				let updatedData = "imgname='" + updateNames + "',photourl='" + updateImgs + "'"
+				
+				updateData('app_task_photo', updatedData, 'sxid', this.recordId.toString()).then((res : UTSJSONObject) => {
+					let data = res?.['data'] as boolean ?? false
+					if (data != null && data== true) {
+						uni.showToast({
+							title: "保存成功!",
+						});
+						const newPath = `${uni.env.USER_DATA_PATH}/uploadImgs/${newImgName}`
+						this.renameFile(this.path, newPath)
+
+						uni.navigateTo({
+							url: `/pages/work/download/PhotoRecord?pdid=${this.joinRecord.pdid}&senum=${this.num}`,
+							// 修改动画方向为从左到右退回
+							animationType: 'slide-in-left', // 使用从左到右滑出的动画效果
+							animationDuration: 300 // 动画持续时间,单位ms
+						})
+					}
+				});
+			},
+			previewSingleImage(imageUrl : string) {
+				uni.previewImage({
+					urls: [imageUrl], // 需要预览的图片链接列表
+					current: 0, // 当前显示图片的索引
+					indicator: 'number', // 图片指示器样式
+					loop: false // 是否可循环预览
+				});
+			},
+			renameFile(oldPath:string, newPath:string) {
+			    // 先拷贝文件到新路径
+			    uni.getFileSystemManager().copyFile({
+			        srcPath: oldPath,
+			        destPath: newPath,
+			        success: function () {
+			            // 可选:删除原文件,如果你需要释放空间的话
+			            uni.getFileSystemManager().unlink({
+			                filePath: oldPath,
+			                success: function () {
+			                    console.log('原文件已删除');
+			                },
+			                fail: function (unlinkErr) {
+			                    console.error('删除原文件失败', unlinkErr);
+			                }
+			            });
+			            console.log('文件重命名成功');
+			        },
+			        fail: function (copyErr) {
+			            console.error('拷贝文件失败', copyErr);
+			        }
+			    });
+			},
+			
+			handleScanCode(ev : UniCameraScanCodeEvent) {
+				const deatil = ev.detail;
+				this.result = {
+					type: deatil.type,
+					result: deatil.result
+				} as CameraScanCodeResult
+			},
+			// 计算最小的可用图片编号
+			calculateMinAvailableNumber() {
+				if (this.imgArrLen === 0) {
+					this.minAvailableNumber = 1;
+					return;
+				}
+
+				// 从已有的图片名称中提取编号
+				const existingNumbers = new Set<number>();
+				const imgNames = this.joinRecord.imgname.split(',');
+
+				imgNames.forEach((name : string) => {
+					if (name != '') {
+						// 提取图片名称中的数字部分
+						const match = name.match(/-(\d+)\.jpg$/);
+						if (match != null && match[1] != null) {
+							const numStr = match[1] as string;
+							existingNumbers.add(parseInt(numStr));
+						}
+					}
+				});
+
+				// 查找1到所需图片数量之间最小的未使用编号
+				for (let i = 1; i <= 10; i++) {
+					if (!existingNumbers.has(i)) {
+						this.minAvailableNumber = i;
+						return;
+					}
+				}
+
+				// 如果1到所需数量都被使用了,则使用当前数量+1
+				this.minAvailableNumber = this.imgArrLen + 1;
+			},
+		}
+	}
+</script>
+
+<style>
+	.camera-scan-code-back-wrap {
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		flex-direction: row;
+	}
+
+	.camera-scan-code-table {
+		background-color: white;
+		margin-top: 20px;
+	}
+
+	.camera-scan-code-table-pair {
+		height: 100px;
+		flex-direction: column;
+		justify-content: space-between;
+		align-items: center;
+	}
+
+	.camera-scan-code-table-pair-label {
+		flex-grow: 1;
+		margin-left: 15px;
+
+	}
+
+	.camera-scan-code-table-pair-value {
+		flex-grow: 2;
+		flex-direction: column;
+	}
+
+	.camera-scan-code-table-pair-value .txt {
+		font-size: 14px;
+	}
+
+	.camera-scan-code-table-top-line {
+		border-top: 1px solid #eee;
+	}
+	
+	.my-page {
+		display: flex;
+		flex-direction: column;
+		box-sizing: border-box;
+		background-color: #fff;
+		/* #ifndef APP-ANDROID */
+		min-height: 100%;
+		/* #endif */
+		height: 100%;
+	}
+
+	.swiper {
+		height: 400px;
+	}
+
+	.swiper-box {
+		height: 300px;
+	}
+
+	.swiper-item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		color: #fff;
+		height: 400px;
+		line-height: 400px;
+	}
+
+	.btn {
+		/*margin-top: 30px; */
+		height: 45px;
+		margin: 20px 20px;
+	}
+</style>

+ 408 - 0
pages/work/download/TaskCamera.uvue

@@ -0,0 +1,408 @@
+<template>
+	<view class="camera-container">
+		<!-- 全屏相机预览 -->
+		<camera class="camera-preview" :resolution="'medium'" :device-position="devicePosition" :flash="flash"
+			:frame-size="frameSize" @stop="handleStop" @error="handleError" @initdone="handleInitDone">
+		</camera>
+
+		<!-- 左上角:闪光灯图标按钮 -->
+		<view class="top-left">
+			<button class="flash-btn" @click="switchFlash">
+				<text class="icon">{{ flash === 'torch' ? '💡' : '🔦' }}</text>
+			</button>
+		</view>
+
+		<!-- 右上角:图像质量设置 -->
+		<view class="top-right">
+			<view class="quality-setting">
+				<text class="setting-label">成像质量</text>
+				<radio-group class="quality-group" @change="takePhotoQualityChange">
+					<radio class="quality-radio" value="normal" :checked="quality === 'normal'">普通</radio>
+					<radio class="quality-radio" value="high" :checked="quality === 'high'">高清</radio>
+					<radio class="quality-radio" value="original" :checked="quality === 'original'">原图</radio>
+				</radio-group>
+			</view>
+		</view>
+
+		<!-- 底部中间:圆形拍照按钮 -->
+		<view class="bottom-center">
+			<button class="shoot-btn" @click="handleTakePhoto">
+				<view class="shoot-inner"></view>
+			</button>
+		</view>
+
+		<!-- 左下角:相册预览 -->
+		<view class="bottom-left">
+			<view class="album-preview" @click="handleScanCode">
+				<image class="preview-img" v-if="imageSrc" :src="imageSrc"></image>
+				<text class="preview-tip" v-else>浏览图片</text>
+			</view>
+		</view>
+
+		<!-- 下方:缩放控制(位置保持不变) -->
+		<view class="zoom-control">
+			<text class="setting-label">预览缩放</text>
+			<view class="zoom-container">
+				<slider class="zoom-slider" :disabled="maxZoom <= 1" :show-value="true" :min="1" :max="maxZoom"
+					:value="1" @change="zoomSliderChange" />
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				devicePosition: "back",
+				flash: "off",
+				frameSize: "medium",
+				listener: null as CameraContextCameraFrameListener | null,
+				maxZoom: 0,
+				imageSrc: "",
+				quality: "normal",
+				timeout: 30,
+				compressed: false,
+				videoSrc: "",
+				startRecordStatus: false,
+				remain: 0,
+				intervalId: -1,
+				timeoutStr: '30',
+				recordId: 0,
+				num: 0,
+				maxcount: 0,
+			}
+		},
+		onLoad(options) {
+			let recordId = options?.['id'] ?? ''
+			let num = options?.['num'] ?? ''
+			if(recordId!=''){
+				this.recordId = parseInt(recordId)
+			}
+			if(num!=''){
+				this.num = parseInt(num)
+			}
+		},
+
+		methods: {
+			handleScanCode() {
+				if(this.imageSrc!=""){
+					let params = "path="+this.imageSrc+"&recordId="+this.recordId+"&num="+this.num
+					uni.navigateTo({
+						url: "/pages/work/download/TaskCamera-scan-code?"+params
+					})
+				}else{
+					uni.showToast({
+					  title: '没有拍照文件',
+					  icon: 'error', 
+					  duration: 2000 
+					});
+				}
+			},
+			switchDevicePosition() {
+				this.devicePosition = this.devicePosition == "back" ? "front" : "back"
+			},
+
+			switchFlash() {
+				this.flash = this.flash == "torch" ? "off" : "torch"
+			},
+
+			handleStop(e : UniCameraStopEvent) {
+				console.log("stop", e.detail);
+			},
+			handleError(e : UniCameraErrorEvent) {
+				console.log("error", e.detail);
+			},
+			handleInitDone(e : UniCameraInitDoneEvent) {
+				console.log("initdone", e.detail);
+				this.maxZoom = e.detail.maxZoom ?? 0
+			},
+			zoomSliderChange(event : UniSliderChangeEvent) {
+				const value = event.detail.value
+				const context = uni.createCameraContext();
+				context?.setZoom({
+					zoom: value,
+					success: (e : any) => {
+						console.log(e);
+					}
+				} as CameraContextSetZoomOptions)
+			},
+			handleTakePhoto() {
+				const context = uni.createCameraContext();
+				context?.takePhoto({
+					quality: this.quality,
+					selfieMirror: false,
+					success: (res : CameraContextTakePhotoResult) => {
+						console.log("res.tempImagePath", res.tempImagePath);
+						this.imageSrc = res.tempImagePath ?? ''
+					},
+					fail: (e : any) => {
+						console.log("take photo", e);
+					}
+				} as CameraContextTakePhotoOptions)
+			},
+			takePhotoQualityChange(event : UniRadioGroupChangeEvent) {
+				this.quality = event.detail.value
+				console.log("quality", this.quality);
+			},
+
+			setOnFrameListener() {
+				const context = uni.createCameraContext();
+				this.listener = context?.onCameraFrame((frame : CameraContextOnCameraFrame) => {
+					console.log("OnFrame :", frame);
+				})
+			},
+			startFrameListener() {
+				this.listener?.start({
+					success: (res : any) => {
+						console.log("startFrameListener success", res);
+					}
+				} as CameraContextCameraFrameListenerStartOptions)
+
+			},
+			stopFrameListener() {
+				this.listener?.stop({
+					success: (res : any) => {
+						console.log("stopFrameListener success", res);
+					}
+				} as CameraContextCameraFrameListenerStopOptions)
+			},
+			startRecord() {
+				const context = uni.createCameraContext();
+				let timeout = this.getTimeout()
+				this.timeout = timeout
+				context?.startRecord({
+					timeout: timeout,
+					selfieMirror: false,
+					timeoutCallback: (res : any) => {
+						console.log("timeoutCallback", res);
+						this.startRecordStatus = false
+						if (typeof res != "string") {
+							const result = res as CameraContextStartRecordTimeoutResult
+							this.videoSrc = result.tempVideoPath ?? ''
+						}
+						clearInterval(this.intervalId)
+					},
+					success: (res : any) => {
+						this.startRecordStatus = true
+						console.log("start record success", res);
+						this.remain = timeout
+						this.intervalId = setInterval(() => {
+							if (this.remain <= 0) {
+								clearInterval(this.intervalId)
+							} else {
+								this.remain--
+							}
+						}, 1000)
+					},
+					fail: (res : any) => {
+						console.log("start record fail", res);
+						this.startRecordStatus = false
+						this.remain = 0
+						clearInterval(this.intervalId)
+					}
+				} as CameraContextStartRecordOptions)
+			},
+			stopRecord() {
+				this.startRecordStatus = false
+				const context = uni.createCameraContext();
+				context?.stopRecord({
+					compressed: this.compressed,
+					success: (res : CameraContextStopRecordResult) => {
+						console.log("stop record success", res);
+						this.videoSrc = res.tempVideoPath ?? ''
+					},
+					fail: (res : any) => {
+						console.log("stop record fail", res);
+					}
+				} as CameraContextStopRecordOptions)
+				clearInterval(this.intervalId)
+				this.remain = 0
+			},
+			startRecordCompressChange(event : UniRadioGroupChangeEvent) {
+				this.compressed = parseInt(event.detail.value) == 1
+			},
+			timeoutInput(event : UniInputEvent) {
+				this.timeoutStr = event.detail.value
+			},
+			getTimeout() : number {
+				let value = parseInt(this.timeoutStr)
+				if (isNaN(value)) {
+					return 30
+				} else {
+					if (value < 1) {
+						return 1
+					} else if (value > 60 * 5) {
+						return 60 * 5
+					} else {
+						return value
+					}
+				}
+			}
+		}
+	}
+</script>
+
+<style scope>
+	/* 基础容器 */
+	.camera-container {
+		width: 100%;
+		height: 100%;
+		position: relative;
+		overflow: hidden;
+		background-color: #000;
+	}
+
+	/* 相机预览 */
+	.camera-preview {
+		width: 100%;
+		height: 100%;
+		position: absolute;
+		top: 0;
+		left: 0;
+	}
+
+	/* 左上角:闪光灯按钮 */
+	.top-left {
+		position: absolute;
+		top: 40rpx;
+		left: 40rpx;
+		z-index: 10;
+	}
+
+	.flash-btn {
+		width: 100rpx;
+		height: 100rpx;
+		border-radius: 100rpx;
+		background-color: rgba(0, 0, 0, 0.4);
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		padding: 0;
+		border: none;
+	}
+
+	.icon {
+		font-size: 48rpx;
+		color: #e0e0e0;
+		/* 银色 */
+	}
+
+	/* 右上角:图像质量设置 */
+	.top-right {
+		position: absolute;
+		top: 40rpx;
+		right: 40rpx;
+		z-index: 10;
+		background-color: rgba(0, 0, 0, 0.4);
+		padding: 20rpx 30rpx;
+		border-radius: 16rpx;
+	}
+
+	/* 底部中间:拍照按钮 */
+	.bottom-center {
+		position: absolute;
+		bottom: 240rpx;
+		left: 50%;
+		transform: translateX(-50%);
+		z-index: 10;
+	}
+
+	.shoot-btn {
+		width: 180rpx;
+		height: 180rpx;
+		border-radius: 180rpx;
+		background-color: #ffffff;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		padding: 0;
+		border: 8rpx solid rgba(255, 255, 255, 0.3);
+		box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0);
+	}
+
+	.shoot-inner {
+		width: 140rpx;
+		height: 140rpx;
+		border-radius: 140rpx;
+		background-color: #f0f0f0;
+	}
+
+	/* 左下角:相册预览 */
+	.bottom-left {
+		position: absolute;
+		bottom: 240rpx;
+		left: 40rpx;
+		z-index: 10;
+	}
+
+	.album-preview {
+		width: 130rpx;
+		height: 130rpx;
+		border: 4rpx solid #e0e0e0;
+		border-radius: 16rpx;
+		overflow: hidden;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		background-color: rgba(255, 255, 255, 0.1);
+	}
+
+	.preview-img {
+		width: 100%;
+		height: 100%;
+		object-fit: cover;
+	}
+
+	.preview-tip {
+		color: #e0e0e0;
+		/* 银色 */
+		font-size: 26rpx;
+	}
+
+	/* 下方:缩放控制 */
+	.zoom-control {
+		position: absolute;
+		bottom: 40rpx;
+		left: 0;
+		width: 100%;
+		padding: 0 40rpx;
+		box-sizing: border-box;
+		z-index: 10;
+	}
+
+	.setting-label {
+		display: block;
+		color: #e0e0e0;
+		/* 银色 */
+		font-size: 28rpx;
+		margin-bottom: 16rpx;
+		font-weight: 500;
+	}
+
+	/* 质量选择样式 */
+	.quality-group {
+		display: flex;
+		gap: 10;
+	}
+
+	.quality-radio {
+		color: #e0e0e0;
+		/* 银色 */
+		font-size: 26rpx;
+		display: flex;
+		align-items: center;
+		gap: 10;
+	}
+
+	/* 缩放控制样式 */
+	.zoom-container {
+		width: 100%;
+		padding: 10rpx 0;
+	}
+
+	.zoom-slider {
+		width: 100%;
+		height: 4px;
+	}
+</style>

二進制
static/db/QT800.db


+ 140 - 1
utils/sqlite.uts

@@ -276,6 +276,7 @@ export function selectTableData (
       sql = `UPDATE ${dbTable} SET ${data} WHERE ${lname} = '${lvalue}'`
     }
 	const sqlite = createSQLiteContext(dbName);
+	console.log(sql)
     // WHERE 前面是要修改的列名、列值,后面是条件的列名、列值
     return new Promise((resolve, reject) => {
       const executeSqlOptions ={
@@ -690,4 +691,142 @@ export function selectLatestInfoData (
      resolve(ret)
    });	
    
-  }
+  }
+  
+  
+  //统计查询任务的详细信息
+  export function selectTaskDetail (
+    field?:string,
+    value?: string,
+  ):Promise<UTSJSONObject>
+  {
+    var sql = `SELECT
+	                m.pdid,
+					m.gxno,
+					p.photoTotal,
+					p.photoCount,
+					CASE WHEN p.photoCount = p.photoTotal THEN '已完成' ELSE '' END as photoStatus,
+					k.keyTotal,
+					k.keyCount,
+					CASE WHEN k.keyCount = k.keyTotal THEN '已完成' ELSE '' END as keyStatus,
+					i.recordTotal,
+					i.recordCount,
+					CASE WHEN i.recordCount = i.recordTotal THEN '已完成' ELSE '' END as recordStatus 
+				FROM
+				  app_task_info m
+				  LEFT JOIN (
+					SELECT 
+					  pdid,
+					  COUNT(pdid) as photoTotal,
+					  SUM(CASE WHEN photourl IS NOT NULL THEN 1 ELSE 0 END) as photoCount
+					FROM app_task_photo 
+					GROUP BY pdid
+				  ) p ON m.pdid = p.pdid
+				  LEFT JOIN (
+					SELECT 
+					  pdid,
+					  COUNT(pdid) as keyTotal,
+					  SUM(CASE WHEN measuredvaluemin IS NOT NULL OR measuredvaluemax IS NOT NULL THEN 1 ELSE 0 END) as keyCount
+					FROM app_task_keyprocess 
+					GROUP BY pdid
+				  ) k ON m.pdid = k.pdid
+				  LEFT JOIN (
+					SELECT 
+					  r.pdid,
+					  COUNT(i.sxid) as recordTotal,
+					  SUM(CASE WHEN i.measuredvalue IS NOT NULL THEN 1 ELSE 0 END) as recordCount
+					FROM app_task_record r
+					LEFT JOIN app_task_record_item i ON r.sxid = i.psxid
+					GROUP BY r.pdid
+				  ) i ON m.pdid = i.pdid
+				  where m.${field} = '${value}'
+				  `;
+    const sqlite = createSQLiteContext(dbName);
+    
+    return new Promise<UTSJSONObject>((resolve, reject) => {
+      const selectSqlOptions ={		
+    	  sql: sql,
+    	  success: (e: selectSqlOptionsResult) => {
+    	    console.log(e)
+    		
+    	  },
+    	  fail: (e: selectSqlOptionsResult) => {
+    	    console.error(e)
+    	  }		
+      } as selectSqlOptions
+    
+      const info = sqlite.selectSql(selectSqlOptions) as selectSqlOptionsResult
+      const ret = {
+    	  errMsg: info?.errMsg ?? '',
+    	  data: info?.data ?? ['']
+      } as UTSJSONObject
+      resolve(ret)
+    });	
+    
+   } 
+   
+   
+   export function selectTableDataByOrder (
+     dbTable: string,
+     lname?: string,
+     lvalue?: string,
+     cc?: string,
+     dd?: string,
+	 order?: string,
+   ):Promise<UTSJSONObject>
+   {
+     if (dbTable !== null) {
+       // 第一个是表单名称,后两个参数是列表名,用来检索
+   	var sql = '';
+       if (lname !== null && cc !== null) {
+         // 两个检索条件
+         sql = `SELECT * FROM ${dbTable} WHERE ${lname} = '${lvalue}' AND ${cc} = '${dd}'`
+       }
+       if (lname !== null && cc == null) {
+         // 一个检索条件
+          sql = `SELECT * FROM ${dbTable} WHERE ${lname} = '${lvalue}'`
+         // console.log(sql);
+       }
+       if (lname == null) {
+          sql = `SELECT * FROM ${dbTable}`
+       }
+	   if (order != null) {
+		   sql += order
+	   }
+	   
+	   
+	console.log(sql)   
+   	const sqlite = createSQLiteContext(dbName);
+   	
+   	return new Promise<UTSJSONObject>((resolve, reject) => {
+   	  const selectSqlOptions ={		
+   		  sql: sql,
+   		  success: (e: selectSqlOptionsResult) => {
+   		    console.log(e)
+   			
+   		  },
+   		  fail: (e: selectSqlOptionsResult) => {
+   		    console.error(e)
+   		  }		
+   	  } as selectSqlOptions
+   	
+   	  const info = sqlite.selectSql(selectSqlOptions) as selectSqlOptionsResult
+   	  
+   	  console.log(info)	
+   	  const ret = {
+   		  errMsg: info?.errMsg ?? '',
+   		  data: info?.data ?? ['']
+   	  } as UTSJSONObject
+   	  resolve(ret)
+   	});	
+   		
+     } else {
+       return new Promise<UTSJSONObject>((resolve, reject) => {
+   		const ret = {
+   			  errMsg: '错误查询',
+   			  data : ['表名不存在']
+   		} as UTSJSONObject
+           resolve(ret);		
+       })
+     }
+    }