yangg 5 روز پیش
والد
کامیت
efd0888434

+ 14 - 0
src/views/system/device/api.ts

@@ -25,6 +25,20 @@ export function getBorrowRecords(id: number) {
 	});
   }
 
+export function getMaintenanceRecords(id: number) {
+	return request({
+		url: `/api/system/device/${id}/maintenance_records/`,
+		method: 'get'
+	});
+}
+
+export function getDeviceStatistics(id: number) {
+	return request({
+		url: `/api/system/device/${id}/statistics/`,
+		method: 'get'
+	});
+}
+
   
 export function GetObj(id: InfoReq) {
 	return request({

+ 120 - 11
src/views/system/device/crud.tsx

@@ -22,7 +22,7 @@ const BorrowRecords = defineComponent({
 			const records = ref([]);
 			const loading = ref(false);
 			const filteredRecords = computed(() =>
-				(records.value || []).filter((item: any) => item?.record_type === 0)
+				(records.value || [])/* .filter((item: any) => item?.record_type === 0) */
 			);
 			const loadData = async () => {
 				if (!props.form?.id) return;
@@ -41,8 +41,9 @@ const BorrowRecords = defineComponent({
 			<ElTable data={filteredRecords.value} v-loading={loading.value} style="width: 100%">
 				<ElTableColumn prop="application_no" label="借用编号" />
 				<ElTableColumn prop="borrower_name" label="借用人" />
+				<ElTableColumn prop="borrower_code"  label="学号/工号"/>
 				<ElTableColumn prop="record_type_label" label="状态" />
-				<ElTableColumn prop="borrower_type" label="借用类型" />
+				<ElTableColumn prop="borrow_type_display" label="借用类型" />
 				
 			</ElTable>
 			);
@@ -88,6 +89,100 @@ const BorrowRecords = defineComponent({
 	}
   });
 
+const MaintenanceRecords = defineComponent({
+	props: { form: Object },
+	setup(props) {
+		try {
+			const records = ref([]);
+			const loading = ref(false);
+			const loadData = async () => {
+				if (!props.form?.id) return;
+				loading.value = true;
+				try {
+					const res = await api.getMaintenanceRecords(props.form.id);
+					records.value = res.data || [];
+				} finally {
+					loading.value = false;
+				}
+			};
+
+			watch(() => props.form?.id, loadData, { immediate: true });
+
+			return () => (
+			<ElTable data={records.value} v-loading={loading.value} style="width: 100%">
+				<ElTableColumn prop="record_no" label="保养编号" />
+				<ElTableColumn prop="plan_name" label="保养计划" />
+				<ElTableColumn prop="planned_date" label="保养日期" />
+				<ElTableColumn prop="maintenance_person" label="保养人员" />
+				<ElTableColumn prop="maintenance_content" label="保养内容" />
+		
+			</ElTable>
+			);
+		} catch (e) {
+			console.error("MaintenanceRecords setup error:", e);
+			return () => <div>组件加载失败</div>;
+		}
+	}
+});
+
+const DeviceStatistics = defineComponent({
+	props: { form: Object },
+	setup(props) {
+		try {
+			const statistics = ref<any>({});
+			const loading = ref(false);
+			const loadData = async () => {
+				if (!props.form?.id) return;
+				loading.value = true;
+				try {
+					const res = await api.getDeviceStatistics(props.form.id);
+					statistics.value = res.data || {};
+				} finally {
+					loading.value = false;
+				}
+			};
+
+			watch(() => props.form?.id, loadData, { immediate: true });
+
+			return () => (
+			<div v-loading={loading.value} style={{ padding: '20px' }}>
+				<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '20px' }}>
+					<div style={{ background: '#f5f7fa', padding: '20px', borderRadius: '8px', textAlign: 'center' }}>
+						<div style={{ fontSize: '24px', fontWeight: 'bold', color: '#409eff' }}>{statistics.value.total_borrow_count || 0}</div>
+						<div style={{ color: '#606266', marginTop: '8px' }}>总借用次数</div>
+					</div>
+					<div style={{ background: '#f5f7fa', padding: '20px', borderRadius: '8px', textAlign: 'center' }}>
+						<div style={{ fontSize: '24px', fontWeight: 'bold', color: '#67c23a' }}>{statistics.value.total_maintenance_count || 0}</div>
+						<div style={{ color: '#606266', marginTop: '8px' }}>总保养次数</div>
+					</div>
+					<div style={{ background: '#f5f7fa', padding: '20px', borderRadius: '8px', textAlign: 'center' }}>
+						<div style={{ fontSize: '24px', fontWeight: 'bold', color: '#e6a23c' }}>{statistics.value.total_repair_count || 0}</div>
+						<div style={{ color: '#606266', marginTop: '8px' }}>总维修次数</div>
+					</div>
+					{/* <div style={{ background: '#f5f7fa', padding: '20px', borderRadius: '8px', textAlign: 'center' }}>
+						<div style={{ fontSize: '24px', fontWeight: 'bold', color: '#f56c6c' }}>{statistics.value.availability_rate || '0%'}</div>
+						<div style={{ color: '#606266', marginTop: '8px' }}>设备可用率</div>
+					</div> */}
+				</div>
+				{statistics.value.recent_activities && (
+					<div style={{ marginTop: '30px' }}>
+						<h3 style={{ marginBottom: '20px', color: '#303133' }}>最近活动</h3>
+						<ElTable data={statistics.value.recent_activities} style={{ width: '100%' }}>
+							<ElTableColumn prop="activity_type" label="活动类型" />
+							<ElTableColumn prop="activity_date" label="活动日期" />
+							<ElTableColumn prop="description" label="描述" />
+						</ElTable>
+					</div>
+				)}
+			</div>
+			);
+		} catch (e) {
+			console.error("DeviceStatistics setup error:", e);
+			return () => <div>组件加载失败</div>;
+		}
+	}
+});
+
   
 export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
 	const pageRequest = async (query: UserPageQuery) => {
@@ -104,14 +199,14 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 		return await api.AddObj(form);
 	};
 
-	const selectedIds = ref([]);
+	const selectedIds = ref<any[]>([]);
 
-	const onSelectionChange = (changed) => {
+	const onSelectionChange = (changed: any[]) => {
 		console.log("selection", changed);
-		selectedIds.value = changed.map((item) => item.id);
+		selectedIds.value = changed.map((item: any) => item.id);
 	};
 
-	crudExpose.selectedIds = selectedIds;
+	(crudExpose as any).selectedIds = selectedIds;
 
 	return {
 		// selectedIds,
@@ -764,16 +859,30 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 						}
 					},
 					maintain: {
+						show: true,
 						label: "保养记录",
-						collapsed: true, 
 						icon: "el-icon-warning-outline",
-						columns: []
+						columns: ["id"],
+						slots: {
+							default: (scope) => {
+								const currentRowMaintain = crudExpose.getFormData();
+								console.log("currentRowMaintain::",currentRowMaintain);
+								return <MaintenanceRecords form={currentRowMaintain || {}} />
+							}
+						}
 					},
 					datastatis: {
+						show: true,
 						label: "数据统计",
-						collapsed: true,
-						icon: "el-icon-warning-outline",
-						columns: []
+						icon: "el-icon-data-analysis",
+						columns: ["id"],
+						slots: {
+							default: (scope) => {
+								const currentRowStats = crudExpose.getFormData();
+								console.log("currentRowStats::",currentRowStats);
+								return <DeviceStatistics form={currentRowStats || {}} />
+							}
+						}
 					},
 
 

+ 9 - 0
src/views/system/home/api.ts

@@ -37,6 +37,15 @@ export function GetBorrowRanking(params:object) {
 	});
 }
 
+/* 复合接口 */
+
+export function GetBorrowRankingComposite(params:object) {
+	return request({
+		url: '/api/system/dashboard/combined_dashboard/',
+		method: 'get',
+		params:params
+	});
+}
 
 
 

+ 32 - 22
src/views/system/home/index.vue

@@ -29,17 +29,20 @@
 									<div class="alltitle">单台设备累计借用时长排名</div>
 									<div class="navboxall">
 										<div class="wraptit">
-											<span>排名</span><span>设备名称</span><span>设备编号</span><span>借用时长</span>
+											<span style="flex: 0 0 50px;text-align: center;">排名</span>
+											<span  style="flex: 1;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;padding: 0 5px;">设备名称</span>
+											<span  style="flex: 1;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;padding: 0 5px;">设备编号</span>
+											<span style="flex: 0 0 80px;text-align: center;">借用时长</span>
 										</div>
 										<div class="wrap" :style="isFullscreen?'height: 85%':'height: 70%'">
 											<ul>
 												<li v-for="(hero, index) in heroData" :key="index" style="width: 100%;padding:5px 0 ;border-bottom: 1px solid #232e63 ;">
 													<div
 														style="display: flex;justify-content: space-between; width: 100%;">
-														<span>{{ index + 1 }}</span>
-														<span>{{ hero.device_name }}</span>
-														<span>{{ hero.device_code }}</span>
-														<span>{{ hero.total_duration }}</span>
+														<span style="flex: 0 0 50px;text-align: center;">{{ index + 1 }}</span>
+														<span style="flex: 1;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;padding: 0 5px;">{{ hero.device_name }}</span>
+														<span style="flex: 1;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;padding: 0 5px;">{{ hero.device_code }}</span>
+														<span style="flex: 0 0 80px;text-align: center;">{{ hero.total_duration }}</span>
 													</div>
 												</li>
 											</ul>
@@ -129,17 +132,20 @@
 									<div class="alltitle">单台设备累计借用次数排名</div>
 									<div class="navboxall">
 										<div class="wraptit">
-											<span>排名</span><span>设备名称</span><span>设备编号</span><span>借用次数</span>
+											<span style="flex: 0 0 50px;text-align: center;">排名</span>
+											<span style="flex: 1;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;padding: 0 5px;">设备名称</span>
+											<span style="flex: 1;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;padding: 0 5px;">设备编号</span>
+											<span style="flex: 0 0 80px;text-align: center;">借用次数</span>
 										</div>
 										<div class="wrap" :style="isFullscreen?'height: 85%':'height: 60%'">
 											<ul>
 												<li v-for="(hero, index) in teamRankings" :key="index" style="width: 100%;padding:5px 0 ;border-bottom: 1px solid #232e63 ;">
 													<div
 														style="display: flex;justify-content: space-between; width: 100%;">
-														<span>{{ index + 1 }}</span>
-														<span>{{ hero.device_name }}</span>
-														<span>{{ hero.device_code }}</span>
-														<span>{{ hero.borrow_count }}</span>
+														<span style="flex: 0 0 50px;text-align: center;">{{ index + 1 }}</span>
+														<span style="flex: 1;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;padding: 0 5px;">{{ hero.device_name }}</span>
+														<span style="flex: 1;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;padding: 0 5px;">{{ hero.device_code }}</span>
+														<span style="flex: 0 0 80px;text-align: center;">{{ hero.borrow_count }}</span>
 													</div>
 												</li>
 											</ul>
@@ -165,17 +171,20 @@
 									<div class="alltitle">活跃用户排名</div>
 									<div class="navboxall">
 										<div class="wraptit">
-											<span>排名</span><span>用户名</span><span>学号/工号</span><span>总借用次数</span>
+											<span style="flex: 0 0 50px;text-align: center;">排名</span>
+											<span style="flex: 1;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;padding: 0 5px;">用户名</span>
+											<span style="flex: 1;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;padding: 0 5px;">学号/工号</span>
+											<span style="flex: 0 0 80px;text-align: center;">总借用次数</span>
 										</div>
 										<div class="wrap" :style="isFullscreen?'height: 85%':'height: 60%'">
 											<ul>
 												<li v-for="(hero, index) in userList" :key="index" style="width: 100%;padding:5px 0 ;border-bottom: 1px solid #232e63 ;">
 													<div
 														style="display: flex;justify-content: space-between; width: 100%;">
-														<span>{{ index + 1 }}</span>
-														<span>{{ hero.user_name }}</span>
-														<span>{{ hero.user_code }}</span>
-														<span>{{ hero.borrow_count }}</span>
+														<span style="flex: 0 0 50px;text-align: center;">{{ index + 1 }}</span>
+														<span style="flex: 1;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;padding: 0 5px;">{{ hero.user_name }}</span>
+														<span style="flex: 1;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;padding: 0 5px;">{{ hero.user_code }}</span>
+														<span style="flex: 0 0 80px;text-align: center;">{{ hero.borrow_count }}</span>
 													</div>
 												</li>
 											</ul>
@@ -660,12 +669,12 @@ export default defineComponent({
 					tag_id:borrow_rank.deviceTagIds
 				};
 				console.log(borrow_rank);
-				const drres = await api.GetDeviceRankList(params);
+				const drres = await api.GetBorrowRankingComposite(params);
 				if (res.code === 2000) {
-					state.teamRankings = [...drres.data.borrow_count_ranking].sort(
+					state.teamRankings = [...drres.data.device_rankings.borrow_count_ranking].sort(
 						(a, b) => b.borrow_count - a.borrow_count
 					);
-					state.heroData = [...drres.data.borrow_duration_ranking].sort((a, b) => Number(b.total_duration) - Number(a.total_duration))
+					state.heroData = [...drres.data.device_rankings.borrow_duration_ranking].sort((a, b) => Number(b.total_duration) - Number(a.total_duration))
 
 					console.log("state.heroData:::", state.heroData)
 
@@ -676,10 +685,10 @@ export default defineComponent({
 					console.log("ulres:::", ulres)
 					updateMonthlyUtilizationChart(ulres.data.trends)
 				}
-				const btres = await api.GetBorrowTrends();
+				const btres = await api.GetBorrowRankingComposite(params);
 				if (btres.code === 2000) {
 					//clos
-					updateBorrowTrendChart(btres.data.trends)
+					updateBorrowTrendChart(btres.data.borrow_trends.trends)
 				}
 				const acres = await api.GetActiveUsers();
 				if (acres.code === 2000) {
@@ -722,9 +731,10 @@ export default defineComponent({
 					end_date: borrow_rank.dateRange.value?.[1],
 					tag_id:borrow_rank.deviceTagIds
 				};
-				const res = await api.GetBorrowRanking(params);
+				const res = await api.GetBorrowRankingComposite(params);
+				console.log("res:::", res)
 				if (res.code === 2000) {
-					state.teamRankings = [...res.data.borrow_count_ranking].sort((a, b) => b.borrow_count - a.borrow_count);
+					state.teamRankings = [...res.data.device_rankings.borrow_count_ranking].sort((a, b) => b.borrow_count - a.borrow_count);
 				}
 			} catch (err) {
 				console.error('获取设备排名失败:', err);

+ 9 - 0
src/views/system/screenconsole/api.ts

@@ -32,6 +32,15 @@ export function GetBorrowRanking(params:object) {
 	});
 }
 
+/* 复合接口 */
+
+export function GetBorrowRankingComposite(params:object) {
+	return request({
+		url: '/api/system/dashboard/combined_dashboard/',
+		method: 'get',
+		params:params
+	});
+}
 
 
 

+ 2 - 2
src/views/system/screenconsole/component/BorrowRankingList.vue

@@ -97,9 +97,9 @@ const fetchRanking = async () => {
     // console.log("params.tag_id::",params.tag_id)
   }
 
-  const res = await api.GetBorrowRanking(params)
+  const res = await api.GetBorrowRankingComposite(params)
   if (res.code === 2000) {
-    rankingData.value = res.data.borrow_count_ranking
+    rankingData.value = res.data.device_rankings.borrow_count_ranking
   } else {
     rankingData.value = []
   }