Преглед изворни кода

Merge branch 'feat-homepage'

liujt пре 1 месец
родитељ
комит
b9984f9d65

+ 26 - 0
api/home/index.js

@@ -78,3 +78,29 @@ export async function getHotProduct(params) {
 	return Promise.reject(new Error(data.message))
 }
 
+// 获取设备监测
+export async function getDeviceCount(params) {
+	const data = await get(Vue.prototype.apiUrl + `/main/asset/querySubstanceRunningMonitor`, params)
+	if (data.code == 0) {
+		return data.data
+	}
+	return Promise.reject(new Error(data.message))
+}
+
+// 获取公文列表
+export async function getNoticeDocumentPage(params) {
+	const data = await get(Vue.prototype.apiUrl + `/fm/noticeDocument/v1/page`, params)
+	if (data.code == 0) {
+		return data.data
+	}
+	return Promise.reject(new Error(data.message))
+}
+
+// 获取公文详情
+export async function getNoticeDocumentDetail(id) {
+	const data = await get(Vue.prototype.apiUrl + `/fm/noticeDocument/v1/get/${id}`)
+	if (data.code == 0) {
+		return data.data
+	}
+	return Promise.reject(new Error(data.message))
+}

+ 11 - 0
api/purchasingManage/index.js

@@ -16,4 +16,15 @@ export async function getReceiveConfirmDetail(id) {
         return res.data;
     }
     return Promise.reject(new Error(res.message));
+}
+
+/**
+ * 获取信息列表
+ */
+export async function getPurchaseOrderList(params) {
+    const res = await get(Vue.prototype.apiUrl + `/eom/purchaseorder/page`,params);
+    if (res.code == 0) {
+        return res.data;
+    }
+    return Promise.reject(new Error(res.message));
 }

+ 48 - 1
enum/dict.js

@@ -11,6 +11,7 @@ export default {
   质检标准类型: "quality_testing_code",
   取样类型: "quality_method_code",
   计量单位: "measuring_uint",
+  销售类型: "order_type",
   记录规则类型: 'record_sheet',
   表计类型: 'meter_type'
 
@@ -351,4 +352,50 @@ export const warehouseDefinition_areaAttribute = [
   { code: 2, label: "冷藏" },
   { code: 3, label: "恒温" },
   { code: 4, label: "低温" },
-];
+];
+
+//订单类型
+export const orderTypeEnum = [
+  { code: 1, label: "有客户生产性订单" },
+  { code: 2, label: "无客户生产性订单" },
+  { code: 4, label: "不定向订单" },
+  { code: 5, label: "委外订单" },
+  { code: 0, label: "库存式订单" },
+]
+
+//销售订单整体进度
+export const saleOrderProgressStatusEnum = [
+  { value: 0, label: '未开始' },
+  { value: 100, label: '待排程' },
+  { value: 200, label: '已排程' },
+  { value: 300, label: '待派单' },
+  { value: 400, label: '已派单' },
+  { value: 500, label: '生产执行中' },
+  { value: 501, label: '部分入库' },
+  { value: 600, label: '已入库' },
+  { value: 700, label: '待发货' },
+  { value: 701, label: '部分发货' },
+  { value: 800, label: '全部发货' },
+  { value: 1000, label: '完成' }
+];
+
+//采购订单整体进度
+export const purchaseOrderProgressStatusEnum = [
+  { value: 0, label: '未开始' },
+  { value: 100, label: '在途' },
+  { value: 101, label: '部分入库' },
+  { value: 102, label: '待质检' },
+  { value: 103, label: '质检中' },
+  { value: 200, label: '已入库' },
+  { value: 1000, label: '完成' }
+];
+
+// 状态(业务状态)
+export const businessStatus = [
+  { code: 0, label: '空闲' },
+  { code: 1, label: '占用' },
+  { code: 2, label: '故障' },
+  { code: 3, label: '维修' },
+  { code: 4, label: '保养' },
+  { code: 5, label: '巡点检' }
+];

+ 32 - 0
pages.json

@@ -2619,6 +2619,38 @@
 				"navigationBarTextStyle": "black"
 			}
 		},
