yusheng 6 일 전
부모
커밋
0ee8561ae5

+ 3 - 1
.hbuilderx/launch.json

@@ -20,12 +20,14 @@
         },
         {
             "customPlaygroundType" : "device",
+            "localRepoPath" : "D:/公司项目/aiot-app/unpackage/debug",
             "openVueDevtools" : true,
             "packageName" : "uni.app.UNI45B3907",
-            "playground" : "standard",
+            "playground" : "custom",
             "type" : "uni-app:app-android"
         },
         {
+            "customPlaygroundType" : "device",
             "openVueDevtools" : true,
             "playground" : "custom",
             "type" : "uni-app:app-ios"

+ 73 - 0
api/snapshot/index.js

@@ -0,0 +1,73 @@
+import {
+  get,
+  put,
+  putJ,
+  postJ,
+  deleteApi
+} from "@/utils/request";
+import Vue from "vue";
+
+// 随手拍分页列表
+export async function getList(params) {
+  const res = await get(Vue.prototype.apiUrl + '/ehs/safetyquickshot/page', params);
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
+}
+
+// 随手拍详情
+export async function getById(id) {
+  const res = await get(Vue.prototype.apiUrl + `/ehs/safetyquickshot/getById/${id}`);
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
+}
+
+// 保存随手拍
+export async function save(data) {
+  const res = await postJ(Vue.prototype.apiUrl + '/ehs/safetyquickshot/save', data);
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
+}
+
+// 更新随手拍
+export async function update(data) {
+  const url = Vue.prototype.apiUrl + '/ehs/safetyquickshot/' + (data.id ? 'update' : 'save');
+  const fn = data.id ? putJ : postJ;
+  const res = await fn(url, data);
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
+}
+
+// 删除随手拍
+export async function remove(data) {
+  const res = await deleteApi(Vue.prototype.apiUrl + '/ehs/safetyquickshot/delete', data);
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
+}
+
+// 处理/下发整改
+export async function handle(data) {
+  const res = await postJ(Vue.prototype.apiUrl + '/ehs/safetyquickshot/handle', data);
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
+}
+
+// 废弃
+export async function discard(data) {
+  const res = await postJ(Vue.prototype.apiUrl + '/ehs/safetyquickshot/discard', data);
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
+}

+ 127 - 0
components/AlbumDeletable/AlbumDeletable.vue

@@ -0,0 +1,127 @@
+<template>
+  <view class="album-deletable">
+    <view
+      class="album-item"
+      v-for="(item, index) in urls"
+      :key="index"
+      :style="itemStyle"
+    >
+      <image
+        class="album-image"
+        :src="getSrc(item)"
+        mode="aspectFill"
+        @tap="previewFullImage ? onPreviewTap(index) : ''"
+      />
+      <view
+        v-if="deletable"
+        class="delete-btn"
+        @tap.stop="handleDelete(index, item)"
+      >
+        <u-icon name="close-circle-fill" color="#ff4d4f" size="22"></u-icon>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: 'AlbumDeletable',
+  props: {
+    urls: {
+      type: Array,
+      default: () => [],
+    },
+    keyName: {
+      type: String,
+      default: '',
+    },
+    singleSize: {
+      type: [String, Number],
+      default: 180,
+    },
+    multipleSize: {
+      type: [String, Number],
+      default: 170,
+    },
+    space: {
+      type: [String, Number],
+      default: 12,
+    },
+    rowCount: {
+      type: [String, Number],
+      default: 3,
+    },
+    deletable: {
+      type: Boolean,
+      default: true,
+    },
+    previewFullImage: {
+      type: Boolean,
+      default: true,
+    },
+  },
+  computed: {
+    itemStyle() {
+      const size =
+        this.urls.length === 1
+          ? uni.$u.addUnit(this.singleSize)
+          : uni.$u.addUnit(this.multipleSize);
+      return {
+        width: size,
+        height: size,
+        marginRight: uni.$u.addUnit(this.space),
+        marginBottom: uni.$u.addUnit(this.space),
+      };
+    },
+  },
+  methods: {
+    getSrc(item) {
+      return uni.$u.test.object(item)
+        ? (this.keyName && item[this.keyName]) || item.src
+        : item;
+    },
+    onPreviewTap(index) {
+      const urls = this.urls.map((item) => this.getSrc(item));
+      uni.previewImage({
+        current: urls[index],
+        urls,
+      });
+    },
+    handleDelete(index, item) {
+      this.$emit('delete', index, item);
+    },
+  },
+};
+</script>
+
+<style scoped lang="scss">
+.album-deletable {
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.album-item {
+  position: relative;
+  flex-shrink: 0;
+}
+
+.album-image {
+  width: 100%;
+  height: 100%;
+  border-radius: 12rpx;
+}
+
+.delete-btn {
+  position: absolute;
+  top: -10rpx;
+  right: -10rpx;
+  width: 44rpx;
+  height: 44rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: #fff;
+  border-radius: 50%;
+  z-index: 2;
+}
+</style>

+ 0 - 0
pages/ems/centralizedMeterReading/components/myCard.vue → components/myCard.vue


+ 15 - 4
manifest.json

@@ -2,7 +2,7 @@
     "name" : "智慧工厂",
     "appid" : "__UNI__45B3907",
     "description" : "",
-    "versionName" : "V1.0.4.14",
+    "versionName" : "V1.0.4.15",
     "versionCode" : "100",
     "transformPx" : false,
     "h5" : {
@@ -42,7 +42,8 @@
         /* 模块配置 */
         "modules" : {
             "Camera" : {},
-            "Barcode" : {}
+            "Barcode" : {},
+            "Push" : {}
         },
         /* 应用发布信息 */
         "distribute" : {
@@ -74,7 +75,10 @@
             },
             /* SDK配置 */
             "sdkConfigs" : {
-                "ad" : {}
+                "ad" : {},
+                "push" : {
+                    "unipush" : {}
+                }
             },
             "icons" : {
                 "android" : {
@@ -134,5 +138,12 @@
     },
     "vueVersion" : "2",
     "fallbackLocale" : "zh-Hans",
-    "sassImplementationName" : "node-sass"
+    "sassImplementationName" : "node-sass",
+    "app-harmony" : {
+        "distribute" : {
+            "modules" : {
+                "uni-push" : {}
+            }
+        }
+    }
 }

+ 48 - 6
pages.json

@@ -2666,7 +2666,7 @@
 				"navigationStyle": "custom",
 				"navigationBarTextStyle": "black"
 			}
-		}, 
+		},
 		{
 			"path": "pages/home/pages/manage/purchaseOrderDetail",
 			"style": {
@@ -2674,7 +2674,7 @@
 				"navigationStyle": "custom",
 				"navigationBarTextStyle": "black"
 			}
-		}, 
+		},
 		{
 			"path": "pages/home/components/DeviceDetail",
 			"style": {
@@ -2730,6 +2730,27 @@
 				"navigationStyle": "custom",
 				"navigationBarTextStyle": "black"
 			}
+		}, {
+			"path": "pages/pcs/QualityInspection",
+			"style": {
+				"navigationBarTitleText": "来煤质检记录",
+				"navigationStyle": "custom",
+				"navigationBarTextStyle": "black"
+			}
+		}, {
+			"path": "pages/pcs/HaulSlag",
+			"style": {
+				"navigationBarTitleText": "拉渣记录表",
+				"navigationStyle": "custom",
+				"navigationBarTextStyle": "black"
+			}
+		}, {
+			"path": "pages/pcs/TransportAsh",
+			"style": {
+				"navigationBarTitleText": "拉灰记录表 ",
+				"navigationStyle": "custom",
+				"navigationBarTextStyle": "black"
+			}
 		},
 		{
 			"path": "pages/ems/centralizedMeterReading/manualcentralizedMeterReading",
@@ -2738,7 +2759,7 @@
 				"navigationStyle": "custom",
 				"navigationBarTextStyle": "black"
 			}
-		},  
+		},
 		{
 			"path": "pages/warehouse/hwQrcode/index",
 			"style": {
@@ -2746,16 +2767,37 @@
 				"navigationStyle": "custom",
 				"navigationBarTextStyle": "black"
 			}
+		},
+
+
+
+
+		//安全生产
+		{
+			"path": "pages/ehs/snapshot/mySnapshot",
+			"style": {
+				"navigationBarTitleText": "我的随手拍",
+				"navigationStyle": "custom",
+				"navigationBarTextStyle": "black"
+			}
+		}, {
+			"path": "pages/ehs/snapshot/snapshotManage",
+			"style": {
+				"navigationBarTitleText": "随手拍管理",
+				"navigationStyle": "custom",
+				"navigationBarTextStyle": "black"
+			}
 		}
