2 Ревизии

Автор SHA1 Съобщение Дата
  jiajunchen 3e4bb2d9ac Merge remote-tracking branch 'origin/develop' into develop преди 1 седмица
  jiajunchen b0d1dc14fa 1 преди 1 седмица
променени са 5 файла, в които са добавени 1606 реда и са изтрити 0 реда
  1. 265
    0
      src/components/AttachmentS3ImageReturnURL.vue
  2. 10
    0
      src/router/index.ts
  3. 4
    0
      src/view/Home2.vue
  4. 617
    0
      src/view/knowledge/Culture.vue
  5. 710
    0
      src/view/knowledge/CultureList.vue

+ 265
- 0
src/components/AttachmentS3ImageReturnURL.vue Целия файл

@@ -0,0 +1,265 @@
1
+<template>
2
+	<div style="padding: 5px;flex: 1">
3
+		<div>
4
+			<van-uploader
5
+        :disabled="readonly"
6
+        v-model="fileListTemp"
7
+				accept=".txt,.pdf,.doc,.docx,.xls,.xlsx,.wps,.et,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,image/*"
8
+				:after-read="uploadFile"
9
+        upload-icon="plus"
10
+        :show-upload="true"
11
+        :before-delete="onDelete"
12
+      />
13
+		</div>
14
+	</div>
15
+</template>
16
+
17
+
18
+<script setup>
19
+	import { ref, onMounted, getCurrentInstance, watch } from 'vue'
20
+  import { showFailToast, showSuccessToast, showConfirmDialog } from 'vant';
21
+	const { proxy } = getCurrentInstance()
22
+
23
+  const emit = defineEmits(['update:firstFileUrl'])
24
+
25
+	const props = defineProps({
26
+		fId: {
27
+			type: String,
28
+			default: () => ''
29
+		},
30
+		value1: {
31
+			type: String,
32
+			default: () => null
33
+		},
34
+		value2: {
35
+			type: String,
36
+			default: () => null
37
+		},
38
+		value3: {
39
+			type: String,
40
+			default: () => null
41
+		},
42
+		value4: {
43
+			type: String,
44
+			default: () => null
45
+		},
46
+		value5: {
47
+			type: String,
48
+			default: () => null
49
+		},
50
+		selectButton: {
51
+			type: Boolean,
52
+			default: () => true
53
+		},
54
+		deleteButton: {
55
+			type: Boolean,
56
+			default: () => true
57
+		},
58
+		readonly: {
59
+			type: Boolean,
60
+			default: () => false
61
+		},
62
+		isFile: {
63
+			type: Boolean,
64
+			default: () => false
65
+		}
66
+	})
67
+
68
+	onMounted(() => {
69
+		getTableData()
70
+	})
71
+
72
+	const tableData = ref([])
73
+	const getTableData = () => {
74
+		//携带自定义参数
75
+		var url = 'framework/Common/queryFileWithValues'
76
+		var param = {
77
+			fId: props.fId, //必填
78
+			value1: props.value1, //非必填
79
+			value2: props.value2, //非必填
80
+			value3: props.value3, //非必填
81
+			value4: props.value4, //非必填
82
+			value5: props.value5, //非必填
83
+		}
84
+		proxy.$axios.get(url, param).then(response => {
85
+			if (response.data.code === 0) {
86
+				tableData.value = response.data.data
87
+        fileListTemp.value = []
88
+        for (let item of tableData.value) {
89
+          fileListTemp.value.push({
90
+            id: item.id,
91
+            url: import.meta.env.VITE_BASE_API + 'framework/Common/downloadFileS3?bucket=' + bucket.value + '&id=' + item.id + '&fullfilename=' + Date.now() + item.fileName
92
+          })
93
+        }
94
+        if (fileListTemp.value.length > 0) {
95
+          emit('update:firstFileUrl', fileListTemp.value[0].url)
96
+        } else {
97
+          emit('update:firstFileUrl', null) // 或 ''
98
+        }
99
+
100
+			} else {
101
+				showFailToast('失败!' + response.data.msg)
102
+			}
103
+		})
104
+	}
105
+	const headers = ref({
106
+		token: localStorage.getItem('token'),
107
+		userId: localStorage.getItem('userId')
108
+	})
109
+	const fileListTemp = ref([])
110
+	const bucket = ref(import.meta.env.VITE_BUCKET)
111
+
112
+	/* 转成blob */
113
+	import {
114
+		atob
115
+	} from 'js-base64';
116
+
117
+	watch(props, (newVal, oldVal) => {
118
+		getTableData()
119
+	})
120
+
121
+	const uploadFile = (file) => {
122
+		const formData = new FormData()
123
+		formData.append('fId', props.fId);
124
+		formData.append('bucket', bucket.value);
125
+		formData.append('value1', props.value1);
126
+		formData.append('value2', props.value2);
127
+		formData.append('value3', props.value3);
128
+		formData.append('value4', props.value4);
129
+		formData.append('value5', props.value5);
130
+		formData.append('file', file.file);
131
+		formData.append('fileName', file.file.name);
132
+		var url = 'framework/Common/uploadFileS3'
133
+		proxy.$axios.post(url, formData, 'multipart/form-data').then(response => {
134
+			showSuccessToast('上传成功')
135
+			getTableData()
136
+		}).catch(error => {
137
+			showFailToast('上传失败' + res.data.msg)
138
+		});
139
+	}
140
+
141
+	/* 在线删除 */
142
+	const showDialogVisible = ref(false)
143
+	const deleteInfo = ref()
144
+	const handleDelete = (row) => {
145
+		showDialogVisible.value = true
146
+		deleteInfo.value = row
147
+	}
148
+
149
+	const onDelete = (file) => {
150
+    console.log(file);
151
+    showConfirmDialog({
152
+      title: '删除照片',
153
+      message:
154
+        '确定删除该照片吗?',
155
+    }).then(() => {
156
+        let url = 'framework/Common/removeFile'
157
+        let param = {
158
+          id: file.id
159
+        }
160
+        proxy.$axios.post(url, param).then(response => {
161
+          if (response.data.code === 0) {
162
+            showSuccessToast('删除成功!')
163
+            getTableData()
164
+          } else {
165
+            showFailToast('删除失败;' + response.data.msg)
166
+          }
167
+        });
168
+        return true
169
+      }).catch(() => {
170
+        return false
171
+      });
172
+	}
173
+
174
+	// 获取文件图标类名
175
+	const getFileIconClass = (fileType) => {
176
+		if (fileType === 'pdf') return 'pdf-icon';
177
+		if (fileType === 'image' || fileType === 'jpg' || fileType === 'png' || fileType === 'gif')
178
+			return 'image-icon';
179
+		if (fileType === 'doc' || fileType === 'docx') return 'doc-icon';
180
+		if (fileType === 'xls' || fileType === 'xlsx') return 'excel-icon';
181
+		if (fileType === 'txt') return 'text-icon';
182
+		return 'other-icon';
183
+	}
184
+
185
+	// 获取文件图标
186
+	const getFileIcon = (fileType) => {
187
+		if (fileType === 'pdf') return 'description';
188
+		if (fileType === 'image' || fileType === 'jpg' || fileType === 'png' || fileType === 'gif') return 'photo-o';
189
+		if (fileType === 'doc' || fileType === 'docx') return 'notes-o';
190
+		if (fileType === 'xls' || fileType === 'xlsx') return 'chart-trending-o';
191
+		if (fileType === 'txt') return 'document';
192
+		return 'description';
193
+	}
194
+
195
+	const convertBytesToSize = (bytes) => {
196
+		const kb = 1024;
197
+		const mb = kb * 1024;
198
+
199
+		if (bytes < kb) return bytes + ' B';
200
+		else if (bytes < mb) return (bytes / kb).toFixed(2) + ' KB';
201
+		else return (bytes / mb).toFixed(2) + ' MB';
202
+	}
203
+</script>
204
+
205
+<style scoped>
206
+	* {
207
+		box-sizing: border-box;
208
+		margin: 0;
209
+		padding: 0;
210
+	}
211
+
212
+	body {
213
+		font-family: 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
214
+		background: linear-gradient(135deg, #f5f7fa 0%, #e4edf5 100%);
215
+		color: #333;
216
+		line-height: 1.6;
217
+		min-height: 100vh;
218
+	}
219
+
220
+	.header h1 {
221
+		font-size: 2.5rem;
222
+		color: #1989fa;
223
+		margin-bottom: 10px;
224
+		text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);
225
+	}
226
+
227
+	.header p {
228
+		font-size: 1.1rem;
229
+		color: #666;
230
+		max-width: 600px;
231
+		margin: 0 auto;
232
+	}
233
+
234
+	.section-title i {
235
+		margin-right: 10px;
236
+		font-size: 1.6rem;
237
+	}
238
+
239
+	.table-row {
240
+		background-color: white;
241
+		border-radius: 8px;
242
+		margin-bottom: 8px;
243
+		box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
244
+		transition: transform 0.2s ease, box-shadow 0.2s ease;
245
+		align-items: center;
246
+	}
247
+
248
+	.table-row:hover {
249
+		transform: translateX(5px);
250
+		box-shadow: 0 5px 15px rgba(25, 137, 250, 0.15);
251
+	}
252
+
253
+	.file-name {
254
+		font-weight: 500;
255
+		white-space: nowrap;
256
+		overflow: hidden;
257
+		text-overflow: ellipsis;
258
+	}
259
+
260
+	.action-buttons {
261
+		display: flex;
262
+		gap: 10px;
263
+		justify-content: flex-start;
264
+	}
265
+</style>