+		{
+			"path": "pages/home/pages/manage/documentDetail",
+			"style": {
+				"navigationBarTitleText": "公文详情",
+				"navigationStyle": "custom",
+				"navigationBarTextStyle": "black"
+			}
+		},
+		{
+			"path": "pages/home/pages/manage/saleOrderDetail",
+			"style": {
+				"navigationBarTitleText": "销售订单明细",
+				"navigationStyle": "custom",
+				"navigationBarTextStyle": "black"
+			}
+		}, 
+		{
+			"path": "pages/home/pages/manage/purchaseOrderDetail",
+			"style": {
+				"navigationBarTitleText": "采购订单明细",
+				"navigationStyle": "custom",
+				"navigationBarTextStyle": "black"
+			}
+		}, 
+		{
+			"path": "pages/home/components/DeviceDetail",
+			"style": {
+				"navigationBarTitleText": "设备监测",
+				"navigationStyle": "custom",
+				"navigationBarTextStyle": "black"
+			}
+		},
 		{
 			"path": "pages/qms/inspectionWork/sampleList",
 			"style": {

+ 346 - 0
pages/home/components/DeviceDetail.vue

@@ -0,0 +1,346 @@
+<template>
+	<view class="device-detail">
+		<uni-nav-bar fixed="true" statusBar="true" left-icon="back" title="设备监测" @clickLeft="back"></uni-nav-bar>
+
+		<view class="top-wrapper">
+			<uni-section>
+				<uni-easyinput prefixIcon="search" style="width: 460rpx" v-model="form.keyWord" placeholder="编码、名称、固资编码">
+				</uni-easyinput>
+			</uni-section>
+			<view style="display: flex;">
+				<button class="search_btn" @click="search">搜索</button>
+				<view class="more_search">
+					<image src="~@/static/moreSearch.svg" mode="" @click="handlScreen"></image>
+				</view>
+			</view>
+		</view>
+
+		<view class="update-time">更新时间:{{ updateTime }}</view>
+
+		<scroll-view scroll-y class="device-list">
+			<view class="device-card" v-for="(item, index) in deviceList" :key="index">
+				<view class="card-header">
+					<view class="card-title">
+                        <text class="device-name">{{ item.name }}</text>
+					    <text v-if="item.status == 2" class="alarm-icon">🚨</text>
+                    </view>
+					<u-tag
+						:text="getStatusLabel(item.status)"
+						:type="getStatusType(item.status, 1)"
+						size="mini"
+						:customStyle="{ marginLeft: 'auto' }"
+					/>
+				</view>
+
+				<view class="status-tag-wrap">
+					<u-tag :text="getStatusText(item.iotList.length ? 1 : 0)" :type="getStatusType(item.iotList.length ? 1 : 0)" size="mini" />
+				</view>
+
+                <view class="data-grid">
+                    <view class="data-item" v-for="iotItem in item.iotList">
+                        <span class="data-label">{{ iotItem.name }}</span>
+                        <span class="data-value">{{
+                        iotItem.dataType.type == 'enum' ||
+                        iotItem.dataType.type == 'bool'
+                            ? iotItem.dataType.specs[iotItem.value]
+                            : iotItem.value +
+                            ' ' +
+                            ((iotItem.unit && iotItem.unit) || '')
+                        }}</span>
+                    </view>
+                </view>
+			</view>
+		</scroll-view>
+
+        <screen ref="screen" @succeed="handleFilter" :postId="form.postId" :postName="form.postName"></screen>
+	</view>
+</template>
+
+<script>
+import screen from './deviceScreen.vue'
+import { getDeviceCount } from '@/api/home'
+import { businessStatus } from '@/enum/dict'
+export default {
+    components: {
+        screen
+    },
+	data() {
+		return {
+			deviceType: '',
+			unit: '',
+			updateTime: '',
+			deviceList: [],
+            form: {
+                keyWord: '',
+                postId: '',
+                postName: ''
+            }
+		}
+	},
+	computed: {
+
+	},
+	created() {
+		this.updateTime = this.formatDate(new Date())
+		this.fetchDeviceData()
+	},
+	methods: {
+        handlScreen() {
+            this.$refs.screen.open()
+        },
+        async getData() {
+            const res = await getDeviceCount({
+                size: 9999
+            })
+
+        },
+	
+		handleFilter(data) {
+            console.log('data---', data)
+            for (let key of Object.keys(data)) {
+                this.form[key] = data[key]
+            }
+			this.fetchDeviceData()
+		},
+		formatDate(date) {
+			const y = date.getFullYear()
+			const m = String(date.getMonth() + 1).padStart(2, '0')
+			const d = String(date.getDate()).padStart(2, '0')
+			const h = String(date.getHours()).padStart(2, '0')
+			const min = String(date.getMinutes()).padStart(2, '0')
+			const s = String(date.getSeconds()).padStart(2, '0')
+			return `${y}-${m}-${d} ${h}:${min}:${s}`
+		},
+        // 获取状态文本
+      getStatusText(status) {
+        const textMap = {
+          1: '在线',
+          0: '离线',
+          fault: '故障'
+        };
+        return textMap[status] || status;
+      },
+		getStatusType(status, type) {
+            const typeMap = !type
+            ? {
+                1: 'success',
+                0: 'info',
+                fault: 'error'
+                }
+            : {
+                0: 'success',
+                1: 'success',
+                4: 'success',
+                5: 'warning',
+                2: 'error',
+                3: 'error'
+            };
+            return typeMap[status];
+
+		},
+        getStatusLabel(status) {
+            return businessStatus.find(item => item.code == status)?.label
+        },
+		async fetchDeviceData() {
+            const res = await getDeviceCount({
+                ...this.form,
+                size: 9999
+            })
+
+            let deviceData = res.list.map((item) => {
+                let iotList = [];
+                if (item.iotPointDataList) {
+                item.iotPointDataList.forEach((element) => {
+                    let data = item.iotModel.properties.find(
+                    (iotModel) => iotModel.identifier == element.identifier
+                    );
+                    if (data) {
+                    iotList.push({
+                        ...element,
+                        dataType: data.dataType
+                    });
+                    }
+                });
+                }
+
+                item['iotList'] = item.iotDashboardPoint.length
+                ? iotList.filter((iotListItem) =>
+                    item.iotDashboardPoint.find(
+                        (Point) =>
+                        Point.identifier == iotListItem.identifier &&
+                        Point.checked1
+                    )
+                    )
+                : iotList.filter((iotListItem, index) => index < 4);
+                return item;
+            });
+			// TODO: 替换为实际接口调用
+			this.deviceList = deviceData
+
+            console.log(deviceData)
+            
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.top-wrapper {
+		display: flex;
+		height: 88rpx;
+		align-items: center;
+		justify-content: space-between;
+		padding: 20rpx;
+
+		/deep/.uni-section {
+			margin-top: 0px;
+		}
+
+		/deep/.uni-section-header {
+			padding: 0px;
+
+		}
+
+		.search_btn {
+			width: 120rpx;
+			height: 70rpx;
+			line-height: 70rpx;
+			background: $theme-color;
+			font-size: 28rpx;
+			color: #fff;
+		}
+
+		.menu_icon {
+			width: 44rpx;
+			height: 44rpx;
+			margin-left: 14rpx;
+		}
+
+		.more_search {
+			display: flex;
+			align-items: center;
+			height: 70rpx;
+			line-height: 70rpx;
+
+		}
+
+		/deep/.u-input {
+			border: 1rpx solid #ccc;
+
+			.u-input__content__field-wrapper__field {
+				height: 40rpx !important;
+			}
+		}
+
+		image {
+			width: 52rpx;
+			height: 52rpx;
+			margin-left: 10rpx;
+		}
+
+	}
+.device-detail {
+	// height: 100vh;
+	display: flex;
+	flex-direction: column;
+	// background-color: #1a1b1f;
+	// color: #fff;
+}
+
+.nav-bar {
+	flex-shrink: 0;
+}
+
+.filter-bar {
+	display: flex;
+	align-items: center;
+	padding: 16rpx 24rpx;
+	// background-color: #22232a;
+
+	.picker-text {
+		font-size: 26rpx;
+		color: #ccc;
+	}
+
+	.filter-btn {
+		flex-shrink: 0;
+		margin-left: auto;
+		padding: 10rpx 28rpx;
+		border: 1rpx solid #4caf50;
+		border-radius: 8rpx;
+		color: #4caf50;
+		font-size: 26rpx;
+	}
+}
+
+.update-time {
+	padding: 12rpx 24rpx;
+	font-size: 24rpx;
+	color: #999;
+	// background-color: #1a1b1f;
+}
+
+.device-list {
+	flex: 1;
+	padding: 20rpx 24rpx;
+}
+
+.device-card {
+	// background-color: #25262c;
+	border-radius: 16rpx;
+	padding: 28rpx 24rpx;
+	margin-bottom: 20rpx;
+    box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
+    border: 1rpx solid #ccc;
+}
+
+.card-header {
+	display: flex;
+	align-items: center;
+	margin-bottom: 20rpx;
+    justify-content: space-between;
+
+	.device-name {
+		font-size: 32rpx;
+		font-weight: bold;
+		color: #333;
+	}
+
+	.alarm-icon {
+		margin-left: 12rpx;
+		font-size: 32rpx;
+	}
+}
+
+.status-tag-wrap {
+    display: flex;
+	margin-bottom: 16rpx;
+}
+
+.data-grid {
+	display: flex;
+	margin-top: 12rpx;
+    flex-wrap: wrap;
+	.data-item {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+        width: 50%;
+        padding: 10rpx 20rpx;
+		.data-label {
+			font-size: 26rpx;
+			color: #333;
+		}
+
+		.data-value {
+			font-size: 28rpx;
+			color: #333;
+			font-family: monospace;
+		}
+
+		.text-red {
+			color: #f44336;
+		}
+	}
+}
+</style>

+ 175 - 0
pages/home/components/deviceScreen.vue

@@ -0,0 +1,175 @@
+<template>
+	<view>
+		<u-popup :show="show" closeOnClickOverlay mode="top" @close="closePopup">
+			<view class="search_list">
+				<u-form labelPosition="left" :model="form" labelWidth="180" labelAlign="left" class="baseForm">
+					<!-- <u-form-item label="创建时间:" class="required-form" borderBottom prop="rangeDate">
+						<uni-datetime-picker v-model="rangeDate" :border="true" :icon="false" type="daterange" />
+					</u-form-item> -->
+					<u-form-item label="使用单位:" class="required-form" borderBottom prop="postName">
+						<!-- <u-input v-model="form.postId" placeholder="请选择" type="text" @click.stop="openDepartmentPicker" /> -->
+						 <view :style="{ color: form.postName ? 'black' : '#c0c4cc' }" class="assetType_box"
+							@click="openDepartmentPicker">
+							{{ form.postName ? form.postName : '请选择使用单位' }}
+						</view>
+					</u-form-item>
+					
+				</u-form>
+			</view>
+			<view class="operate_box rx-bc">
+				<u-button size="small" class="u-reset-button" @click="reset">
+					重置
+				</u-button>
+				<u-button type="success" size="small" class="u-reset-button" @click="submit">
+					确定
+				</u-button>
+			</view>
+		</u-popup>
+
+		<ba-tree-picker ref="departmentPicker" :multiple="false" @select-change="departmentConfirm" title="选择领料部门"
+			:localdata="departmentOption" valueKey="id" textKey="name" childrenKey="children" />
+	</view>
+</template>
+
+<script>
+	import {
+		getWarehouseList,
+		getProduceTreeByPid
+	} from '@/api/warehouseManagement'
+	import {
+		post,
+		get
+	} from '@/utils/api.js'
+	import DictSelection from "@/components/Dict/DictSelection.vue";
+	import dictMxins from "@/mixins/dictMixins";
+	import { orderTypeEnum, saleOrderProgressStatusEnum, reviewStatusEnum } from '@/enum/dict.js'
+	import {
+		listOrganizations
+	} from '@/api/common'
+	import {
+		toTreeData
+	} from '@/utils/utils.js'
+	export default {
+		mixins: [dictMxins],
+		components: {
+			DictSelection
+		},
+		props: ['type', 'postId', 'postName'],
+
+		data() {
+			return {
+				show: false,
+				rangeDate: [],
+				form: {
+					postId: '',
+					postName: ''
+				},
+				orderTypeEnum,
+				saleOrderProgressStatusEnum,
+				reviewStatusEnum,
+				departmentOption: []
+			}
+		},
+		created() {
+			this.initDeptData()
+		},
+		methods: {
+			openDepartmentPicker() {
+				this.$refs.departmentPicker._show()
+			},
+			// 部门列表
+			async initDeptData() {
+				let deptTreeList = await listOrganizations()
+				this.departmentOption = toTreeData({
+					data: deptTreeList,
+					idField: 'id',
+					parentIdField: 'parentId'
+				})
+			},
+			departmentConfirm(data, name, allList) {
+				console.log(data, name, allList)
+				this.form.postId = data[0]
+				this.form.postName = name
+			},
+			handleSaleTypeChange(val) {
+				console.log(val)
+			},
+			open() {
+				this.show = true
+				for (let key of Object.keys(this.form)) {
+					this.form[key] = this[key]
+				}
+
+				// if(this.createTimeStart && this.createTimeEnd) {
+				// this.rangeDate = [this.createTimeStart, this.createTimeEnd]
+				// } else {
+				// 	this.setDefaultRangeDate()
+				// }
+			},
+			setDefaultRangeDate() {
+				const now = new Date()
+				const year = now.getFullYear()
+				const month = String(now.getMonth() + 1).padStart(2, '0')
+				const day = String(now.getDate()).padStart(2, '0')
+				const today = `${year}-${month}-${day}`
+				if (this.type === 'year') {
+					this.rangeDate = [`${year}-01-01`, today]
+				} else if (this.type === 'month') {
+					this.rangeDate = [`${year}-${month}-01`, today]
+				}
+			},
+			closePopup() {
+				this.show = false
+			},
+			reset() {
+				this.form = {
+					postId: '',
+					postName: ''
+				}
+				this.rangeDate = [],
+				this.$emit('succeed', this.form)
+				this.closePopup()
+			},
+			submit() {
+				// if(this.rangeDate.length) {
+				// 	this.form.createTimeStart = this.rangeDate[0]
+				// 	this.form.createTimeEnd = this.rangeDate[1]
+				// }
+				this.$emit('succeed', this.form)
+				this.closePopup()
+			},
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.search_list {
+		min-height: 100rpx;
+
+		/deep/ .baseForm {
+			padding: 0 20rpx;
+		}
+	}
+
+	.operate_box {
+		padding: 10rpx 32rpx;
+
+		/deep/ .u-button {
+			width: 40%;
+		}
+	}
+	/deep/.baseForm {
+		.u-form-item__body {
+			padding: 4px !important;
+		}
+
+		.assetType_box {
+			padding: 12rpx 18rpx;
+			width: 100%;
+			overflow: hidden;
+			white-space: nowrap;
+			text-overflow: ellipsis;
+			font-size: 30rpx;
+		}
+	}
+</style>

+ 671 - 0
pages/home/homeNew.vue

@@ -0,0 +1,671 @@
+<template>
+	<view class="ss">
+		<!-- 头 -->
+		<uni-nav-bar fixed="true" statusBar="true" right-icon="scan" title="首页" @clickLeft="back"
+			@clickRight="HandlScanCode"></uni-nav-bar>
+
+		<view class="container">
+			<navigation :workOrder="workOrder" ref="navigationRef"></navigation>
+			<!-- 设备主管 -->
+			<equipment v-if="roleId == 102" ref="equipmentRef"></equipment>
+			<!-- 运维 -->
+			<Mocha v-if="roleId == 157" ref="mochaRef"></Mocha>
+			<!-- 模具舟皿 -->
+			<mould v-if="roleId == 155" ref="mouldRef"></mould>
+			<!-- 备品备件 -->
+			<sparePart v-if="roleId == 150" ref="sparePartRef"></sparePart>
+
+			<view class="data-middle">
+				<view class="cell">
+					<view class="label">
+						成品库存总量
+					</view>
+					<view class="num">
+						{{homeData.totalFinishedProducts}}
+					</view>
+				</view>
+
+				<view class="cell">
+					<view class="label">
+						物料库存总量
+					</view>
+					<view class="num">
+						{{homeData.totalRawMaterials}}
+					</view>
+				</view>
+
+				<view class="cell" @click="toDeviceDetail">
+					<view class="label">
+						设备监测
+					</view>
+					<view class="num">
+						<text style="font-size: 22rpx;">在线:</text>{{homeData.deviceOnLineCount}} 
+					</view>
+					<view class="num">
+						<text style="font-size: 22rpx;">离线:</text><text style="color: #ff0000;">{{ homeData.deviceOffLineCount }}</text>
+					</view>
+				</view>
+
+				<view class="cell">
+					<view class="label">
+						年度合同额(万元)
+					</view>
+					<view class="num">
+						{{homeData.yearAmount}}
+					</view>
+				</view>
+
+				<view class="cell">
+					<view class="label">
+						年度应收款(万元)
+					</view>
+					<view class="num">
+						{{homeData.receivableAmount}}
+					</view>
+				</view>
+
+				<view class="cell">
+					<view class="label">
+						年度应付款(万元)
+					</view>
+					<view class="num">
+						{{homeData.payableAmount}}
+					</view>
+				</view>
+				
+			</view>
+
+			<!-- 通知公告 -->
+			<view class="notice-bar" v-if="noticeList.length > 0">
+				<u-icon name="volume" size="30rpx" color="#ff9900"></u-icon>
+				<swiper class="notice-swiper" vertical autoplay circular :interval="3000">
+					<swiper-item v-for="(item, index) in noticeList" :key="index" @click="toNoticeDetail(item)">
+						<view class="notice-content">
+							<text class="notice-text">{{ item.title }}</text>
+							<text class="notice-date">{{ item.date }}</text>
+						</view>
+					</swiper-item>
+				</swiper>
+			</view>
+
+			<manage ref="manageRef"></manage>
+		</view>
+	</view>
+</template>
+
+<script>
+	import navigation from './components/navigation.vue'
+	import equipment from './pages/equipment/equipment.vue'
+	import Mocha from './pages/Mocha/Mocha.vue'
+	import mould from './pages/mould/mould.vue'
+	import sparePart from './pages/sparePart/sparePart.vue'
+	import ScanCode from '@/components/ScanCode.vue'
+	import manage from './pages/manage/manage.vue'
+
+	import {
+		getDateNew
+	} from '@/utils/utils.js'
+	import {
+		postJ,
+		post,
+		get
+	} from '@/utils/api'
+	import {
+		statistics
+	} from '@/api/myTicket'
+	import {
+		getCount,
+		getYearAmount,
+		getPayableAmount,
+		getReceivableAmount,
+		getGoodsPage,
+		getProduceAmount,
+		// getPendingAmount,
+		getHotProduct,
+		getDeviceCount,
+		getNoticeDocumentPage
+	}
+	from '@/api/home'
+	export default {
+		components: {
+			navigation,
+			equipment,
+			Mocha,
+			mould,
+			sparePart,
+			ScanCode,
+			manage
+		},
+		onShow() {
+			this.init()
+			let _this = this
+			uni.$off('scancodedate') // 每次进来先 移除全局自定义事件监听器
+			uni.$on('scancodedate', function(data) {
+				console.log(data, '-----scancodedate')
+				_this.cbScancodedate(data)
+			})
+			// this.getStatistics()
+			// this.Scancodedate()
+		},
+		onReady() {
+			this.getHomeData()
+			setTimeout(() => {
+				this.$refs.manageRef?.initCharts()
+			}, 300)
+		},
+		onLoad() {
+			// this.getHomeData()
+			// this.getStatistics()
+		},
+		onUnload() {
+			uni.$off('scancodedate')
+		},
+		onHide() {
+			uni.$off('scancodedate')
+		},
+		data() {
+			return {
+				noticeList: [],
+				roleId: null,
+				timer: null,
+				qrContent: null,
+				barType: null,
+				// 扫码后的设备信息
+				equipmentInfo: '',
+				qrContent: '',
+				barType: '',
+				workOrder: {
+					maintenanceNum: 0,
+					patrolInspection: 0,
+					quantityNum: 0,
+					repairsNum: 0,
+					total: 0
+				}, // 工单统计数据
+				activeIndex: 0,
+				tabList: [{
+					name: '热销品排行榜',
+					index: 0,
+				}, {
+					name: '滞销品排行榜',
+					index: 1,
+				}],
+				tableData: [],
+				homeData: {
+					totalFinishedProducts: '',
+					totalRawMaterials: '',
+					goodsCount: '',
+					yearAmount: '',
+					receivableAmount: '',
+					payableAmount: '',
+					yearProduceAmount: '',
+					monthProduceAmount: '',
+					pendingAmount: '',
+					deviceOnLineCount: '',
+					deviceOffLineCount: '',
+				},
+				hotProductList: [],
+
+			}
+		},
+		created() {
+			uni.getStorage({
+				key: 'userInfo',
+				success: res => {
+					// console.log(res);
+					this.roleId = res.data.roleId[0]
+				}
+			})
+			this.getNoticeDocumentList()
+		},
+		onHide() {
+			clearTimeout(this.timer);
+		},
+		onUnload() {
+			clearTimeout(this.timer);
+		},
+
+
+		methods: {
+			toDeviceDetail() {
+				console.log('toDeviceDetail')
+				uni.navigateTo({
+					url: '/pages/home/components/DeviceDetail'
+				})
+			},
+			getNoticeDocumentList() {
+				getNoticeDocumentPage({
+					pageNum: 1,
+					size: 5,
+					approvalStatus: 2
+				}).then(res => {
+					console.log('getNoticeDocumentPage', res)
+					this.noticeList = res.list.map(item => ({
+						...item,
+						title: item.title || item.content,
+						date: getDateNew(item.createTime)
+					}))
+					console.log(this.noticeList)
+				})
+			},
+			toNoticeDetail(item) {
+				console.log('toNoticeDetail', item)
+				this.$router.push({
+					path: '/pages/home/pages/manage/documentDetail',
+					query: {
+						id: item.id,
+					}
+				})
+				uni.navigateTo({
+					url: '/home/pages/manage/documentDetail?id=' + item.id
+				})
+			},
+			init() {
+				this.getStatistics()
+				this.$refs.navigationRef && this.$refs.navigationRef.getCount()
+				this.$refs.equipmentRef && this.$refs.equipmentRef.getData()
+				this.$refs.mochaRef && this.$refs.mochaRef.getData()
+				this.$refs.mouldRef &&
+					(this.$refs.mouldRef.getBoatInventoryCountList(),
+						this.$refs.mouldRef.getModeInventoryCountList())
+				this.$refs.sparePartRef && this.$refs.sparePartRef.getData()
+				this.timer = setTimeout(() => {
+					this.init()
+				}, 12000)
+			},
+			// 获取工单统计数
+			getStatistics() {
+				statistics().then(res => {
+					this.workOrder = res
+				})
+			},
+
+			// 相机扫码
+			HandlScanCode() {
+				uni.scanCode({
+					success: (res) => {
+						this.Scancodedate(res.result)
+					}
+				})
+				//_this.Scancodedate('res')
+			},
+			// 根据条码请求设备数据
+			getData() {
+				let par = {
+					barType: this.barType,
+					qrContent: this.qrContent
+				}
+				this.equipmentInfo = {}
+				return postJ(this.apiUrl + '/scan/getAssetInfo', par)
+					.then(res => {
+						console.log(res.data)
+						this.equipmentInfo = res.data
+					})
+					.catch(err => {
+						console.log(err, 'err-----------------')
+						uni.showToast({
+							title: '系统错误!',
+							icon: 'none',
+							duration: 2000
+						})
+					})
+			},
+			// 扫码枪扫码
+			cbScancodedate(data) {
+				this.Scancodedate(data.code)
+			},
+			async Scancodedate(code) {
+				this.qrContent = code.trim()
+				// this.qrContent = 'w01000002100001@_@0' //code.trim()
+				//this.qrContent = '005/w01000001120041/锤锤专用02-不拆包-批量/规格01//成型/成型工序@_@0'
+				this.barType = this.setBarType(this.qrContent)
+				await this.getData()
+
+				if (this.equipmentInfo.assetCode) {
+					if (this.equipmentInfo.assetType != 1) {
+						uni.showToast({
+							title: '请扫描生产设备码!',
+							icon: 'none',
+							duration: 2000
+						})
+
+						return
+					}
+					let par = {
+						info: encodeURIComponent(JSON.stringify(this.equipmentInfo)),
+						qrContent: this.qrContent
+					}
+					par = this.URLSearchParams(par)
+					console.log('qrwewett')
+					uni.navigateTo({
+						url: '/pages/equipment_ledger/index?' + par
+					})
+				}
+			},
+			// 设置barType
+			setBarType(val) {
+				let index = val.indexOf('@_@')
+				let result = 0
+				if (index !== -1) {
+					let item = val.substr(index + 3, 1)
+					if (item) {
+						result = Number(item)
+					}
+				}
+				return result
+			},
+			// 切换排行版tab
+			handleTabChange(item) {
+				this.activeIndex = item.index
+				this.tableData
+				// console.log(item);
+			},
+			async getHomeData() {
+				uni.showLoading({
+					title: '加载中'
+				})
+
+				const res1 = await getCount()
+				const res2 = await getGoodsPage()
+				const res3 = await getYearAmount()
+				const res4 = await getReceivableAmount()
+				const res5 = await getPayableAmount()
+				// 年度
+				const res6 = await getProduceAmount({
+					createTimeStart: getDateNew('year') + '-01',
+					createTimeEnd: getDateNew('year') + '-12',
+					factoryId: null
+				})
+				// 本月
+				const res7 = await getProduceAmount({
+					createTimeStart:  getDateNew('month'),
+					createTimeEnd:  getDateNew('month'),
+					factoryId: null
+				})
+
+
+				const res9 = await getHotProduct()
+
+				const res10 = await getDeviceCount({
+					size: 9999
+				})
+
+				let deviceData = res10.list.map((item) => {
+					let iotList = [];
+					if (item.iotPointDataList) {
+					item.iotPointDataList.forEach((element) => {
+						let data = item.iotModel.properties.find(
+						(iotModel) => iotModel.identifier == element.identifier
+						);
+						if (data) {
+						iotList.push({
+							...element,
+							dataType: data.dataType
+						});
+						}
+					});
+					}
+
+					item['iotList'] = item.iotDashboardPoint.length
+					? iotList.filter((iotListItem) =>
+						item.iotDashboardPoint.find(
+							(Point) =>
+							Point.identifier == iotListItem.identifier &&
+							Point.checked1
+						)
+						)
+					: iotList.filter((iotListItem, index) => index < 4);
+					return item;
+				});
+
+				this.homeData.deviceOnLineCount = deviceData.filter((item) => item.iotList.length > 0).length
+
+				this.homeData.deviceOffLineCount = deviceData.filter((item) => item.iotList.length == 0).length
+
+				this.homeData.totalFinishedProducts = res1?.totalFinishedProducts ?? 0
+				this.homeData.totalRawMaterials = res1?.totalRawMaterials ?? 0
+				this.homeData.goodsCount = res2?.count ?? 0
+				this.homeData.yearAmount = (res3 / 10000).toFixed(2)
+				this.homeData.receivableAmount = res4 ?? 0
+				this.homeData.payableAmount = res5 ?? 0
+				this.homeData.yearProduceAmount = res6?.reduce((pre, cur) => {
+					return pre + cur?.formedNum
+				}, 0) ?? 0
+
+				this.homeData.monthProduceAmount = res7?.reduce((pre, cur) => {
+					return pre + cur?.formedNum
+				}, 0) ?? 0
+				this.homeData.pendingAmount = res6?.reduce((pre, cur) => {
+					return pre + cur?.pendingProductionCount
+				}, 0) ?? 0
+				this.hotProductList = res9
+				this.tableData = this.hotProductList.slice(0, 4)
+				uni.hideLoading()
+
+			}
+
+		}
+	}
+</script>
+
+<style>
+	page {
+		background-color: #f0f0f0;
+	}
+</style>
+
+<style lang="scss" scoped>
+	// /deep/.uni-page-wrapper{
+	// 	background-color: pink;
+	// }
+
+	/deep/.uni-table {
+		min-width: auto !important;
+		border-radius: 0;
+	}
+
+	page {
+		background-color: #f0f0f0;
+	}
+
+	.container {
+		background-color: $page-bg;
+		padding: 20rpx;
+
+		.data-middle {
+			display: flex;
+			flex-wrap: wrap;
+			justify-content: space-between;
+
+			.cell {
+				display: flex;
+				width: 32%;
+				padding: 20rpx 0;
+				margin-bottom: 16rpx;
+				flex-direction: column;
+				background-color: rgb(22, 146, 50);
+				justify-content: center;
+				align-items: center;
+				border-radius: 8rpx;
+				color: #fff;
+				min-height: 164rpx;
+				.num {
+					font-size: 28rpx;
+				}
+
+				.label {
+					font-size: 24rpx;
+					margin-bottom: 10rpx;
+				}
+			}
+
+		}
+
+		/* 通知公告 */
+		.notice-bar {
+			display: flex;
+			align-items: center;
+			padding: 18rpx 20rpx;
+			background: #fff;
+			margin-bottom: 16rpx;
+
+			.notice-swiper {
+				flex: 1;
+				height: 40rpx;
+				margin-left: 12rpx;
+
+				swiper-item {
+				height: 40rpx;
+				display: flex;
+				align-items: center;
+				}
+
+				.notice-content {
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				width: 100%;
+				}
+
+				.notice-text {
+				font-size: 24rpx;
+				color: #333;
+				flex: 1;
+				overflow: hidden;
+				text-overflow: ellipsis;
+				white-space: nowrap;
+				}
+
+				.notice-date {
+				font-size: 22rpx;
+				color: #999;
+				margin-left: 16rpx;
+				flex-shrink: 0;
+				}
+			}
+		}
+
+		.data-rank {
+			width: 100%;
+			padding: 10rpx 20rpx 0 20rpx;
+			margin-bottom: 20rpx;
+			background-color: #fff;
+			border-radius: 20rpx 20rpx 0 0rpx;
+
+			.tab-top {
+				display: flex;
+				margin-bottom: 20rpx;
+
+				.tab-item {
+					margin-right: 20rpx;
+
+					.active {
+						border-bottom: 2px solid rgb(22, 146, 50);
+					}
+				}
+			}
+
+
+			.table-title {
+				width: 100%;
+				display: flex;
+				color: #333;
+				flex-wrap: nowrap;
+				justify-content: space-between;
+
+				.code {
+					width: 40%;
+					word-break: normal
+				}
+
+				.name {
+					width: 40%;
+					word-break: normal
+				}
+
+				.total {
+					width: 15%;
+					word-break: normal
+				}
+
+			}
+
+			.table-content {
+				font-size: 28rpx;
+				display: flex;
+				padding: 10rpx 0;
+				width: 100%;
+				color: #333;
+				flex-wrap: nowrap;
+				justify-content: space-between;
+				border-bottom: 1px solid #eee;
+
+
+				.code {
+					display: flex;
+					width: 40%;
+
+					.index {
+						width: 20rpx;
+						margin-right: 20rpx;
+					}
+
+					.value {
+						word-break: break-all;
+						flex: 1;
+					}
+				}
+
+				.name {
+					width: 40%;
+					white-space: nowarp;
+					over-flow: hidden;
+					text-overflow: ellipsip;
+					word-break: break-all;
+				}
+
+				.total {
+					text-align: center;
+					width: 15%;
+					white-space: nowarp;
+					over-flow: hidden;
+					text-overflow: ellipsip;
+					word-break: break-all;
+				}
+			}
+
+		}
+
+		.data-rank .table-content:last-child {
+			border-bottom: none;
+		}
+
+		.data-bottom {
+			display: flex;
+			flex-wrap: wrap;
+			justify-content: space-between;
+
+			.cell {
+				display: flex;
+				width: 30%;
+				padding: 20rpx 0;
+				margin-bottom: 20rpx;
+				flex-direction: column;
+				background-color: #fff;
+				justify-content: center;
+				align-items: center;
+				border-radius: 10rpx;
+				color: #000;
+
+				.num {
+					font-size: 28rpx;
+				}
+
+				.label {
+
+					font-size: 20rpx;
+				}
+			}
+		}
+
+	}
+</style>

+ 141 - 0
pages/home/pages/manage/components/purchaseScreen.vue

@@ -0,0 +1,141 @@
+<template>
+	<view>
+		<u-popup :show="show" closeOnClickOverlay mode="top" @close="closePopup">
+			<view class="search_list">
+				<u-form labelPosition="left" :model="form" labelWidth="180" labelAlign="left" class="baseForm">
+					<u-form-item label="创建时间:" class="required-form" borderBottom prop="rangeDate">
+						<uni-datetime-picker v-model="rangeDate" :border="true" :icon="false" type="daterange" />
+					</u-form-item>
+					<u-form-item label="订单类型:" class="required-form" borderBottom prop="sourceType">
+						<zxz-uni-data-select :localdata="requirementSourceType" v-model="form.sourceType" dataValue='value'
+							dataKey="text" filterable format='{text}'></zxz-uni-data-select>
+					</u-form-item>
+					<u-form-item label="订单进度:" class="required-form" borderBottom prop="progress">
+						<zxz-uni-data-select :localdata="purchaseOrderProgressStatusEnum" v-model="form.progress" dataValue='value'
+							dataKey="label" filterable format='{label}'></zxz-uni-data-select>
+					</u-form-item>
+					<u-form-item label="审核状态:" class="required-form" borderBottom prop="orderStatus">
+						<zxz-uni-data-select :localdata="reviewStatusEnum" v-model="form.orderStatus" dataValue='value'
+							dataKey="label" filterable format='{label}'></zxz-uni-data-select>
+					</u-form-item>
+				</u-form>
+			</view>
+			<view class="operate_box rx-bc">
+				<u-button size="small" class="u-reset-button" @click="reset">
+					重置
+				</u-button>
+				<u-button type="success" size="small" class="u-reset-button" @click="submit">
+					确定
+				</u-button>
+			</view>
+		</u-popup>
+	</view>
+</template>
+
+<script>
+	import {
+		getWarehouseList,
+		getProduceTreeByPid
+	} from '@/api/warehouseManagement'
+	import {
+		post,
+		get
+	} from '@/utils/api.js'
+	import DictSelection from "@/components/Dict/DictSelection.vue";
+	import dictMxins from "@/mixins/dictMixins";
+	import { requirementSourceType, purchaseOrderProgressStatusEnum, reviewStatusEnum } from '@/enum/dict.js'
+	export default {
+		mixins: [dictMxins],
+		components: {
+			DictSelection
+		},
+		props: ['type', 'createTimeStart', 'createTimeEnd', 'sourceType',  'progress', 'orderStatus'],
+
+		data() {
+			return {
+				show: false,
+				rangeDate: [],
+				form: {
+					createTimeStart: '',
+					createTimeEnd: '',
+					sourceType: '',
+					progress: '',
+					orderStatus: ''
+				},
+				requirementSourceType,
+				purchaseOrderProgressStatusEnum,
+				reviewStatusEnum
+			}
+		},
+		created() {
+	
+		},
+		methods: {
+			open() {
+				this.show = true
+				for (let key of Object.keys(this.form)) {
+					this.form[key] = this[key]
+				}
+
+				// if(this.createTimeStart && this.createTimeEnd) {
+				this.rangeDate = [this.createTimeStart, this.createTimeEnd]
+				// } else {
+				// 	this.setDefaultRangeDate()
+				// }
+			},
+			setDefaultRangeDate() {
+				const now = new Date()
+				const year = now.getFullYear()
+				const month = String(now.getMonth() + 1).padStart(2, '0')
+				const day = String(now.getDate()).padStart(2, '0')
+				const today = `${year}-${month}-${day}`
+				if (this.type === 'year') {
+					this.rangeDate = [`${year}-01-01`, today]
+				} else if (this.type === 'month') {
+					this.rangeDate = [`${year}-${month}-01`, today]
+				}
+			},
+			closePopup() {
+				this.show = false
+			},
+			reset() {
+				this.form = {
+					createTimeStart: '',
+					createTimeEnd: '',
+					sourceType: '',
+					progress: '',
+					orderStatus: ''
+				}
+				this.rangeDate = [],
+				this.$emit('succeed', this.form)
+				this.closePopup()
+			},
+			submit() {
+				if(this.rangeDate.length) {
+					this.form.createTimeStart = this.rangeDate[0]
+					this.form.createTimeEnd = this.rangeDate[1]
+				}
+				this.$emit('succeed', this.form)
+				this.closePopup()
+			},
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.search_list {
+		min-height: 100rpx;
+
+		/deep/ .baseForm {
+			padding: 0 20rpx;
+		}
+	}
+
+	.operate_box {
+		padding: 10rpx 32rpx;
+
+		/deep/ .u-button {
+			width: 40%;
+		}
+	}
+</style>

+ 153 - 0
pages/home/pages/manage/components/salesScreen.vue

@@ -0,0 +1,153 @@
+<template>
+	<view>
+		<u-popup :show="show" closeOnClickOverlay mode="top" @close="closePopup">
+			<view class="search_list">
+				<u-form labelPosition="left" :model="form" labelWidth="180" labelAlign="left" class="baseForm">
+					<u-form-item label="创建时间:" class="required-form" borderBottom prop="rangeDate">
+						<uni-datetime-picker v-model="rangeDate" :border="true" :icon="false" type="daterange" />
+					</u-form-item>
+					<u-form-item label="订单类型:" class="required-form" borderBottom prop="needProduce">
+						<zxz-uni-data-select :localdata="orderTypeEnum" v-model="form.needProduce" dataValue='code'
+							dataKey="label" filterable format='{label}'></zxz-uni-data-select>
+					</u-form-item>
+					<u-form-item label="销售类型:" class="required-form" borderBottom prop="saleType">
+						<zxz-uni-data-select :localdata="dict['order_type']" v-model="form.saleType" dataValue='dictCode'
+							dataKey="dictValue" filterable format='{dictValue}'></zxz-uni-data-select>
+					</u-form-item>
+					<u-form-item label="订单进度:" class="required-form" borderBottom prop="progress">
+						<zxz-uni-data-select :localdata="saleOrderProgressStatusEnum" v-model="form.progress" dataValue='value'
+							dataKey="label" filterable format='{label}'></zxz-uni-data-select>
+					</u-form-item>
+					<u-form-item label="审核状态:" class="required-form" borderBottom prop="orderStatus">
+						<zxz-uni-data-select :localdata="reviewStatusEnum" v-model="form.orderStatus" dataValue='value'
+							dataKey="label" filterable format='{label}'></zxz-uni-data-select>
+					</u-form-item>
+				</u-form>
+			</view>
+			<view class="operate_box rx-bc">
+				<u-button size="small" class="u-reset-button" @click="reset">
+					重置
+				</u-button>
+				<u-button type="success" size="small" class="u-reset-button" @click="submit">
+					确定
+				</u-button>
+			</view>
+		</u-popup>
+	</view>
+</template>
+
+<script>
+	import {
+		getWarehouseList,
+		getProduceTreeByPid
+	} from '@/api/warehouseManagement'
+	import {
+		post,
+		get
+	} from '@/utils/api.js'
+	import DictSelection from "@/components/Dict/DictSelection.vue";
+	import dictMxins from "@/mixins/dictMixins";
+	import { orderTypeEnum, saleOrderProgressStatusEnum, reviewStatusEnum } from '@/enum/dict.js'
+	export default {
+		mixins: [dictMxins],
+		components: {
+			DictSelection
+		},
+		props: ['type', 'createTimeStart', 'createTimeEnd', 'needProduce', 'saleType', 'progress', 'orderStatus'],
+
+		data() {
+			return {
+				show: false,
+				rangeDate: [],
+				form: {
+					createTimeStart: '',
+					createTimeEnd: '',
+					needProduce: '',
+					saleType: '',
+					progress: '',
+					orderStatus: ''
+				},
+				orderTypeEnum,
+				saleOrderProgressStatusEnum,
+				reviewStatusEnum
+			}
+		},
+		created() {
+			this.requestDict("销售类型");
+	
+
+			console.log('dict~~~', this.dict)
+		},
+		methods: {
+			handleSaleTypeChange(val) {
+				console.log(val)
+			},
+			open() {
+				this.show = true
+				for (let key of Object.keys(this.form)) {
+					this.form[key] = this[key]
+				}
+
+				// if(this.createTimeStart && this.createTimeEnd) {
+				this.rangeDate = [this.createTimeStart, this.createTimeEnd]
+				// } else {
+				// 	this.setDefaultRangeDate()
+				// }
+			},
+			setDefaultRangeDate() {
+				const now = new Date()
+				const year = now.getFullYear()
+				const month = String(now.getMonth() + 1).padStart(2, '0')
+				const day = String(now.getDate()).padStart(2, '0')
+				const today = `${year}-${month}-${day}`
+				if (this.type === 'year') {
+					this.rangeDate = [`${year}-01-01`, today]
+				} else if (this.type === 'month') {
+					this.rangeDate = [`${year}-${month}-01`, today]
+				}
+			},
+			closePopup() {
+				this.show = false
+			},
+			reset() {
+				this.form = {
+					createTimeStart: '',
+					createTimeEnd: '',
+					needProduce: '',
+					saleType: '',
+					progress: '',
+					orderStatus: ''
+				}
+				this.rangeDate = [],
+				this.$emit('succeed', this.form)
+				this.closePopup()
+			},
+			submit() {
+				if(this.rangeDate.length) {
+					this.form.createTimeStart = this.rangeDate[0]
+					this.form.createTimeEnd = this.rangeDate[1]
+				}
+				this.$emit('succeed', this.form)
+				this.closePopup()
+			},
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.search_list {
+		min-height: 100rpx;
+
+		/deep/ .baseForm {
+			padding: 0 20rpx;
+		}
+	}
+
+	.operate_box {
+		padding: 10rpx 32rpx;
+
+		/deep/ .u-button {
+			width: 40%;
+		}
+	}
+</style>

+ 56 - 0
pages/home/pages/manage/documentDetail.vue

@@ -0,0 +1,56 @@
+<template>
+    <view class="main-container">
+        <uni-nav-bar fixed="true" statusBar="true" left-icon="back" title="公文详情" @clickLeft="back"></uni-nav-bar>
+        <view class="content-container">
+            <!-- <rich-text class="content" :nodes="formData.content"></rich-text> -->
+             <u-parse :content="formData.content"></u-parse>
+        </view>
+        <view class="file-container">
+            <fileMain v-model="fileIds" type="view"></fileMain>
+        </view>
+    </view>
+</template>
+<script>
+import { getNoticeDocumentDetail } from '@/api/home/index.js'
+import fileMain from "@/pages/doc/index.vue"
+export default {
+    components: {
+        fileMain
+    },
+    data() {
+        return {
+            query: {},
+            formData: {},
+            fileIds: []
+        }
+    },
+    onLoad(options) {
+        console.log(options)
+        this.query = options
+        this.getNoticeDocumentDetail()
+    },
+    methods: {
+        async getNoticeDocumentDetail() {
+            const res = await getNoticeDocumentDetail(this.query.id)
+            this.formData = res
+            const fileIds =this.formData.fields.find((item) => item.fieldKey == 'attachments')?.defaultValue || '';
+            this.fileIds = fileIds.split(',');
+            console.log(this.fileIds)
+        }
+    }
+}
+</script>
+<style scoped>
+.content-container {
+    padding: 20rpx;
+}
+
+.content {
+    width: 100%;
+}
+
+.file-container {
+    padding: 20rpx;
+    display: flex;
+}
+</style>

+ 536 - 0
pages/home/pages/manage/manage.vue

@@ -0,0 +1,536 @@
+<template>
+  <view class="manage-container">
+    <!-- 营销数据 -->
+    <view class="section">
+      <view class="section-header">
+        <view class="section-title">营销数据</view>
+      </view>
+      <view class="section-content">
+        <view class="data-cards">
+          <view class="data-card orange" @click="toSaleOrderDetail('year')">
+            <view class="data-header">本年度</view>
+            <view class="data-divider"></view>
+            <view class="data-row">
+              <text class="data-label">订单数量</text>
+              <text class="data-value">{{ marketing.yearOrderCount }}</text>
+            </view>
+            <view class="data-divider"></view>
+            <view class="data-row">
+              <text class="data-label">订单金额</text>
+              <text class="data-value">{{ marketing.yearOrderAmount }}<text class="data-unit">万元</text></text>
+            </view>
+          </view>
+          <view class="data-card orange" @click="toSaleOrderDetail('month')">
+            <view class="data-header">本月</view>
+            <view class="data-divider"></view>
+            <view class="data-row">
+              <text class="data-label">订单数量</text>
+              <text class="data-value">{{ marketing.monthOrderCount }}</text>
+            </view>
+            <view class="data-divider"></view>
+            <view class="data-row">
+              <text class="data-label">订单金额</text>
+              <text class="data-value">{{ marketing.monthOrderAmount }}<text class="data-unit">万元</text></text>
+            </view>
+          </view>
+        </view>
+        <view class="chart-wrapper">
+          <view class="chart-box">
+             <view id="marketingChart" class="chart"></view>
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <!-- 生产数据 -->
+    <view class="section">
+      <view class="section-header">
+        <view class="section-title">生产数据</view>
+      </view>
+      <view class="section-content">
+        <view class="data-cards">
+          <view class="data-card orange">
+            <view class="data-header">本年度</view>
+            <view class="data-row">
+              <text class="data-label">生产工单</text>
+              <text class="data-value">{{ production.yearWorkOrder }}</text>
+            </view>
+            <view class="data-divider"></view>
+            <view class="data-row">
+              <text class="data-label">生产总量</text>
+              <text class="data-value">{{ production.yearTotal }}<text class="data-unit">件</text></text>
+            </view>
+          </view>
+          <view class="data-card orange">
+            <view class="data-header">本月</view>
+            <view class="data-row">
+              <text class="data-label">生产工单</text>
+              <text class="data-value">{{ production.monthWorkOrder }}</text>
+            </view>
+            <view class="data-divider"></view>
+            <view class="data-row">
+              <text class="data-label">生产总量</text>
+              <text class="data-value">{{ production.monthTotal }}<text class="data-unit">件</text></text>
+            </view>
+          </view>
+        </view>
+        <view class="chart-wrapper">
+          <view class="chart-box">
+            <!-- <canvas canvas-id="productionChart" type="2d" class="chart"></canvas> -->
+             <view id="productionChart" class="chart"></view>
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <!-- 采购数据 -->
+    <view class="section">
+      <view class="section-header">
+        <view class="section-title">采购数据</view>
+      </view>
+      <view class="section-content">
+        <view class="data-cards">
+          <view class="data-card orange" @click="toPurchaseOrderDetail('year')">
+            <view class="data-header">本年度</view>
+            <view class="data-divider"></view>
+            <view class="data-row">
+              <text class="data-label">采购数量</text>
+              <text class="data-value">{{ purchase.yearCount }}</text>
+            </view>
+            <view class="data-divider"></view>
+            <view class="data-row">
+              <text class="data-label">采购金额</text>
+              <text class="data-value">{{ purchase.yearAmount }}<text class="data-unit">万元</text></text>
+            </view>
+          </view>
+          <view class="data-card orange" @click="toPurchaseOrderDetail('month')">
+            <view class="data-header">本月</view>
+            <view class="data-divider"></view>
+            <view class="data-row">
+              <text class="data-label">采购数量</text>
+              <text class="data-value">{{ purchase.monthCount }}</text>
+            </view>
+            <view class="data-divider"></view>
+            <view class="data-row">
+              <text class="data-label">采购金额</text>
+              <text class="data-value">{{ purchase.monthAmount }}<text class="data-unit">万元</text></text>
+            </view>
+          </view>
+        </view>
+        <view class="chart-wrapper">
+          <view class="chart-title">采购走势</view>
+          <view class="chart-box">
+            <!-- <canvas canvas-id="purchaseChart" type="2d" class="chart"></canvas> -->
+             <view id="purchaseChart" class="chart"></view>
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <!-- 仓储数据 -->
+    <view class="section">
+      <view class="section-header">
+        <view class="section-title">仓储数据</view>
+      </view>
+      <view class="section-content">
+        <view class="data-cards">
+          <view class="data-card orange">
+            <view class="data-header">年度出入库</view>
+            <view class="data-divider"></view>
+            <view class="data-row small">
+              <text class="data-label">采购入库</text>
+              <text class="data-value">{{ warehouse.yearPurchaseIn }}</text>
+            </view>
+            <view class="data-divider"></view>
+            <view class="data-row small">
+              <text class="data-label">领料出库</text>
+              <text class="data-value">{{ warehouse.yearMaterialOut }}</text>
+            </view>
+            <view class="data-divider"></view>
+            <view class="data-row small">
+              <text class="data-label">生产入库</text>
+              <text class="data-value">{{ warehouse.yearProduceIn }}</text>
+            </view>
+            <view class="data-divider"></view>
+            <view class="data-row small">
+              <text class="data-label">发货出库</text>
+              <text class="data-value">{{ warehouse.yearDeliveryOut }}</text>
+            </view>
+          </view>
+          <view class="data-card orange">
+            <view class="data-header">本月出入库</view>
+            <view class="data-divider"></view>
+            <view class="data-row small">
+              <text class="data-label">采购入库</text>
+              <text class="data-value">{{ warehouse.monthPurchaseIn }}</text>
+            </view>
+            <view class="data-divider"></view>
+            <view class="data-row small">
+              <text class="data-label">领料出库</text>
+              <text class="data-value">{{ warehouse.monthMaterialOut }}</text>
+            </view>
+            <view class="data-divider"></view>
+            <view class="data-row small">
+              <text class="data-label">生产入库</text>
+              <text class="data-value">{{ warehouse.monthProduceIn }}</text>
+            </view>
+            <view class="data-divider"></view>
+            <view class="data-row small">
+              <text class="data-label">发货出库</text>
+              <text class="data-value">{{ warehouse.monthDeliveryOut }}</text>
+            </view>
+          </view>
+        </view>
+        <view class="chart-wrapper">
+          <view class="chart-title">物料走势</view>
+          <view class="chart-box">
+            <!-- <canvas canvas-id="materialChart" type="2d" class="chart"></canvas> -->
+             <view id="materialChart" class="chart"></view>
+          </view>
+        </view>
+        <view class="chart-wrapper">
+          <view class="chart-title">成品走势</view>
+          <view class="chart-box">
+            <!-- <canvas canvas-id="finishedChart" type="2d" class="chart"></canvas> -->
+             <view id="finishedChart" class="chart"></view>
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <view class="bottom-safe"></view>
+  </view>
+</template>
+
+<script>
+import * as echarts from 'echarts'
+let chartInstances = {}
+
+export default {
+  data() {
+    return {
+      marketing: {
+        yearOrderCount: 23,
+        yearOrderAmount: 98,
+        monthOrderCount: 23,
+        monthOrderAmount: 98
+      },
+      production: {
+        yearWorkOrder: 23,
+        yearTotal: 98,
+        monthWorkOrder: 23,
+        monthTotal: 98
+      },
+      purchase: {
+        yearCount: 23,
+        yearAmount: 98,
+        monthCount: 23,
+        monthAmount: 98
+      },
+      warehouse: {
+        yearPurchaseIn: 23,
+        yearMaterialOut: 23,
+        yearProduceIn: 98,
+        yearDeliveryOut: 98,
+        monthPurchaseIn: 23,
+        monthMaterialOut: 23,
+        monthProduceIn: 98,
+        monthDeliveryOut: 98
+      },
+      chartData: {
+        marketingChart: {
+          categories: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
+          // 混合图表:柱状图(订单量) + 折线图(订单金额)
+          series: [
+            { name: '月订单量', data: [15, 20, 25, 30, 45, 50, 48, 40, 35, 42, 48, 52], type: 'bar' },
+            { name: '去年同期订单量', data: [12, 18, 22, 28, 40, 45, 42, 38, 32, 38, 45, 48], type: 'bar' },
+            { name: '月订单金额', data: [8.5, 10.2, 12.5, 15.0, 22.5, 25.0, 24.0, 20.0, 17.5, 21.0, 24.0, 26.0], type: 'line' },
+            { name: '去年同期订单金额', data: [6.0, 9.0, 11.0, 14.0, 20.0, 22.5, 21.0, 19.0, 16.0, 19.0, 22.5, 24.0], type: 'line' }
+          ]
+        },
+        productionChart: {
+          categories: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
+          series: [
+            { name: '生产工单', data: [18, 22, 28, 35, 42, 48, 45, 40, 38, 45, 50, 55], type: 'bar' },
+            { name: '去年同期工单', data: [15, 20, 25, 30, 38, 42, 40, 35, 32, 38, 45, 48], type: 'bar' },
+            { name: '生产总量', data: [180, 220, 280, 350, 420, 480, 450, 400, 380, 450, 500, 550], type: 'line' },
+            { name: '去年同期总量', data: [150, 200, 250, 300, 380, 420, 400, 350, 320, 380, 450, 480], type: 'line' }
+          ]
+        },
+        purchaseChart: {
+          categories: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
+          series: [
+            { name: '采购数量', data: [20, 25, 30, 38, 45, 52, 48, 42, 38, 45, 52, 58], type: 'bar' },
+            { name: '去年同期数量', data: [18, 22, 28, 35, 42, 48, 45, 38, 35, 42, 48, 52], type: 'bar' },
+            { name: '采购金额', data: [10.5, 12.5, 15.0, 19.0, 22.5, 26.0, 24.0, 21.0, 19.0, 22.5, 26.0, 29.0], type: 'line' },
+            { name: '去年同期金额', data: [9.0, 11.0, 14.0, 17.5, 21.0, 24.0, 22.5, 19.0, 17.5, 21.0, 24.0, 26.0], type: 'line' }
+          ]
+        },
+        materialChart: {
+          categories: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
+          series: [
+            { name: '采购入库', data: [22, 28, 35, 42, 50, 58, 52, 45, 42, 50, 58, 65], type: 'bar' },
+            { name: '去年同期入库', data: [18, 22, 28, 35, 42, 48, 45, 38, 35, 42, 48, 52], type: 'bar' },
+            { name: '领料出库', data: [20, 25, 32, 38, 45, 52, 48, 42, 38, 45, 52, 58], type: 'line' },
+            { name: '去年同期出库', data: [15, 20, 25, 32, 38, 45, 42, 38, 35, 42, 48, 52], type: 'line' }
+          ]
+        },
+        finishedChart: {
+          categories: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
+          series: [
+            { name: '生产入库', data: [18, 22, 28, 35, 42, 48, 45, 40, 38, 45, 50, 55], type: 'bar' },
+            { name: '去年同期入库', data: [15, 20, 25, 32, 38, 45, 42, 38, 35, 42, 48, 52], type: 'bar' },
+            { name: '发货出库', data: [15, 20, 25, 32, 38, 45, 42, 38, 35, 42, 48, 52], type: 'line' },
+            { name: '去年同期发货', data: [12, 18, 22, 28, 35, 42, 40, 35, 32, 38, 45, 48], type: 'line' }
+          ]
+        }
+      }
+    }
+  },
+  onReady() {
+    console.log('onReady11111111111111111111111111111111111111')
+    this.$nextTick(() => {
+      console.log('onReady - initCharts')
+      this.initCharts()
+    })
+  },
+  onLoad() {
+    console.log('onLoad22222222222222222222222222222222222222')
+  },
+  onUnload() {
+    Object.keys(chartInstances).forEach(key => {
+      chartInstances[key]?.dispose()
+    })
+  },
+  methods: {
+    toSaleOrderDetail(type) {
+      uni.navigateTo({
+        url: '/pages/home/pages/manage/saleOrderDetail?type=' + type
+      })
+    },
+    toPurchaseOrderDetail(type) {
+      uni.navigateTo({
+        url: '/pages/home/pages/manage/purchaseOrderDetail?type=' + type
+      })
+    },
+    initCharts() {
+      console.log('initCharts')
+      Object.keys(this.chartData).forEach(chartId => {
+        this.initChart(chartId, this.chartData[chartId])
+      })
+    },
+    initChart(domId, data) {
+      const query = uni.createSelectorQuery().in(this)
+      query.select(`#${domId}`).boundingClientRect()
+      query.exec(res => {
+        if (!res[0]) {
+          console.error(`Element #${domId} not found`)
+          return
+        }
+        const width = res[0].width || 355
+        const height = res[0].height || 200
+        console.log('init chart:', domId, width, height)
+
+        const chart = echarts.init(document.getElementById(domId))
+        chart.resize({ width, height })
+
+        const option = {
+          grid: {
+            left: 35,
+            right: 15,
+            top: 35,
+            bottom: 30
+          },
+          tooltip: {
+            show: true,
+            trigger: 'axis',
+            axisPointer: {
+              type: 'cross',
+              label: {
+                backgroundColor: '#6a7985'
+              }
+            },
+            backgroundColor: 'rgba(50, 50, 50, 0.9)',
+            borderColor: '#333',
+            textStyle: {
+              color: '#fff',
+              fontSize: 12
+            }
+          },
+          xAxis: {
+            type: 'category',
+            data: data.categories,
+            axisLine: { lineStyle: { color: '#e5e5e5' } },
+            axisLabel: { fontSize: 10, color: '#666' },
+            axisTick: { show: false }
+          },
+          yAxis: {
+            type: 'value',
+            min: 0,
+            splitNumber: 4,
+            axisLine: { show: false },
+            axisTick: { show: false },
+            splitLine: {
+              lineStyle: { color: '#e5e5e5', type: 'dashed' }
+            },
+            axisLabel: { fontSize: 10, color: '#666' }
+          },
+          series: data.series.map((item, index) => {
+            const chartType = item.type || 'line'
+            const barColors = ['#34c759', '#8bc34a', '#00bcd4', '#9c27b0']
+            const lineColors = ['#ff9500', '#faad14', '#e91e63', '#9c27b0']
+
+            if (chartType === 'bar') {
+              return {
+                name: item.name,
+                type: 'bar',
+                barWidth: 10,
+                itemStyle: {
+                  color: barColors[index % barColors.length]
+                },
+                data: item.data
+              }
+            } else {
+              return {
+                name: item.name,
+                type: 'line',
+                smooth: true,
+                symbol: 'circle',
+                symbolSize: 4,
+                lineStyle: {
+                  width: 2,
+                  color: lineColors[index % lineColors.length]
+                },
+                itemStyle: {
+                  color: lineColors[index % lineColors.length]
+                },
+                data: item.data
+              }
+            }
+          })
+        }
+
+        chart.setOption(option)
+        chartInstances[domId] = chart
+      })
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.manage-container {
+  min-height: 100vh;
+  // background: #f0f0f0;
+  padding-bottom: constant(safe-area-inset-bottom);
+  padding-bottom: env(safe-area-inset-bottom);
+}
+
+/* 数据区块 */
+.section {
+  margin-top: 2rpx;
+  padding-bottom: 8rpx;
+
+  .section-header {
+    padding: 24rpx 0 24rpx;
+
+    .section-title {
+      font-size: 30rpx;
+      font-weight: 600;
+      color: #333;
+      padding-left: 12rpx;
+      border-left: 6rpx solid #34c759;
+    }
+  }
+  .section-content {
+    background: #fff;
+  }
+}
+
+/* 数据卡片 */
+.data-cards {
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
+  gap: 16rpx;
+  padding: 20rpx;
+  border-radius: 4rpx;
+
+  .data-card {
+    border-radius: 12rpx;
+    overflow: hidden;
+    background: linear-gradient(135deg, #ff9500 0%, #ff6b00 100%);
+    box-shadow: 0 4rpx 16rpx rgba(255, 149, 0, 0.25);
+    padding: 20rpx;
+
+    .data-header {
+      font-size: 26rpx;
+      font-weight: 600;
+      color: #fff;
+      margin-bottom: 6rpx;
+    }
+
+    .data-divider {
+      height: 1rpx;
+      background: rgba(255, 255, 255, 0.2);
+    }
+
+    .data-row {
+      display: flex;
+      align-items: baseline;
+      justify-content: space-between;
+      padding: 8rpx 0;
+
+      &.small {
+        padding: 6rpx 0;
+      }
+
+      .data-label {
+        font-size: 24rpx;
+        color: rgba(255, 255, 255, 0.9);
+      }
+
+      .data-value {
+        font-size: 34rpx;
+        font-weight: 700;
+        color: #fff;
+      }
+
+      .data-unit {
+        font-size: 22rpx;
+        margin-left: 4rpx;
+        opacity: 0.85;
+      }
+    }
+  }
+}
+
+/* 图表 */
+.chart-wrapper {
+  padding: 16rpx 20rpx 8rpx;
+
+  .chart-title {
+    font-size: 26rpx;
+    color: #333;
+    margin-bottom: 10rpx;
+    font-weight: 500;
+  }
+
+  .chart-box {
+    // background: #f7f7f7;
+    border-radius: 10rpx;
+    overflow: hidden;
+  }
+
+  .chart {
+    width: 100%;
+    height: 280px;
+    min-height: 200px;
+    display: block;
+  }
+}
+
+.bottom-safe {
+  height: constant(safe-area-inset-bottom);
+  height: env(safe-area-inset-bottom);
+}
+</style>

+ 368 - 0
pages/home/pages/manage/purchaseOrderDetail.vue

@@ -0,0 +1,368 @@
+<template>
+	<view>
+		<uni-nav-bar fixed="true" statusBar="true" left-icon="back" title="采购订单明细" @clickLeft="back"></uni-nav-bar>
+		<view class="top-wrapper">
+			<uni-section>
+				<uni-easyinput prefixIcon="search" style="width: 460rpx" v-model="form.searchName" placeholder="请输入订单编码/供应商名称/合同编号/产品名称">
+				</uni-easyinput>
+			</uni-section>
+			<view style="display: flex;">
+				<button class="search_btn" @click="search">搜索</button>
+				<view class="more_search">
+					<image src="~@/static/moreSearch.svg" mode="" @click="handlScreen"></image>
+				</view>
+			</view>
+		</view>
+		<view class="mainBox">
+			<view class="scroll_box">
+				<scroll-view scroll-y="true" class="scroll-Y" @scrolltolower="lower">
+					<uni-table border stripe emptyText="暂无更多数据" style="width: 100%;">
+						<uni-tr style="width: 100%;">
+							<uni-th width="50" align="center" class="ellipsis">序号</uni-th>
+                            <uni-th width="120" align="center" class="ellipsis">订单编码</uni-th>
+                            <uni-th width="100" align="center" class="ellipsis">订单类型</uni-th>
+                            <uni-th width="120" align="center" class="ellipsis">采购部门</uni-th>
+							<uni-th width="120" align="center" class="ellipsis">产品名称</uni-th>
+                            <uni-th width="120" align="center" class="ellipsis">产品编码</uni-th>
+                            <uni-th width="120" align="center" class="ellipsis">采购方名称</uni-th>
+                            <uni-th width="120" align="center" class="ellipsis">供应商名称</uni-th>
+							<uni-th width="100" align="center" class="ellipsis">数量</uni-th>
+							<uni-th width="100" align="center" class="ellipsis">收货数量</uni-th>
+                            <uni-th width="100" align="center" class="ellipsis">金额</uni-th>
+                            <uni-th width="100" align="center" class="ellipsis">订单进度</uni-th>
+							<uni-th width="100" align="center" class="ellipsis">审核状态</uni-th>
+							<uni-th width="100" align="center" class="ellipsis">创建人</uni-th>
+							<uni-th width="100" align="center" class="ellipsis">创建时间</uni-th>
+						</uni-tr>
+						<!-- 表格数据行 -->
+						<uni-tr v-for="(item, index) in listData" :key="index">
+							<uni-td>
+								<view class="ellipsis">{{index+Number(1)}}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">
+									{{ item.orderNo }}
+								</view>
+							</uni-td>
+							<uni-td class="ellipsis">
+								<view>{{ item.sourceTypeName }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.deptName }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.productNames }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.productCodes }}</view>
+							</uni-td>
+                            <uni-td>
+								<view class="ellipsis">{{ item.partaName }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">
+									{{ item.partbName }}
+								</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.productCount }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.inboundCount }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.payAmount }}</view>
+							</uni-td>
+                            <uni-td>
+								<view class="ellipsis">{{ item.progressName }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.orderStatusName }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.createUserName }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.createTime }}</view>
+							</uni-td>
+						</uni-tr>
+					</uni-table>
+				</scroll-view>
+			</view>
+		</view>
+
+		<screen ref="screen" @succeed="cabScreen" :type="type" :createTimeStart="form.createTimeStart" :createTimeEnd="form.createTimeEnd" 
+			:sourceType="form.sourceType" :progress="form.progress" :orderStatus="form.orderStatus"></screen>
+	</view>
+
+</template>
+
+<script>
+	import screen from './components/purchaseScreen'
+    import { getPurchaseOrderList } from '@/api/purchasingManage/index.js'
+    import { listOrganizations } from '@/api/common.js'
+    import { purchaseOrderProgressStatusEnum, reviewStatusEnum } from '@/enum/dict.js'
+    
+	export default {
+		components: {
+			screen,
+            
+		},
+		data() {
+			return {
+				page: 1,
+				size: 20,
+				isEnd: true,
+				listData: [],
+                organizations: [],
+                type: '',
+				form: {
+					createTimeStart: '',
+					createTimeEnd: '',
+					sourceType: '',
+					progress: '',
+					orderStatus: ''
+				},
+                rangeDate: [],
+				status: 'loading'
+			}
+		},
+		onLoad(options) {
+			this.type = options.type
+		},
+		onShow() {},
+		//加载更多
+		onReachBottom() {
+			console.log('加载更多')
+			if (this.isEnd) {
+				return
+			}
+			this.getMoreLists()
+		},
+		created() {
+            this.setDefaultRangeDate()
+            this.getDeptInfo()
+			this.getData()
+		},
+		computed: {
+			
+		},
+		methods: {
+            setDefaultRangeDate() {
+				const now = new Date()
+				const year = now.getFullYear()
+				const month = String(now.getMonth() + 1).padStart(2, '0')
+				const day = String(now.getDate()).padStart(2, '0')
+				const today = `${year}-${month}-${day}`
+				if (this.type === 'year') {
+					this.rangeDate = [`${year}-01-01`, today]
+				} else if (this.type === 'month') {
+					this.rangeDate = [`${year}-${month}-01`, today]
+				}
+                this.form.createTimeStart = this.rangeDate[0]
+                this.form.createTimeEnd = this.rangeDate[1]
+			},
+            async getDeptInfo() {
+                try {
+                    const res = await listOrganizations(); // 假设接口直接返回部门数组(如用户提供的示例数据)
+                    this.organizations = res; // 存储部门列表到状态中
+                    console.log('部门列表加载完成:', this.organizations);
+                } catch (err) {
+                    console.error('加载部门列表失败:', err);
+                    this.organizations = []; // 异常时置空,避免匹配错误
+                }
+            },
+			lower() {
+				console.log('加载更多')
+				if (this.isEnd) {
+					return
+				}
+				this.getMoreLists()
+			},
+			expand(index, isOpen) {
+				this.$set(this.listData[index], 'open', isOpen)
+				console.log(this.listData[index])
+			},
+			//筛选
+			getData() {
+				let par = {
+					createTimeStart: '',
+					createTimeEnd: '',
+					sourceType: '',
+					progress: '',
+					orderStatus: ''
+				}
+				par.pageNum = this.page
+				par.size = this.size
+				// par = this.URLSearchParams(par)
+				console.log(par)
+				uni.showLoading({
+					title: '加载中'
+				})
+		
+                getPurchaseOrderList(par)
+                    .then(res => {
+                        console.log('res----', res)
+                        res.list = res.list.map(item => {
+                            const matchedDept = this.organizations.find(
+                                (dept) => dept.id === item.createDept 
+                            );
+                            item.deptName = matchedDept ? matchedDept.name : ''
+            
+                            item.progressName = purchaseOrderProgressStatusEnum.find(
+                                (val) => val.value == item.progress
+                            )?.label;
+                            item.orderStatusName = reviewStatusEnum.find(
+                                (val) => val.value == item.orderStatus
+                            )?.label;
+                            return {
+                                ...item
+                            }
+                        })
+                        console.log(res.list)
+                        this.listData = [...this.listData, ...res.list]
+                        let pages = res.count
+                        console.log(this.page)
+                        console.log(pages)
+                        if (this.listData.length < pages) {
+                            this.isEnd = false
+                            this.status = 'loading'
+                        } else {
+                            this.isEnd = true
+                            this.status = 'nomore'
+                        }
+                    })
+                    .finally(() => {
+                        uni.hideLoading()
+                    })
+			},
+
+			handlScreen() {
+				this.$refs.screen.open()
+			},
+			cabScreen(data) {
+				console.log('data---', data)
+				for (let key of Object.keys(data)) {
+					this.form[key] = data[key]
+				}
+				this.page = 1
+				this.listData = []
+				this.search()
+			},
+			search() {
+				this.listData = []
+				this.page = 1
+				this.getData()
+			},
+			getMoreLists() {
+				this.page++
+				this.getData()
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.mainBox {
+		height: 100vh;
+		width: 100%;
+		// display: flex;
+		// flex-direction: column;
+	}
+
+	.uni-easyinput__placeholder-class {
+		font-size: 28rpx;
+	}
+
+	/deep/.uni-table {
+		min-width: 100vw !important;
+		font-size: 28rpx;
+
+		.uni-table-td,
+		.uni-table-th {
+			padding: 10rpx !important;
+			text-align: center !important;
+			font-size: 28rpx;
+			color: #000000;
+		}
+	}
+
+	.ellipsis {
+		overflow: hidden;
+		text-overflow: ellipsis;
+		white-space: nowrap;
+		max-width: 160px;
+	}
+
+	/* 当屏幕宽度小于600px时,调整最大宽度 */
+	@media (max-width: 600px) {
+		.ellipsis {
+			max-width: 140px;
+			/* 小屏幕下更小的最大宽度 */
+		}
+	}
+
+	.top-wrapper {
+		display: flex;
+		height: 88rpx;
+		align-items: center;
+		justify-content: space-between;
+		padding: 20rpx;
+
+		/deep/.uni-section {
+			margin-top: 0px;
+		}
+
+		/deep/.uni-section-header {
+			padding: 0px;
+
+		}
+
+		.search_btn {
+			width: 120rpx;
+			height: 70rpx;
+			line-height: 70rpx;
+			background: $theme-color;
+			font-size: 28rpx;
+			color: #fff;
+		}
+
+		.menu_icon {
+			width: 44rpx;
+			height: 44rpx;
+			margin-left: 14rpx;
+		}
+
+		.more_search {
+			display: flex;
+			align-items: center;
+			height: 70rpx;
+			line-height: 70rpx;
+
+		}
+
+		/deep/.u-input {
+			border: 1rpx solid #ccc;
+
+			.u-input__content__field-wrapper__field {
+				height: 40rpx !important;
+			}
+		}
+
+		image {
+			width: 52rpx;
+			height: 52rpx;
+			margin-left: 10rpx;
+		}
+
+	}
+
+	.scroll_box {
+		flex: 1;
+		overflow: scroll;
+
+		.scroll-Y {
+			height: 100%;
+		}
+	}
+</style>

+ 370 - 0
pages/home/pages/manage/saleOrderDetail.vue

@@ -0,0 +1,370 @@
+<template>
+	<view>
+		<uni-nav-bar fixed="true" statusBar="true" left-icon="back" title="销售订单明细" @clickLeft="back"></uni-nav-bar>
+		<view class="top-wrapper">
+			<uni-section>
+				<uni-easyinput prefixIcon="search" style="width: 460rpx" v-model="form.searchName" placeholder="请输入订单编码/客户名称/合同编号/产品名称">
+				</uni-easyinput>
+			</uni-section>
+			<view style="display: flex;">
+				<button class="search_btn" @click="search">搜索</button>
+				<view class="more_search">
+					<image src="~@/static/moreSearch.svg" mode="" @click="handlScreen"></image>
+				</view>
+			</view>
+		</view>
+		<view class="mainBox">
+			<view class="scroll_box">
+				<scroll-view scroll-y="true" class="scroll-Y" @scrolltolower="lower">
+					<uni-table border stripe emptyText="暂无更多数据" style="width: 100%;">
+						<uni-tr style="width: 100%;">
+							<uni-th width="50" align="center" class="ellipsis">序号</uni-th>
+                            <uni-th width="120" align="center" class="ellipsis">订单编码</uni-th>
+                            <uni-th width="100" align="center" class="ellipsis">订单类型</uni-th>
+                            <uni-th width="120" align="center" class="ellipsis">发起人所属部门</uni-th>
+							<uni-th width="120" align="center" class="ellipsis">产品名称</uni-th>
+                            <uni-th width="120" align="center" class="ellipsis">产品编码</uni-th>
+                            <uni-th width="100" align="center" class="ellipsis">销售类型</uni-th>
+                            <uni-th width="100" align="center" class="ellipsis">到货方式</uni-th>
+                            <uni-th width="120" align="center" class="ellipsis">客户名称</uni-th>
+                            <uni-th width="120" align="center" class="ellipsis">售出方名称</uni-th>
+							<uni-th width="100" align="center" class="ellipsis">数量</uni-th>
+                            <uni-th width="100" align="center" class="ellipsis">金额</uni-th>
+                            <uni-th width="100" align="center" class="ellipsis">订单进度</uni-th>
+							<uni-th width="100" align="center" class="ellipsis">审核状态</uni-th>
+							<uni-th width="100" align="center" class="ellipsis">创建人</uni-th>
+							<uni-th width="100" align="center" class="ellipsis">创建时间</uni-th>
+						</uni-tr>
+						<!-- 表格数据行 -->
+						<uni-tr v-for="(item, index) in listData" :key="index">
+							<uni-td>
+								<view class="ellipsis">{{index+Number(1)}}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">
+									{{ item.orderNo }}
+								</view>
+							</uni-td>
+							<uni-td class="ellipsis">
+								<view>{{ item.needProduceName }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.deptName }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.productNames }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.productCodes }}</view>
+							</uni-td>
+                            <uni-td>
+								<view class="ellipsis">{{ item.saleTypeName }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">
+									{{ item.arrivalWaysName }}
+								</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.partaName }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.partbName }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.productCount }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.payAmount }}</view>
+							</uni-td>
+                            <uni-td>
+								<view class="ellipsis">{{ item.progressName }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.orderStatusName }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.createUserName }}</view>
+							</uni-td>
+							<uni-td>
+								<view class="ellipsis">{{ item.createTime }}</view>
+							</uni-td>
+						</uni-tr>
+					</uni-table>
+				</scroll-view>
+			</view>
+		</view>
+
+		<screen ref="screen" @succeed="cabScreen" :type="type" :createTimeStart="form.createTimeStart" :createTimeEnd="form.createTimeEnd" 
+			:needProduce="form.needProduce" :saleType="form.saleType" :progress="form.progress" :orderStatus="form.orderStatus"></screen>
+	</view>
+
+</template>
+
+<script>
+	import screen from './components/salesScreen'
+    import { getTableList } from '@/api/saleManage/saleorder/index.js'
+    import { listOrganizations } from '@/api/common.js'
+    import { orderTypeEnum, saleOrderProgressStatusEnum, reviewStatusEnum } from '@/enum/dict.js'
+    
+	export default {
+		components: {
+			screen,
+            
+		},
+		data() {
+			return {
+				page: 1,
+				size: 20,
+				isEnd: true,
+				listData: [],
+                organizations: [],
+                type: '',
+				form: {
+					createTimeStart: '',
+					createTimeEnd: '',
+					needProduce: '',
+					saleType: '',
+					progress: '',
+					orderStatus: ''
+				},
+                rangeDate: [],
+				status: 'loading'
+			}
+		},
+		onLoad(options) {
+			this.type = options.type
+		},
+		onShow() {},
+		//加载更多
+		onReachBottom() {
+			console.log('加载更多')
+			if (this.isEnd) {
+				return
+			}
+			this.getMoreLists()
+		},
+		created() {
+            this.setDefaultRangeDate()
+            this.getDeptInfo()
+			this.getData()
+		},
+		computed: {
+			
+		},
+		methods: {
+            setDefaultRangeDate() {
+				const now = new Date()
+				const year = now.getFullYear()
+				const month = String(now.getMonth() + 1).padStart(2, '0')
+				const day = String(now.getDate()).padStart(2, '0')
+				const today = `${year}-${month}-${day}`
+				if (this.type === 'year') {
+					this.rangeDate = [`${year}-01-01`, today]
+				} else if (this.type === 'month') {
+					this.rangeDate = [`${year}-${month}-01`, today]
+				}
+                this.form.createTimeStart = this.rangeDate[0]
+                this.form.createTimeEnd = this.rangeDate[1]
+			},
+            async getDeptInfo() {
+                try {
+                    const res = await listOrganizations(); // 假设接口直接返回部门数组(如用户提供的示例数据)
+                    this.organizations = res; // 存储部门列表到状态中
+                    console.log('部门列表加载完成:', this.organizations);
+                } catch (err) {
+                    console.error('加载部门列表失败:', err);
+                    this.organizations = []; // 异常时置空,避免匹配错误
+                }
+            },
+			lower() {
+				console.log('加载更多')
+				if (this.isEnd) {
+					return
+				}
+				this.getMoreLists()
+			},
+			expand(index, isOpen) {
+				this.$set(this.listData[index], 'open', isOpen)
+				console.log(this.listData[index])
+			},
+			//筛选
+			getData() {
+				let par = JSON.parse(JSON.stringify(this.form))
+				par.pageNum = this.page
+				par.size = this.size
+				// par = this.URLSearchParams(par)
+				console.log(par)
+				uni.showLoading({
+					title: '加载中'
+				})
+		
+                getTableList(par)
+                    .then(res => {
+                        console.log('res----', res)
+                        res.list = res.list.map(item => {
+                            const matchedDept = this.organizations.find(
+                                (dept) => dept.id === item.createDept 
+                            );
+                            item.deptName = matchedDept ? matchedDept.name : ''
+                            item.needProduceName = orderTypeEnum.find(
+                                (type) => type.code === item.needProduce 
+                            )?.label || ''
+                            item.arrivalWaysName = item.arrivalWays == 1 ? '一次性到货' : item.arrivalWays == 2 ? '分批到货' : ''
+                            item.progressName = saleOrderProgressStatusEnum.find(
+                                (val) => val.value == item.progress
+                            )?.label;
+                            item.orderStatusName = reviewStatusEnum.find(
+                                (val) => val.value == item.orderStatus
+                            )?.label;
+                            return {
+                                ...item
+                            }
+                        })
+                        console.log(res.list)
+                        this.listData = [...this.listData, ...res.list]
+                        let pages = res.count
+                        console.log(this.page)
+                        console.log(pages)
+                        if (this.listData.length < pages) {
+                            this.isEnd = false
+                            this.status = 'loading'
+                        } else {
+                            this.isEnd = true
+                            this.status = 'nomore'
+                        }
+                    })
+                    .finally(() => {
+                        uni.hideLoading()
+                    })
+			},
+
+			handlScreen() {
+				this.$refs.screen.open()
+			},
+			cabScreen(data) {
+				console.log('data---', data)
+				for (let key of Object.keys(data)) {
+					this.form[key] = data[key]
+				}
+				this.page = 1
+				this.listData = []
+				this.search()
+			},
+			search() {
+				this.listData = []
+				this.page = 1
+				this.getData()
+			},
+			getMoreLists() {
+				this.page++
+				this.getData()
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.mainBox {
+		height: 100vh;
+		width: 100%;
+		// display: flex;
+		// flex-direction: column;
+	}
+
+	.uni-easyinput__placeholder-class {
+		font-size: 28rpx;
+	}
+
+	/deep/.uni-table {
+		min-width: 100vw !important;
+		font-size: 28rpx;
+
+		.uni-table-td,
+		.uni-table-th {
+			padding: 10rpx !important;
+			text-align: center !important;
+			font-size: 28rpx;
+			color: #000000;
+		}
+	}
+
+	.ellipsis {
+		overflow: hidden;
+		text-overflow: ellipsis;
+		white-space: nowrap;
+		max-width: 160px;
+	}
+
+	/* 当屏幕宽度小于600px时,调整最大宽度 */
+	@media (max-width: 600px) {
+		.ellipsis {
+			max-width: 140px;
+			/* 小屏幕下更小的最大宽度 */
+		}
+	}
+
+	.top-wrapper {
+		display: flex;
+		height: 88rpx;
+		align-items: center;
+		justify-content: space-between;
+		padding: 20rpx;
+
+		/deep/.uni-section {
+			margin-top: 0px;
+		}
+
+		/deep/.uni-section-header {
+			padding: 0px;
+
+		}
+
+		.search_btn {
+			width: 120rpx;
+			height: 70rpx;
+			line-height: 70rpx;
+			background: $theme-color;
+			font-size: 28rpx;
+			color: #fff;
+		}
+
+		.menu_icon {
+			width: 44rpx;
+			height: 44rpx;
+			margin-left: 14rpx;
+		}
+
+		.more_search {
+			display: flex;
+			align-items: center;
+			height: 70rpx;
+			line-height: 70rpx;
+
+		}
+
+		/deep/.u-input {
+			border: 1rpx solid #ccc;
+
+			.u-input__content__field-wrapper__field {
+				height: 40rpx !important;
+			}
+		}
+
+		image {
+			width: 52rpx;
+			height: 52rpx;
+			margin-left: 10rpx;
+		}
+
+	}
+
+	.scroll_box {
+		flex: 1;
+		overflow: scroll;
+
+		.scroll-Y {
+			height: 100%;
+		}
+	}
+</style>