+
+
 	],
 	"tabBar": {
 		"color": "#908f8f",
 		"selectedColor": "#157a2c",
-		"borderStyle": "black", 
+		"borderStyle": "black",
 		"backgroundColor": "#ffffff",
 		"fontSize": "14px",
-		"list": [
-			{
+		"list": [{
 				"pagePath": "pages/home/home",
 				"iconPath": "static/tab/home.png",
 				"selectedIconPath": "static/tab/home_.png",

+ 49 - 0
pages/ehs/snapshot/common-style.scss

@@ -0,0 +1,49 @@
+// pages/snapshot/common-style.scss
+.mainBox {
+  background-color: #f3f8fb;
+  min-height: 100vh;
+}
+.top-wrapper {
+  background-color: #fff;
+  display: flex;
+  width: 750rpx;
+  padding: 16rpx 32rpx;
+  align-items: center;
+  position: sticky;
+  top: 0;
+  z-index: 999;
+  .search-form {
+    flex: 1;
+    /deep/ .uni-forms-item {
+      margin-bottom: 0;
+    }
+  }
+  .search_btn {
+    width: 120rpx;
+    height: 70rpx;
+    line-height: 70rpx;
+    padding: 0 24rpx;
+    background: $theme-color; // 全局主题色变量
+    font-size: 32rpx;
+    color: #fff;
+    margin: 0;
+    margin-left: 26rpx;
+    border-radius: 12rpx;
+  }
+}
+.wrapper {
+  padding-top: 20rpx;
+}
+.add {
+  width: 96rpx;
+  height: 96rpx;
+  border-radius: 48rpx;
+  background: #3c9cff;
+  position: fixed;
+  bottom: 100rpx;
+  right: 24rpx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.2);
+}

+ 74 - 0
pages/ehs/snapshot/components/discardDialog.vue

@@ -0,0 +1,74 @@
+<!-- components/discardDialog.vue - 废弃弹窗 -->
+<template>
+  <uni-popup ref="popup" type="center">
+    <view class="discard-dialog">
+      <view class="title">废弃</view>
+      <uni-forms ref="form" :modelValue="formData" :rules="rules" label-width="100px">
+        <uni-forms-item label="废弃原因" name="handleOpinion">
+          <textarea v-model="formData.handleOpinion" placeholder="请输入废弃原因(100字以内)" maxlength="100" />
+        </uni-forms-item>
+        <uni-forms-item label="废弃人">
+          <input v-model="formData.handlerName" disabled />
+        </uni-forms-item>
+      </uni-forms>
+      <view class="footer">
+        <button @click="close">取消</button>
+        <button type="primary" @click="handleSubmit">确定</button>
+      </view>
+    </view>
+  </uni-popup>
+</template>
+
+<script>
+export default {
+  emits: ['confirm'],
+  data() {
+    return {
+      formData: { id: '', handleOpinion: '', handlerName: '' },
+      rules: { handleOpinion: { required: true, message: '请输入废弃原因', trigger: 'blur' } }
+    };
+  },
+  methods: {
+    open(row) {
+      const userInfo = uni.getStorageSync('userInfo') || {};
+      this.formData = {
+        id: row.id,
+        handleOpinion: row.handleOpinion || '',
+        handlerName: row.handlerName || userInfo.name || ''
+      };
+      this.$refs.popup.open();
+    },
+    close() {
+      this.$refs.popup.close();
+      this.$refs.form?.resetFields();
+    },
+    async handleSubmit() {
+      const valid = await this.$refs.form.validate();
+      if (!valid) return;
+      this.$emit('confirm', { id: this.formData.id, handleOpinion: this.formData.handleOpinion });
+      this.close();
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.discard-dialog {
+  width: 500rpx;
+  background: #fff;
+  border-radius: 16rpx;
+  padding: 30rpx;
+  .title {
+    font-size: 36rpx;
+    font-weight: bold;
+    text-align: center;
+    margin-bottom: 30rpx;
+  }
+  .footer {
+    display: flex;
+    gap: 20rpx;
+    margin-top: 30rpx;
+    button { flex: 1; margin: 0; }
+  }
+}
+</style>

+ 478 - 0
pages/ehs/snapshot/components/snapshotDialog.vue

@@ -0,0 +1,478 @@
+<template>
+	<u-popup :show="visible" :round="0" :closeOnClickOverlay="false" :zIndex="99999" @close="handleCancel"
+		class="u-popup-my">
+		<view class="popup-content">
+			<view class="popup-header">
+				<text class="popup-title">{{ dialogTitle }}</text>
+				<view class="close-btn" @click="handleCancel">×</view>
+			</view>
+
+			<scroll-view class="popup-body" scroll-y>
+				<view class="page">
+					<view class="card-a">
+						<!-- 头部 -->
+						<view class="a-header">
+							<text class="a-main-title">随手拍记录</text>
+						</view>
+
+						<!-- 基础信息 -->
+						<view class="card-section">
+							<view class="section-title">📝 基础信息</view>
+							<view class="info-list">
+								<view class="info-item">
+									<text class="info-label">问题描述</text>
+									<textarea v-if="canEdit" class="info-textarea" v-model="formData.description"
+										placeholder="请输入问题描述" :disabled="!canEdit" />
+									<text v-else class="info-value readonly">{{ formData.description }}</text>
+								</view>
+								<view class="info-item">
+									<text class="info-label">问题所在位置</text>
+									<input v-if="canEdit" class="info-input" v-model="formData.location"
+										placeholder="请输入位置" :disabled="!canEdit" />
+									<text v-else class="info-value readonly">{{ formData.location }}</text>
+								</view>
+								<view class="info-item">
+									<text class="info-label">问题所属部门</text>
+
+
+									<view class="info-value" :class="{ disabled: !canEdit }"
+										@click="title != '详情' && $refs.treePicker._show()">
+										{{ formData.problemDeptName || "请选择" }}
+									</view>
+
+								</view>
+								<view class="info-item">
+									<text class="info-label">随手拍图片</text>
+									<fileMain v-if="canEdit" v-model="formData.attachment"
+										:type="canEdit ? '' : 'view'" />
+									<view v-else class="image-list">
+										<image v-for="(img, idx) in formData.attachment" :key="idx" :src="img.url"
+											mode="aspectFill" @click="previewImage(img.url)" />
+									</view>
+								</view>
+							</view>
+						</view>
+
+						<!-- 上报信息 -->
+						<view class="card-section">
+							<view class="section-title">👤 上报信息</view>
+							<view class="info-list">
+								<view class="info-item">
+									<text class="info-label">上报人</text>
+									<text class="info-value readonly">{{ formData.reporterName }}</text>
+								</view>
+								<view class="info-item">
+									<text class="info-label">上报人部门</text>
+									<text class="info-value readonly">{{ formData.reporterDeptName }}</text>
+								</view>
+								<view class="info-item" v-if="!canEdit">
+									<text class="info-label">处理结果</text>
+									<view class="info-value">
+										<text v-if="formData.handleResult == 0" class="status-pending">待处理</text>
+										<text v-else class="status-link" :class="{
+                        'status-done': formData.handleResult == 1,
+                        'status-discard': formData.handleResult == 2
+                      }" @click="handleViewResult">{{ getResultLabel(formData.handleResult) }}</text>
+									</view>
+								</view>
+							</view>
+						</view>
+					</view>
+				</view>
+			</scroll-view>
+
+			<view class="popup-footer">
+				<template v-if="isView">
+					<u-button type="default" @click="handleCancel">关闭</u-button>
+				</template>
+				<template v-else-if="isHandle">
+					<u-button type="default" @click="handleDiscard">废弃</u-button>
+					<u-button type="primary" @click="handleRectify">下发整改</u-button>
+				</template>
+				<template v-else>
+					<u-button type="default" @click="handleCancel">取消</u-button>
+					<u-button type="primary" @click="handleSubmit" :loading="loading">保存</u-button>
+				</template>
+			</view>
+		</view>
+		<u-toast ref="uToast"></u-toast>
+		<ba-tree-picker ref="treePicker" key="verify" :multiple="false" @select-change="searchDeptNodeClick"
+			title="选择部门" :localdata="classificationList" valueKey="id" textKey="name" childrenKey="children" />
+	</u-popup>
+</template>
+
+<script>
+	import {
+		getById,
+		save,
+		update
+	} from '@/api/snapshot/index.js';
+	import fileMain from "@/pages/doc/index.vue"
+	import {
+		listOrganizations
+	} from "@/api/common.js";
+	import {
+		toTreeData
+	} from "@/utils/utils.js";
+	export default {
+		emits: ['reload', 'rectify', 'discard'],
+		components: {
+			fileMain
+		},
+		data() {
+			return {
+				visible: false,
+				loading: false,
+				dialogType: 'add',
+				formData: this.getDefaultForm(),
+				classificationList: [],
+				resultOptions: [{
+						value: 1,
+						label: '下发整改'
+					},
+					{
+						value: 2,
+						label: '废弃'
+					}
+				]
+			};
+		},
+		computed: {
+			dialogTitle() {
+				const map = {
+					add: '新增随手拍',
+					edit: '编辑随手拍',
+					view: '随手拍详情',
+					handle: '随手拍处理'
+				};
+				return map[this.dialogType] || '随手拍';
+			},
+			isView() {
+				return this.dialogType === 'view';
+			},
+			isHandle() {
+				return this.dialogType === 'handle';
+			},
+			canEdit() {
+				return ['add', 'edit'].includes(this.dialogType);
+			}
+		},
+		methods: {
+			getDefaultForm() {
+				return {
+					id: '',
+					description: '',
+					location: '',
+					problemDeptId: '',
+					problemDeptName: '',
+					attachment: [],
+					reporterId: '',
+					reporterName: '',
+					reporterDeptId: '',
+					reporterDeptName: '',
+					handleResult: 0,
+					handleOpinion: '',
+					invHazardId: ''
+				};
+			},
+			async getTreeList() {
+				const data = await listOrganizations({});
+				let treeList = toTreeData({
+					data: data || [],
+					idField: "id",
+					parentIdField: "parentId",
+				});
+				this.classificationList = treeList;
+			},
+			async open(type, row = null) {
+				this.dialogType = type;
+				if (row && row.id && ['edit', 'view', 'handle'].includes(type)) {
+					try {
+						const data = await getById(row.id);
+						this.formData = {
+							...data,
+							attachment: data.attachment || []
+						};
+					} catch (e) {
+						console.error(e);
+					}
+				} else {
+					this.formData = this.getDefaultForm();
+					const userInfo = uni.getStorageSync('userInfo') || {};
+					this.formData.reporterName = userInfo.name || '';
+					this.formData.reporterId = userInfo.userId || '';
+					this.formData.reporterDeptName = userInfo.groupName || '';
+					this.formData.reporterDeptId = userInfo.groupId || '';
+				}
+				this.getTreeList();
+				this.visible = true;
+			},
+			//选择部门(搜索)
+			async searchDeptNodeClick(id, name, type) {
+				this.formData.problemDeptId = id[0];
+				this.formData.problemDeptName = name;
+	
+			},
+			handleCancel() {
+				this.visible = false;
+				this.resetForm();
+			},
+			resetForm() {
+				this.formData = this.getDefaultForm();
+			},
+			getResultLabel(result) {
+				const item = this.resultOptions.find(opt => opt.value == result);
+				return item ? item.label : '待处理';
+			},
+			previewImage(url) {
+				uni.previewImage({
+					urls: [url]
+				});
+			},
+			handleViewResult() {
+				if (this.formData.handleResult == 2) {
+					uni.showModal({
+						title: '废弃原因',
+						content: this.formData.handleOpinion || '无',
+						showCancel: false
+					});
+				} else if (this.formData.handleResult == 1 && this.formData.invHazardId) {
+					uni.navigateTo({
+						url: `/pages/hazard/detail?id=${this.formData.invHazardId}`
+					});
+				}
+			},
+			async handleSubmit() {
+				// 简单校验
+				if (!this.formData.description) {
+					this.$refs.uToast.show({
+						type: 'error',
+						message: '请输入问题描述'
+					});
+					return;
+				}
+				if (!this.formData.location) {
+					this.$refs.uToast.show({
+						type: 'error',
+						message: '请输入问题所在位置'
+					});
+					return;
+				}
+				const api = this.dialogType === 'add' ? save : update;
+				this.loading = true;
+				try {
+					await api(this.formData);
+					this.$refs.uToast.show({
+						type: 'success',
+						message: this.dialogType === 'add' ? '新增成功' : '编辑成功'
+					});
+					this.visible = false;
+					this.$emit('reload');
+					this.resetForm();
+				} catch (e) {
+					console.error(e);
+				} finally {
+					this.loading = false;
+				}
+			},
+			handleRectify() {
+				this.$emit('rectify', this.formData);
+				this.visible = false;
+			},
+			handleDiscard() {
+				this.$emit('discard', this.formData);
+				this.visible = false;
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.popup-content {
+		width: 100vw;
+		height: calc(100vh - 100px);
+		background: #fff;
+		border-radius: 0;
+		display: flex;
+		flex-direction: column;
+		background-color: #eff2f7;
+	}
+
+	.popup-header {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		padding: 30rpx;
+		border-bottom: 1rpx solid #e5e5e5;
+		background: #fff;
+
+		.popup-title {
+			font-size: 36rpx;
+			font-weight: bold;
+			color: #333;
+		}
+
+		.close-btn {
+			width: 60rpx;
+			height: 60rpx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			font-size: 60rpx;
+			color: #999;
+			line-height: 1;
+		}
+	}
+
+	.popup-body {
+		flex: 1;
+		overflow-y: auto;
+		padding: 28rpx;
+	}
+
+	.page {
+		font-family: system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, sans-serif;
+	}
+
+	.card-a {
+		background: #ffffff;
+		border-radius: 48rpx;
+		box-shadow: 0 12rpx 40rpx rgba(0, 0, 0, 0.05);
+		overflow: hidden;
+	}
+
+	.a-header {
+		background: linear-gradient(135deg, #e8f5e9 0%, #f1f8e9 100%);
+		padding: 40rpx 32rpx 24rpx;
+		text-align: center;
+
+		.a-main-title {
+			font-size: 36rpx;
+			font-weight: 800;
+			color: #2e7d32;
+		}
+	}
+
+	.card-section {
+		padding: 30rpx 32rpx;
+		border-bottom: 2rpx solid #f0f2f5;
+
+		&:last-child {
+			border-bottom: none;
+		}
+	}
+
+	.section-title {
+		font-size: 30rpx;
+		font-weight: 700;
+		color: #1f2a44;
+		margin-bottom: 24rpx;
+		padding-left: 16rpx;
+		border-left: 6rpx solid #4caf50;
+	}
+
+	.info-list {
+		display: flex;
+		flex-direction: column;
+		gap: 28rpx;
+	}
+
+	.info-item {
+		display: flex;
+		flex-direction: column;
+		gap: 8rpx;
+	}
+
+	.info-label {
+		font-size: 26rpx;
+		font-weight: 600;
+		color: #6c7a91;
+	}
+
+	.info-value {
+		font-size: 28rpx;
+		font-weight: 500;
+		color: #1e2a3a;
+		padding: 16rpx 20rpx;
+		border-radius: 24rpx;
+		border: 2rpx solid #e9edf2;
+		background: #fff;
+
+		&.readonly {
+			color: #999;
+			background: #f5f5f5;
+		}
+	}
+
+	.info-input,
+	.info-textarea {
+		font-size: 28rpx;
+		color: #1e2a3a;
+		height: 60rpx;
+		padding: 16rpx 20rpx;
+		border-radius: 24rpx;
+		border: 2rpx solid #e9edf2;
+		background: #fff;
+	}
+
+	.info-textarea {
+		min-height: 160rpx;
+	}
+
+	.image-list {
+		display: flex;
+		flex-wrap: wrap;
+		gap: 16rpx;
+
+		image {
+			width: 160rpx;
+			height: 160rpx;
+			border-radius: 16rpx;
+			background: #f5f5f5;
+			object-fit: cover;
+		}
+	}
+
+	.status-pending {
+		color: #e6a23c;
+		background: #fff3e0;
+		padding: 8rpx 20rpx;
+		border-radius: 32rpx;
+		font-size: 26rpx;
+		display: inline-block;
+	}
+
+	.status-done {
+		color: #67c23a;
+		background: #e0f3e8;
+		padding: 8rpx 20rpx;
+		border-radius: 32rpx;
+		font-size: 26rpx;
+		display: inline-block;
+	}
+
+	.status-discard {
+		color: #f56c6c;
+		background: #fef0f0;
+		padding: 8rpx 20rpx;
+		border-radius: 32rpx;
+		font-size: 26rpx;
+		display: inline-block;
+	}
+
+	.status-link {
+		text-decoration: none;
+	}
+
+	.popup-footer {
+		display: flex;
+		padding: 20rpx 30rpx;
+		border-top: 1rpx solid #e5e5e5;
+		background: #fff;
+		gap: 20rpx;
+
+		/deep/ .u-button {
+			flex: 1;
+		}
+	}
+</style>

+ 154 - 0
pages/ehs/snapshot/components/snapshotSelectDialog.vue

@@ -0,0 +1,154 @@
+<!-- components/snapshotSelectDialog.vue - 选择随手拍弹窗 -->
+<template>
+  <uni-popup ref="popup" type="center">
+    <view class="select-dialog">
+      <view class="header">选择随手拍</view>
+      <view class="search">
+        <uni-forms :modelValue="where" label-width="70px">
+          <uni-forms-item label="上报人">
+            <uni-easyinput v-model="where.reporterName" placeholder="请输入" clearable />
+          </uni-forms-item>
+          <uni-forms-item label="上报时间">
+            <uni-datetime-picker v-model="where.createTime" type="datetime" return-type="string" />
+          </uni-forms-item>
+          <view class="search-buttons">
+            <button type="primary" size="mini" @click="handleSearch">查询</button>
+            <button size="mini" @click="handleReset">重置</button>
+          </view>
+        </uni-forms>
+      </view>
+      <scroll-view scroll-y class="list">
+        <view v-for="item in list" :key="item.id" class="list-item" :class="{ active: selectedId === item.id }" @click="selectItem(item)">
+          <text class="desc">{{ item.description }}</text>
+          <text class="info">{{ item.location }} | {{ item.reporterName }} | {{ item.createTime }}</text>
+        </view>
+        <view v-if="list.length === 0 && !loading" class="empty">暂无数据</view>
+      </scroll-view>
+      <uni-pagination :current="page" :total="total" :page-size="limit" @change="onPageChange" show-icon />
+      <view class="footer">
+        <button @click="close">取消</button>
+        <button type="primary" :disabled="!selectedItem" @click="handleConfirm">确定</button>
+      </view>
+    </view>
+  </uni-popup>
+</template>
+
+<script>
+import { getList } from '@/api/snapshot/index.js';
+
+export default {
+  emits: ['confirm'],
+  data() {
+    return {
+      list: [],
+      total: 0,
+      page: 1,
+      limit: 10,
+      loading: false,
+      where: { reporterName: '', createTime: '' },
+      selectedItem: null,
+      selectedId: null
+    };
+  },
+  methods: {
+    open() {
+      this.selectedItem = null;
+      this.selectedId = null;
+      this.page = 1;
+      this.where = { reporterName: '', createTime: '' };
+      this.loadData();
+      this.$refs.popup.open();
+    },
+    close() {
+      this.$refs.popup.close();
+    },
+    async loadData() {
+      this.loading = true;
+      try {
+        const res = await getList({ ...this.where, handleResult: 0, pageNum: this.page, size: this.limit });
+        this.list = res.rows || [];
+        this.total = res.total || 0;
+      } finally {
+        this.loading = false;
+      }
+    },
+    selectItem(item) {
+      this.selectedId = item.id;
+      this.selectedItem = item;
+    },
+    handleConfirm() {
+      if (!this.selectedItem) return;
+      this.$emit('confirm', {
+        sourceType: 4,
+        sourceId: this.selectedItem.id,
+        sourceName: '随手拍',
+        foundUserName: this.selectedItem.reporterName,
+        foundUserId: this.selectedItem.reporterId,
+        foundTime: this.selectedItem.createTime,
+        description: this.selectedItem.location + this.selectedItem.description,
+        reportAttachments: this.selectedItem.attachment
+      });
+      this.close();
+    },
+    handleSearch() {
+      this.page = 1;
+      this.loadData();
+    },
+    handleReset() {
+      this.where = { reporterName: '', createTime: '' };
+      this.handleSearch();
+    },
+    onPageChange(e) {
+      this.page = e.current;
+      this.loadData();
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.select-dialog {
+  width: 600rpx;
+  max-width: 90vw;
+  background: #fff;
+  border-radius: 16rpx;
+  display: flex;
+  flex-direction: column;
+  max-height: 80vh;
+  .header {
+    padding: 30rpx;
+    font-size: 36rpx;
+    font-weight: bold;
+    text-align: center;
+    border-bottom: 1px solid #eee;
+  }
+  .search {
+    padding: 20rpx;
+    border-bottom: 1px solid #eee;
+    .search-buttons {
+      display: flex;
+      gap: 20rpx;
+      margin-top: 20rpx;
+    }
+  }
+  .list {
+    flex: 1;
+    padding: 20rpx;
+    .list-item {
+      padding: 20rpx;
+      border-bottom: 1px solid #f0f0f0;
+      &.active { background: #e6f7ff; }
+      .desc { font-weight: bold; display: block; }
+      .info { font-size: 24rpx; color: #666; margin-top: 10rpx; display: block; }
+    }
+    .empty { text-align: center; padding: 40rpx; color: #999; }
+  }
+  .footer {
+    padding: 20rpx;
+    display: flex;
+    gap: 20rpx;
+    border-top: 1px solid #eee;
+    button { flex: 1; margin: 0; }
+  }
+}
+</style>

+ 150 - 0
pages/ehs/snapshot/mySnapshot.vue

@@ -0,0 +1,150 @@
+<!-- pages/snapshot/mySnapshot.vue -->
+<template>
+  <view class="mainBox">
+    <uni-nav-bar fixed="true" statusBar="true" left-icon="back" title="我的随手拍" @clickLeft="back" />
+
+    <!-- 搜索区域 -->
+    <view class="top-wrapper">
+      <uni-forms :modelValue="where" label-width="100px" class="search-form">
+        <uni-forms-item label="处理结果">
+          <uni-data-select v-model="where.handleResult" :localdata="resultOptions" placeholder="全部" clearable />
+        </uni-forms-item>
+ 
+      </uni-forms>
+      <button class="search_btn" @click="handleSearch">搜索</button>
+    </view>
+
+    <view class="wrapper">
+      <u-list @scrolltolower="scrolltolower" class="listContent">
+        <view v-for="(item, idx) in tableList" :key="item.id" style="position: relative">
+          <myCard
+            :item="item"
+            :index="idx + 1"
+            :btnList="myBtnList" 
+            :columns="columns"
+            :title="item.description"
+            :status="statusMap[item.handleResult]"
+            @goDetail="goDetail"
+            @handleDelete="handleDelete"
+          />
+        </view>
+        <view style="width: 100%; height: 40rpx"></view>
+        <view style="margin-top: 20vh" v-if="tableList.length == 0">
+          <u-empty iconSize="150" textSize="32" text="暂无数据" />
+        </view>
+      </u-list>
+    </view>
+
+    <!-- 新增/编辑/查看弹窗 -->
+    <snapshot-dialog ref="snapshotDialog" @reload="reloadList" />
+
+    <view class="add" @click="goDetail({}, 'add')">
+      <u-icon name="plus" color="#fff"></u-icon>
+    </view>
+  </view>
+</template>
+ 
+<script>
+	import myCard from "@/components/myCard.vue";
+import snapshotDialog from './components/snapshotDialog.vue';
+import { getList, remove } from '@/api/snapshot/index.js';
+
+export default {
+  components: { myCard, snapshotDialog },
+  data() {
+    return {
+      where: { handleResult: '', createTime: '' },
+      resultOptions: [
+        { value: 0, text: '待处理' },
+        { value: 1, text: '下发整改' },
+        { value: 2, text: '废弃' }
+      ],
+      statusMap: { 0: '待处理', 1: '已整改', 2: '已废弃' },
+      columns: [
+        [{ prop: 'location', label: '位置', className: 'perce100' }],
+        [{ prop: 'problemDeptName', label: '所属部门', className: 'perce100' }],
+        [{ prop: 'createTime', label: '上报时间', className: 'perce100' }],
+        [{ prop: 'handleResult', label: '处理结果', className: 'perce100', formatter: (row) => this.statusMap[row.handleResult] }]
+      ],
+      tableList: [],
+      page: 1,
+      size: 10,
+      isEnd: false,
+      userInfo: {}
+    };
+  },
+  computed: {
+    myBtnList() {
+      return [
+        {
+          name: '编辑',
+          apiName: 'edit',
+          btnType: 'primary',
+          judge: [{ fn: (item) => item.handleResult === 0 }]
+        },
+        {
+          name: '删除',
+          apiName: 'delete',
+          btnType: 'danger',
+          judge: [{ fn: (item) => item.handleResult === 0 }]
+        }
+      ];
+    }
+  },
+  onLoad() {
+    this.userInfo = uni.getStorageSync('userInfo') || {};
+    this.getList();
+  },
+  methods: {
+    back() { uni.navigateBack(); },
+    goDetail(item, type) {
+      this.$refs.snapshotDialog.open(type, item);
+    },
+    async handleDelete(row) {
+      const res = await uni.showModal({ title: '提示', content: '确认删除该记录吗?' });
+      if (res.confirm) {
+        await remove([row.id]);
+        uni.showToast({ title: '删除成功', icon: 'success' });
+        this.reloadList();
+      }
+    },
+    reloadList() {
+      this.page = 1;
+      this.isEnd = false;
+      this.getList();
+    },
+    handleSearch() {
+      this.page = 1;
+      this.isEnd = false;
+      this.getList();
+    },
+    async getList() {
+      if (this.isEnd) return;
+      uni.showLoading({ title: '加载中' });
+      try {
+        const data = {
+          pageNum: this.page,
+          size: this.size,
+          reporterId: this.userInfo.userId,
+          handleResult: this.where.handleResult !== '' ? this.where.handleResult : undefined,
+          createTime: this.where.createTime || undefined
+        };
+        const res = await getList(data);
+        const newList = res.list || [];
+        if (this.page === 1) this.tableList = newList;
+        else this.tableList.push(...newList);
+        this.isEnd = this.tableList.length >= res.count;
+        this.page += 1;
+      } catch (e) { console.error(e); }
+      finally { uni.hideLoading(); }
+    },
+    scrolltolower() {
+      if (!this.isEnd) this.getList();
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+@import './common-style.scss'; // 共用样式见下方
+</style>

+ 229 - 0
pages/ehs/snapshot/snapshotManage.vue

@@ -0,0 +1,229 @@
+<!-- pages/snapshot/snapshotManage.vue -->
+<template>
+	<view class="mainBox">
+		<uni-nav-bar fixed="true" statusBar="true" left-icon="back" title="随手拍管理" @clickLeft="back" />
+
+		<view class="top-wrapper">
+			<uni-forms :modelValue="where" label-width="100px" class="search-form">
+	
+				<uni-forms-item label="处理结果">
+					<uni-data-select v-model="where.handleResult" :localdata="resultOptions" placeholder="全部"
+						clearable />
+				</uni-forms-item>
+	
+			</uni-forms>
+			<button class="search_btn" @click="handleSearch">搜索</button>
+		</view>
+
+		<view class="wrapper">
+			<u-list @scrolltolower="scrolltolower" class="listContent">
+				<view v-for="(item, idx) in tableList" :key="item.id" style="position: relative">
+					<myCard :item="item" :index="idx + 1" :btnList="manageBtnList" :columns="columns"
+						:title="item.description" :status="statusMap[item.handleResult]" @goDetail="goDetail"
+						@handleProcess="handleProcess" />
+				</view>
+				<view style="width: 100%; height: 40rpx"></view>
+				<view style="margin-top: 20vh" v-if="tableList.length == 0">
+					<u-empty iconSize="150" textSize="32" text="暂无数据" />
+				</view>
+			</u-list>
+		</view>
+
+		<snapshot-dialog ref="snapshotDialog" @rectify="onRectify" @discard="onDiscard" />
+		<discard-dialog ref="discardDialogRef" @confirm="doDiscard" />
+		<!-- <hazardDialog ref="hazardDialogRef" @reload="doRectify" /> -->
+	</view>
+</template>
+
+<script>
+	import myCard from "@/components/myCard.vue";
+	import snapshotDialog from './components/snapshotDialog.vue';
+	import discardDialog from './components/discardDialog.vue';
+	// import hazardDialog from '@/views/hazardManagement/hazardDialog.vue';
+	import {
+		getList,
+		discard,
+		handle
+	} from '@/api/snapshot/index.js';
+
+	export default {
+		components: {
+			myCard,
+			snapshotDialog,
+			discardDialog,
+			// hazardDialog
+		},
+		data() {
+			return {
+				where: {
+					reporterName: '',
+					handleResult: '',
+					createTime: ''
+				},
+				resultOptions: [{
+						value: 0,
+						text: '待处理'
+					},
+					{
+						value: 1,
+						text: '下发整改'
+					},
+					{
+						value: 2,
+						text: '废弃'
+					}
+				],
+				statusMap: {
+					0: '待处理',
+					1: '已整改',
+					2: '已废弃'
+				},
+				columns: [
+					[{
+						prop: 'location',
+						label: '位置',
+						className: 'perce100'
+					}],
+					[{
+						prop: 'problemDeptName',
+						label: '所属部门',
+						className: 'perce100'
+					}],
+					[{
+						prop: 'reporterName',
+						label: '上报人',
+						className: 'perce100'
+					}],
+					[{
+						prop: 'createTime',
+						label: '上报时间',
+						className: 'perce100'
+					}],
+					[{
+						prop: 'handleResult',
+						label: '处理结果',
+						className: 'perce100',
+						formatter: (row) => this.statusMap[row.handleResult]
+					}]
+				],
+				tableList: [],
+				page: 1,
+				size: 10,
+				isEnd: false,
+				currentId: null
+			};
+		},
+		computed: {
+			manageBtnList() {
+				return [{
+					name: '处理',
+					apiName: 'handleProcess',
+					btnType: 'primary',
+					judge: [{
+						fn: (item) => item.handleResult === 0
+					}]
+				}];
+			}
+		},
+		onLoad() {
+			this.getList();
+		},
+		methods: {
+			back() {
+				uni.navigateBack();
+			},
+			goDetail(item, type) {
+				this.$refs.snapshotDialog.open(type, item);
+			},
+			handleProcess(row) {
+				this.$refs.snapshotDialog.open('handle', row);
+			},
+			onRectify(data) {
+				this.currentId = data.id;
+				this.$refs.hazardDialogRef.open('add', '', 'report', {
+					sourceType: 4,
+					sourceId: data.id,
+					sourceName: '随手拍',
+					foundUserName: data.reporterName,
+					foundUserId: data.reporterId,
+					foundTime: data.createTime,
+					description: data.location + data.description,
+					reportAttachments: data.attachment
+				});
+			},
+			doRectify(opinion) {
+				handle({
+					id: this.currentId,
+					handleOpinion: opinion,
+					invHazardId: '下发整改'
+				}).then(() => {
+					uni.showToast({
+						title: '下发整改成功',
+						icon: 'success'
+					});
+					this.reloadList();
+				});
+			},
+			onDiscard(data) {
+				this.$refs.discardDialogRef.open(data);
+			},
+			doDiscard({
+				id,
+				handleOpinion
+			}) {
+				discard({
+					id,
+					handleOpinion
+				}).then(() => {
+					uni.showToast({
+						title: '废弃成功',
+						icon: 'success'
+					});
+					this.reloadList();
+				});
+			},
+			reloadList() {
+				this.page = 1;
+				this.isEnd = false;
+				this.getList();
+			},
+			handleSearch() {
+				this.page = 1;
+				this.isEnd = false;
+				this.getList();
+			},
+			async getList() {
+				if (this.isEnd) return;
+				uni.showLoading({
+					title: '加载中'
+				});
+				try {
+					const data = {
+						pageNum: this.page,
+						size: this.size,
+						reporterName: this.where.reporterName || undefined,
+						handleResult: this.where.handleResult !== '' ? this.where.handleResult : undefined,
+						createTime: this.where.createTime || undefined
+					};
+					const res = await getList(data);
+					const newList = res.rows || [];
+					if (this.page === 1) this.tableList = newList;
+					else this.tableList.push(...newList);
+					this.isEnd = newList.length < this.size;
+					this.page += 1;
+				} catch (e) {
+					console.error(e);
+				} finally {
+					uni.hideLoading();
+				}
+			},
+			scrolltolower() {
+				if (!this.isEnd) this.getList();
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	@import './common-style.scss';
+</style>

+ 1 - 1
pages/ems/centralizedMeterReading/list.vue

@@ -45,7 +45,7 @@
 
 <script>
 	import dictMixns from "@/mixins/dictMixins";
-	import myCard from "./components/myCard.vue";
+	import myCard from "@/components/myCard.vue";
 	import {
 		getTreeByPid
 	} from "@/api/classifyManage";

+ 168 - 1
pages/home/home.vue

@@ -222,6 +222,7 @@
 		},
 		onLoad() {
 			this.getHomeData()
+			// this.initPush()
 			// this.getStatistics()
 		},
 		onUnload() {
@@ -236,6 +237,7 @@
 				timer: null,
 				qrContent: null,
 				barType: null,
+				cid:'',
 				// 扫码后的设备信息
 				equipmentInfo: '',
 				qrContent: '',
@@ -456,8 +458,173 @@
 				this.tableData = this.hotProductList.slice(0, 4)
 				uni.hideLoading()
 
+			},
+			/**
+			 * 初始化推送功能(仅App端执行)
+			 */
+			initPush() {
+				// 1. 申请Android通知权限(Android 13+ 需要动态申请POST_NOTIFICATIONS)
+				this.requestNotificationPermission()
+			
+				// 2. 获取设备推送标识(cid),用于服务端定向推送
+				this.getPushClientId()
+			
+				// 3. 监听推送消息的到达和点击事件
+				this.setupPushListeners()
+			},
+			
+			/**
+			 * 申请Android通知权限
+			 * 参考文档:https://uniapp.dcloud.net.cn/tutorial/app-push-unipush.html
+			 */
+			requestNotificationPermission() {
+				// #ifdef APP-PLUS
+				if (plus.os.name === 'Android') {
+					// Android 13(API 33)及以上需要申请 POST_NOTIFICATIONS 权限
+					plus.android.requestPermissions(
+						['android.permission.POST_NOTIFICATIONS'],
+						function(e) {
+							console.log('通知权限申请结果:', e)
+						},
+						function(e) {
+							console.error('通知权限申请失败:', e)
+						}
+					)
+				}
+			
+				// 检测当前通知授权状态,若被拒绝则引导用户去设置页面开启
+				const notificationAuthorized = uni.getAppAuthorizeSetting().notificationAuthorized
+				if (notificationAuthorized === 'denied') {
+					uni.showModal({
+						title: '提示',
+						content: '请开启通知权限,以便接收重要消息提醒',
+						success: (res) => {
+							if (res.confirm) {
+								// 跳转到应用设置页面
+								uni.openAppAuthorizeSetting()
+							}
+						}
+					})
+				}
+				// #endif
+			},
+			
+			/**
+			 * 获取设备推送标识(cid/clientid)
+			 * 该标识用于服务端向指定设备推送消息,需要在服务端存储并与用户账号关联
+			 * 参考:https://uniapp.dcloud.net.cn/tutorial/app-push-unipush.html
+			 */
+			getPushClientId() {
+				uni.getPushClientId({
+					success: (res) => {
+						console.log('获取cid成功:', res.cid)
+						// TODO: 将 cid 发送到你的后端服务器,与当前登录用户关联
+						this.sendCidToServer(res.cid)
+					},
+					fail: (err) => {
+						console.error('获取cid失败:', err)
+						// 获取失败时,延迟重试
+						setTimeout(() => {
+							this.getPushClientId()
+						}, 2000)
+					}
+				})
+			},
+			
+			/**
+			 * 将设备cid发送到后端服务器
+			 * @param {string} cid 设备推送标识
+			 */
+			sendCidToServer(cid) {
+				// 示例:使用 uni.request 发送到你的后端接口
+				// uni.request({
+				// 	url: 'https://your-server.com/api/push/register',
+				// 	method: 'POST',
+				// 	data: { cid: cid },
+				// 	success: (res) => {
+				// 		console.log('cid上报成功')
+				// 	}
+				// })
+				this.cid=cid
+				console.log('TODO: 将cid发送到后端,cid:', cid)
+			},
+			
+			/**
+			 * 监听推送消息(接收和点击事件)
+			 * 参考:https://uniapp.dcloud.net.cn/tutorial/app-push-unipush.html
+			 */
+			setupPushListeners() {
+				// 监听透传消息(应用在前台或后台接收,自定义处理)
+				uni.onPushMessage((res) => {
+					console.log('收到推送消息:', JSON.stringify(res))
+			
+					// 消息类型:click 表示用户点击通知栏消息,receive 表示收到消息(未点击)
+					if (res.type === 'receive') {
+						// 收到消息,根据业务需求处理
+						this.handlePushReceive(res.data)
+					} else if (res.type === 'click') {
+						// 用户点击通知栏消息
+						this.handlePushClick(res.data)
+					}
+				})
+			},
+			
+			/**
+			 * 处理收到推送消息(未点击)
+			 * @param {object} payload 推送携带的自定义数据
+			 */
+			handlePushReceive(payload) {
+				console.log('收到推送数据:', payload)
+			
+				// 示例:根据业务类型处理
+				// if (payload.type === 'chat') {
+				// 	// 聊天消息:更新聊天记录
+				// 	this.updateChatList(payload)
+				// } else if (payload.type === 'order') {
+				// 	// 订单消息:更新订单状态
+				// 	this.refreshOrderStatus(payload)
+				// }
+			
+				// 如果需要在应用内弹框提示,可自行实现
+				uni.showToast({
+					title: payload?.title || '收到新消息',
+					icon: 'none',
+					duration: 2000
+				})
+			},
+			
+			/**
+			 * 处理用户点击通知栏消息
+			 * @param {object} payload 推送携带的自定义数据
+			 */
+			handlePushClick(payload) {
+				console.log('点击推送消息:', payload)
+			
+				// 根据 payload 中的数据跳转到指定页面
+				// 例如:payload = { page: '/pages/message/detail', id: '123' }
+				if (payload?.page) {
+					uni.navigateTo({
+						url: payload.page + (payload.id ? '?id=' + payload.id : ''),
+						fail: (err) => {
+							console.error('跳转失败:', err)
+							// 跳转失败则跳转到首页
+							uni.switchTab({
+								url: '/pages/index/index'
+							})
+						}
+					})
+				} else if (payload?.url) {
+					// 支持外部链接跳转
+					uni.navigateTo({
+						url: '/pages/webview/index?url=' + encodeURIComponent(payload.url)
+					})
+				} else {
+					// 默认跳转到消息中心页面
+					uni.navigateTo({
+						url: '/pages/message/index'
+					})
+				}
 			}
-
 		}
 	}
 </script>

+ 26 - 1
pages/index/index.vue

@@ -146,8 +146,20 @@
 					</view>
 				</view>
 			</view>
+			<view v-if="productionSafetyManagement.length > 0" :id="'module-anquan'" :data-index="11">
+				<CellTip title="生产安全"></CellTip>
+				<view class="nav">
+					<view class="nav-content">
+						<view class="nav-item" v-for="(item, index) in productionSafetyManagement" @click="toNav(item.path)">
+							<span :class="'iconfont ' + item.icon"></span>
+							<i class="badge" v-if="item.badge">{{ item.badge }}</i>
+							<label>{{ item.name }}</label>
+						</view>
+					</view>
+				</view>
+			</view>
 
-			<view v-if="traceabilityList.length > 0" :id="'module-suyuan'" :data-index="11">
+			<view v-if="traceabilityList.length > 0" :id="'module-suyuan'" :data-index="12">
 				<CellTip title="溯源管理"></CellTip>
 				<view class="nav">
 					<view class="nav-content">
@@ -199,6 +211,8 @@
 				// 导航相关
 				moduleNavList: [],
 				energyManagement:[],
+				//安全生产
+				productionSafetyManagement:[],
 				scrollIntoViewId: "",
 				currentNavIndex: 0,
 				moduleObserver: null,
@@ -348,6 +362,9 @@
 						} else if (f.path == 'energyManagement') {
 							this.energyManagement = f.children
 
+						} else if (f.path == 'productionSafetyManagement') {
+							this.productionSafetyManagement = f.children
+
 						}
 					});
 				}
@@ -407,6 +424,14 @@
 						name: "质量管理",
 						id: "zhiliang"
 					},
+					qmsList: {
+						name: "能源管理",
+						id: "module-nengyuan"
+					},
+					qmsList: {
+						name: "生产安全",
+						id: "module-anquan"
+					},
 					traceabilityList: {
 						name: "溯源管理",
 						id: "suyuan"

+ 43 - 0
pages/pcs/HaulSlag.vue

@@ -0,0 +1,43 @@
+<template>
+	<view>
+		<list ref="listRef" pageName="HaulSlag"></list>
+	</view>
+</template>
+
+<script>
+	import list from './list.vue'
+
+	export default {
+		components: {
+			list
+		},
+		mixins: [],
+		data() {
+			return {}
+		},
+		computed: {},
+		created() {
+			uni.$off('successInit')
+			uni.$on('successInit', (data) => {
+				this.$nextTick(() => {
+					this.$refs.listRef.successInit()
+				})
+			})
+		},
+		onUnload() {
+			uni.$off('successInit')
+		},
+		onLoad() {
+			this.$nextTick(() => {
+				this.$refs.listRef.getList()
+			})
+			uni.setNavigationBarColor({
+				frontColor: '#000000',
+			})
+		},
+		methods: {}
+	}
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 43 - 0
pages/pcs/QualityInspection.vue

@@ -0,0 +1,43 @@
+<template>
+	<view>
+		<list ref="listRef" pageName="QualityInspection"></list>
+	</view>
+</template>
+
+<script>
+	import list from './list.vue'
+
+	export default {
+		components: {
+			list
+		},
+		mixins: [],
+		data() {
+			return {}
+		},
+		computed: {},
+		created() {
+			uni.$off('successInit')
+			uni.$on('successInit', (data) => {
+				this.$nextTick(() => {
+					this.$refs.listRef.successInit()
+				})
+			})
+		},
+		onUnload() {
+			uni.$off('successInit')
+		},
+		onLoad() {
+			this.$nextTick(() => {
+				this.$refs.listRef.getList()
+			})
+			uni.setNavigationBarColor({
+				frontColor: '#000000',
+			})
+		},
+		methods: {}
+	}
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 43 - 0
pages/pcs/TransportAsh.vue

@@ -0,0 +1,43 @@
+<template>
+	<view>
+		<list ref="listRef" pageName="TransportAsh"></list>
+	</view>
+</template>
+
+<script>
+	import list from './list.vue'
+
+	export default {
+		components: {
+			list
+		},
+		mixins: [],
+		data() {
+			return {}
+		},
+		computed: {},
+		created() {
+			uni.$off('successInit')
+			uni.$on('successInit', (data) => {
+				this.$nextTick(() => {
+					this.$refs.listRef.successInit()
+				})
+			})
+		},
+		onUnload() {
+			uni.$off('successInit')
+		},
+		onLoad() {
+			this.$nextTick(() => {
+				this.$refs.listRef.getList()
+			})
+			uni.setNavigationBarColor({
+				frontColor: '#000000',
+			})
+		},
+		methods: {}
+	}
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 307 - 0
pages/pcs/components/OrderListDialog.vue

@@ -0,0 +1,307 @@
+<!-- OrderListDialog.vue - 订单选择弹窗(UniApp版本) -->
+<template>
+	<u-popup :show="visible" :round="0" :closeOnClickOverlay="false" :zIndex="99999" @close="handleClose"
+		class="order-popup">
+		<view class="popup-content">
+			<view class="popup-header">
+				<text class="popup-title">选择订单</text>
+				<view class="close-btn" @click="handleClose">×</view>
+			</view>
+
+			<!-- 搜索区域 -->
+			<view class="search-wrapper">
+				<uni-easyinput prefixIcon="search" style="flex: 1" v-model="keyword" placeholder="订单编码/名称/合同名称">
+				</uni-easyinput>
+				<button class="search_btn" @click="handleSearch">搜索</button>
+			</view>
+
+			<!-- 订单列表 -->
+			<scroll-view class="popup-body" scroll-y @scrolltolower="loadMore">
+				<view v-for="(item, index) in orderList" :key="item.id" style="position: relative">
+					<myCard :item="item" :index="index + 1" :columns="cardColumns" :title="item.orderNo"
+						:showRadio="true" :radioValue="selectedId" @radioChange="onRadioChange">
+					</myCard>
+				</view>
+				<view style="width: 100%; height: 40rpx"></view>
+				<view style="margin-top: 60rpx" v-if="loading && orderList.length === 0">
+					<u-empty iconSize="150" textSize="32" text="加载中..."></u-empty>
+				</view>
+				<view style="margin-top: 60rpx" v-if="!loading && orderList.length === 0">
+					<u-empty iconSize="150" textSize="32" text="暂无订单数据"></u-empty>
+				</view>
+				<view class="loadmore-text" v-if="!isEnd && orderList.length > 0">加载更多...</view>
+				<view class="loadmore-text" v-if="isEnd && orderList.length > 0">没有更多了</view>
+			</scroll-view>
+
+			<view class="popup-footer">
+				<u-button type="default" @click="handleClose">关闭</u-button>
+				<u-button type="primary" @click="confirmSelect">选择</u-button>
+			</view>
+		</view>
+		<u-toast ref="uToast"></u-toast>
+	</u-popup>
+</template>
+
+<script>
+	import myCard from './myCard.vue';
+	import {
+		getPurchaseOrderList
+	} from '@/api/purchasingManage/index.js'
+
+	export default {
+		components: {
+			myCard
+		},
+		props: {
+			searchParams: {
+				type: Object,
+				default: () => ({})
+			},
+			isOutsourcing: {
+				type: String,
+				default: ''
+			}
+		},
+		data() {
+			return {
+				visible: false,
+				keyword: '',
+				orderList: [],
+				selectedId: null,
+				selectedOrder: null,
+				page: 1,
+				size: 10,
+				isEnd: false,
+				loading: false,
+				partbId: '',
+				sourceType: '',
+				// 卡片展示列配置
+				cardColumns: [
+					[{
+						label: "订单编码",
+						prop: "orderNo",
+						className: "perce100"
+					}],
+					[{
+						label: "订单类型",
+						prop: "sourceTypeName",
+						className: "perce50"
+					}, {
+						label: "金额(元)",
+						prop: "payAmount",
+						className: "perce50"
+					}],
+					[{
+						label: "名称",
+						prop: "productNames",
+						className: "perce100"
+					}],
+					[{
+						label: "编码",
+						prop: "productCodes",
+						className: "perce100"
+					}],
+					[{
+						label: "合同名称",
+						prop: "contractName",
+						className: "perce100"
+					}],
+					[{
+						label: "供应商",
+						prop: "partbName",
+						className: "perce50"
+					}, {
+						label: "采购方",
+						prop: "partaName",
+						className: "perce50"
+					}],
+					[{
+						label: "创建时间",
+						prop: "createTime",
+						className: "perce100"
+					}]
+				]
+			};
+		},
+		methods: {
+			// 打开弹窗
+			open(partbId, sourceType) {
+				this.partbId = partbId;
+				this.sourceType = sourceType || '';
+				this.selectedId = null;
+				this.selectedOrder = null;
+				this.orderList = [];
+				this.page = 1;
+				this.isEnd = false;
+				this.keyword = '';
+				this.visible = true;
+				this.loadOrders();
+			},
+			// 搜索
+			handleSearch() {
+				this.page = 1;
+				this.orderList = [];
+				this.isEnd = false;
+				this.loadOrders();
+			},
+			// 加载订单列表
+			async loadOrders() {
+				if (this.loading || this.isEnd) return;
+				this.loading = true;
+				try {
+					const where = {};
+					if (this.keyword) {
+						// 支持订单编码、名称模糊查询
+						where.orderNo = this.keyword;
+						where.productNames = this.keyword;
+						where.contractName = this.keyword;
+					}
+					if (this.sourceType) {
+						where.sourceType = this.sourceType;
+					}
+					const res = await getPurchaseOrderList({
+						pageNum: this.page,
+						size: this.size,
+						...where,
+						orderStatus: 2,
+						partbId: this.partbId,
+						...this.searchParams
+					});
+					const list = res.list || [];
+					if (this.page === 1) {
+						this.orderList = list;
+					} else {
+						this.orderList.push(...list);
+					}
+					this.isEnd = list.length < this.size || (this.orderList.length >= res.count);
+					this.page += 1;
+				} catch (error) {
+					console.error('获取订单列表失败', error);
+					this.$refs.uToast.show({
+						type: 'error',
+						message: '加载订单失败'
+					});
+				} finally {
+					this.loading = false;
+				}
+			},
+			// 滚动加载更多
+			loadMore() {
+				if (!this.isEnd && !this.loading) {
+					this.loadOrders();
+				}
+			},
+			// 单选变化
+			onRadioChange(item) {
+				this.selectedId = item.id;
+				this.selectedOrder = item;
+			},
+			// 确认选择
+			confirmSelect() {
+				if (!this.selectedOrder) {
+					this.$refs.uToast.show({
+						type: 'warning',
+						message: '请至少选择一条数据'
+					});
+					return;
+				}
+				this.$emit('changeParent', this.selectedOrder);
+				this.handleClose();
+			},
+			// 关闭弹窗
+			handleClose() {
+				this.visible = false;
+				this.selectedId = null;
+				this.selectedOrder = null;
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.order-popup {
+		.popup-content {
+			width: 100vw;
+			height: 85vh;
+			background: #fff;
+			border-radius: 32rpx 32rpx 0 0;
+			display: flex;
+			flex-direction: column;
+			background-color: #f5f7fb;
+		}
+
+		.popup-header {
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			padding: 30rpx;
+			border-bottom: 2rpx solid #eef2f6;
+			background: #fff;
+
+			.popup-title {
+				font-size: 36rpx;
+				font-weight: bold;
+				color: #1f2b3c;
+			}
+
+			.close-btn {
+				width: 60rpx;
+				height: 60rpx;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				font-size: 60rpx;
+				color: #8e9aae;
+				line-height: 1;
+			}
+		}
+
+		.search-wrapper {
+			display: flex;
+			align-items: center;
+			padding: 20rpx 30rpx;
+			background: #fff;
+			border-bottom: 2rpx solid #eef2f6;
+			gap: 20rpx;
+
+			.search_btn {
+				width: 140rpx;
+				height: 70rpx;
+				line-height: 70rpx;
+				padding: 0;
+				background: $theme-color;
+				font-size: 28rpx;
+				color: #fff;
+				margin: 0;
+				border-radius: 48rpx;
+			}
+		}
+
+		.popup-body {
+			flex: 1;
+			overflow-y: auto;
+			padding: 20rpx 24rpx;
+			box-sizing: border-box;
+		}
+
+		.loadmore-text {
+			text-align: center;
+			font-size: 26rpx;
+			color: #aaa;
+			padding: 24rpx 0 40rpx;
+		}
+
+		.popup-footer {
+			display: flex;
+			padding: 20rpx 30rpx 30rpx;
+			border-top: 2rpx solid #eef2f6;
+			gap: 20rpx;
+			background: #fff;
+
+			.u-button {
+				flex: 1;
+				border-radius: 48rpx;
+			}
+		}
+	}
+</style>

+ 360 - 364
pages/pcs/components/myCard.vue

@@ -1,371 +1,367 @@
+<!-- myCard.vue(增强版,添加单选功能) -->
 <template>
-  <view class="card_container">
-    <view class="card_box">
-      <!-- 标题区域 - 独立出来,宽度100% -->
-      <view class="header_box" v-if="title">
-        <view class="title_left">
-          <view class="round" v-if="index">{{ index }}</view>
-          <view class="orderId" :style="{ marginLeft: index ? '16rpx' : '' }">{{
-            title
-          }}</view>
-        </view>
-        <!-- 状态 - 固定在右上角 -->
-        <view class="status-tag" v-if="status">{{ status }}</view>
-      </view>
-
-      <view class="item_box rx-bc" v-for="(_item, i) in columns" :key="i">
-        <template v-for="val in _item">
-          <view
-            class="perce50"
-            :class="[val.className, { 'full-width': val.isFullWidth }]"
-            :style="val.style"
-            :key="val.prop"
-            v-if="!val.isNone"
-          >
-            <!-- 操作行 -->
-            <view class="item_one rx-sc" v-if="val.type == 'action'">
-              <view class="lable">{{ val.label }}</view>
-              <view class="text" style="flex-wrap: wrap">
-                <template v-for="(btn, bI) in btnList">
-                  <u-button
-                    :plain="true"
-                    :hairline="true"
-                    size="mini"
-                    :type="btn.btnType"
-                    v-if="judge(btn)"
-                    :text="btn.name"
-                    @click="action(btn)"
-                    :key="bI"
-                  ></u-button>
-                </template>
-              </view>
-            </view>
-
-            <!-- 普通信息行 -->
-            <view class="item_one rx-sc kk" v-else>
-              <view class="lable">{{ val.label }}</view>
-              <view class="text" :class="val.valueClass" v-if="val.formatter">{{
-                val.formatter(item) || ""
-              }}</view>
-              <view class="text" :class="val.valueClass" v-else-if="val.slot">
-                <slot :name="val.slot"></slot>
-              </view>
-              <view class="text" :class="val.valueClass" v-else>{{
-                item[val.prop] || ""
-              }}</view>
-            </view>
-          </view>
-        </template>
-      </view>
-
-      <!-- 查看详情 -->
-      <view class="footer-link" v-if="showDetail" @click="goDetail">
-        <text>查看详情</text>
-        <u-icon name="arrow-right" size="24" color="#999999"></u-icon>
-      </view>
-    </view>
-  </view>
+	<view class="card_container">
+		<view class="card_box">
+			<!-- 标题区域 -->
+			<view class="header_box" v-if="title">
+				<view class="title_left">
+					<view class="round" v-if="index">{{ index }}</view>
+					<view class="orderId" :style="{ marginLeft: index ? '16rpx' : '' }">{{
+						title
+					}}</view>
+				</view>
+				<!-- 状态标签 -->
+				<view class="status-tag" v-if="status">{{ status }}</view>
+				<!-- 单选按钮 -->
+				<view class="radio-tag" v-if="showRadio" @click.stop="handleRadioClick">
+					<u-radio-group v-model="radioValueModel" placement="row">
+						<u-radio :name="item.id" :iconSize="32" activeColor="#3c9cff"></u-radio>
+					</u-radio-group>
+				</view>
+			</view>
+
+			<view class="item_box rx-bc" v-for="(_item, i) in columns" :key="i">
+				<template v-for="val in _item">
+					<view class="perce50" :class="[val.className, { 'full-width': val.isFullWidth }]"
+						:style="val.style" :key="val.prop" v-if="!val.isNone">
+						<!-- 操作行 -->
+						<view class="item_one rx-sc" v-if="val.type == 'action'">
+							<view class="lable">{{ val.label }}</view>
+							<view class="text" style="flex-wrap: wrap">
+								<template v-for="(btn, bI) in btnList">
+									<u-button :plain="true" :hairline="true" size="mini" :type="btn.btnType"
+										v-if="judge(btn)" :text="btn.name" @click="action(btn)" :key="bI">
+									</u-button>
+								</template>
+							</view>
+						</view>
+						<!-- 普通信息行 -->
+						<view class="item_one rx-sc kk" v-else>
+							<view class="lable">{{ val.label }}</view>
+							<view class="text" :class="val.valueClass" v-if="val.formatter">{{
+								val.formatter(item) || ""
+							}}</view>
+							<view class="text" :class="val.valueClass" v-else-if="val.slot">
+								<slot :name="val.slot"></slot>
+							</view>
+							<view class="text" :class="val.valueClass" v-else>{{
+								item[val.prop] || ""
+							}}</view>
+						</view>
+					</view>
+				</template>
+			</view>
+
+			<!-- 查看详情 -->
+			<view class="footer-link" v-if="showDetail" @click="goDetail">
+				<text>查看详情</text>
+				<u-icon name="arrow-right" size="24" color="#999999"></u-icon>
+			</view>
+		</view>
+	</view>
 </template>
 
 <script>
-export default {
-  props: {
-    btnList: {
-      type: Array,
-      default: () => [],
-    },
-    item: {
-      type: Object,
-      default: () => ({}),
-    },
-    columns: {
-      type: Array,
-      default: () => [],
-    },
-    title: {
-      type: String,
-      default: "",
-    },
-    status: {
-      type: String,
-      default: "",
-    },
-    index: "",
-    showDetail: {
-      type: Boolean,
-      default: true,
-    },
-  },
-  computed: {
-    judge() {
-      return (item) => {
-        if (item.judge) {
-          let is = true;
-          item.judge.forEach(({ key, value, authorities, fn }) => {
-            if (authorities) {
-              is = this.$isAuthorities(authorities);
-            }
-            if (value && !value.includes(this.item[key])) {
-              is = false;
-            }
-            if (fn) {
-              is = fn(this.item);
-            }
-          });
-          return is;
-        } else {
-          return true;
-        }
-      };
-    },
-  },
-  data() {
-    return {};
-  },
-  methods: {
-    action(item) {
-      if (item.type == 1) {
-        uni.navigateTo({
-          url: item.pageUrl + "?id=" + this.item.id + (item.query || ""),
-        });
-      } else {
-        this.$emit(item.apiName);
-      }
-    },
-    goDetail() {
-      this.$emit("goDetail", this.item);
-    },
-  },
-};
+	export default {
+		props: {
+			btnList: {
+				type: Array,
+				default: () => []
+			},
+			item: {
+				type: Object,
+				default: () => ({})
+			},
+			columns: {
+				type: Array,
+				default: () => []
+			},
+			title: {
+				type: String,
+				default: ""
+			},
+			status: {
+				type: String,
+				default: ""
+			},
+			index: {
+				type: [String, Number],
+				default: ""
+			},
+			showDetail: {
+				type: Boolean,
+				default: true
+			},
+			// 新增:是否显示单选按钮
+			showRadio: {
+				type: Boolean,
+				default: false
+			},
+			// 新增:当前选中的值(父组件传入)
+			radioValue: {
+				type: [String, Number],
+				default: null
+			}
+		},
+		computed: {
+			judge() {
+				return (item) => {
+					if (item.judge) {
+						let is = true;
+						item.judge.forEach(({
+							key,
+							value,
+							authorities,
+							fn
+						}) => {
+							if (authorities) {
+								is = this.$isAuthorities(authorities);
+							}
+							if (value && !value.includes(this.item[key])) {
+								is = false;
+							}
+							if (fn) {
+								is = fn(this.item);
+							}
+						});
+						return is;
+					} else {
+						return true;
+					}
+				};
+			},
+			radioValueModel: {
+				get() {
+					return this.radioValue;
+				},
+				set(val) {
+					// 当单选值变化时触发事件
+					if (val === this.item.id) {
+						this.$emit('radioChange', this.item);
+					}
+				}
+			}
+		},
+		methods: {
+			action(item) {
+				if (item.type == 1) {
+					uni.navigateTo({
+						url: item.pageUrl + "?id=" + this.item.id + (item.query || ""),
+					});
+				} else {
+					this.$emit(item.apiName);
+				}
+			},
+			goDetail() {
+				this.$emit("goDetail", this.item);
+			},
+			handleRadioClick() {
+				// 触发选中事件,与radioChange保持一致
+				this.$emit('radioChange', this.item);
+			}
+		}
+	};
 </script>
 
 <style lang="scss" scoped>
-.card_container {
-  padding: 20rpx 24rpx;
-  background: #f5f5f5;
-}
-
-.card_box {
-  background: #ffffff;
-  border-radius: 16rpx;
-  padding: 28rpx;
-  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
-  position: relative;
-
-  .rx-bc {
-    display: flex;
-    align-items: flex-start;
-    flex-flow: row wrap;
-
-    > view {
-      margin-top: 28rpx;
-
-      &:first-child,
-      &:nth-child(2) {
-        margin-top: 0;
-      }
-    }
-  }
-
-  .rx-sc {
-    display: flex;
-    align-items: flex-start;
-  }
-
-  // 头部样式
-  .header_box {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    width: 100%;
-    position: relative;
-    background: linear-gradient(135deg, #e8f5e9 0%, #f1f8e9 100%);
-    padding: 20rpx 24rpx;
-    border-radius: 12rpx 12rpx 0 0;
-    margin: -28rpx -28rpx 28rpx -28rpx;
-    width: calc(100% + 56rpx);
-    box-sizing: border-box;
-    .round {
-      width: 44rpx;
-      height: 44rpx;
-      line-height: 44rpx;
-      border-radius: 50%;
-      background: $theme-color;
-      color: #fff;
-      text-align: center;
-      font-size: 24rpx;
-      font-weight: 600;
-      flex-shrink: 0;
-    }
-
-    .orderId {
-      color: #333333;
-      font-size: 32rpx;
-      font-weight: 600;
-      white-space: nowrap;
-      overflow: hidden;
-      text-overflow: ellipsis;
-    }
-
-    .title_left {
-      display: flex;
-      align-items: center;
-      flex: 1;
-      padding-right: 140rpx;
-      overflow: hidden;
-    }
-
-    // 状态标签
-    .status-tag {
-      background: #e3f2fd;
-      color: #2196f3;
-      font-size: 24rpx;
-      padding: 8rpx 20rpx;
-      border-radius: 24rpx;
-      font-weight: 500;
-      position: absolute;
-      top: 50%;
-      transform: translateY(-50%);
-      right: 24rpx;
-      z-index: 1;
-    }
-  }
-
-  .item_box {
-    .text {
-      display: flex;
-      flex: 1;
-
-      uni-button:after {
-        border: none;
-      }
-
-      uni-button {
-        width: 100rpx;
-        margin-left: 10rpx;
-        margin-right: 0;
-        color: #fff !important;
-        border: none;
-        background: #157a2c;
-        margin-top: 3px;
-      }
-    }
-
-    .kk .text {
-      overflow: hidden;
-      text-overflow: ellipsis;
-      white-space: nowrap;
-      display: block;
-    }
-
-    .item_one {
-      width: 100%;
-      font-size: 28rpx;
-      line-height: 44rpx;
-      display: flex;
-      align-items: flex-start;
-
-      .lable {
-        color: #666666;
-        flex-shrink: 0;
-        margin-right: 12rpx;
-        font-size: 28rpx;
-      }
-
-      .text {
-        color: #000;
-        font-size: 28rpx;
-        flex: 1;
-        white-space: nowrap;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        min-width: 0;
-
-        // 高亮值样式
-        &.highlight {
-          color: #4caf50;
-        }
-      }
-    }
-
-    .gylx {
-      color: $theme-color;
-    }
-
-    .perce50 {
-      width: 50%;
-      box-sizing: border-box;
-      padding-right: 20rpx;
-
-      &:nth-child(2n) {
-        padding-right: 0;
-        padding-left: 20rpx;
-      }
-    }
-    .perce100 {
-      width: 100%;
-    }
-
-    .full-width {
-      width: 100% !important;
-      padding-left: 0 !important;
-      padding-right: 0 !important;
-    }
-  }
-
-  // 底部查看详情
-  .footer-link {
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    margin-top: 28rpx;
-    padding-top: 24rpx;
-    border-top: 1rpx solid #f0f0f0;
-    color: #666666;
-    font-size: 28rpx;
-    cursor: pointer;
-
-    &:active {
-      opacity: 0.7;
-    }
-  }
-}
-
-/deep/.u-input {
-  padding: 0 !important;
-  height: 44rpx !important;
-  font-size: 26rpx !important;
-}
-
-/deep/.u-input__content__field-wrapper__field {
-  font-size: 26rpx !important;
-}
-
-/deep/.uni-date-editor--x .uni-date__icon-clear {
-  border: none !important;
-}
-
-/deep/.uni-date__x-input,
-/deep/.uni-date-x {
-  padding: 0 !important;
-  height: 44rpx !important;
-  font-size: 26rpx !important;
-}
-
-/deep/.input-value {
-  font-size: 26rpx !important;
-  height: 44rpx !important;
-
-  uni-text {
-    font-size: 26rpx !important;
-  }
-}
-
-/deep/.u-textarea {
-  padding: 2px !important;
-}
-
-/deep/.u-textarea__field {
-  font-size: 26rpx !important;
-}
-</style>
+	.card_container {
+		padding: 16rpx 0;
+	}
+
+	.card_box {
+		background: #ffffff;
+		border-radius: 24rpx;
+		padding: 24rpx;
+		box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
+		position: relative;
+
+		.rx-bc {
+			display: flex;
+			align-items: flex-start;
+			flex-flow: row wrap;
+
+			>view {
+				margin-top: 24rpx;
+
+				&:first-child,
+				&:nth-child(2) {
+					margin-top: 0;
+				}
+			}
+		}
+
+		.rx-sc {
+			display: flex;
+			align-items: flex-start;
+		}
+
+		.header_box {
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			width: 100%;
+			position: relative;
+			background: linear-gradient(135deg, #eef5ff 0%, #f5f9ff 100%);
+			padding: 20rpx 24rpx;
+			border-radius: 20rpx 20rpx 0 0;
+			margin: -24rpx -24rpx 24rpx -24rpx;
+			width: calc(100% + 48rpx);
+			box-sizing: border-box;
+
+			.round {
+				width: 44rpx;
+				height: 44rpx;
+				line-height: 44rpx;
+				border-radius: 50%;
+				background: $theme-color;
+				color: #fff;
+				text-align: center;
+				font-size: 24rpx;
+				font-weight: 600;
+				flex-shrink: 0;
+			}
+
+			.orderId {
+				color: #1f2b3c;
+				font-size: 30rpx;
+				font-weight: 600;
+				white-space: nowrap;
+				overflow: hidden;
+				text-overflow: ellipsis;
+			}
+
+			.title_left {
+				display: flex;
+				align-items: center;
+				flex: 1;
+				padding-right: 120rpx;
+				overflow: hidden;
+			}
+
+			.status-tag {
+				background: #e3f2fd;
+				color: #2196f3;
+				font-size: 24rpx;
+				padding: 6rpx 20rpx;
+				border-radius: 30rpx;
+				font-weight: 500;
+				position: absolute;
+				top: 50%;
+				transform: translateY(-50%);
+				right: 24rpx;
+				z-index: 1;
+			}
+
+			.radio-tag {
+				position: absolute;
+				top: 50%;
+				transform: translateY(-50%);
+				right: 24rpx;
+				z-index: 2;
+				background: transparent;
+
+				/deep/ .u-radio-group {
+					.u-radio {
+						padding: 0;
+						margin-right: 0;
+					}
+				}
+			}
+		}
+
+		.item_box {
+			.text {
+				display: flex;
+				flex: 1;
+
+				uni-button:after {
+					border: none;
+				}
+
+				uni-button {
+					width: 100rpx;
+					margin-left: 10rpx;
+					margin-right: 0;
+					color: #fff !important;
+					border: none;
+					background: #157a2c;
+					margin-top: 3px;
+				}
+			}
+
+			.kk .text {
+				overflow: hidden;
+				text-overflow: ellipsis;
+				white-space: nowrap;
+				display: block;
+			}
+
+			.item_one {
+				width: 100%;
+				font-size: 28rpx;
+				line-height: 44rpx;
+				display: flex;
+				align-items: flex-start;
+
+				.lable {
+					color: #8e9aae;
+					flex-shrink: 0;
+					margin-right: 16rpx;
+					font-size: 26rpx;
+				}
+
+				.text {
+					color: #1f2b3c;
+					font-size: 28rpx;
+					flex: 1;
+					white-space: nowrap;
+					overflow: hidden;
+					text-overflow: ellipsis;
+					min-width: 0;
+
+					&.highlight {
+						color: #4caf50;
+					}
+				}
+			}
+
+			.perce50 {
+				width: 50%;
+				box-sizing: border-box;
+				padding-right: 20rpx;
+
+				&:nth-child(2n) {
+					padding-right: 0;
+					padding-left: 20rpx;
+				}
+			}
+
+			.perce100 {
+				width: 100%;
+			}
+
+			.full-width {
+				width: 100% !important;
+				padding-left: 0 !important;
+				padding-right: 0 !important;
+			}
+		}
+
+		.footer-link {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			margin-top: 24rpx;
+			padding-top: 20rpx;
+			border-top: 2rpx solid #f0f2f5;
+			color: #8e9aae;
+			font-size: 28rpx;
+			cursor: pointer;
+			gap: 8rpx;
+
+			&:active {
+				opacity: 0.7;
+			}
+		}
+	}
+</style>

+ 304 - 73
pages/pcs/components/workOrderReport.vue

@@ -25,8 +25,7 @@
 							<view class="info-item">
 								<text class="info-label">检查时间</text>
 								<uni-datetime-picker type="datetime" v-model="form.checkStartTime"
-									returnType="timestamp"
-									:disabled="title == '详情'">
+									returnType="timestamp" :disabled="title == '详情'">
 									<view class="info-value">{{
                     form.checkStartTime&& dayjs(form.checkStartTime).format('YYYY-MM-DD HH:mm:ss')|| "请选择" }}</view>
 								</uni-datetime-picker>
@@ -35,7 +34,7 @@
 								<text class="info-label">报工时间</text>
 
 								<uni-datetime-picker type="datetime" v-model="form.checkFinishTime"
-									:disabled="title == '详情'" returnType="timestamp" >
+									:disabled="title == '详情'" returnType="timestamp">
 									<view class="info-value">
 										{{ form.checkFinishTime&& dayjs(form.checkFinishTime).format('YYYY-MM-DD HH:mm:ss')|| "请选择"}}
 									</view>
@@ -74,24 +73,52 @@
 									{{ form.productLineName || "请选择" }}
 								</view>
 							</view>
-							<view class="info-item" v-if="pageName == 'steamInjectionInspectionRecord'">
-								<text class="info-label">甲方检查人</text>
+							<view class="info-item" v-if="pageName == 'productionRecords' || pageName == 'qualityTestRecords'
+          "><text class="info-label">客户</text>
 								<view class="info-value" :class="{ disabled: title == '详情' }"
 									@click="title != '详情' && selectContactShow(17)">{{ form.contactName || "请选择" }}
 								</view>
 							</view>
-							<view class="info-item" v-if="pageName == 'solidWasteRecord'">
-								<text class="info-label">处理方</text>
+							<view class="info-item"
+								v-if="['QualityInspection', 'TransportAsh', 'HaulSlag'].includes(pageName)">
+								<text class="info-label">供应商</text>
 								<view class="info-value" :class="{ disabled: title == '详情' }"
 									@click="title != '详情' && selectContactShow(19)">{{ form.supplierName || "请选择" }}
 								</view>
 							</view>
-							<view class="info-item" v-if="pageName == 'qualityTestRecords'">
-								<text class="info-label">联合站检查人</text>
-								<view class="info-value" :class="{ disabled: title == '详情' }"
-									@click="title != '详情' && selectContactShow(17)">{{ form.contactName || "请选择" }}
+							<view class="info-item" v-if="
+							            ['QualityInspection', 'TransportAsh', 'HaulSlag'].includes(pageName)
+							          ">
+								<text class="info-label">采购订单</text>
+								<view class="info-value" :class="{ disabled: title == '详情' }" @click="openOrd">
+									{{ form.purchaseOrderNo || "请选择" }}
 								</view>
 							</view>
+							<view class="info-item" v-if="pageName == 'QualityInspection'">
+								<text class="info-label">检查卸车是否到位</text>
+								<view class="info-value" :class="{ disabled: title == '详情' }">
+
+									<u-radio-group class="result-group" v-model="form.unloadCheckStatus"
+										:disabled="title == '详情'">
+										<u-radio label="已到位" :name="1"></u-radio>
+										<u-radio label="未到位" :name="2"></u-radio>
+									</u-radio-group>
+
+								</view>
+							</view>
+							<view class="info-item" v-if="pageName == 'QualityInspection'">
+								<view class="info-label" style="display: flex;align-items: center;">车辆照片 <u-button
+										type="primary" style="width: 150rpx;margin-left: 10px;" size="small" text="拍照上传"
+										v-if="title != '详情'" @click="chooseImage"></u-button>
+								</view>
+
+							</view>
+						</view>
+						<view style="padding-left: 30rpx;" v-if="pageName == 'QualityInspection'">
+
+							<AlbumDeletable :urls="getUrl(form.vehiclePhotoUrl)" :singleSize="170" :multipleSize="170"
+								:deletable="title != '详情'" @delete="handleDeleteImage"></AlbumDeletable>
+
 						</view>
 						<!-- 运行参数记录区 -->
 						<view class="records-area">
@@ -101,7 +128,13 @@
 								</view>
 							</view>
 							<!-- 批量操作按钮放在标题下方 -->
-							<view class="batch-bar" v-if="pageName != 'productionRecords' && title != '详情'">
+							<view class="batch-bar" v-if="![
+                'qualityTestRecords',
+                'productionRecords',
+                'QualityInspection',
+                'HaulSlag',
+                'TransportAsh'
+              ].includes(pageName) && title != '详情'">
 								<button class="btn btn-primary" @click="batchCheck">
 									✅ 批量检查
 								</button>
@@ -124,12 +157,10 @@
 								</view>
 								<!-- 描述/数量 -->
 								<view class="item-row-input">
-									<text class="input-label">{{
-                    pageName == "qualityTestRecords" ? "描述" : "数量"
-                  }}</text>
+									<text class="input-label">值</text>
 
 									<input class="item-input" v-model="item.num" type="text" placeholder="请输入数量"
-										:disabled="title == '详情'" />
+										@input="setValue" :disabled="title == '详情'" />
 								</view>
 								<view class="item-row-input" v-if="pageName == 'qualityTestRecords'">
 									<text class="input-label">执行人</text>
@@ -144,7 +175,13 @@
                       "请选择"
                     }}</view>
 								</view>
-								<view class="item-actions" v-if="pageName != 'productionRecords'">
+								<view class="item-actions" v-if="![
+                'qualityTestRecords',
+                'productionRecords',
+                'QualityInspection',
+                'HaulSlag',
+                'TransportAsh'
+              ].includes(pageName)">
 									<u-radio-group class="result-group" v-model="item.checkStatus"
 										:disabled="title == '详情'">
 										<u-radio label="已检查" :name="1"></u-radio>
@@ -199,22 +236,7 @@
         []
       " title="选择" @confirm="executeIdListChange1">
 		</search-select>
-		<!-- <u-picker
-      :show="showCheckUsersIds"
-      keyName="label"
-      mode="multiSelector"
-      :columns="[
-        form.executeUsers &&
-          form.executeUsers.map((item) => {
-            return {
-              label: item.userName,
-              value: item.userId,
-            };
-          }),
-      ]"
-      @confirm="confirmCheckUsersIds"
-      @cancel="showCheckUsersIds = false"
-    ></u-picker> -->
+		<orderListDialog ref="orderListDialogRef" @changeParent="orderListDialogSuccess" :radioValue='true'></orderListDialog>
 	</u-popup>
 </template>
 
@@ -227,6 +249,7 @@
 		checkStartTime: "",
 		checkValidity: null,
 		checkValidityUnit: "",
+		checkValidityUnit: "",
 		conclusion: null,
 		detailList: [],
 		deviceId: 0,
@@ -276,6 +299,12 @@
 		supplierName: "",
 		productLineId: null,
 		productLineName: "",
+		unloadCheckStatus: '',
+		vehiclePhotoUrl: [],
+		purchaseOrderId: '',
+		purchaseOrderNo: '',
+		clientEnvironmentId: uni.getStorageSync("userInfo") &&
+			uni.getStorageSync("userInfo").clientEnvironmentId,
 	};
 	import {
 		getById,
@@ -295,12 +324,19 @@
 		mapGetters
 	} from "vuex";
 	import searchSelect from "@/pages/salesServiceManagement/accessory/components/searchSelect.vue";
+	import AlbumDeletable from "@/components/AlbumDeletable/AlbumDeletable.vue";
+	import orderListDialog from './OrderListDialog.vue';
+
+	import {
+		getPurchaseOrderList
+	} from '@/api/purchasingManage/index.js'
 	import dayjs from 'dayjs'
 	export default {
 		data() {
 			return {
 				visible: false,
 				executeUsersIds: [],
+				imgs: [],
 				title: "",
 				loading: false,
 				butLoading: false,
@@ -311,6 +347,7 @@
 				classificationList: [],
 				showProductLineIdPicker: false,
 				showCheckUsersIds: false,
+				checkUsersIds: '',
 				executorList: [],
 				allTeamList: [],
 				productLineList: [],
@@ -324,6 +361,8 @@
 		},
 		components: {
 			searchSelect,
+			AlbumDeletable,
+			orderListDialog
 		},
 		props: {
 			pageName: "",
@@ -332,12 +371,31 @@
 			async open(row, type) {
 				uni.$off("setSelectList");
 				uni.$on("setSelectList", (data) => {
-					console.log(data, "data");
 					if (data && data.length > 0) {
 						this.form.contactName = data[0].name;
 						this.form.contactId = data[0].id;
 						this.form.supplierName = data[0].name;
 						this.form.supplierId = data[0].id;
+
+						if (['QualityInspection', 'HaulSlag', 'TransportAsh'].includes(
+								this.pageName
+							)) {
+
+							this.form.purchaseOrderId = ''
+							this.form.purchaseOrderNo = ''
+							//来煤获取采购订单
+							getPurchaseOrderList({
+								pageNum: 1,
+								size: 999,
+								orderStatus: 2,
+								partbId: data[0].id
+							}).then((res) => {
+								if (res.list?.length == 1) {
+									this.form.purchaseOrderId = res.list[0].id;
+									this.form.purchaseOrderNo = res.list[0].orderNo;
+								}
+							});
+						}
 					}
 				});
 
@@ -371,7 +429,7 @@
 					url: "/pages/saleManage/components/selectContact?isAll=" +
 						false +
 						"&contactType=" +
-						type,
+						type + '&code=' + this.getCode(),
 				});
 			},
 			confirmProductLine(e) {
@@ -383,15 +441,39 @@
 			closePopup() {
 				this.cancel();
 			},
-
-			handParent() {
-				this.$refs.parentListRef.open();
+			openOrd() {
+				if (!this.form.supplierId) {
+					this.$refs.uToast.show({
+						type: "error",
+						icon: false,
+						message: `请先选择供应商!`,
+					});
+					return;
+				}
+				this.$refs.orderListDialogRef.open(
+					this.form.supplierId,
+					//渣和灰拿委外订单
+					['TransportAsh', 'HaulSlag'].includes(this.pageName) ?
+					'3,4,5,6,7' :
+					''
+				);
+			},
+			orderListDialogSuccess(data) {
+				this.form.purchaseOrderId = data.id;
+				this.form.purchaseOrderNo = data.orderNo;
 			},
-			changeParent(data) {
-				this.form.contactName = data.name;
-				this.form.contactId = data.id;
-				this.form.supplierName = data.name;
-				this.form.supplierId = data.id;
+			getCode() {
+				if (this.clientEnvironmentId == 10) {
+					return this.pageName == 'QualityInspection' ?
+						'06mei' :
+						this.pageName == 'TransportAsh' ?
+						'07lafei' :
+						this.pageName == 'HaulSlag' ?
+						'08lazha' :
+						'';
+				} else {
+					return '';
+				}
 			},
 			// 获取工单详情
 			async getOrderDetials(id) {
@@ -427,7 +509,19 @@
 					});
 					// this.$util.assignObject(this.form, data);
 					Object.assign(this.form, data);
-
+					this.form.vehiclePhotoUrl = this.form.vehiclePhotoUrl || [];
+					this.form.unloadCheckStatus = this.form.unloadCheckStatus || 1;
+
+					this.form.checkStartTime =
+						this.form.checkStartTime ||
+						dayjs(new Date()).format('YYYY-M-D HH:mm:ss');
+					this.form.checkFinishTime =
+						this.form.checkFinishTime ||
+						dayjs(new Date()).format('YYYY-M-D HH:mm:ss');
+					console.log(
+						this.form.checkStartTime,
+						'this.form.checkStartTime'
+					);
 					this.form.executeUsersIds = this.form.executeUsers
 						.map((i) => i.userId)
 						.filter((i) => i); // 过滤掉 undefined
@@ -472,7 +566,26 @@
 							}
 						});
 					}
-
+					//宇信
+					if (
+						this.clientEnvironmentId == 10 && ['productionRecords',
+							'qualityTestRecords'
+						].includes(this.pageName)
+					) {
+						//客户:5#和6#默认是重油公司7#默认是红山 2008389016775864321==7#
+						if (this.form.productLineId == '2008389016775864321') {
+							this.form.contactId =
+								this.form.contactId || '2008562263580520449';
+							this.form.contactName =
+								this.form.contactName || '克拉玛依红山油田有限责任公司';
+						} else {
+							this.form.contactId =
+								this.form.contactId || '2008383566202318850';
+							this.form.contactName =
+								this.form.contactName || '中国石油新疆油田分公司(重油公司)';
+						}
+					}
+					this.setValue();
 					this.$nextTick(() => {
 						this.loading = false;
 					});
@@ -488,6 +601,126 @@
 				console.log("this.teamUserList", this.teamUserList);
 			},
 
+
+			chooseImage() {
+				const _this = this
+				uni.chooseImage({
+					count: 9, //默认9
+					sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
+					sourceType: ['camera'], //从相册选择
+					success: function(res) {
+						uni.showLoading({
+							title: '加载中'
+						})
+
+						_this.uploadFile(res.tempFilePaths).then(res => {
+							res.forEach(item => {
+								let fileNames = item.storePath.split('/')
+								let url =
+									'/main/file/getFile?objectName=' + item.storePath +
+									'&fullfilename=' + fileNames[fileNames.length -
+										1]
+								_this.form.vehiclePhotoUrl.push(url)
+							})
+
+							uni.hideLoading()
+
+						})
+
+					}
+				});
+			},
+			getUrl(arr) {
+				console.log(arr, 'arr')
+				if (arr.length) {
+					return arr.map(item => {
+						return this.apiUrl + item
+					})
+				} else {
+					return []
+				}
+
+
+			},
+			uploadFile(list) {
+				let PromiseAll = []
+				const apiUrl = this.apiUrl
+				const token = uni.getStorageSync("token"); //取存本地的token
+				list.forEach(item => {
+					PromiseAll.push(
+						new Promise((resolve, reject) => {
+							uni.uploadFile({
+								url: apiUrl + '/main/file/upload',
+								filePath: item,
+								name: 'multiPartFile',
+								header: {
+									authorization: token
+								},
+								success: (uploadFileRes) => {
+									let data = JSON.parse(uploadFileRes.data)
+									resolve(data.data)
+								}
+							});
+						}),
+					)
+				})
+
+				return Promise.all(PromiseAll)
+
+			},
+			setValue() {
+				if (this.title == '报工') {
+					this.form.detailList.forEach((item, index) => {
+
+						if (this.pageName == 'qualityTestRecords') {
+							let num1 = this.form.detailList.find(
+								(item1) => item1.paramValue == '给水量'
+							)?.num;
+							let num2 = this.form.detailList.find(
+								(item1) => item1.paramValue == '炉水量'
+							)?.num;
+							let num = 0;
+							if (num1 && num2) {
+								num = (num2 - num1) / num2;
+							}
+							if (item.paramValue == '干度') {
+								this.$set(
+									this.form.detailList[index],
+									'num',
+									parseFloat(num.toFixed(5)) * 100
+								);
+							}
+							if (item.paramValue == '是否合格' && num1) {
+								this.$set(
+									this.form.detailList[index],
+									'num',
+									parseFloat(num.toFixed(5)) * 100 >= 90 ? '合格' : '不合格'
+								);
+							}
+						}
+						if (this.pageName == 'productionRecords') {
+							let num1 = this.form.detailList.find(
+								(item1) => item1.paramValue == '日用水量'
+							)?.num;
+
+							let num = 0;
+							if (num1) {
+								num = num1 * 0.1034;
+							}
+							if (item.paramValue == '日用煤量') {
+								this.$set(
+									this.form.detailList[index],
+									'num',
+									parseFloat(num.toFixed(5))
+								);
+							}
+						}
+					});
+				}
+			},
+			handleDeleteImage(index) {
+				this.form.vehiclePhotoUrl.splice(index, 1);
+			},
 			// 批量检查
 			batchCheck() {
 				this.form.detailList.forEach((i, index) => {
@@ -623,35 +856,28 @@
 					});
 					return;
 				}
-				if (this.pageName == 'steamInjectionInspectionRecord'&&!this.form.contactName) {
-					this.$refs.uToast.show({
-						type: "error",
-						icon: false,
-						message: `请选择甲方检查人!`,
-					});
-					return;
-				}
-				if (this.pageName == 'solidWasteRecord'&&!this.form.supplierName) {
-					this.$refs.uToast.show({
-						type: "error",
-						icon: false,
-						message: `请选择处理方!`,
-					});
-					return;
-				}
-				if (this.pageName == 'qualityTestRecords'&&!this.form.contactName) {
-					this.$refs.uToast.show({
-						type: "error",
-						icon: false,
-						message: `请选择联合站检查人!`,
-					});
-					return;
-				}
-				
+				// if (this.pageName == 'steamInjectionInspectionRecord' && !this.form.contactName) {
+				// 	this.$refs.uToast.show({
+				// 		type: "error",
+				// 		icon: false,
+				// 		message: `请选择甲方检查人!`,
+				// 	});
+				// 	return;
+				// }
+				// if (this.pageName == 'solidWasteRecord' && !this.form.supplierName) {
+				// 	this.$refs.uToast.show({
+				// 		type: "error",
+				// 		icon: false,
+				// 		message: `请选择处理方!`,
+				// 	});
+				// 	return;
+				// }
+
+
 				// 验证报工时间必须大于等于检查时间
 				const startTime = new Date(this.form.checkStartTime).getTime();
 				const finishTime = new Date(this.form.checkFinishTime).getTime();
-		
+
 				if (finishTime < startTime) {
 					this.$refs.uToast.show({
 						type: "error",
@@ -670,8 +896,13 @@
 					return;
 				}
 
-				// 报工需要验证 缓存不验证 排除 recordTemplateStyle ==3 物料添加 == 4生产统计 模板
-				if (this.pageName != "productionRecords") {
+				if (![
+						'qualityTestRecords',
+						'productionRecords',
+						'QualityInspection',
+						'HaulSlag',
+						'TransportAsh'
+					].includes(this.pageName)) {
 					// 验证检查项目
 					const detailRequired = this.form.detailList.some((i) => {
 						return i.checkResult == null || i.checkStatus == null;

+ 25 - 16
pages/pcs/list.vue

@@ -19,8 +19,9 @@
 		<view class="wrapper">
 			<u-list @scrolltolower="scrolltolower" class="listContent">
 				<view v-for="(item, index) in tableList" :key="index" style="position: relative">
-					<myCard :item="item" :index="index + 1" :btnList="activeTab === 'all' ? [] : btnList" :columns="columns" :title="item.code"
-						:status="statusMap[item.status]" @goDetail="goDetail(item, 'view')" @openRedeployOther="openRedeployOther(item)"
+					<myCard :item="item" :index="index + 1" :btnList="activeTab === 'all' ? [] : btnList"
+						:columns="columns" :title="item.code" :status="statusMap[item.status]"
+						@goDetail="goDetail(item, 'view')" @openRedeployOther="openRedeployOther(item)"
 						@edit="goDetail(item, 'edit')">
 					</myCard>
 				</view>
@@ -48,7 +49,8 @@
 	export default {
 		components: {
 			myCard,
-			workOrderReport,Assign,
+			workOrderReport,
+			Assign,
 		},
 		mixins: [dictMixns],
 		props: {
@@ -69,6 +71,9 @@
 					solidWasteRecord: 4,
 					qualityTestRecords: 5,
 					boilerOperationRecord: 6,
+					QualityInspection: 7,
+					HaulSlag: 8,
+					TransportAsh: 9
 				},
 				btnList: [{
 					name: "报工",
@@ -136,23 +141,24 @@
 						},
 					}, ],
 					[{
-							label: "甲方检查人:",
+							label: "客户:",
 							prop: "contactName",
 							className: "perce100",
-							isNone: this.pageName != "steamInjectionInspectionRecord",
+							isNone: !['productionRecords', 'qualityTestRecords'].includes(
+								this.pageName
+							) || this.pageName == 'boilerOperationRecord'
 						},
 						{
-							label: "处理方:",
+							label: "供应商:",
 							prop: "supplierName",
 							className: "perce100",
-							isNone: this.pageName != "solidWasteRecord",
-						},
-						{
-							label: "联合站检查人:",
-							prop: "contactName",
-							className: "perce100",
-							isNone: this.pageName != "qualityTestRecords",
+							isNone: [
+								'productionRecords',
+								'qualityTestRecords',
+								'boilerOperationRecord'
+							].includes(this.pageName)
 						},
+
 					],
 					[{
 						label: "操作:",
@@ -180,7 +186,10 @@
 					this.pageName == "solidWasteRecord" ?
 					"固废记录" :
 					this.pageName == "qualityTestRecords" ?
-					"质量检查检测记录" :
+					"质量检查检测记录" : this.pageName == "HaulSlag" ?
+					"拉渣记录表" : this.pageName == "TransportAsh" ?
+					"拉灰记录表" : this.pageName == "QualityInspection" ?
+					"来煤质检记录" :
 					"锅炉运行记录";
 			},
 		},
@@ -194,8 +203,8 @@
 				console.log(item, "item");
 				this.$refs.workOrderReportRef.open(item, type);
 			},
-            openRedeployOther(row){
-				 this.$refs.Assign.open(row)
+			openRedeployOther(row) {
+				this.$refs.Assign.open(row)
 			},
 			switchTab(tab) {
 				if (this.activeTab === tab) return;

+ 445 - 467
pages/saleManage/components/selectContact.vue

@@ -1,476 +1,454 @@
 <template>
-  <view class="mainBox">
-    <uni-nav-bar
-      fixed="true"
-      statusBar="true"
-      left-icon="back"
-      title="选择"
-      @clickLeft="backAdd"
-    >
-      <!--右菜单-->
-      <template slot="right">
-        <u-button
-          type="success"
-          size="small"
-          class="u-reset-button"
-          @click="$refs.treePicker._show()"
-          text="选择分类"
-        ></u-button>
-      </template>
-    </uni-nav-bar>
-    <view class="searchBox">
-      <input v-model="searchVal" placeholder="请输入名称" class="searchInput" />
-      <u-button
-        type="icon-shixiangxinzeng"
-        size="30"
-        @click="doSearch"
-        data-icon="Search"
-        class="searchBtn"
-      >
-        <view class="iconfont icon-sousuo"></view>
-        <view class="text">搜索</view>
-      </u-button>
-    </view>
-    <view class="wrapper">
-      <u-list @scrolltolower="scrolltolower" class="listContent">
-        <checkbox-group
-          v-for="(item, index) in listData"
-          :key="index"
-          @change="(e) => selectVal(e, item, index)"
-        >
-          <label>
-            <view class="listBox">
-              <view class="listBox-sel">
-                <checkbox
-                  :value="item.code"
-                  color="#fff"
-                  :disabled="item.disabled"
-                  :checked="item.checked"
-                />
-              </view>
-              <view class="listBox-con">
-                <view class="listBox-top">
-                  <view class="listBox-name">
-                    {{ item.name }}
-                  </view>
-                </view>
-                <view class="listBox-bottom">
-                  <!-- <view v-for="(itm, index) in tableHeader" :key="index">{{ itm.label }}:{{ item[itm.prop] }}</view> -->
-                  <view>代号:{{ item.serialNo || "" }}</view>
-                  <view
-                    >详细地址:{{
+	<view class="mainBox">
+		<uni-nav-bar fixed="true" statusBar="true" left-icon="back" title="选择" @clickLeft="backAdd">
+			<!--右菜单-->
+			<template slot="right">
+				<u-button type="success" size="small" class="u-reset-button" @click="$refs.treePicker._show()"
+					text="选择分类"></u-button>
+			</template>
+		</uni-nav-bar>
+		<view class="searchBox">
+			<input v-model="searchVal" placeholder="请输入名称" class="searchInput" />
+			<u-button type="icon-shixiangxinzeng" size="30" @click="doSearch" data-icon="Search" class="searchBtn">
+				<view class="iconfont icon-sousuo"></view>
+				<view class="text">搜索</view>
+			</u-button>
+		</view>
+		<view class="wrapper">
+			<u-list @scrolltolower="scrolltolower" class="listContent">
+				<checkbox-group v-for="(item, index) in listData" :key="index"
+					@change="(e) => selectVal(e, item, index)">
+					<label>
+						<view class="listBox">
+							<view class="listBox-sel">
+								<checkbox :value="item.code" color="#fff" :disabled="item.disabled"
+									:checked="item.checked" />
+							</view>
+							<view class="listBox-con">
+								<view class="listBox-top">
+									<view class="listBox-name">
+										{{ item.name }}
+									</view>
+								</view>
+								<view class="listBox-bottom">
+									<!-- <view v-for="(itm, index) in tableHeader" :key="index">{{ itm.label }}:{{ item[itm.prop] }}</view> -->
+									<view>代号:{{ item.serialNo || "" }}</view>
+									<view>详细地址:{{
                       (item.addressName || "") + item.address || ""
-                    }}</view
-                  >
-                  <view
-                    >是否指派:{{
+                    }}</view>
+									<view>是否指派:{{
                       (item.assignStatus === 1 ? "是" : "否") || ""
-                    }}</view
-                  >
-                  <view>销售员:{{ item.salesmanName || "" }}</view>
-                  <view>创建人:{{ item.createUsername || "" }}</view>
-                </view>
-              </view>
-            </view>
-          </label>
-        </checkbox-group>
-        <u-empty
-          class="noDate"
-          style="margin-top: 20vh"
-          v-if="!listData.length"
-        ></u-empty>
-      </u-list>
-    </view>
-
-    <view class="footer">
-      <view class="bottom" v-if="this.isAll == 1">
-        <checkbox
-          v-if="!seletedAll"
-          color="#fff"
-          :checked="seletedAll"
-          @tap="_seletedAll"
-          >全选</checkbox
-        >
-        <checkbox
-          class="select-all"
-          color="#fff"
-          v-else
-          :checked="seletedAll"
-          @tap="_seletedAll"
-          >取消全选
-        </checkbox>
-      </view>
-      <u-button
-        type="success"
-        size="small"
-        class="u-reset-button"
-        :disabled="!checkListLen"
-        @click="jumpAdd"
-      >
-        <view class="selBtn">选择( {{ checkListLen }} )</view>
-      </u-button>
-    </view>
-    <ba-tree-picker
-      ref="treePicker"
-      key="verify"
-      :multiple="false"
-      @select-change="confirm"
-      title="选择分类"
-      :localdata="classificationList"
-      valueKey="id"
-      textKey="name"
-    />
-  </view>
+                    }}</view>
+									<view>销售员:{{ item.salesmanName || "" }}</view>
+									<view>创建人:{{ item.createUsername || "" }}</view>
+								</view>
+							</view>
+						</view>
+					</label>
+				</checkbox-group>
+				<u-empty class="noDate" style="margin-top: 20vh" v-if="!listData.length"></u-empty>
+			</u-list>
+		</view>
+
+		<view class="footer">
+			<view class="bottom" v-if="this.isAll == 1">
+				<checkbox v-if="!seletedAll" color="#fff" :checked="seletedAll" @tap="_seletedAll">全选</checkbox>
+				<checkbox class="select-all" color="#fff" v-else :checked="seletedAll" @tap="_seletedAll">取消全选
+				</checkbox>
+			</view>
+			<u-button type="success" size="small" class="u-reset-button" :disabled="!checkListLen" @click="jumpAdd">
+				<view class="selBtn">选择( {{ checkListLen }} )</view>
+			</u-button>
+		</view>
+		<ba-tree-picker ref="treePicker" key="verify" :multiple="false" @select-change="confirm" title="选择分类"
+			:localdata="classificationList" valueKey="id" textKey="name" />
+	</view>
 </template>
 
 <script>
-import { contactPage } from "@/api/saleManage/contact/index.js";
-import { getTreeByPid } from "@/api/classifyManage/index.js";
-import baTreePicker from "@/components/ba-tree-picker/ba-tree-picker.vue";
-export default {
-  components: {
-    baTreePicker,
-  },
-
-  data() {
-    return {
-      page: 1,
-      size: 20,
-      isEnd: true,
-      searchVal: "",
-      pickTabIndex: 1,
-      popupShow: false, //右侧搜索窗
-      typeIndex: 1,
-      listData: [], //列表数据
-      classificationList: [], //分类数据
-      seletedAll: false, //全选状态,
-      isAll: "",
-      isDemand: "",
-      contactType: "",
-    };
-  },
-  //选择的列表长度
-  computed: {
-    checkListLen() {
-      return this.listData.filter((el) => el.checked).length;
-    },
-  },
-  onLoad({ isAll, type, contactType }) {
-    this.isAll = isAll; //1多选 2单选
-    this.contactType = contactType || 17; //17客户 20供应商
-
-    // *** 新增 需求进来的话 要增加查询条件
-    if (type == "需求") {
-      this.isDemand = "1";
-    }
-    this.getClassify();
-  },
-  onShow() {},
-  methods: {
-    scrolltolower() {
-      if (this.isEnd) {
-        return;
-      }
-      // 显示加载图标
-      uni.showLoading({
-        title: "数据加载中",
-      });
-      //获取更多数据
-      this.page++;
-      this.getList();
-    },
-    //列表数据
-    async getList() {
-      this.isEnd = false;
-      this._getClassifyList();
-    },
-    async _getClassifyList() {
-      uni.showLoading({
-        title: "数据加载中",
-      });
-      const params = {
-        pageNum: this.page,
-        size: this.size,
-        name: this.searchVal,
-        categoryId: this.categoryLevelId,
-        status: 1,
-        type: this.contactType == 17 ? 1 : 2,
-      };
-      // 需求新增参数 ***
-      if (this.isDemand == "1") {
-        params.type = "1";
-        params.status = "1";
-      }
-      contactPage(params).then((res) => {
-        uni.hideLoading();
-        if (this.page == 1) {
-          this.listData = [];
-        }
-        this.listData = this.listData.concat(res.list);
-        this.isEnd = this.listData.length >= res.count;
-      });
-    },
-    confirm([id]) {
-      this.categoryLevelId = id;
-      this.page = 1;
-
-      if (this.isAll === "2") {
-        this.listData.forEach((item) => (item.checked = false));
-      }
-
-      this.getList();
-    },
-    async getClassify() {
-      getTreeByPid(17).then((res) => {
-        this.classificationList = res.data;
-        this.page = 1;
-        this.getList();
-      });
-    },
-    doSearch() {
-      this.page = 1;
-      this.getList();
-    },
-    //勾选
-    selectVal(e, val, index) {
-      this.$set(this.listData[index], "checked", !this.listData[index].checked);
-
-      if (this.isAll != 1) {
-        this.listData.forEach((item, i) => {
-          if (item.id != val.id) {
-            this.$set(this.listData[i], "checked", false);
-          }
-        });
-      } else {
-        this.seletedAll = !this.listData.some((item) => !item.checked);
-      }
-    },
-    //全选按钮
-    _seletedAll() {
-      if (!this.seletedAll) {
-        this.seletedAll = true;
-        this.listData.map((item) => {
-          this.$set(item, "checked", true);
-        });
-      } else {
-        this.seletedAll = false;
-        //this.checkListLen = 0;
-        this.listData.map((item) => {
-          this.$set(item, "checked", false);
-        });
-      }
-    },
-    //跳转回添加页面
-    jumpAdd() {
-      uni.$emit(
-        "setSelectList",
-        this.listData.filter((item) => item.checked),
-      );
-      console.log(
-        this.listData.filter((item) => item.checked),
-        "222",
-      );
-      uni.navigateBack();
-    },
-    //返回添加页
-    backAdd() {
-      uni.navigateBack();
-    },
-  },
-};
+	import {
+		contactPage
+	} from "@/api/saleManage/contact/index.js";
+	import {
+		getTreeByPid
+	} from "@/api/classifyManage/index.js";
+	import baTreePicker from "@/components/ba-tree-picker/ba-tree-picker.vue";
+	export default {
+		components: {
+			baTreePicker,
+		},
+
+		data() {
+			return {
+				page: 1,
+				size: 20,
+				isEnd: true,
+				searchVal: "",
+				pickTabIndex: 1,
+				popupShow: false, //右侧搜索窗
+				typeIndex: 1,
+				listData: [], //列表数据
+				classificationList: [], //分类数据
+				seletedAll: false, //全选状态,
+				isAll: "",
+				isDemand: "",
+				contactType: "",
+				code: ''
+			};
+		},
+		//选择的列表长度
+		computed: {
+			checkListLen() {
+				return this.listData.filter((el) => el.checked).length;
+			},
+		},
+		onLoad({
+			isAll,
+			type,
+			contactType,code
+		}) {
+			this.isAll = isAll; //1多选 2单选
+			this.contactType = contactType || 17; //17客户 19供应商
+			this.code = code
+
+			// *** 新增 需求进来的话 要增加查询条件
+			if (type == "需求") {
+				this.isDemand = "1";
+			}
+			this.getClassify();
+		},
+		onShow() {},
+		methods: {
+			scrolltolower() {
+				if (this.isEnd) {
+					return;
+				}
+				// 显示加载图标
+				uni.showLoading({
+					title: "数据加载中",
+				});
+				//获取更多数据
+				this.page++;
+				this.getList();
+			},
+			//列表数据
+			async getList() {
+				this.isEnd = false;
+				this._getClassifyList();
+			},
+			async _getClassifyList() {
+				uni.showLoading({
+					title: "数据加载中",
+				});
+				const params = {
+					pageNum: this.page,
+					size: this.size,
+					name: this.searchVal,
+					categoryId: this.categoryLevelId,
+					status: 1,
+					type: this.contactType == 17 ? 1 : 2,
+				};
+				// 需求新增参数 ***
+				if (this.isDemand == "1") {
+					params.type = "1";
+					params.status = "1";
+				}
+				contactPage(params).then((res) => {
+					uni.hideLoading();
+					if (this.page == 1) {
+						this.listData = [];
+					}
+					this.listData = this.listData.concat(res.list);
+					this.isEnd = this.listData.length >= res.count;
+				});
+			},
+			confirm([id]) {
+				this.categoryLevelId = id;
+				this.page = 1;
+
+				if (this.isAll === "2") {
+					this.listData.forEach((item) => (item.checked = false));
+				}
+
+				this.getList();
+			},
+			async getClassify() {
+				getTreeByPid(this.contactType).then((res) => {
+					this.classificationList = res.data;
+
+					if (this.classificationList.length) {
+						if (this.code) {
+							this.classificationList = this.filterTreeByCode(this.classificationList, this
+							.code);
+						}
+						this.categoryLevelId = this.classificationList[0].id
+						this.page = 1;
+						this.getList();
+					}
+
+
+
+				});
+			},
+			/* 递归过滤树节点 */
+			filterTreeByCode(list, code) {
+				const result = [];
+				const walk = (nodes) => {
+					for (const node of nodes) {
+						if (node.code === code) {
+							result.push(node);
+						} else if (node.children && node.children.length) {
+							walk(node.children);
+						}
+					}
+				};
+				walk(list);
+				return result;
+			},
+			doSearch() {
+				this.page = 1;
+				this.getList();
+			},
+			//勾选
+			selectVal(e, val, index) {
+				this.$set(this.listData[index], "checked", !this.listData[index].checked);
+
+				if (this.isAll != 1) {
+					this.listData.forEach((item, i) => {
+						if (item.id != val.id) {
+							this.$set(this.listData[i], "checked", false);
+						}
+					});
+				} else {
+					this.seletedAll = !this.listData.some((item) => !item.checked);
+				}
+			},
+			//全选按钮
+			_seletedAll() {
+				if (!this.seletedAll) {
+					this.seletedAll = true;
+					this.listData.map((item) => {
+						this.$set(item, "checked", true);
+					});
+				} else {
+					this.seletedAll = false;
+					//this.checkListLen = 0;
+					this.listData.map((item) => {
+						this.$set(item, "checked", false);
+					});
+				}
+			},
+			//跳转回添加页面
+			jumpAdd() {
+				uni.$emit(
+					"setSelectList",
+					this.listData.filter((item) => item.checked),
+				);
+				console.log(
+					this.listData.filter((item) => item.checked),
+					"222",
+				);
+				uni.navigateBack();
+			},
+			//返回添加页
+			backAdd() {
+				uni.navigateBack();
+			},
+		},
+	};
 </script>
 
 <style lang="scss" scoped>
-.mainBox {
-  height: 100vh;
-  display: flex;
-  flex-direction: column;
-
-  .wrapper {
-    flex: 1;
-    overflow: hidden;
-  }
-
-  .searchBox {
-    padding: 10rpx 0;
-    box-sizing: border-box;
-    background-color: #dedede;
-    height: 90rpx;
-    width: 100%;
-    line-height: 90rpx;
-    display: flex;
-    justify-content: space-around;
-    align-items: center;
-
-    input {
-      height: 78rpx;
-      width: 65%;
-      background: #f9f9f9 !important;
-      margin: 0 10rpx;
-      padding: 0 10rpx;
-      box-sizing: border-box;
-      border-radius: 5rpx;
-    }
-
-    .searchBtn {
-      height: 80rpx;
-      background: #f9f9f9 !important;
-      color: #676767;
-      font-size: 28rpx;
-      padding: 0 42rpx;
-      box-sizing: border-box;
-      outline: none;
-      border: none;
-      width: 260rpx;
-
-      .icon-sousuo {
-        font-size: 22px;
-      }
-
-      .text {
-        font-size: 16px;
-        margin-left: 10px;
-      }
-    }
-  }
-
-  .tab-title {
-    position: fixed;
-    top: 190rpx;
-    z-index: 99;
-    width: 100%;
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    height: $tab-height;
-    line-height: $tab-height;
-    background-color: #ffffff;
-    border-bottom: 2rpx solid #f2f2f2;
-    box-sizing: border-box;
-
-    .tab-item {
-      width: 25%;
-      text-align: center;
-      font-size: 32rpx;
-      color: $uni-text-color-grey;
-    }
-
-    .tab-item.active {
-      color: $j-primary-border-green;
-      border-bottom: 1px solid $j-primary-border-green;
-      font-weight: bold;
-    }
-
-    .tab-item.filter {
-      flex: 1;
-      padding: 0px 30rpx;
-
-      .uni-icons {
-        display: flex;
-        padding-top: 5px;
-      }
-    }
-
-    .screenIcon {
-      display: flex;
-      width: 80px;
-      justify-content: center;
-
-      .screenText {
-        font-size: 32rpx;
-        color: $uni-text-color-grey;
-      }
-    }
-  }
-
-  .listContent {
-    height: 100% !important;
-
-    .listBox {
-      display: flex;
-      // height: 180rpx;
-      padding: 20rpx 0;
-      border-bottom: 2rpx solid #e5e5e5;
-
-      .listBox-sel {
-        height: 90rpx;
-        width: 80rpx;
-        // line-height: 90rpx;
-        text-align: center;
-
-        checkbox {
-          transform: scale(1.2);
-        }
-      }
-
-      .listBox-con {
-        width: 100%;
-        // display: flex;
-        // flex-wrap: wrap;
-        // justify-content: space-between;
-        align-items: center;
-        padding: 0 18rpx 0 0;
-
-        .listBox-top {
-          width: 100%;
-          display: flex;
-          justify-content: space-between;
-          padding-bottom: 10rpx;
-
-          .listBox-name,
-          .listBox-code {
-            display: inline-block;
-            font-size: $uni-font-size-sm;
-            font-weight: bold;
-          }
-        }
-
-        .listBox-bottom {
-          width: 100%;
-          display: flex;
-          justify-content: space-between;
-          font-size: $uni-font-size-sm;
-          flex-wrap: wrap;
-
-          > view {
-            width: 50%;
-            overflow: hidden;
-            white-space: nowrap;
-            text-overflow: ellipsis;
-          }
-        }
-      }
-    }
-
-    .noDate {
-      height: 100%;
-    }
-  }
-
-  //底部按钮
-  .footer {
-    height: 90rpx;
-    position: relative;
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    bottom: 0;
-    width: 100%;
-    height: 100rpx;
-    border-top: 1rpx solid #eeecec;
-    background-color: #ffffff;
-    z-index: 999;
-
-    .bottom {
-      margin-left: 10rpx;
-    }
-
-    .u-reset-button {
-      position: absolute;
-      right: 10rpx;
-      top: 20rpx;
-      width: 150rpx;
-    }
-  }
-}
-</style>
+	.mainBox {
+		height: 100vh;
+		display: flex;
+		flex-direction: column;
+
+		.wrapper {
+			flex: 1;
+			overflow: hidden;
+		}
+
+		.searchBox {
+			padding: 10rpx 0;
+			box-sizing: border-box;
+			background-color: #dedede;
+			height: 90rpx;
+			width: 100%;
+			line-height: 90rpx;
+			display: flex;
+			justify-content: space-around;
+			align-items: center;
+
+			input {
+				height: 78rpx;
+				width: 65%;
+				background: #f9f9f9 !important;
+				margin: 0 10rpx;
+				padding: 0 10rpx;
+				box-sizing: border-box;
+				border-radius: 5rpx;
+			}
+
+			.searchBtn {
+				height: 80rpx;
+				background: #f9f9f9 !important;
+				color: #676767;
+				font-size: 28rpx;
+				padding: 0 42rpx;
+				box-sizing: border-box;
+				outline: none;
+				border: none;
+				width: 260rpx;
+
+				.icon-sousuo {
+					font-size: 22px;
+				}
+
+				.text {
+					font-size: 16px;
+					margin-left: 10px;
+				}
+			}
+		}
+
+		.tab-title {
+			position: fixed;
+			top: 190rpx;
+			z-index: 99;
+			width: 100%;
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			height: $tab-height;
+			line-height: $tab-height;
+			background-color: #ffffff;
+			border-bottom: 2rpx solid #f2f2f2;
+			box-sizing: border-box;
+
+			.tab-item {
+				width: 25%;
+				text-align: center;
+				font-size: 32rpx;
+				color: $uni-text-color-grey;
+			}
+
+			.tab-item.active {
+				color: $j-primary-border-green;
+				border-bottom: 1px solid $j-primary-border-green;
+				font-weight: bold;
+			}
+
+			.tab-item.filter {
+				flex: 1;
+				padding: 0px 30rpx;
+
+				.uni-icons {
+					display: flex;
+					padding-top: 5px;
+				}
+			}
+
+			.screenIcon {
+				display: flex;
+				width: 80px;
+				justify-content: center;
+
+				.screenText {
+					font-size: 32rpx;
+					color: $uni-text-color-grey;
+				}
+			}
+		}
+
+		.listContent {
+			height: 100% !important;
+
+			.listBox {
+				display: flex;
+				// height: 180rpx;
+				padding: 20rpx 0;
+				border-bottom: 2rpx solid #e5e5e5;
+
+				.listBox-sel {
+					height: 90rpx;
+					width: 80rpx;
+					// line-height: 90rpx;
+					text-align: center;
+
+					checkbox {
+						transform: scale(1.2);
+					}
+				}
+
+				.listBox-con {
+					width: 100%;
+					// display: flex;
+					// flex-wrap: wrap;
+					// justify-content: space-between;
+					align-items: center;
+					padding: 0 18rpx 0 0;
+
+					.listBox-top {
+						width: 100%;
+						display: flex;
+						justify-content: space-between;
+						padding-bottom: 10rpx;
+
+						.listBox-name,
+						.listBox-code {
+							display: inline-block;
+							font-size: $uni-font-size-sm;
+							font-weight: bold;
+						}
+					}
+
+					.listBox-bottom {
+						width: 100%;
+						display: flex;
+						justify-content: space-between;
+						font-size: $uni-font-size-sm;
+						flex-wrap: wrap;
+
+						>view {
+							width: 50%;
+							overflow: hidden;
+							white-space: nowrap;
+							text-overflow: ellipsis;
+						}
+					}
+				}
+			}
+
+			.noDate {
+				height: 100%;
+			}
+		}
+
+		//底部按钮
+		.footer {
+			height: 90rpx;
+			position: relative;
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			bottom: 0;
+			width: 100%;
+			height: 100rpx;
+			border-top: 1rpx solid #eeecec;
+			background-color: #ffffff;
+			z-index: 999;
+
+			.bottom {
+				margin-left: 10rpx;
+			}
+
+			.u-reset-button {
+				position: absolute;
+				right: 10rpx;
+				top: 20rpx;
+				width: 150rpx;
+			}
+		}
+	}
+</style>