+ 10
- 0
src/router/index.ts Целия файл

@@ -614,6 +614,16 @@ const router = createRouter({
614 614
 			name: '管理案例编辑',
615 615
 			component: () => import('@/view/knowledge/managerList.vue')
616 616
 		},
617
+		{
618
+			path: '/knowledge/Culture',
619
+			name: '安全文化',
620
+			component: () => import('@/view/knowledge/Culture.vue')
621
+		},
622
+		{
623
+			path: '/CultureList',
624
+			name: '安全文化编辑',
625
+			component: () => import('@/view/knowledge/CultureList.vue')
626
+		},
617 627
 		{
618 628
 			path: '/knowledge/project',
619 629
 			name: '项目案例库',

+ 4
- 0
src/view/Home2.vue Целия файл

@@ -244,6 +244,10 @@
244 244
           <img src="../../public/images/zd.png" width="45rpx" />
245 245
           <span class="vanicon_text">管理案例</span>
246 246
         </van-grid-item>
247
+        <van-grid-item to="/knowledge/Culture">
248
+          <img src="../../public/images/zd.png" width="45rpx" />
249
+          <span class="vanicon_text">安全环保文化</span>
250
+        </van-grid-item>
247 251
         <van-grid-item to="/knowledge/project">
248 252
           <img src="../../public/images/zd.png" width="45rpx" />
249 253
           <span class="vanicon_text">项目案例库</span>

+ 617
- 0
src/view/knowledge/Culture.vue Целия файл

@@ -0,0 +1,617 @@
1
+<template>
2
+  <div class="h5-container">
3
+    <van-nav-bar title="安全环保文化" @click-left="onClickLeft" @click-right="handAdd">
4
+      <template #right>
5
+        <van-icon name="add" size="25" color="#000" />
6
+      </template>
7
+    </van-nav-bar>
8
+    <van-search v-model="query.caseTitle" show-action placeholder="请输入案例标题" @search="onRefresh"
9
+                @cancel="handdelectTitle" />
10
+
11
+    <!-- 项目列表 -->
12
+    <van-pull-refresh v-model="isRefreshing" success-text="刷新成功" @refresh="onRefresh">
13
+      <van-list v-model:loading="isLoading" :finished="isFinished" finished-text="没有更多了" offset="200" @load="onLoad">
14
+        <div v-for="(item, idx) in resultData" :key="item.id">
15
+          <van-swipe-cell title-style="color: #007aff" style="height: 80px;" :ref="el => getSwipeCellRef(el, idx)">
16
+            <template #default>
17
+              <div class="swipe-cell-default">
18
+                <van-cell style="min-height: 100px; padding: 0 0 0 0; display: flex; align-items: flex-start;" @click="edits(item)">
19
+                  <template #title>
20
+                    <div class="cell-title">
21
+                      {{ item.activityTitle }}
22
+                    </div>
23
+                  </template>
24
+                  <template #label>
25
+                      <div>案例编号:{{ item.caseNumber }} </div>
26
+                      <div>案例类型:{{ item.caseType }}</div>
27
+                      <div> 浏览量:{{item.viewCount}}</div>
28
+
29
+<!--                    <div style="width: 112px" :class="getStatusClass(item.isFinish)">
30
+                      类型:
31
+                      <span v-if="item.isFinish === '待学习'" style="width: 200px">待学习</span>
32
+                      <span v-else-if="item.isFinish === '已学习'" style="width: 200px">已学习</span>
33
+                      <span v-else-if="item.isFinish === '已扣除'" style="width: 200px">已扣除</span>
34
+                    </div>-->
35
+                  </template>
36
+                </van-cell>
37
+                <div class="swipe-cell-default-icon">
38
+                  <van-icon v-if="openStatus[idx]" name="arrow-double-left" @click.stop="openSwipe(idx)" />
39
+                  <van-icon v-else name="arrow-double-right" @click.stop="closeSwipe(idx)" />
40
+                </div>
41
+              </div>
42
+            </template>
43
+
44
+            <template #right>
45
+              <van-button  square class="delete-button" text="删除" v-show="item.canDelete"  @click="handleDelete(item)" />
46
+            </template>
47
+          </van-swipe-cell>
48
+        </div>
49
+
50
+      </van-list>
51
+    </van-pull-refresh>
52
+
53
+    <!-- 删除确认弹窗 -->
54
+    <van-dialog v-model:show="deleteDialogVisible" show-cancel-button @confirm="confirmDelete">
55
+      <template #title>
56
+        <div>删除确认</div>
57
+      </template>
58
+      <div style="padding: 30px;">确定要删除该项目吗?</div>
59
+    </van-dialog>
60
+
61
+  </div>
62
+</template>
63
+
64
+<script setup>
65
+import { ref, reactive, onMounted, getCurrentInstance, nextTick, toRaw } from 'vue';
66
+import { Dialog, showDialog, showSuccessToast, showToast, Toast } from 'vant';
67
+
68
+import tools from '@/tools'
69
+
70
+const { proxy } = getCurrentInstance();
71
+
72
+const onClickLeft = () => {
73
+  history.back();
74
+};
75
+const headers = ref({
76
+  token: localStorage.getItem('token'),
77
+  userId: localStorage.getItem('userId'),
78
+  dept: JSON.parse(localStorage.getItem('dept'))[0].deptCode
79
+});
80
+const switchIconState = (idx) => {
81
+  openStatus.value[idx] = !openStatus.value[idx]
82
+  openStatus.value = new Array(resultData.value.length).fill(true);
83
+}
84
+
85
+// const onClickRight = () =>{
86
+//   searchShow.value = !searchShow.value;
87
+// }
88
+
89
+const searchShow = ref(false);
90
+const query = ref({
91
+  caseNumber:'',
92
+  caseTitle:'',
93
+})
94
+
95
+
96
+
97
+const tableData = ref([]);
98
+const selectedRows = ref([]);
99
+const dialogVisibleLook = ref(false);
100
+const deleteDialogVisible = ref(false);
101
+const currentDeleteItem = ref([]);
102
+const dialogVisible = ref(false);
103
+const dialogVisibleFile = ref(false);
104
+const date = ref(null);
105
+
106
+const kz = ref(true);
107
+import { useRouter } from 'vue-router';
108
+const router = useRouter();
109
+const handAdd =  () => {
110
+
111
+  router.push({ path: "/CultureList",
112
+    query: {
113
+      mark:-1
114
+    } });
115
+
116
+};
117
+const goaddPeo = (item) => {
118
+  router.push({
119
+    path: '/addPeo',
120
+    query: {
121
+      data: JSON.stringify(item)
122
+    }
123
+  })
124
+}
125
+
126
+const edits = (row) => {
127
+  const isOwner = String(row.addId) === currentUserId;
128
+  kz.value = true;
129
+  form.value = { ...row };
130
+  router.push({ path: "/CultureList",
131
+    query: {
132
+      mark:1,
133
+      data:JSON.stringify(form.value),
134
+      readOnly: !isOwner ? 'true' : undefined
135
+    } });
136
+  //浏览量
137
+  saveManagerRecord(form.value)
138
+};
139
+
140
+const saveManagerRecord = async (formValue) => {
141
+  const payload = formValue;
142
+  payload.viewCount = String((Number(payload.viewCount) || 0) + 1);
143
+
144
+  var url = '/sgsafe/Manager/saveCulture';
145
+  var param = {
146
+    json: JSON.stringify(payload)
147
+  };
148
+  proxy.$axios.post(url, param).then(response => {
149
+    if (response.data.code == '0') {
150
+      getTableData();
151
+    }
152
+  });
153
+};
154
+const form = ref({
155
+  caseNumber:'',
156
+  caseTitle:'',
157
+  caseSource:'',
158
+  accidentLevel:'',
159
+  accidentDept:'',
160
+  accidentLocation:'',
161
+  accidentTime:'',
162
+  accidentType:'',
163
+  accidentTags:'',
164
+  casualtyCount:'',
165
+  accidentSummary:'',
166
+  preventiveMeasures:'',
167
+  fileId:'',
168
+  viewCount:'',
169
+  downloadCount:''
170
+});
171
+
172
+
173
+const isRefreshing = ref(false);
174
+const isLoading = ref(false);
175
+const isFinished = ref(false);
176
+const currentPage = ref(1);
177
+const pageSize = ref(10);
178
+const totalRows = ref(0);
179
+const resultData = ref([]);
180
+
181
+const dept=localStorage.getItem("dept")[0].deptCode;
182
+const currentUserId = String(localStorage.getItem('userId'));
183
+const getTableData = async () => {
184
+  var url = '/sgsafe/Manager/queryCulture'
185
+  var param = {
186
+    page: currentPage.value,
187
+    rows: pageSize.value,
188
+    params: JSON.stringify(query.value)
189
+  }
190
+  const response = await proxy.$axios.get(url, param);
191
+  if (response.data.code == 0) {
192
+    tableData.value = response.data.data.records.map(item => ({
193
+      ...item,
194
+      canDelete: String(item.addId) === currentUserId
195
+    }));
196
+    console.log('列表数据',tableData.value)
197
+    totalRows.value = response.data.data.total;
198
+  } else {
199
+    showToast({
200
+      type: 'error',
201
+      message: '操作失败!' + response.data.msg
202
+    });
203
+  }
204
+};
205
+const ruleIds = ref([]);
206
+
207
+const onRefresh = () => {
208
+  basicReset();
209
+  onLoad();
210
+};
211
+
212
+//*************************************
213
+
214
+
215
+
216
+//定义字典集合
217
+const dicList = ref([])
218
+
219
+const getDicList = () => {
220
+  tools.dic.getDicList([ 'case_type','SEX', 'case_source','accident_level','accident_type','sgsafe_taccidentTags']).then((response => {
221
+    console.log(JSON.stringify(response.data.data))
222
+    dicList.value = response.data.data
223
+
224
+  }))
225
+}
226
+
227
+
228
+const onLoad = async () => {
229
+  if (isRefreshing.value) {
230
+    resultData.value = [];
231
+    currentPage.value = 1;
232
+    isRefreshing.value = false;
233
+  }
234
+
235
+  getDicList()
236
+
237
+
238
+
239
+
240
+
241
+  try {
242
+    await getTableData();
243
+
244
+    if (pageSize.value * currentPage.value < totalRows.value) {
245
+      resultData.value = [...resultData.value, ...tableData.value];
246
+      openStatus.value = new Array(resultData.value.length).fill(true);
247
+      currentPage.value++;
248
+
249
+    } else {
250
+      resultData.value = [...resultData.value, ...tableData.value];
251
+      openStatus.value = new Array(resultData.value.length).fill(true);
252
+      isFinished.value = true;
253
+    }
254
+
255
+    console.log('resultData',resultData.value)
256
+  } catch (error) {
257
+    console.log(error);
258
+    isFinished.value = true;
259
+  } finally {
260
+    isLoading.value = false;
261
+  }
262
+};
263
+/* 通用方法: 重置list数据 */
264
+const basicReset = () => {
265
+  isFinished.value = false;
266
+  isLoading.value = true;
267
+  currentPage.value = 1;
268
+  resultData.value = [];
269
+};
270
+
271
+/*onMounted(() => {
272
+  handleSearch();
273
+});
274
+
275
+const handleSearch = () => {
276
+/!*  currentPage.value = 1;
277
+  isFinished.value = false;
278
+  tableData.value = [];*!/
279
+  basicReset()
280
+  onLoad()
281
+};*/
282
+
283
+const handdelectNumber = () => {
284
+  query.value.caseNumber = '';
285
+  onRefresh()
286
+};
287
+
288
+const handdelectTitle = () => {
289
+  query.value.caseTitle = '';
290
+  onRefresh()
291
+};
292
+
293
+
294
+
295
+
296
+// 定义生成编号的函数
297
+const generateCode = () => {
298
+  // 获取当前日期并格式化为 YYYYMMDD
299
+  const now = new Date();
300
+  const year = now.getFullYear();
301
+  const month = String(now.getMonth() + 1).padStart(2, '0'); // 月份从0开始,需加1
302
+  const day = String(now.getDate()).padStart(2, '0');
303
+  const formattedDate = `${year}${month}${day}`;
304
+  // 时间部分:HHmmss
305
+  const hours = String(now.getHours()).padStart(2, '0');
306
+  const minutes = String(now.getMinutes()).padStart(2, '0');
307
+  const seconds = String(now.getSeconds()).padStart(2, '0');
308
+  const formattedTime = `${hours}${minutes}${seconds}`;
309
+
310
+  // 模拟生成三位流水号(可以根据需要替换为递增逻辑)
311
+  const sequenceNumber = Math.floor(Math.random() * 1000); // 随机生成 0-999
312
+  const paddedSequence = String(sequenceNumber).padStart(3, '0'); // 补零到三位
313
+
314
+  // 拼接编号
315
+  return `SGAL${formattedDate}${formattedTime}${paddedSequence}`;
316
+};
317
+
318
+// 使用 ref 存储生成的编号
319
+const generatedCode = ref(generateCode());
320
+
321
+// 定义重新生成编号的方法
322
+const regenerateCode = () => {
323
+  generatedCode.value = generateCode();
324
+};
325
+
326
+const handleDetailLook = (row) => {
327
+  form.value = { ...row };
328
+  proxy.$router.push({
329
+    name: 'taiZhang_detail',
330
+    query: {
331
+      form: form.value.id
332
+    }
333
+  });
334
+  // dialogVisibleLook.value = true;
335
+};
336
+const deleteData=ref({})
337
+
338
+const handleDelete = (item) => {
339
+
340
+  deleteData.value=item
341
+  const now = new Date();
342
+  const year = now.getFullYear();
343
+  const month = String(now.getMonth() + 1).padStart(2, '0'); // 月份从0开始
344
+  const day = String(now.getDate()).padStart(2, '0');
345
+  const hours = String(now.getHours()).padStart(2, '0');
346
+  const minutes = String(now.getMinutes()).padStart(2, '0');
347
+  const seconds = String(now.getSeconds()).padStart(2, '0');
348
+  deleteData.value.cancelTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
349
+
350
+    deleteData.value.cancelFlag='1'
351
+  var url = '/sgsafe/Manager/saveCulture';
352
+  var param = {
353
+    json: JSON.stringify(deleteData.value)
354
+  };
355
+  proxy.$axios.post(url, param).then(response => {
356
+    if (response.data.code == '0') {
357
+      showSuccessToast("删除成功")
358
+      onRefresh();
359
+
360
+    } else {
361
+    }
362
+
363
+  })
364
+};
365
+
366
+
367
+const confirmDelete = () => {
368
+  for (let item of currentDeleteItem.value) {
369
+    if (item.addId !== headers.value.userId) {
370
+      showToast({
371
+        type: 'warning',
372
+        message: '只能删除自己添加的数据!'
373
+      });
374
+      return;
375
+    }
376
+  }
377
+
378
+  if (currentDeleteItem.value[0].status !== '0' && currentDeleteItem.value[0].hdSelect !== '下发隐患'
379
+    && currentDeleteItem.value[0].hdSelect !== '即查即改') {
380
+    showToast({
381
+      type: 'fail',
382
+      message: '只有尚未提交流程的记录或回到起点的流程经过作废后才可以删除!'
383
+    });
384
+    return;
385
+  }
386
+  if (currentDeleteItem.value[0].status !== '2' && currentDeleteItem.value[0].hdSelect === '下发隐患'
387
+    && currentDeleteItem.value[0].hdSelect !== '即查即改') {
388
+    showToast({
389
+      type: 'fail',
390
+      message: '只有尚未提交流程的记录或回到起点的流程经过作废后才可以删除!'
391
+    });
392
+    return;
393
+  }
394
+
395
+  var url = 'sgsafe/Hiddendanger/remove';
396
+  var param = {
397
+    params: JSON.stringify({ ...currentDeleteItem.value.map(x => x.id) })
398
+  };
399
+  proxy.$axios.get(url, param).then(response => {
400
+    if (response.data.code == 0) {
401
+      showToast({
402
+        type: 'success',
403
+        message: '删除成功'
404
+      });
405
+      onRefresh();
406
+    } else {
407
+      showToast({
408
+        type: 'fail',
409
+        message: '操作失败!' + response.data.msg
410
+      });
411
+    }
412
+  });
413
+};
414
+
415
+
416
+
417
+
418
+const resetForm = () => {
419
+  form.value = {
420
+    projectName: '',
421
+    projectLeader: '',
422
+    phone: '',
423
+    dept: ''
424
+  };
425
+};
426
+
427
+
428
+//处理人员code
429
+const repairLL = ref('');
430
+const repairOO = ref('');
431
+const acceptLL = ref('');
432
+
433
+const jsons = ref({});
434
+
435
+const reback = () => {
436
+  // 返回逻辑
437
+};
438
+
439
+const deleteRow = (row) => {
440
+  selectedRows.value = [row];
441
+  handleDelete(row);
442
+};
443
+
444
+const deleteRowa = (row) => {
445
+  deleteRow(row);
446
+};
447
+
448
+/**
449
+ * 按钮实现swipe-cell滑动
450
+ */
451
+const openStatus = ref([])
452
+const swipeCellRefs = ref([])
453
+const getSwipeCellRef = (el, index) => {
454
+  if (el) {
455
+    swipeCellRefs.value[index] = el;
456
+  }
457
+}
458
+const openSwipe = (idx) => {
459
+  openStatus.value = new Array(resultData.value.length).fill(true);
460
+  if (idx >= 0 && idx < swipeCellRefs.value.length) {
461
+    openStatus.value[idx] = false
462
+    swipeCellRefs.value[idx].open('right')
463
+  }
464
+  document.addEventListener('click', handleDocumentClick)
465
+}
466
+/**
467
+ * 当点击滑动单元格时,开始监听点击事件
468
+ */
469
+const handleDocumentClick = (event) => {
470
+  openStatus.value = new Array(resultData.value.length).fill(true);
471
+}
472
+
473
+const closeSwipe = (idx) => {
474
+  if (idx >= 0 && idx < swipeCellRefs.value.length) {
475
+    openStatus.value[idx] = true
476
+    swipeCellRefs.value[idx].close()
477
+  }
478
+}
479
+// *********************************** 事故案例 ************************************************
480
+
481
+
482
+
483
+
484
+
485
+</script>
486
+
487
+<style scoped>
488
+.h5-container {
489
+  width: 100%;
490
+  padding: 5px;
491
+  box-sizing: border-box;
492
+}
493
+
494
+.status-pending {
495
+  background-color: #fff3cd;
496
+  color: #856404;
497
+  padding: 2px 4px;
498
+  border-radius: 4px;
499
+}
500
+
501
+.status-registered {
502
+  background-color: #d1ecf1;
503
+  color: #0c5460;
504
+  padding: 2px 4px;
505
+  border-radius: 4px;
506
+}
507
+
508
+.status-analyzing {
509
+  background-color: #fff8e1;
510
+  color: #ff8f00;
511
+  padding: 2px 4px;
512
+  border-radius: 4px;
513
+}
514
+
515
+.status-rectifying {
516
+  background-color: #e8f5e9;
517
+  color: #2e7d32;
518
+  padding: 2px 4px;
519
+  border-radius: 4px;
520
+}
521
+
522
+.status-accepting {
523
+  background-color: #e3f2fd;
524
+  color: #1565c0;
525
+  padding: 2px 2px;
526
+  border-radius: 2px;
527
+}
528
+
529
+.status-closed {
530
+  background-color: #f8bbd0;
531
+  color: #b71c1c;
532
+  padding: 2px 2px;
533
+  border-radius: 2px;
534
+}
535
+
536
+.status-finished {
537
+  background-color: #e8eaf6;
538
+  color: #311b92;
539
+  padding: 2px 2px;
540
+  border-radius: 2px;
541
+}
542
+
543
+.status-unknown {
544
+  background-color: #efebe9;
545
+  color: #424242;
546
+  padding: 2px 2px;
547
+  border-radius: 2px;
548
+}
549
+
550
+.cell-title {
551
+  display: -webkit-box;
552
+  /* 旧版弹性盒子模型 */
553
+  -webkit-box-orient: vertical;
554
+  /* 内容垂直排列 */
555
+  -webkit-line-clamp: 2;
556
+  /* 限制显示行数 */
557
+  overflow: hidden;
558
+  /* 超出隐藏 */
559
+  text-overflow: ellipsis;
560
+  /* 省略号 */
561
+  line-height: 1.5;
562
+  /* 可选:设置行高 */
563
+  max-height: calc(1.5em * 2);
564
+  /* 可选:根据行高限制最大高度 */
565
+  font-size: 16px;
566
+  font-weight: bold;
567
+  color: #333;
568
+  /* 字号 */
569
+}
570
+
571
+.swipe-cell-default {
572
+  display: flex;
573
+  background-color: #ffffff;
574
+  justify-content: center;
575
+  align-items: center;
576
+}
577
+
578
+.swipe-cell-default-icon {
579
+  width: 60px;
580
+  display: flex;
581
+  justify-content: center;
582
+}
583
+
584
+.delete-button {
585
+  height: 100%;
586
+  border: none;
587
+  color: #ff0000;
588
+  background-image: url('@/assets/img/del.png');
589
+  background-size: auto 100%;
590
+  background-repeat: no-repeat;
591
+}
592
+
593
+.submit-button {
594
+  height: 100%;
595
+  border: none;
596
+  color: #07c160;
597
+  background-image: url('@/assets/img/sub.png');
598
+  background-size: auto 100%;
599
+  background-repeat: no-repeat;
600
+}
601
+
602
+.subsuccess {
603
+  height: 100%;
604
+  border: none;
605
+  color: #07c160;
606
+  background-image: url('@/assets/img/sub1.png');
607
+  background-size: auto 100%;
608
+  background-repeat: no-repeat;
609
+}
610
+.single-line-text {
611
+  white-space: nowrap;        /* 强制不换行 */
612
+  overflow: hidden;           /* 超出部分隐藏 */
613
+  text-overflow: ellipsis;    /* 超出显示省略号 ... */
614
+  width: 100%;                /* 或指定宽度 */
615
+  box-sizing: border-box;
616
+}
617
+</style>

+ 710
- 0
src/view/knowledge/CultureList.vue Целия файл

@@ -0,0 +1,710 @@
1
+<script setup>
2
+import { getCurrentInstance, onMounted, ref , computed } from 'vue';
3
+import { useRoute, useRouter } from 'vue-router';
4
+import tools from '@/tools'
5
+
6
+const {
7
+  proxy
8
+} = getCurrentInstance()
9
+const accidentDictList = ref([])
10
+const columns =  ref([])
11
+const columnsLevel =  ref([])
12
+const columnsprimary=ref([])
13
+
14
+//     [
15
+//   { text: '杭州', value: 'Hangzhou' },
16
+//   { text: '宁波', value: 'Ningbo' },
17
+//   { text: '温州', value: 'Wenzhou' },
18
+//   { text: '绍兴', value: 'Shaoxing' },
19
+//   { text: '湖州', value: 'Huzhou' },
20
+// ];
21
+
22
+// 定义生成编号的函数(你已写好的逻辑)
23
+
24
+const generateCode = () => {
25
+  const now = new Date();
26
+  const year = now.getFullYear();
27
+  const month = String(now.getMonth() + 1).padStart(2, '0');
28
+  const day = String(now.getDate()).padStart(2, '0');
29
+  const formattedDate = `${year}${month}${day}`;
30
+  const hours = String(now.getHours()).padStart(2, '0');
31
+  const minutes = String(now.getMinutes()).padStart(2, '0');
32
+  const seconds = String(now.getSeconds()).padStart(2, '0');
33
+  const formattedTime = `${hours}${minutes}${seconds}`;
34
+  const sequenceNumber = Math.floor(Math.random() * 1000);
35
+  const paddedSequence = String(sequenceNumber).padStart(3, '0');
36
+  return `SGAL${formattedDate}${formattedTime}${paddedSequence}`;
37
+};
38
+
39
+// 存储生成的编号(响应式变量)
40
+const generatedCode = ref('');
41
+
42
+// 重新生成编号的方法
43
+const regenerateCode = () => {
44
+  generatedCode.value = generateCode();
45
+};
46
+
47
+
48
+
49
+const getAccidentDicList = () => {
50
+  tools.dic.getDicList([ 'case_type','sgsafe_culture_case_type', 'case_source','primary_domain','primary_domain_two','accident_level','accident_type','sgsafe_taccidentTags','sgsafe_culture_activity_type']).then((response => {
51
+    console.log(JSON.stringify(response.data.data))
52
+    accidentDictList.value = response.data.data
53
+    console.log('case_source',accidentDictList.value.case_source)
54
+    columns.value = accidentDictList.value.sgsafe_culture_case_type.map(item => ({
55
+      text: item.dicName,
56
+      value: item.dicCode
57
+    }));
58
+    columnsLevel.value = accidentDictList.value.sgsafe_culture_activity_type.map(item => ({
59
+      text: item.dicName,
60
+      value: item.dicCode
61
+    }));
62
+    columnsprimary.value = accidentDictList.value.primary_domain.map(item => ({
63
+      text: item.dicName,
64
+      value: item.dicCode
65
+    }));
66
+
67
+
68
+    console.log('accident_level',accidentDictList.value.accident_level)
69
+
70
+  }))
71
+}
72
+
73
+
74
+const caseSourceFlag = ref(false)
75
+const accidentLevelFlag = ref(false)
76
+const primaryDomainFlag = ref(false)
77
+const primaryDomainTwoFlag = ref(false)
78
+let title = '新增事故案例'
79
+
80
+/* 返回上一级页面 */
81
+const router = useRouter()
82
+const onClickLeft = () => {
83
+  router.go(-1)
84
+}
85
+
86
+const currentYear = ref()
87
+currentYear.value = new Date().getFullYear()
88
+
89
+/* 获取用户部门信息 */
90
+const jsonArray = localStorage.getItem('dept')
91
+const deptInformation = ref([])
92
+try {
93
+  deptInformation.value = jsonArray ? JSON.parse(jsonArray) : [];
94
+} catch (error) {
95
+  deptInformation.value = [];
96
+}
97
+const deptName = deptInformation.value[0].deptName
98
+const deptCode = deptInformation.value[0].deptCode
99
+
100
+const guid = () =>  {
101
+  function S4() {
102
+    return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
103
+  }
104
+  return (S4()+S4()+S4()+S4()+S4()+S4()+S4()+S4())
105
+}
106
+const formJieguo = ref({
107
+  resultWhether:'',
108
+  resultDetail:'',
109
+  resultWhy:'',
110
+  resultFile:'',
111
+  itemsId:'',
112
+  resultFileId:'',
113
+  resType:''
114
+})
115
+const route = useRoute()
116
+let planInfo = {}
117
+const  userName1=localStorage.getItem('userName');
118
+const isEdit = ref(route.query.mark === '1');
119
+
120
+const result1=ref('')
121
+const result2=ref('')
122
+const result3=ref('')
123
+const result4=ref('')
124
+const result5=ref('')
125
+const fromVue=ref({})
126
+if (route.query.mark) {
127
+  planInfo = JSON.parse(route.query.mark)
128
+}
129
+console.log(planInfo);
130
+if (planInfo==-1){
131
+  result1.value=guid()
132
+  result2.value=guid()
133
+  result3.value=guid()
134
+  result4.value=guid()
135
+  result5.value=guid()
136
+  generatedCode.value = generateCode();
137
+
138
+}
139
+
140
+const resDetail=ref('')
141
+const ruleIds = ref([]);
142
+/*const getRuleId = () => {
143
+  var url = '/sgsafe/ExamHead/getCheckRuleId'
144
+  var param = {}
145
+  proxy.$axios.get(url, param).then(response => {
146
+    if (response.data.code == '0') {
147
+      ruleIds.value = response.data.data
148
+    } else {
149
+      console.log("1111111");
150
+    }
151
+  })
152
+  console.log('ruleIds', ruleIds)
153
+}
154
+getRuleId()*/
155
+const showRule=ref(false);
156
+const showSmit=ref(true);
157
+const distestType=ref(false)
158
+if (planInfo==1) {
159
+  console.log(planInfo);
160
+  title = '修改管理档案'
161
+  fromVue.value= JSON.parse(route.query.data)
162
+  generatedCode.value = fromVue.value.caseNumber || '';
163
+  result1.value=fromVue.value.filePlan
164
+  result2.value=fromVue.value.filePic
165
+  result3.value=fromVue.value.fileEnd
166
+  result4.value=fromVue.value.fileOther
167
+  const userIds= localStorage.getItem('userId')
168
+  if (userIds != fromVue.value.addId) {
169
+    showSmit.value=false
170
+    title = '查看管理档案'
171
+  }
172
+
173
+}
174
+ const  whether=ref(false)
175
+
176
+const planLevelList1=ref([])
177
+
178
+
179
+/* 下拉框 */
180
+const showActionSheet = ref(false)
181
+const showActionSheet1 = ref(false)
182
+const planLevelList = [
183
+  { name: '转发', value: '转发' },
184
+  { name: '内部', value: '内部' },
185
+  { name: '文章', value: '文章' }
186
+];
187
+const isdisabled=ref(true)
188
+const isdisabled2=ref(true)
189
+const onSelect = (item) => {
190
+fromVue.value.fileContent = item.name
191
+
192
+  showActionSheet.value=false
193
+}
194
+
195
+const onSelect2 = (item) => {
196
+  fromVue.value.fileType=item.name
197
+  showActionSheet2.value=false
198
+  }
199
+
200
+const onCaseSourseSelect = (item) => {
201
+  fromVue.value.caseSource=item.dicCode
202
+  caseSourceFlag.value = false
203
+}
204
+
205
+const onAccidentLevelSelect = (item) => {
206
+  fromVue.value.accidentLevel = item.dicCode
207
+  accidentLevelFlag.value = false
208
+
209
+}
210
+
211
+const displayFileName = ref('')
212
+const onSelect1 = (item) => {
213
+  console.log(item);
214
+  formJieguo.value.resultFile = item.value
215
+  result.value=formJieguo.value.resultFile
216
+  displayFileName.value = item.name
217
+
218
+  showActionSheet1.value = false
219
+}
220
+const questionIds = ref([])
221
+const actions=ref([])
222
+/*const getQuestionId = () => {
223
+  var url = '/sgsafe/AssessmentRecord/queryRuleNoPage';
224
+  var param = {};
225
+  proxy.$axios.get(url, param).then(response => {
226
+    if (response.data.code == '0') {
227
+      questionIds.value = response.data.data; // 先赋值给 questionIds.value
228
+
229
+
230
+      // ✅ 关键:使用 questionIds.value.map
231
+      actions.value = questionIds.value.map(item => ({
232
+        name: item.ruleName,
233
+        value: item.id
234
+      }));
235
+      console.log('actions:', actions.value); // 看看有没有输出
236
+    } else {
237
+      ElMessage.error('操作失败!' + response.data.msg);
238
+    }
239
+  });
240
+};
241
+getQuestionId()*/
242
+
243
+const baocun3 = (ruleFormRef) => {
244
+  console.log(formJieguo.value)
245
+  ruleFormRef.validate((valid, fields) => {
246
+    if (valid) {
247
+
248
+      var url = '/sgsafe/Manager/save';
249
+      var param = {
250
+        json: JSON.stringify(formJieguo.value)
251
+      };
252
+      proxy.$axios.post(url, param).then(response => {
253
+        if (response.data.code == '0') {
254
+          getTableData1()
255
+          ElMessage({
256
+            message: '保存成功',
257
+            type: 'success',
258
+          })
259
+          if (ruleFormRef.value) {
260
+            ruleFormRef.value.resetFields();
261
+          }
262
+          dialogVisibletemplate.value=false
263
+        } else {
264
+          ElMessage.error('操作失败!' + response.data.msg)
265
+        }
266
+
267
+      })
268
+    }
269
+  })
270
+}
271
+
272
+/* 组织树选择 */
273
+const showBottom = ref(false)
274
+import OrganizationalWithLeaf from '@/components/OrganizationalWithLeaf.vue';
275
+import { showFailToast, showLoadingToast, showSuccessToast } from 'vant';
276
+const handleTableDataUserDeptUpdate = async (nodeData) => {
277
+  console.log(nodeData);
278
+  const [deptCode, deptName] = nodeData.split('-', 2); // 只按第一个 '-' 分割
279
+  fromVue.value.activityDept = deptCode.trim();
280
+  fromVue.value.activityName = deptName.trim();
281
+
282
+  showBottom.value = false
283
+}
284
+
285
+/* 组织树选择 */
286
+const showBottom1 = ref(false)
287
+
288
+const handleTableDataUserDeptUpdate1 = async (nodeData) => {
289
+  console.log('选中的部门字符串:', nodeData); // e.g. "D1101120701-型钢炼钢站"
290
+
291
+  // 确保 nodeData 是字符串
292
+  if (typeof nodeData !== 'string') {
293
+    console.warn('nodeData 不是字符串,跳过处理');
294
+    showBottom1.value = false; // 假设你有另一个 showBottom1 控制弹窗
295
+    return;
296
+  }
297
+
298
+  // 获取当前已选的 otherDept,转为数组(按逗号分割)
299
+  const currentList = fromVue.value.otherDept
300
+      ? fromVue.value.otherDept.split(',').filter(item => item.trim() !== '')
301
+      : [];
302
+
303
+  // 可选:防止重复添加
304
+  if (!currentList.includes(nodeData)) {
305
+    currentList.push(nodeData);
306
+  }
307
+
308
+  // 重新拼成逗号分隔的字符串
309
+  fromVue.value.otherDept = currentList.join(',');
310
+
311
+  showBottom1.value = false;
312
+}
313
+
314
+const addEmergencyDrillPlan = async () => {
315
+  const loadingToast = showLoadingToast({
316
+    duration: 0,
317
+    message: '加载中',
318
+    forbidClick: true
319
+  })
320
+  var url = '/sgsafe/Manager/save';
321
+  const params = {
322
+    json: JSON.stringify(fromVue.value)
323
+  }
324
+  proxy.$axios.post(url,params).then(res=>{
325
+    if (res.data.code === 0) {
326
+      loadingToast.close()
327
+      showSuccessToast('保存成功')
328
+      onClickLeft()
329
+
330
+    } else {
331
+      loadingToast.close()
332
+      showFailToast('操作失败!' + res.data.msg)
333
+    }
334
+  })
335
+}
336
+const showDatePicker = ref(false)
337
+const onDatePicker = (value) => {
338
+  const dateArr = value.selectedValues
339
+  fromVue.value.startTime = dateArr[0] + '-' + dateArr[1] + '-' + dateArr[2]
340
+  showDatePicker.value = false
341
+}
342
+const currentDate = ref([2025, 7, 25])
343
+//定义字典集合
344
+const dicList = ref([])
345
+//获取字典集合
346
+// import tools from '@/tools'
347
+const getDicList = () => {
348
+  tools.dic.getDicList(['systemTypes']).then((response => {
349
+
350
+   const rawData = response.data.data
351
+    dicList.value = rawData.systemTypes.map(item => ({
352
+      name: item.dicName,      // 必须有 name 字段!
353
+      code: item.dicCode       // 可选,保留原始 code 供后续使用
354
+    }));
355
+    console.log(JSON.stringify(dicList.value))
356
+  }))
357
+}
358
+onMounted(() => {
359
+  getAccidentDicList()
360
+  console.log('这是编辑页面')
361
+  const today = new Date()
362
+  const year = today.getFullYear()
363
+  const month = today.getMonth() + 1 // 月份从 0 开始
364
+  const day = today.getDate()
365
+  currentDate.value = [year, month, day]
366
+  currentDate1.value = [year, month, day]
367
+
368
+  //selectedDateText.value = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`
369
+  getDicList()
370
+})
371
+const showActionSheet2=ref(false)
372
+/* 文件上传 */
373
+import AttachmentS3 from '@/components/AttachmentS3.vue';
374
+import OrganizationalWithLeafUser from '@/components/OrganizationalWithLeafUser.vue';
375
+
376
+const onSubmit = (values) => {
377
+  fromVue.value.caseNumber = generatedCode.value;
378
+
379
+  fromVue.value.filePlan =result1.value
380
+  fromVue.value.filePic=result2.value
381
+  fromVue.value.fileEnd =result3.value
382
+  fromVue.value.fileOther=result4.value
383
+  fromVue.value.filePicBefore=fileUrl.value
384
+  addEmergencyDrillPlan()
385
+}
386
+const leaderKeyysr = guid();
387
+const PopupDepartmentLeaderNameRefysr = ref();
388
+const handleDepartmentLeaderNameysr = () => {
389
+  PopupDepartmentLeaderNameRefysr.value.open();
390
+};
391
+const getDepartmentLeaderNameysr = (item) => {
392
+  fromVue.value.punCode = item.user.userCode;
393
+  fromVue.value.punName = item.user.userDesc;
394
+  fromVue.value.punId = item.user.id
395
+};
396
+
397
+const onCaseSourceConfirm = ({ selectedOptions }) => {
398
+  caseSourceFlag.value = false;
399
+  fromVue.value.caseType = selectedOptions[0].text;
400
+};
401
+
402
+const onAccidentLevelConfirm = ({ selectedOptions }) => {
403
+  accidentLevelFlag.value = false;
404
+  fromVue.value.caseType = selectedOptions[0].text;
405
+};
406
+
407
+const onprimaryTwoConfirm = ({ selectedOptions }) => {
408
+  primaryDomainTwoFlag.value = false;
409
+  fromVue.value.primaryDomainTwo = selectedOptions[0].text;
410
+};
411
+const selectedPrimary = ref(null)
412
+const onprimaryConfirm = ({ selectedOptions }) => {
413
+  if (!selectedOptions?.length) {
414
+    selectedPrimary.value = null;
415
+    fromVue.value.primaryDomainTwo = '';
416
+    primaryDomainFlag.value = false;
417
+    return;
418
+  }
419
+
420
+  primaryDomainFlag.value = false;
421
+  fromVue.value.primaryDomain = selectedOptions[0].text;
422
+
423
+  const primaryList = accidentDictList.value?.primary_domain || [];
424
+  const selectedItem = primaryList.find(item => item.dicName === selectedOptions[0].text);
425
+
426
+  selectedPrimary.value = selectedItem || null;
427
+  fromVue.value.primaryDomainTwo = '';
428
+};
429
+
430
+const filteredSecondaryList = computed(() =>
431
+  selectedPrimary.value?.dicValue1
432
+    ? (accidentDictList.value?.primary_domain_two || [])
433
+      .filter(item => item.dicValue1 === selectedPrimary.value.dicValue1)
434
+      .map(({ dicName, dicCode }) => ({ text: dicName, value: dicCode }))
435
+    : []
436
+);
437
+const getDepartmentJoinPerson = (userArray) => {
438
+
439
+}
440
+const currentDate1 = ref([2025, 7, 25])
441
+const showDatePicker1 = ref(false)
442
+const onDatePicker1 = (value) => {
443
+  const dateArr = value.selectedValues
444
+  fromVue.value.endTime = dateArr[0] + '-' + dateArr[1] + '-' + dateArr[2]
445
+  showDatePicker1.value = false
446
+}
447
+const fileUrl=ref('')
448
+const handleFirstFileUrl = (url) => {
449
+  console.log('第一张文件URL:', url)
450
+  fileUrl.value=url
451
+}
452
+import AttachmentS3ImageReturnURL from '@/components/AttachmentS3ImageReturnURL.vue';
453
+</script>
454
+
455
+<template>
456
+
457
+  <div class="page-container">
458
+    <van-sticky class="header">
459
+      <van-nav-bar
460
+        :title="title"
461
+        left-text="返回"
462
+        left-arrow
463
+        @click-left="onClickLeft" >
464
+      </van-nav-bar>
465
+    </van-sticky>
466
+    <div class="scroll-container">
467
+      <van-form @submit="onSubmit">
468
+<!--        <van-field-->
469
+<!--          v-model="fromVue.caseNumber"-->
470
+<!--          label="案例编号"-->
471
+<!--          name="caseNumber"-->
472
+<!--          required-->
473
+<!--          placeholder="请输入案例编号"-->
474
+<!--          :rules="[{required: true, message: '请输入文件编号'}]"-->
475
+<!--        />-->
476
+        <van-field
477
+            v-model="generatedCode"
478
+        label="案例编号"
479
+        name="caseNumber"
480
+            :readonly="true"
481
+        :rules="[{required: true, message: '编号生成失败,请点击“重新生成”'}]"
482
+        />
483
+
484
+        <van-field
485
+          v-model="fromVue.activityTitle"
486
+          label="活动主题"
487
+          name="caseTitle"
488
+          required
489
+          placeholder="请输入活动主题"
490
+          :rules="[{required: true, message: '请输入活动主题'}]"
491
+        />
492
+
493
+        <van-field
494
+          v-model="fromVue.caseType"
495
+          readonly
496
+          label="案例类型"
497
+          name="caseType"
498
+          required
499
+          @click="caseSourceFlag = true"
500
+        />
501
+        <van-field
502
+          readonly
503
+          v-model="fromVue.activityType"
504
+          label="活动形式"
505
+          name="activityType"
506
+          @click="accidentLevelFlag = true"
507
+        />
508
+
509
+        <van-field
510
+            v-model="fromVue.startTime"
511
+            readonly
512
+            label="开始时间"
513
+            name="startTime"
514
+            required
515
+            placeholder="请选择开始时间"
516
+            :rules="[{required: true, message: '请输入开始时间'}]"
517
+            @click="showDatePicker = true"
518
+        />
519
+        <van-field
520
+            v-model="fromVue.endTime"
521
+            readonly
522
+            label="结束时间"
523
+            name="endTime"
524
+            required
525
+            placeholder="请选择结束时间"
526
+            :rules="[{required: true, message: '请输入结束时间'}]"
527
+            @click="showDatePicker1 = true"
528
+        />
529
+        <van-field
530
+            readonly
531
+            v-model="fromVue.activityName"
532
+            label="主办单位"
533
+            name="perName"
534
+            @click="showBottom=true"
535
+        />
536
+        <van-field
537
+            readonly
538
+            v-model="fromVue.otherDept"
539
+            label="协办/承办单位"
540
+            name="perName"
541
+            @click="showBottom1=true"
542
+        />
543
+
544
+        <van-field
545
+            v-model="fromVue.activitySummary"
546
+            label="活动简介"
547
+            name="activitySummary"
548
+            required
549
+            rows="3"
550
+            autosize
551
+            type="textarea"
552
+            placeholder="请输入活动简介"
553
+            :rules="[{required: true, message: '请输入活动简介'}]"
554
+        />
555
+
556
+        <van-field label="活动照片">
557
+          <template #input>
558
+            <AttachmentS3ImageReturnURL style="background-color: white;" :f-id="result2"  @update:firstFileUrl="handleFirstFileUrl" />
559
+          </template>
560
+        </van-field>
561
+
562
+        <van-field label="活动方案" >
563
+          <template #input>
564
+            <AttachmentS3 :f-id="result1" />
565
+          </template>
566
+        </van-field>
567
+        <van-field label="活动总结及效果评价" >
568
+          <template #input>
569
+            <AttachmentS3 :f-id="result3" />
570
+          </template>
571
+        </van-field>
572
+        <van-field label="签到表及其他材料" >
573
+          <template #input>
574
+            <AttachmentS3 :f-id="result4" />
575
+          </template>
576
+        </van-field>
577
+        <div style="margin: 16px;">
578
+          <van-button round block type="primary" v-show='showSmit' native-type="submit">
579
+            {{ isEdit ? '保存' : '提交' }}
580
+          </van-button>
581
+        </div>
582
+      </van-form>
583
+
584
+      <van-action-sheet
585
+        v-model:show="showActionSheet"
586
+        :actions="planLevelList"
587
+        @select="onSelect"
588
+      />
589
+      <van-action-sheet
590
+        v-model:show="showActionSheet2"
591
+        :actions="dicList"
592
+        @select="onSelect2"
593
+      />
594
+
595
+      <van-popup v-model:show="caseSourceFlag" round position="bottom">
596
+        <van-picker
597
+            :columns="columns"
598
+            @cancel="caseSourceFlag = false"
599
+            @confirm="onCaseSourceConfirm"
600
+        />
601
+      </van-popup>
602
+
603
+      <van-popup v-model:show="accidentLevelFlag" round position="bottom">
604
+        <van-picker
605
+            :columns="columnsLevel"
606
+            @cancel="accidentLevelFlag = false"
607
+            @confirm="onAccidentLevelConfirm"
608
+        />
609
+      </van-popup>
610
+      <van-popup v-model:show="primaryDomainFlag" round position="bottom">
611
+        <van-picker
612
+          :columns="columnsprimary"
613
+          @cancel="primaryDomainFlag = false"
614
+          @confirm="onprimaryConfirm"
615
+        />
616
+      </van-popup>
617
+      <van-popup v-model:show="primaryDomainTwoFlag" round position="bottom">
618
+        <van-picker
619
+          :columns="filteredSecondaryList"
620
+          @cancel="primaryDomainTwoFlag = false"
621
+          @confirm="onprimaryTwoConfirm"
622
+        />
623
+      </van-popup>
624
+
625
+<!--      <van-action-sheet-->
626
+<!--          v-model:show="accidentLevelFlag"-->
627
+<!--          :actions="accidentDictList.accident_level"-->
628
+<!--          @select="onAccidentLevelSelect"-->
629
+<!--      />-->
630
+
631
+<!--      <van-action-sheet-->
632
+<!--        v-model:show="showActionSheet1"-->
633
+<!--        :actions="planLevelList1"-->
634
+<!--        field-names="{ text: 'fileName', value: 'fileId' }"-->
635
+<!--        @select="onSelect1"-->
636
+<!--      />-->
637
+
638
+      <van-popup v-model:show="showBottom" position="bottom" :style="{ height: '30%' }">
639
+        <OrganizationalWithLeaf @update:selected-node="handleTableDataUserDeptUpdate" />
640
+      </van-popup>
641
+      <van-popup v-model:show="showBottom1" position="bottom" :style="{ height: '30%' }">
642
+        <OrganizationalWithLeaf @update:selected-node="handleTableDataUserDeptUpdate1" />
643
+      </van-popup>
644
+      <van-popup v-model:show="showDatePicker" position="bottom">
645
+        <van-date-picker
646
+          v-model="currentDate"
647
+          @confirm="onDatePicker"
648
+          @cancel="showDatePicker = false" />
649
+      </van-popup>
650
+      <van-popup v-model:show="showDatePicker1" position="bottom">
651
+        <van-date-picker
652
+            v-model="currentDate1"
653
+            @confirm="onDatePicker1"
654
+            @cancel="showDatePicker1 = false" />
655
+      </van-popup>
656
+
657
+    </div>
658
+  </div>
659
+</template>
660
+
661
+<style scoped>
662
+.page-container {
663
+  height: 100vh; /* 关键:外层容器高度设为视口高度 */
664
+  display: flex;
665
+  flex-direction: column;
666
+
667
+}
668
+/*  overflow-y: auto; !* 启用垂直滚动 *!*/
669
+
670
+
671
+.scroll-container {
672
+  flex: 1;
673
+  overflow: auto;
674
+  -webkit-overflow-scrolling: touch; /* iOS 平滑滚动 */
675
+}
676
+
677
+/* 可选:隐藏滚动条(视觉优化) */
678
+.scroll-container::-webkit-scrollbar {
679
+  display: none;
680
+}
681
+
682
+.header, .footer {
683
+  /* 固定高度区域 */
684
+  flex-shrink: 0; /* 防止被压缩 */
685
+  background: #f5f5f5;
686
+  padding: 12px;
687
+}
688
+.row-container {
689
+  display: flex;
690
+  justify-content: space-between; /* 关键:左右分布 */
691
+  align-items: center;             /* 垂直居中 */
692
+
693
+}
694
+
695
+.cell-period-text {
696
+  font-size: 14px;
697
+  color: #333;
698
+  white-space: nowrap;
699
+  overflow: hidden;
700
+  text-overflow: ellipsis;
701
+
702
+}
703
+
704
+.mini-btn {
705
+  height: 22px;
706
+  font-size: 12px;
707
+  padding: 0 8px;
708
+  min-width: 60px;                 /* 可选:保持按钮最小宽度一致 */
709
+}
710
+</style>

Loading…
Отказ
Запис