瀏覽代碼

feat(用户管理): 新增用户信息编辑页面功能

- 新增用户信息编辑页面,包含基本身份信息、状态管理、资质能力、工作履历、评价指标等模块
- 添加部门选择、岗位类型多选、资质等级联动等功能
- 实现团队配合人员选择、关键词评价等复杂表单组件
- 优化表单验证逻辑,根据用户角色动态调整必填项
- 修复用户信息保存时数组字段转换问题
- 调整页面样式,添加底部固定提交按钮

refactor(违禁品上报): 优化开箱检查岗位相关功能

- 新增开机指令选项和X光开机员选择功能
- 调整岗位切换逻辑,重置相关字段
- 优化表单验证规则和字段处理逻辑

fix(资质统计): 修正资质等级显示问题

- 将"LEVEL_ONE"改为"高级"显示
- 优化资质等级统计图表的数据处理逻辑
- 移除不必要的字典转换代码

style: 统一代码格式和缩进
huoyi 1 月之前
父節點
當前提交
93cb297f9f

+ 17 - 0
src/api/system/user.js

@@ -108,4 +108,21 @@ export function getAppList(params) {
108 108
     method: 'get',
109 109
     params: params
110 110
   })
111
+}
112
+
113
+// 修改用户
114
+export function updateUser(data) {
115
+  return request({
116
+    url: '/system/user',
117
+    method: 'put',
118
+    data: data
119
+  })
120
+}
121
+
122
+//查询所有岗位
123
+export function getPostAllList() {
124
+  return request({
125
+    url: '/system/post/listAllTree',
126
+    method: 'get',
127
+  })
111 128
 }

+ 1 - 1
src/pages/checklist/index.vue

@@ -675,7 +675,7 @@ export default {
675 675
                 checkTime: data.checkTime || formatTime(new Date(), 'YYYY-MM-DD hh:mm:ss'),
676 676
                 checkerName: this.currentUser.userInfo.nickName || this.currentUser.userInfo.userName || '',
677 677
                 checkerId: this.currentUser.userInfo.userId || '',
678
-                rectificationDeadline: fourDaysLater,
678
+                rectificationDeadline: data.rectificationDeadline || fourDaysLater,
679 679
                 baseAttachmentList: (data.baseAttachmentList && data.baseAttachmentList.map(item => ({
680 680
                     ...item,
681 681
                     url: item.attachmentUrl,

+ 20 - 12
src/pages/eikonStatistics/components/Qualification.vue

@@ -32,12 +32,13 @@
32 32
             <div class="item-value">{{ localSystemData.isPoliticalReviewPassed ? '是' : '否' }}</div>
33 33
           </div>
34 34
           <div class="content-item">
35
-            <div class="item-label">身体健康情况:</div>
35
+            <div class="item-label">健康异常情况:</div>
36 36
             <div class="item-value">{{ !localSystemData.isHealthy ? '健康' : localSystemData.isHealthy }}</div>
37 37
           </div>
38 38
           <div class="content-item">
39 39
             <div class="item-label">有无行政处罚:</div>
40
-            <div class="item-value">{{ !localSystemData.hasAdministrativePenalty ? '无' : localSystemData.hasAdministrativePenalty }}</div>
40
+            <div class="item-value">{{ !localSystemData.hasAdministrativePenalty ? '无' :
41
+              localSystemData.hasAdministrativePenalty }}</div>
41 42
           </div>
42 43
         </template>
43 44
         <template v-else>
@@ -124,7 +125,7 @@ export default {
124 125
         this.localSystemData = {};
125 126
         return;
126 127
       }
127
-      
128
+
128 129
       const res = { ...newVal };
129 130
       const { qualificationLevelStats, positionCompetencyStats, politicalStatusStats, educationStats, ageStats, politicalReviewStats, physicalHealthStats, administrativePenaltyStats } = newVal
130 131
 
@@ -133,18 +134,25 @@ export default {
133 134
         return;
134 135
       }
135 136
 
136
-      // 使用useDict获取资质等级字典
137
-      const dict = await this.useDict('sys_user_qualification_level')
138
-      const qualificationDict = dict['sys_user_qualification_level'] || []
137
+      // // 使用useDict获取资质等级字典
138
+      // const dict = await this.useDict('sys_user_qualification_level')
139
+      // const qualificationDict = dict['sys_user_qualification_level'] || []
140
+
141
+      // // 按照字典顺序遍历,确保从一级开始显示
142
+      // for (const dictItem of qualificationDict) {
143
+      //   const statItem = qualificationLevelStats.find(item => item.levelName === dictItem.value)
144
+      //   if (statItem) {
145
+      //     res.qualificationLevelSum = `${res.qualificationLevelSum ? res.qualificationLevelSum + '、' : ''}${dictItem.label} ${statItem.count}人`
146
+      //   }
147
+      // }
148
+     
139 149
 
140 150
       // 按照字典顺序遍历,确保从一级开始显示
141
-      for (const dictItem of qualificationDict) {
142
-        const statItem = qualificationLevelStats.find(item => item.levelName === dictItem.value)
143
-        if (statItem) {
144
-          res.qualificationLevelSum = `${res.qualificationLevelSum ? res.qualificationLevelSum + '、' : ''}${dictItem.label} ${statItem.count}人`
145
-        }
151
+      for (const dictItem of qualificationLevelStats) {
152
+        res.qualificationLevelSum = `${res.qualificationLevelSum ? res.qualificationLevelSum + '、' : ''}${dictItem.levelName} ${dictItem.count}人`
146 153
       }
147 154
 
155
+
148 156
       let availablePositionsSum = []
149 157
       for (const item of positionCompetencyStats) {
150 158
         availablePositionsSum.push(`${item.postName} ${item.competentCount}人`)
@@ -210,7 +218,7 @@ export default {
210 218
         this.localSystemData = {};
211 219
         return;
212 220
       }
213
-      
221
+
214 222
       // 创建新对象而不是直接修改传入的对象
215 223
       const res = { ...newVal };
216 224
       //资质等级

+ 2 - 2
src/pages/eikonStatistics/components/general-overview.vue

@@ -7,7 +7,7 @@
7 7
         <view class="stack-item item-1">
8 8
           <view class="item-content">
9 9
             <view class="item-label">资质能力</view>
10
-            <view class="item-number">{{ !isPersonal ? '级' : '' }}{{ localOverviewData.qualificationLevel }}{{
10
+            <view class="item-number">{{ !isPersonal ? '级' : '' }}{{ localOverviewData.qualificationLevel }}{{
11 11
               !isPersonal ?
12 12
                 '人' : '' }}</view>
13 13
             <view class="item-description">资质等级</view>
@@ -115,7 +115,7 @@ export default {
115 115
     async handleSystemData(newVal) {
116 116
       if (newVal) {
117 117
         const { qualificationLevelStats } = newVal;
118
-        let levelOne = qualificationLevelStats && qualificationLevelStats.find(item => item.levelName === 'LEVEL_ONE')?.count || 0;
118
+        let levelOne = qualificationLevelStats && qualificationLevelStats.find(item => item.levelName === '高级')?.count || 0;
119 119
         this.localOverviewData.qualificationLevel = levelOne;
120 120
         // this.localOverviewData.workYears = newVal.workYearsStats && newVal.workYearsStats.averageWorkYears;
121 121
       }

+ 671 - 96
src/pages/mine/info/edit.vue

@@ -1,127 +1,702 @@
1 1
 <template>
2 2
   <view class="container">
3 3
     <view class="example">
4
-      <uni-forms ref="form" :model="user" labelWidth="80px">
5
-        <uni-forms-item label="用户昵称" name="nickName">
6
-          <uni-easyinput v-model="user.nickName" placeholder="请输入昵称" />
7
-        </uni-forms-item>
8
-        <uni-forms-item label="手机号码" name="phonenumber">
9
-          <uni-easyinput v-model="user.phonenumber" placeholder="请输入手机号码" />
10
-        </uni-forms-item>
11
-        <uni-forms-item label="邮箱" name="email">
12
-          <uni-easyinput v-model="user.email" placeholder="请输入邮箱" />
13
-        </uni-forms-item>
14
-        <uni-forms-item label="性别" name="sex" required>
15
-          <uni-data-checkbox v-model="user.sex" :localdata="sexs" />
16
-        </uni-forms-item>
4
+      <uni-forms ref="form" :model="user" :labelWidth="'80px'" style="margin-bottom: 80px;">
5
+
6
+        <!-- 基本身份信息 -->
7
+        <uni-collapse class="collapse" :accordion="false" :value="['basicInfo']">
8
+          <uni-collapse-item class="collapse-item" title="基本身份信息" name="basicInfo" :show-animation="true">
9
+            <uni-forms-item label="用户昵称" name="nickName" required>
10
+              <uni-easyinput v-model="user.nickName" placeholder="请输入昵称" />
11
+            </uni-forms-item>
12
+            <uni-forms-item label="归属部门" name="deptId" required>
13
+              <uni-data-picker v-model="user.deptId" :localdata="deptOptions" popup-title="请选择归属部门" />
14
+            </uni-forms-item>
15
+            <uni-forms-item label="手机号码" name="phonenumber">
16
+              <uni-easyinput v-model="user.phonenumber" placeholder="请输入手机号码" />
17
+            </uni-forms-item>
18
+            <uni-forms-item label="邮箱" name="email">
19
+              <uni-easyinput v-model="user.email" placeholder="请输入邮箱" />
20
+            </uni-forms-item>
21
+            <uni-forms-item label="身份证号" name="cardNumber">
22
+              <uni-easyinput v-model="user.cardNumber" placeholder="请输入身份证号" />
23
+            </uni-forms-item>
24
+            <uni-forms-item label="用户性别" name="sex" required>
25
+              <uni-data-picker v-model="user.sex" :localdata="sys_user_sex" popup-title="请选择性别" />
26
+            </uni-forms-item>
27
+            <uni-forms-item label="生肖" name="zodiac">
28
+              <uni-data-picker v-model="user.zodiac" :localdata="sys_user_zodiac" popup-title="请选择生肖" />
29
+            </uni-forms-item>
30
+            <uni-forms-item label="星座" name="constellation">
31
+              <uni-data-picker v-model="user.constellation" :localdata="sys_user_constellation" popup-title="请选择星座" />
32
+            </uni-forms-item>
33
+            <uni-forms-item label="血型" name="blooGroup">
34
+              <uni-data-picker v-model="user.blooGroup" :localdata="sys_user_blood_group" popup-title="请选择血型" />
35
+            </uni-forms-item>
36
+          </uni-collapse-item>
37
+        </uni-collapse>
38
+
39
+        <!-- 状态管理信息 -->
40
+        <uni-collapse class="collapse" :accordion="false" :value="['status']">
41
+          <uni-collapse-item class="collapse-item" title="状态管理信息" name="status" :show-animation="true">
42
+
43
+            <uni-forms-item label="培训合规状态" name="trainingComplianceStatus">
44
+              <uni-data-checkbox v-model="user.trainingComplianceStatus" :localdata="yesNoOptions" />
45
+            </uni-forms-item>
46
+          </uni-collapse-item>
47
+        </uni-collapse>
48
+
49
+        <!-- 资质能力信息 -->
50
+        <uni-collapse class="collapse" :accordion="false" :value="['qualification']">
51
+          <uni-collapse-item class="collapse-item" title="资质能力信息" name="qualification" :show-animation="true">
52
+            <uni-forms-item label="资质等级" name="qualificationLevel" :required="isSecurityRole">
53
+              <uni-data-picker v-model="user.qualificationLevel" :localdata="sys_user_qualification_level"
54
+                popup-title="请选择资质等级" @change="handleQualificationLevelChange" />
55
+            </uni-forms-item>
56
+            <uni-forms-item label="岗位类型" name="postIds" :required="isSecurityRole">
57
+              <zxz-uni-data-select v-model="user.postIds" :localdata="postTreeData" multiple placeholder="请选择岗位类型" />
58
+            </uni-forms-item>
59
+            <uni-forms-item label="是否通过政审" name="politicalReviewSituation">
60
+              <uni-data-checkbox v-model="user.politicalReviewSituation" :localdata="yesNoOptions" />
61
+            </uni-forms-item>
62
+            <uni-forms-item label="政治面貌" name="politicalStatus">
63
+              <uni-data-picker v-model="user.politicalStatus" :localdata="sys_user_political_status"
64
+                popup-title="请选择政治面貌" />
65
+            </uni-forms-item>
66
+            <uni-forms-item label="学历" name="schooling">
67
+              <uni-data-picker v-model="user.schooling" :localdata="sys_user_schooling" popup-title="请选择学历" />
68
+            </uni-forms-item>
69
+            <uni-forms-item label="行政处罚情况" name="administrativeStatus">
70
+              <uni-easyinput v-model="user.administrativeStatus" type="textarea" placeholder="请输入行政处罚情况" />
71
+            </uni-forms-item>
72
+            <uni-forms-item label="健康异常情况" name="physicalHealthStatus">
73
+              <uni-easyinput v-model="user.physicalHealthStatus" type="textarea" placeholder="请输入健康异常情况" />
74
+            </uni-forms-item>
75
+          </uni-collapse-item>
76
+        </uni-collapse>
77
+
78
+        <!-- 工作履历/经验 -->
79
+        <uni-collapse class="collapse" :accordion="false" :value="['experience']">
80
+          <uni-collapse-item class="collapse-item" title="工作履历/经验" name="experience" :show-animation="true">
81
+            <uni-forms-item label="开始工作时间" name="startWorkingDate">
82
+              <uni-datetime-picker v-model="user.startWorkingDate" type="date" placeholder="请选择开始工作时间" />
83
+            </uni-forms-item>
84
+            <uni-forms-item label="开始安检工作时间" name="securityCheckStartDate">
85
+              <uni-datetime-picker v-model="user.securityCheckStartDate" type="date" placeholder="请选择开始安检工作时间" />
86
+            </uni-forms-item>
87
+            <uni-forms-item label="曾在安检工作中担任的最高职务" name="securityInspectionPosition">
88
+              <uni-data-picker v-model="user.securityInspectionPosition" :localdata="securityPositionOptions"
89
+                popup-title="请选择最高职务" />
90
+            </uni-forms-item>
91
+            <uni-forms-item label="接受奖励次数" name="workRewardsNumber">
92
+              <uni-easyinput v-model="user.workRewardsNumber" type="number" placeholder="请输入接受奖励次数" />
93
+            </uni-forms-item>
94
+            <uni-forms-item label="接受处罚次数" name="workPenaltiesNumber">
95
+              <uni-easyinput v-model="user.workPenaltiesNumber" type="number" placeholder="请输入接受处罚次数" />
96
+            </uni-forms-item>
97
+          </uni-collapse-item>
98
+        </uni-collapse>
99
+
100
+        <!-- 评价类指标 -->
101
+        <uni-collapse class="collapse" :accordion="false" :value="['evaluation']">
102
+          <uni-collapse-item class="collapse-item" title="评价类指标" name="evaluation" :show-animation="true">
103
+            <uni-forms-item label="性格特征" name="characterCharacteristics">
104
+              <uni-data-picker v-model="user.characterCharacteristics" :localdata="sys_user_character_characteristics"
105
+                popup-title="请选择性格特征" />
106
+            </uni-forms-item>
107
+            <uni-forms-item label="工作风格" name="workingStyle">
108
+              <uni-data-picker v-model="user.workingStyle" :localdata="sys_user_working_style" popup-title="请选择工作风格" />
109
+            </uni-forms-item>
110
+            <uni-forms-item label="团队配合人员" name="teamCooperation">
111
+              <zxz-uni-data-select v-model="user.teamCooperation" :localdata="teamCooperationOptions" multiple
112
+                placeholder="请选择团队配合人员" />
113
+            </uni-forms-item>
114
+            <uni-forms-item label="自我关键词评价" name="selfKeywords">
115
+              <view class="evaluation-column">
116
+                <uni-data-picker v-model="user.selfAssessmentPersonalityTrait" :localdata="sys_user_personality_trait"
117
+                  popup-title="请选择性格特质" style="width: 100%; margin-bottom: 10px;" />
118
+                <uni-data-picker v-model="user.selfAssessmentCapabilityPerformance"
119
+                  :localdata="sys_user_capability_performance" popup-title="请选择能力表现"
120
+                  style="width: 100%; margin-bottom: 10px;" />
121
+                <uni-data-picker v-model="user.selfAssessmentInterpersonalInteraction"
122
+                  :localdata="sys_user_interpersonal_interaction" popup-title="请选择人际互动"
123
+                  style="width: 100%; margin-bottom: 10px;" />
124
+                <uni-data-picker v-model="user.selfAssessmentGrowthPotential" :localdata="sys_user_growth_potential"
125
+                  popup-title="请选择成长潜力" style="width: 100%;" />
126
+              </view>
127
+            </uni-forms-item>
128
+            <uni-forms-item label="同事关键词评价" name="colleagueKeywords">
129
+              <view class="evaluation-column">
130
+                <uni-data-picker v-model="user.colleagueCommentsPersonalityTrait"
131
+                  :localdata="sys_user_personality_trait" popup-title="请选择性格特质"
132
+                  style="width: 100%; margin-bottom: 10px;" />
133
+                <uni-data-picker v-model="user.colleagueCommentsCapabilityPerformance"
134
+                  :localdata="sys_user_capability_performance" popup-title="请选择能力表现"
135
+                  style="width: 100%; margin-bottom: 10px;" />
136
+                <uni-data-picker v-model="user.colleagueCommentsInterpersonalInteraction"
137
+                  :localdata="sys_user_interpersonal_interaction" popup-title="请选择人际互动"
138
+                  style="width: 100%; margin-bottom: 10px;" />
139
+                <uni-data-picker v-model="user.colleagueCommentsGrowthPotential" :localdata="sys_user_growth_potential"
140
+                  popup-title="请选择成长潜力" style="width: 100%;" />
141
+              </view>
142
+            </uni-forms-item>
143
+            <uni-forms-item label="上级关键词评价" name="superiorKeywords">
144
+              <view class="evaluation-column">
145
+                <uni-data-picker v-model="user.superiorEvaluationPersonalityTrait"
146
+                  :localdata="sys_user_personality_trait" popup-title="请选择性格特质"
147
+                  style="width: 100%; margin-bottom: 10px;" />
148
+                <uni-data-picker v-model="user.superiorEvaluationCapabilityPerformance"
149
+                  :localdata="sys_user_capability_performance" popup-title="请选择能力表现"
150
+                  style="width: 100%; margin-bottom: 10px;" />
151
+                <uni-data-picker v-model="user.superiorEvaluationInterpersonalInteraction"
152
+                  :localdata="sys_user_interpersonal_interaction" popup-title="请选择人际互动"
153
+                  style="width: 100%; margin-bottom: 10px;" />
154
+                <uni-data-picker v-model="user.superiorEvaluationGrowthPotential" :localdata="sys_user_growth_potential"
155
+                  popup-title="请选择成长潜力" style="width: 100%;" />
156
+              </view>
157
+            </uni-forms-item>
158
+            <uni-forms-item label="下级关键词评价" name="subordinateKeywords">
159
+              <view class="evaluation-column">
160
+                <uni-data-picker v-model="user.subordinateEvaluationPersonalityTrait"
161
+                  :localdata="sys_user_personality_trait" popup-title="请选择性格特质"
162
+                  style="width: 100%; margin-bottom: 10px;" />
163
+                <uni-data-picker v-model="user.subordinateEvaluationCapabilityPerformance"
164
+                  :localdata="sys_user_capability_performance" popup-title="请选择能力表现"
165
+                  style="width: 100%; margin-bottom: 10px;" />
166
+                <uni-data-picker v-model="user.subordinateEvaluationInterpersonalInteraction"
167
+                  :localdata="sys_user_interpersonal_interaction" popup-title="请选择人际互动"
168
+                  style="width: 100%; margin-bottom: 10px;" />
169
+                <uni-data-picker v-model="user.subordinateEvaluationGrowthPotential"
170
+                  :localdata="sys_user_growth_potential" popup-title="请选择成长潜力" style="width: 100%;" />
171
+              </view>
172
+            </uni-forms-item>
173
+          </uni-collapse-item>
174
+        </uni-collapse>
175
+
176
+        <!-- 应急联络信息 -->
177
+        <uni-collapse class="collapse" :accordion="false" :value="['emergency']">
178
+          <uni-collapse-item class="collapse-item" title="应急联络信息" name="emergency" :show-animation="true">
179
+            <uni-forms-item label="紧急联系人姓名" name="emergencyContactName">
180
+              <uni-easyinput v-model="user.emergencyContactName" placeholder="请输入紧急联系人姓名" />
181
+            </uni-forms-item>
182
+            <uni-forms-item label="紧急联系人电话" name="emergencyContactPhone">
183
+              <uni-easyinput v-model="user.emergencyContactPhone" placeholder="请输入紧急联系人电话" />
184
+            </uni-forms-item>
185
+            <uni-forms-item label="紧急联系人关系" name="emergencyContactRelationship">
186
+              <uni-data-picker v-model="user.emergencyContactRelationship"
187
+                :localdata="sys_user_emergency_contact_relationship" popup-title="请选择紧急联系人关系" />
188
+            </uni-forms-item>
189
+          </uni-collapse-item>
190
+        </uni-collapse>
191
+
192
+        <!-- 其他信息 -->
193
+        <uni-collapse class="collapse" :accordion="false" :value="['other']">
194
+          <uni-collapse-item class="collapse-item" title="其他信息" name="other" :show-animation="true">
195
+            <uni-forms-item label="备注" name="remark">
196
+              <uni-easyinput v-model="user.remark" type="textarea" placeholder="请输入备注" />
197
+            </uni-forms-item>
198
+          </uni-collapse-item>
199
+        </uni-collapse>
200
+
17 201
       </uni-forms>
18
-      <button type="primary" @click="submit">提交</button>
202
+    </view>
203
+
204
+    <!-- 固定在底部的提交按钮 -->
205
+    <view class="submit-button">
206
+      <button type="primary" @click="submit" style="margin-top: 0;width: 100%;">提交</button>
19 207
     </view>
20 208
   </view>
21 209
 </template>
22 210
 
23 211
 <script>
24
-  import { getUserProfile } from "@/api/system/user"
25
-  import { updateUserProfile } from "@/api/system/user"
26 212
 
27
-  export default {
28
-    data() {
213
+import { updateUser, listAllUser, getPostAllList, getUserInfoById } from "@/api/system/user"
214
+import { getDeptList } from "@/api/system/dept/dept"
215
+import storage from "@/utils/storage"
216
+import constant from "@/utils/constant"
217
+import useDictMixin from "@/utils/dict"
218
+
219
+export default {
220
+  mixins: [useDictMixin],
221
+  data() {
222
+    return {
223
+      user: {
224
+        // 基本身份信息
225
+        nickName: "",
226
+        deptId: "",
227
+        phonenumber: "",
228
+        email: "",
229
+        cardNumber: "",
230
+        sex: "",
231
+        zodiac: "",
232
+        constellation: "",
233
+        blooGroup: "",
234
+
235
+        // 状态管理信息
236
+        trainingComplianceStatus: "",
237
+
238
+        // 资质能力信息
239
+        qualificationLevel: "",
240
+        postIds: [],
241
+        politicalReviewSituation: "",
242
+        politicalStatus: "",
243
+        schooling: "",
244
+        administrativeStatus: "",
245
+        physicalHealthStatus: "",
246
+
247
+        // 工作履历/经验
248
+        startWorkingDate: "",
249
+        securityCheckStartDate: "",
250
+        securityInspectionPosition: "",
251
+        workRewardsNumber: "",
252
+        workPenaltiesNumber: "",
253
+
254
+        // 评价类指标
255
+        characterCharacteristics: "",
256
+        workingStyle: "",
257
+        teamCooperation: [],
258
+        selfAssessmentPersonalityTrait: "",
259
+        selfAssessmentCapabilityPerformance: "",
260
+        selfAssessmentInterpersonalInteraction: "",
261
+        selfAssessmentGrowthPotential: "",
262
+        colleagueCommentsPersonalityTrait: "",
263
+        colleagueCommentsCapabilityPerformance: "",
264
+        colleagueCommentsInterpersonalInteraction: "",
265
+        colleagueCommentsGrowthPotential: "",
266
+        superiorEvaluationPersonalityTrait: "",
267
+        superiorEvaluationCapabilityPerformance: "",
268
+        superiorEvaluationInterpersonalInteraction: "",
269
+        superiorEvaluationGrowthPotential: "",
270
+        subordinateEvaluationPersonalityTrait: "",
271
+        subordinateEvaluationCapabilityPerformance: "",
272
+        subordinateEvaluationInterpersonalInteraction: "",
273
+        subordinateEvaluationGrowthPotential: "",
274
+
275
+        // 应急联络信息
276
+        emergencyContactName: "",
277
+        emergencyContactPhone: "",
278
+        emergencyContactRelationship: "",
279
+
280
+        // 其他信息
281
+        remark: ""
282
+      },
283
+
284
+      // 性别选项
285
+      sys_user_sex: [],
286
+
287
+      // 生肖选项
288
+      sys_user_zodiac: [],
289
+
290
+      // 星座选项
291
+      sys_user_constellation: [],
292
+
293
+      // 血型选项
294
+      sys_user_blood_group: [],
295
+
296
+      // 资质等级选项
297
+      sys_user_qualification_level: [],
298
+
299
+      // 岗位类型选项
300
+      sys_user_post_type: [],
301
+
302
+      // 是否通过政审选项
303
+      yesNoOptions: [
304
+        { text: '是', value: '1' },
305
+        { text: '否', value: '0' }
306
+      ],
307
+
308
+      // 政治面貌选项
309
+      sys_user_political_status: [],
310
+
311
+      // 学历选项
312
+      sys_user_schooling: [],
313
+
314
+      // 安检最高职务选项
315
+      sys_user_security_position: [],
316
+
317
+      // 安检最高职务选项(写死)
318
+      securityPositionOptions: [
319
+        { text: '安检员', value: '安检员' },
320
+        { text: '班组长', value: '班组长' }
321
+      ],
322
+
323
+      // 性格特征选项
324
+      sys_user_character_characteristics: [],
325
+
326
+      // 工作风格选项
327
+      sys_user_working_style: [],
328
+
329
+      // 团队配合人员选项
330
+      sys_user_team_cooperation: [],
331
+
332
+      // 性格特质选项
333
+      sys_user_personality_trait: [],
334
+
335
+      // 能力表现选项
336
+      sys_user_capability_performance: [],
337
+
338
+      // 人际互动选项
339
+      sys_user_interpersonal_interaction: [],
340
+
341
+      // 成长潜力选项
342
+      sys_user_growth_potential: [],
343
+
344
+      // 紧急联系人关系选项
345
+      sys_user_emergency_contact_relationship: [],
346
+
347
+      // 团队配合人员选项
348
+      teamCooperationOptions: [],
349
+
350
+      // 岗位类型树状数据
351
+      postTreeData: [],
352
+
353
+      // 部门选项数据
354
+      deptOptions: [],
355
+
356
+    }
357
+  },
358
+  onLoad() {
359
+    this.loadDictData()
360
+    this.getUser()
361
+    this.loadTeamCooperationData()
362
+    this.loadPostTreeData()
363
+    this.loadDeptData()
364
+  },
365
+  onReady() {
366
+    this.$refs.form.setRules(this.rules)
367
+  },
368
+  computed: {
369
+    rules() {
29 370
       return {
30
-        user: {
31
-          nickName: "",
32
-          phonenumber: "",
33
-          email: "",
34
-          sex: ""
371
+        nickName: {
372
+          rules: [{
373
+            required: true,
374
+            errorMessage: '用户昵称不能为空'
375
+          }]
35 376
         },
36
-        sexs: [{
37
-          text: '男',
38
-          value: "0"
39
-        }, {
40
-          text: '女',
41
-          value: "1"
42
-        }],
43
-        rules: {
44
-          nickName: {
45
-            rules: [{
46
-              required: true,
47
-              errorMessage: '用户昵称不能为空'
48
-            }]
49
-          },
50
-          phonenumber: {
51
-            rules: [{
52
-              required: true,
53
-              errorMessage: '手机号码不能为空'
54
-            }, {
55
-              pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
56
-              errorMessage: '请输入正确的手机号码'
57
-            }]
58
-          },
59
-          email: {
60
-            rules: [{
61
-              required: true,
62
-              errorMessage: '邮箱地址不能为空'
63
-            }, {
64
-              format: 'email',
65
-              errorMessage: '请输入正确的邮箱地址'
66
-            }]
67
-          }
377
+        deptId: {
378
+          rules: [{
379
+            required: true,
380
+            errorMessage: '归属部门不能为空'
381
+          }]
382
+        },
383
+        qualificationLevel: {
384
+          rules: [{
385
+            required: this.isSecurityRole,
386
+            errorMessage: '资质等级不能为空'
387
+          }]
388
+        },
389
+        postIds: {
390
+          rules: [{
391
+            required: this.isSecurityRole,
392
+            errorMessage: '岗位类型不能为空'
393
+          }]
394
+        },
395
+        phonenumber: {
396
+          rules: [{
397
+            required: true,
398
+            errorMessage: '手机号码不能为空'
399
+          }, {
400
+            pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
401
+            errorMessage: '请输入正确的手机号码'
402
+          }]
403
+        },
404
+        email: {
405
+          rules: [{
406
+            required: true,
407
+            errorMessage: '邮箱地址不能为空'
408
+          }, {
409
+            format: 'email',
410
+            errorMessage: '请输入正确的邮箱地址'
411
+          }]
68 412
         }
69 413
       }
70 414
     },
71
-    onLoad() {
72
-      this.getUser()
415
+    // 判断当前用户是否是安检员或班组长角色
416
+    isSecurityRole() {
417
+      // 安检员和班组长的角色ID通常是固定的,这里假设安检员角色ID为101,班组长角色ID为102
418
+      // 您可以根据实际情况调整这些ID
419
+      const securityRoleIds = ['banzuzhang', 'SecurityCheck'] // 安检员和班组长的角色ID
420
+
421
+      // 检查当前用户的角色ID是否包含安检员或班组长的角色ID
422
+      console.log((this.user?.roles && this.user?.roles.length > 0) && this.user.roles.some(role => securityRoleIds.includes(role.roleKey)), "this.user.roleIds.some(role => securityRoleIds.includes(role.roleKey))")
423
+      return (this.user?.roles && this.user?.roles.length > 0) && this.user?.roles.some(role => securityRoleIds.includes(role.roleKey))
424
+
425
+    }
426
+  },
427
+  methods: {
428
+    async loadDictData() {
429
+      try {
430
+        const dicts = await this.useDict(
431
+          'sys_user_sex',
432
+          'sys_user_zodiac',
433
+          'sys_user_constellation',
434
+          'sys_user_blood_group',
435
+          'sys_user_qualification_level',
436
+          'sys_user_post_type',
437
+          'sys_user_political_status',
438
+          'sys_user_schooling',
439
+          'sys_user_security_position',
440
+          'sys_user_character_characteristics',
441
+          'sys_user_working_style',
442
+          'sys_user_team_cooperation',
443
+          'sys_user_personality_trait',
444
+          'sys_user_capability_performance',
445
+          'sys_user_interpersonal_interaction',
446
+          'sys_user_growth_potential',
447
+          'sys_user_emergency_contact_relationship'
448
+        )
449
+
450
+        // 将获取到的字典数据转换为uni-data-picker需要的格式
451
+        Object.keys(dicts).forEach(key => {
452
+          // console.log(dicts[key])
453
+          // 将dictLabel/dictValue格式转换为label/value格式
454
+          this[key] = dicts[key].map(item => ({
455
+            text: item.label,
456
+            value: item.value
457
+          }))
458
+        })
459
+      } catch (error) {
460
+        console.error('加载字典数据失败:', error)
461
+      }
73 462
     },
74
-    onReady() {
75
-      this.$refs.form.setRules(this.rules)
463
+
464
+    // 加载团队配合人员数据
465
+    async loadTeamCooperationData() {
466
+      try {
467
+        const res = await listAllUser()
468
+        if (res && res.data) {
469
+          this.teamCooperationOptions = res.data.map(item => ({
470
+            text: `${item.nickName}(${item.userName})`,
471
+            value: item.userId
472
+          }))
473
+        }
474
+      } catch (error) {
475
+        console.error('加载团队配合人员数据失败:', error)
476
+      }
477
+    },
478
+
479
+    // 加载岗位类型树状数据
480
+    async loadPostTreeData() {
481
+      try {
482
+        const res = await getPostAllList()
483
+
484
+        if (res && res.data) {
485
+          // 保存原始树状数据
486
+          this.postTreeDataAll = JSON.parse(JSON.stringify(res.data))
487
+
488
+          // 将树状数据扁平化,显示为"父级岗位名称 - 子级岗位名称"格式
489
+          const flattenTreeWithParent = (nodes, parentName = '') => {
490
+            let result = []
491
+            nodes.forEach(node => {
492
+              // 如果有子节点,只处理子节点
493
+              if (node.children && node.children.length > 0) {
494
+                result = result.concat(flattenTreeWithParent(node.children, node.postName))
495
+              } else {
496
+                // 如果没有子节点,显示当前节点(带父级名称)
497
+                const displayText = parentName ? `${parentName}/${node.postName}` : node.postName
498
+                result.push({
499
+                  text: displayText,
500
+                  value: node.postId
501
+                })
502
+              }
503
+            })
504
+            return result
505
+          }
506
+
507
+          this.postTreeData = flattenTreeWithParent(res.data)
508
+        }
509
+      } catch (error) {
510
+        console.error('加载岗位类型树状数据失败:', error)
511
+      }
76 512
     },
77
-    methods: {
78
-      getUser() {
79
-        getUserProfile().then(response => {
80
-          this.user = response.data
513
+
514
+    // 资质等级变化处理
515
+    handleQualificationLevelChange(e) {
516
+      console.log('资质等级变化', e)
517
+      // 清空岗位类型选择
518
+      this.user.postIds = []
519
+
520
+      // 如果资质等级为五级,需要重新生成过滤后的扁平化数据
521
+      const flattenTreeWithParent = (nodes, parentName = '') => {
522
+        let result = []
523
+        nodes.forEach(node => {
524
+          if (node.children && node.children.length > 0) {
525
+            result = result.concat(flattenTreeWithParent(node.children, node.postName))
526
+          } else {
527
+            const displayText = parentName ? `${parentName}/${node.postName}` : node.postName
528
+            result.push({
529
+              text: displayText,
530
+              value: node.postId
531
+            })
532
+          }
81 533
         })
82
-      },
83
-      submit(ref) {
84
-        this.$refs.form.validate().then(res => {
85
-          updateUserProfile(this.user).then(response => {
86
-            this.$modal.msgSuccess("修改成功")
87
-          })
534
+        return result
535
+      }
536
+
537
+      if (e?.detail?.value[0]?.value === 'LEVEL_FIVE') {
538
+        this.postTreeData = flattenTreeWithParent(this.postTreeDataAll).filter(item => item.value !== 9 && item.value !== 10)
539
+      } else {
540
+        this.postTreeData = flattenTreeWithParent(this.postTreeDataAll)
541
+      }
542
+
543
+
544
+    },
545
+
546
+    // 递归过滤树形数据
547
+    filterPostTree(data) {
548
+      return data.filter(item => {
549
+        // 过滤掉postId为9或10的选项
550
+        if (item.postId == 9 || item.postId == 10) {
551
+          return false
552
+        }
553
+
554
+        // 如果有子节点,递归过滤
555
+        if (item.children && item.children.length > 0) {
556
+          item.children = this.filterPostTree(item.children)
557
+        }
558
+
559
+        return true
560
+      })
561
+    },
562
+
563
+    // 加载部门数据
564
+    async loadDeptData() {
565
+      try {
566
+        const res = await getDeptList()
567
+        if (res && res.data) {
568
+          // 直接使用树状数据,转换为uni-data-picker需要的格式
569
+          const transformDeptTree = (nodes) => {
570
+            return nodes.map(node => ({
571
+              text: node.label,
572
+              value: node.id,
573
+              children: node.children ? transformDeptTree(node.children) : []
574
+            }))
575
+          }
576
+          this.deptOptions = transformDeptTree(res.data)
577
+        }
578
+      } catch (error) {
579
+        console.error('加载部门数据失败:', error)
580
+      }
581
+    },
582
+    getUser() {
583
+      // 获取当前登录用户的ID
584
+      const currentUserId = storage.get(constant.id)
585
+      if (currentUserId) {
586
+        getUserInfoById(currentUserId).then(response => {
587
+          let res = { ...response.data }
588
+          res.teamCooperation = res.teamCooperation ? res.teamCooperation.split(",") : []
589
+          res.postIds = response.postIds || []
590
+          res.roleIds = response.roleIds || []
591
+          this.user = res
88 592
         })
593
+      } else {
594
+        console.error('未找到当前登录用户ID')
89 595
       }
596
+    },
597
+    submit(ref) {
598
+      // 重新设置验证规则,确保角色变化后规则能更新
599
+      this.$refs.form.setRules(this.rules)
600
+      
601
+      this.$refs.form.validate().then(res => {
602
+        // 准备提交数据,将数组字段转换为字符串
603
+        const submitData = {
604
+          ...this.user,
605
+          teamCooperation: this.user.teamCooperation ? this.user.teamCooperation.join(',') : ''
606
+        }
607
+
608
+        updateUser(submitData).then(response => {
609
+          this.$modal.msgSuccess("修改成功")
610
+          // 提交成功后返回上一个页面
611
+          setTimeout(() => {
612
+            uni.navigateBack()
613
+          }, 1500)
614
+        })
615
+      }).catch(err => {
616
+        // 验证失败时显示错误提示
617
+        console.error('表单验证失败:', err)
618
+        this.$modal.msgError('请检查表单填写是否正确')
619
+      })
90 620
     }
91 621
   }
622
+}
92 623
 </script>
93 624
 
94 625
 <style lang="scss" scoped>
95
-  page {
96
-    background-color: #ffffff;
97
-  }
626
+page {
627
+  background-color: #ffffff;
628
+  padding-bottom: 80px;
629
+  /* 为底部按钮预留空间 */
630
+}
98 631
 
99
-  .example {
100
-    padding: 15px;
101
-    background-color: #fff;
102
-  }
632
+.example {
633
+  padding: 15px;
103 634
 
104
-  .segmented-control {
105
-    margin-bottom: 15px;
106
-  }
635
+  background-color: #fff;
636
+}
107 637
 
108
-  .button-group {
109
-    margin-top: 15px;
110
-    display: flex;
111
-    justify-content: space-around;
112
-  }
638
+.submit-button {
639
+  position: fixed;
640
+  bottom: 0;
641
+  left: 0;
642
+  right: 0;
643
+  z-index: 999;
644
+  background: #fff;
645
+  padding: 15px;
646
+  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
647
+}
113 648
 
114
-  .form-item {
115
-    display: flex;
116
-    align-items: center;
117
-    flex: 1;
118
-  }
649
+.collapse {
650
+  margin-bottom: 10px;
651
+  border-radius: 8px;
652
+  overflow: hidden;
653
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
654
+}
119 655
 
120
-  .button {
121
-    display: flex;
122
-    align-items: center;
123
-    height: 35px;
124
-    line-height: 35px;
125
-    margin-left: 10px;
126
-  }
656
+.collapse-item {
657
+  background-color: #fff;
658
+  padding: 10px;
659
+}
660
+
661
+.segmented-control {
662
+  margin-bottom: 15px;
663
+}
664
+
665
+.button-group {
666
+  margin-top: 15px;
667
+  display: flex;
668
+  justify-content: space-around;
669
+}
670
+
671
+.form-item {
672
+  display: flex;
673
+  align-items: center;
674
+  flex: 1;
675
+}
676
+
677
+.button {
678
+  display: flex;
679
+  align-items: center;
680
+  height: 35px;
681
+  line-height: 35px;
682
+  margin-left: 10px;
683
+}
684
+
685
+button[type="primary"] {
686
+  margin-top: 20px;
687
+  background-color: #409EFF;
688
+}
689
+
690
+.evaluation-row {
691
+  display: flex;
692
+  flex-wrap: wrap;
693
+  justify-content: space-between;
694
+  width: 100%;
695
+}
696
+
697
+.evaluation-column {
698
+  display: flex;
699
+  flex-direction: column;
700
+  width: 100%;
701
+}
127 702
 </style>

+ 116 - 13
src/pages/seizedReported/index.vue

@@ -81,6 +81,26 @@
81 81
 
82 82
               <uni-easyinput v-else :disabled="true" placeholder="请选择查获班组" :value="formData.attendanceTeamName" />
83 83
             </uni-forms-item>
84
+
85
+            <!-- 开机指令(仅开箱检查岗位显示) -->
86
+            <uni-forms-item v-if="isPackageInspection" label="开机指令" name="powerOnInstruction" required>
87
+              <radio-group v-if="!isDetailMode" @change="onpowerOnInstructionChange" class="radio-group"
88
+                :class="{ 'disabled-group': isDetailMode }">
89
+                <label class="radio-item" v-for="(item, index) in powerOnInstructionOptions" :key="index">
90
+                  <radio :value="item.value" :checked="formData.powerOnInstruction == item.value" color="#409EFF" />
91
+                  <text>{{ item.text }}</text>
92
+                </label>
93
+              </radio-group>
94
+              <uni-easyinput v-else :disabled="true" placeholder="请选择开机指令" :value="formData.powerOnInstructionText" />
95
+            </uni-forms-item>
96
+
97
+            <!-- X光开机员(仅非指令时显示) -->
98
+            <uni-forms-item v-if="showXrayOperator" label="X光开机员" name="xrayOperatorId" required>
99
+              <fuzzy-select v-if="!isDetailMode" v-model="formData.xrayOperatorId" :options="xrayOperatorOptions"
100
+                placeholder="请输入X光开机员姓名搜索" data-value="userId" data-text="nickName" @change="handleXrayOperatorSelect"
101
+                :disabled="isDetailMode" />
102
+              <uni-easyinput v-else :disabled="true" placeholder="请选择X光开机员" :value="formData.xrayOperatorName" />
103
+            </uni-forms-item>
84 104
           </uni-collapse-item>
85 105
         </uni-collapse>
86 106
         <!-- </view> -->
@@ -243,7 +263,7 @@ import HomeContainer from "@/components/HomeContainer.vue";
243 263
 import SearchView from "@/pages/attendance/components/SearchView.vue"
244 264
 import { treeSelectByType } from "@/api/system/common"
245 265
 import useDictMixin from '@/utils/dict'
246
-
266
+import FuzzySelect from "@/components/fuzzy-select/fuzzy-select.vue"
247 267
 import { addSeizureRecord, approvalStart, getInfo } from '@/api/seizure/seizureRecord.js'
248 268
 import { getLocationsbyTime, categoryInfo, categoryList } from '@/api/seizureRecord/seizureRecord.js'
249 269
 import config from '@/config'
@@ -254,7 +274,7 @@ import { formatTime } from '@/utils/formatUtils'
254 274
 import { getUserInfoById, getPostListsByUserId } from '@/api/system/user.js'
255 275
 import { getUserList } from '@/api/attendance/attendance'
256 276
 export default {
257
-  components: { HomeContainer, SearchView },
277
+  components: { HomeContainer, SearchView, FuzzySelect },
258 278
   mixins: [useDictMixin],
259 279
   computed: {
260 280
     currentUser() {
@@ -273,6 +293,14 @@ export default {
273 293
       // console.log(this.item_check_method_options.map(item => item.postName || item.label || item.text || item.value),"this.item_check_method_options.map(item => item.postName || item.label || item.text || item.value)")
274 294
       return this.item_check_method_options.map(item => item.postName || item.label || item.text || item.value);
275 295
     },
296
+    // 判断是否为开箱(包)检查岗位
297
+    isPackageInspection() {
298
+      return this.formData.checkMethodText === '开箱(包)检查岗位';
299
+    },
300
+    // 判断是否显示X光开机员选择(非指令时显示)
301
+    showXrayOperator() {
302
+      return this.isPackageInspection && this.formData.powerOnInstruction == '1';
303
+    },
276 304
     // // 判断是新增模式还是详情模式
277 305
     isDetailMode() {
278 306
 
@@ -298,7 +326,11 @@ export default {
298 326
         teamName: '',
299 327
         reportTeam: '',
300 328
         reportTeamText: '',
301
-
329
+        // 开机指令相关字段(开箱检查岗位使用)
330
+        powerOnInstruction: '0', // 开机指令:'0'-指令, '1'-非指令
331
+        powerOnInstructionText: '指令',
332
+        xrayOperatorId: '', // X光开机员ID
333
+        xrayOperatorName: '', // X光开机员姓名
302 334
         // 查获位置信息
303 335
         channelCode: '',
304 336
         channelName: '',
@@ -365,6 +397,12 @@ export default {
365 397
         reportTeam: {
366 398
           rules: [{ required: true, errorMessage: '请选择上报班组' }]
367 399
         },
400
+        powerOnInstruction: {
401
+          rules: [{ required: true, errorMessage: '请选择开机指令' }]
402
+        },
403
+        xrayOperatorId: {
404
+          rules: [{ required: true, errorMessage: '请选择X光开机员' }]
405
+        },
368 406
         forbiddenCategory: {
369 407
           rules: [{ required: true, errorMessage: '请选择违禁品类别' }]
370 408
         },
@@ -419,7 +457,13 @@ export default {
419 457
         { name: '是', value: '1' },
420 458
         { name: '否', value: '0' }
421 459
       ],
422
-
460
+      // 开机指令选项
461
+      powerOnInstructionOptions: [
462
+        { text: '指令', value: '0' },
463
+        { text: '非指令', value: '1' }
464
+      ],
465
+      // X光开机员选项
466
+      xrayOperatorOptions: [],
423 467
       // 其他数据
424 468
       startDate: '2020-01-01',
425 469
       endDate: '2030-12-31',
@@ -463,12 +507,12 @@ export default {
463 507
     this.type = params?.type || 'add';
464 508
     // }
465 509
     await this.initPageData();
466
-    
510
+
467 511
     // 如果是kezhang角色,加载部门人员
468 512
     if (this.isKezhang) {
469 513
       await this.loadDepartmentUsers();
470 514
     }
471
-    
515
+
472 516
     if (this.type == 'add' && !this.isKezhang) {
473 517
       this.invokerGetLocationsbyTime()
474 518
     }
@@ -637,6 +681,14 @@ export default {
637 681
           }
638 682
         })
639 683
 
684
+        // 处理powerOnInstruction字段,确保为字符串类型
685
+        if (detailData.powerOnInstruction != null) {
686
+          this.formData.powerOnInstruction = String(detailData.powerOnInstruction);
687
+          this.formData.powerOnInstructionText = detailData.powerOnInstructionText || (detailData.powerOnInstruction == 1 ? '非指令' : '指令');
688
+        } else {
689
+          this.formData.powerOnInstruction = '0';
690
+          this.formData.powerOnInstructionText = '指令';
691
+        }
640 692
 
641 693
       })
642 694
 
@@ -767,7 +819,7 @@ export default {
767 819
         ]);
768 820
         // 初始化岗位选项数据
769 821
         await this.initPositionAndOptions();
770
-        
822
+
771 823
         const convertTree = (list = []) =>
772 824
           list.map(node => ({
773 825
             text: node.label,
@@ -831,7 +883,7 @@ export default {
831 883
 
832 884
         // 更新岗位选项
833 885
         this.item_check_method_options = postListsRes.data || [];
834
-        
886
+
835 887
         console.log("岗位和选项数据已更新,用户ID:", userId);
836 888
       } catch (error) {
837 889
         console.error("初始化岗位和选项数据失败:", error);
@@ -841,11 +893,11 @@ export default {
841 893
     // 加载部门人员(kezhang角色使用)
842 894
     async loadDepartmentUsers() {
843 895
       if (!this.isKezhang) return;
844
-      
896
+
845 897
       try {
846 898
         const currentUserInfo = this.userInfo || {};
847 899
         const currentUserDeptId = currentUserInfo.departmentId || currentUserInfo.deptId;
848
-        
900
+
849 901
         if (!currentUserDeptId) {
850 902
           console.warn('无法获取当前用户的部门ID');
851 903
           return;
@@ -862,7 +914,7 @@ export default {
862 914
             ...user,
863 915
             value: user.userId,
864 916
             text: user.nickName || user.userName,
865
-      
917
+
866 918
           }));
867 919
         }
868 920
       } catch (error) {
@@ -971,11 +1023,62 @@ export default {
971 1023
         this.formData.checkMethodText = '';
972 1024
         return
973 1025
       }
1026
+      // 如果切换了岗位,重置开机指令相关字段
1027
+      if (this.formData.checkMethodText !== text) {
1028
+        this.formData.powerOnInstruction = '';
1029
+        this.formData.powerOnInstructionText = '';
1030
+        this.formData.xrayOperatorId = '';
1031
+        this.formData.xrayOperatorName = '';
1032
+      }
1033
+
974 1034
 
975 1035
       this.formData.checkMethod = selectedItem?.postCode || text;
976 1036
       this.formData.checkMethodText = selectedItem?.postName || selectedItem?.label || selectedItem?.text || text;
1037
+      // 如果是开箱(包)检查岗位,加载X光开机员列表
1038
+      if (text === '开箱(包)检查岗位') {
1039
+        this.loadXrayOperators();
1040
+      }
1041
+    },
1042
+    // 开机指令变化
1043
+    onpowerOnInstructionChange(e) {
1044
+      const selectedValue = e.detail.value;
1045
+
1046
+      this.formData.powerOnInstruction = selectedValue;
1047
+      this.formData.powerOnInstructionText = selectedValue === '1' ? '非指令' : '指令';
1048
+      this.formData.xrayOperatorId = '';
1049
+      this.formData.xrayOperatorName = '';
1050
+
1051
+      // 如果选择了指令,清空X光开机员
1052
+      if (this.formData.powerOnInstruction === '0') {
1053
+        this.loadXrayOperators();
1054
+      }
1055
+    },
1056
+
1057
+    // 加载X光开机员列表
1058
+    async loadXrayOperators() {
1059
+      try {
1060
+        // 使用现有的用户列表接口,可以根据需要调整参数
1061
+        const { listAllUser } = await import('@/api/system/user.js');
1062
+        const res = await listAllUser();
1063
+        if (res && res.data) {
1064
+          this.xrayOperatorOptions = res.data.map(item => ({
1065
+            ...item,
1066
+            nickName: `${item.nickName}(${item.userName})`,
1067
+          })) || [];
1068
+        }
1069
+      } catch (error) {
1070
+        console.error('加载X光开机员列表失败:', error);
1071
+      }
977 1072
     },
978 1073
 
1074
+    // X光开机员选择
1075
+    handleXrayOperatorSelect(value) {
1076
+      const selectedUser = this.xrayOperatorOptions.find(user => user.userId === value);
1077
+      if (selectedUser) {
1078
+        this.formData.xrayOperatorId = selectedUser.userId;
1079
+        this.formData.xrayOperatorName = selectedUser.nickName;
1080
+      }
1081
+    },
979 1082
     // 安检岗位 - 原data-picker版本(已弃用)
980 1083
     onItemCheckMethodChange(e) {
981 1084
       this.formData.checkMethod = e.detail.value[0]?.value || '';
@@ -1075,7 +1178,7 @@ export default {
1075 1178
       const arr = e.detail.value || [];
1076 1179
       this.formData.inspectUserId = arr[arr.length - 1]?.value || '';
1077 1180
       this.formData.inspectUserName = arr.map(item => item.text).join('/');
1078
-      
1181
+
1079 1182
       this.formData.reportTeam = this.departmentUserOptions.find(item => item.userId === this.formData.inspectUserId)?.deptId;
1080 1183
       this.formData.reportTeamText = this.teams.find(item => item.value === this.formData.reportTeam)?.text;
1081 1184
       // 切换查获人员后,重新初始化岗位和选项数据
@@ -1175,7 +1278,7 @@ export default {
1175 1278
 
1176 1279
 
1177 1280
 
1178
-      
1281
+
1179 1282
       const payload = {
1180 1283
         ...this.formData,
1181 1284
         itemSeizureItemsList: [item],

+ 107 - 6
src/pages/seizedReportedVoice/index.vue

@@ -72,6 +72,26 @@
72 72
 
73 73
               <uni-easyinput v-else :disabled="true" placeholder="请选择查获班组" :value="formData.reportTeamText" />
74 74
             </uni-forms-item>
75
+
76
+            <!-- 开机指令(仅开箱检查岗位显示) -->
77
+            <uni-forms-item v-if="isPackageInspection" label="开机指令" name="powerOnInstruction" required>
78
+              <radio-group v-if="!isDetailMode" @change="onpowerOnInstructionChange" class="radio-group"
79
+                :class="{ 'disabled-group': isDetailMode }">
80
+                <label class="radio-item" v-for="(item, index) in powerOnInstructionOptions" :key="index">
81
+                  <radio :value="item.value" :checked="formData.powerOnInstruction === item.value" color="#409EFF" />
82
+                  <text>{{ item.label }}</text>
83
+                </label>
84
+              </radio-group>
85
+              <uni-easyinput v-else :disabled="true" placeholder="请选择开机指令" :value="formData.powerOnInstructionText" />
86
+            </uni-forms-item>
87
+
88
+            <!-- X光开机员(仅非指令时显示) -->
89
+            <uni-forms-item v-if="showXrayOperator" label="X光开机员" name="xrayOperatorId" required>
90
+              <fuzzy-select v-if="!isDetailMode" v-model="formData.xrayOperatorId" :options="xrayOperatorOptions"
91
+                placeholder="请输入X光开机员姓名搜索" data-value="userId" data-text="nickName" @change="handleXrayOperatorSelect"
92
+                :disabled="isDetailMode" />
93
+              <uni-easyinput v-else :disabled="true" placeholder="请选择X光开机员" :value="formData.xrayOperatorName" />
94
+            </uni-forms-item>
75 95
           </view>
76 96
 
77 97
 
@@ -208,6 +228,7 @@ import HomeContainer from "@/components/HomeContainer.vue";
208 228
 import SearchView from "@/pages/attendance/components/SearchView.vue"
209 229
 import { treeSelectByType } from "@/api/system/common"
210 230
 import useDictMixin from '@/utils/dict'
231
+import FuzzySelect from "@/components/fuzzy-select/fuzzy-select.vue"
211 232
 import { getVoiceInfo, deleteVoiceDraft } from '@/api/voiceSubmissionDraft/voiceSubmissionDraft.js'
212 233
 import { addSeizureRecord, approvalStart, getInfo } from '@/api/seizure/seizureRecord.js'
213 234
 import { getLocationsbyTime, categoryInfo, categoryList } from '@/api/seizureRecord/seizureRecord.js'
@@ -218,7 +239,7 @@ import { getDeptList } from "@/api/system/dept/dept.js"
218 239
 import { formatTime } from '@/utils/formatUtils'
219 240
 import { getUserInfoById, getPostListsByUserId } from '@/api/system/user.js'
220 241
 export default {
221
-  components: { HomeContainer, SearchView },
242
+  components: { HomeContainer, SearchView, FuzzySelect },
222 243
   mixins: [useDictMixin],
223 244
   computed: {
224 245
     currentUser() {
@@ -233,6 +254,14 @@ export default {
233 254
       // console.log(this.item_check_method_options.map(item => item.postName || item.label || item.text || item.value),"this.item_check_method_options.map(item => item.postName || item.label || item.text || item.value)")
234 255
       return this.item_check_method_options.map(item => item.postName || item.label || item.text || item.value);
235 256
     },
257
+    // 判断是否为开箱(包)检查岗位
258
+    isPackageInspection() {
259
+      return this.formData.checkMethodText === '开箱(包)检查岗位';
260
+    },
261
+    // 判断是否显示X光开机员选择(非指令时显示)
262
+    showXrayOperator() {
263
+      return this.isPackageInspection && this.formData.powerOnInstruction === '1';
264
+    },
236 265
     // // 判断是新增模式还是详情模式
237 266
     isDetailMode() {
238 267
 
@@ -259,7 +288,11 @@ export default {
259 288
         teamName: '',
260 289
         reportTeam: '',
261 290
         reportTeamText: '',
262
-
291
+        // 开机指令相关字段(开箱检查岗位使用)
292
+        powerOnInstruction: '0', // 开机指令:'0'-指令, '1'-非指令
293
+        powerOnInstructionText: '指令',
294
+        xrayOperatorId: '', // X光开机员ID
295
+        xrayOperatorName: '', // X光开机员姓名
263 296
         // 查获位置信息
264 297
         channelCode: '',
265 298
         channelName: '',
@@ -332,6 +365,12 @@ export default {
332 365
         forbiddenType: {
333 366
           rules: [{ required: true, errorMessage: '请选择违禁品类型' }]
334 367
         },
368
+        powerOnInstruction: {
369
+          rules: [{ required: true, errorMessage: '请选择开机指令' }]
370
+        },
371
+        xrayOperatorId: {
372
+          rules: [{ required: true, errorMessage: '请选择X光开机员' }]
373
+        },
335 374
         // forbiddenName: {
336 375
         //   rules: [{ required: true, errorMessage: '请输入违禁品名称' }]
337 376
         // },
@@ -382,7 +421,13 @@ export default {
382 421
         { name: '是', value: '1' },
383 422
         { name: '否', value: '0' }
384 423
       ],
385
-
424
+      // 开机指令选项
425
+      powerOnInstructionOptions: [
426
+        { label: '指令', value: '0' },
427
+        { label: '非指令', value: '1' }
428
+      ],
429
+      // X光开机员选项
430
+      xrayOperatorOptions: [],
386 431
       // 其他数据
387 432
       startDate: '2020-01-01',
388 433
       endDate: '2030-12-31',
@@ -490,7 +535,7 @@ export default {
490 535
             this.formData.securityLocation = locationResult.current?.value;
491 536
           }
492 537
 
493
-  
538
+
494 539
 
495 540
 
496 541
         } else {
@@ -899,7 +944,14 @@ export default {
899 944
           }
900 945
         })
901 946
 
902
-
947
+        // 处理powerOnInstruction字段,确保为字符串类型
948
+        if (detailData.powerOnInstruction != null) {
949
+          this.formData.powerOnInstruction = String(detailData.powerOnInstruction);
950
+          this.formData.powerOnInstructionText = detailData.powerOnInstructionText || (detailData.powerOnInstruction == 1 ? '非指令' : '指令');
951
+        } else {
952
+          this.formData.powerOnInstruction = '0';
953
+          this.formData.powerOnInstructionText = '指令';
954
+        }
903 955
       })
904 956
 
905 957
       console.log('表单数据已回填:', this.formData);
@@ -1190,12 +1242,61 @@ export default {
1190 1242
         this.formData.checkMethodText = '';
1191 1243
         return
1192 1244
       }
1193
-
1245
+      // 如果切换了岗位,重置开机指令相关字段
1246
+      if (this.formData.checkMethodText !== text) {
1247
+        this.formData.powerOnInstruction = '';
1248
+        this.formData.powerOnInstructionText = '';
1249
+        this.formData.xrayOperatorId = '';
1250
+        this.formData.xrayOperatorName = '';
1251
+      }
1194 1252
       this.formData.checkMethod = selectedItem?.postCode || text;
1195 1253
       this.formData.checkMethodText = selectedItem?.postName || selectedItem?.label || selectedItem?.text || text;
1254
+      // 如果是开箱(包)检查岗位,加载X光开机员列表
1255
+      if (text === '开箱(包)检查岗位') {
1256
+        this.loadXrayOperators();
1257
+      }
1258
+    },
1259
+
1260
+    // 开机指令变化
1261
+    onpowerOnInstructionChange(e) {
1262
+      const selectedValue = e.detail.value;
1263
+
1264
+      this.formData.powerOnInstruction = selectedValue;
1265
+      this.formData.powerOnInstructionText = selectedValue === '1' ? '非指令' : '指令';
1266
+      this.formData.xrayOperatorId = '';
1267
+      this.formData.xrayOperatorName = '';
1268
+
1269
+      // 如果选择了指令,清空X光开机员
1270
+      if (this.formData.powerOnInstruction === '0') {
1271
+        this.loadXrayOperators();
1272
+      }
1196 1273
     },
1197 1274
 
1275
+    // 加载X光开机员列表
1276
+    async loadXrayOperators() {
1277
+      try {
1278
+        // 使用现有的用户列表接口,可以根据需要调整参数
1279
+        const { listAllUser } = await import('@/api/system/user.js');
1280
+        const res = await listAllUser();
1281
+        if (res && res.data) {
1282
+          this.xrayOperatorOptions = res.data.map(item => ({
1283
+            ...item,
1284
+            nickName: `${item.nickName}(${item.userName})`,
1285
+          })) || [];
1286
+        }
1287
+      } catch (error) {
1288
+        console.error('加载X光开机员列表失败:', error);
1289
+      }
1290
+    },
1198 1291
 
1292
+    // X光开机员选择
1293
+    handleXrayOperatorSelect(value) {
1294
+      const selectedUser = this.xrayOperatorOptions.find(user => user.userId === value);
1295
+      if (selectedUser) {
1296
+        this.formData.xrayOperatorId = selectedUser.userId;
1297
+        this.formData.xrayOperatorName = selectedUser.nickName;
1298
+      }
1299
+    },
1199 1300
 
1200 1301
     // 查获班组变化
1201 1302
     onTeamChange(e) {

+ 22 - 23
src/pages/workProfile/components/organization-support.vue

@@ -132,12 +132,12 @@ export default {
132 132
 
133 133
             // 获取availablePositions数据,如果没有数据则使用默认数据
134 134
             let qualificationLevel = this.moduleMetrics.system && this.moduleMetrics.system.qualificationLevelStats || []
135
-            let qualificationLevelArr = qualificationLevel.filter(item => item.levelName)
135
+            //let qualificationLevelArr = qualificationLevel.filter(item => item.levelName)
136 136
 
137 137
             // 转换数据格式用于环形图
138
-            const chartData = qualificationLevelArr.map((position, index) => ({
138
+            const chartData = qualificationLevel.map((position, index) => ({
139 139
                 value: position.count, // 使用索引+1作为值,确保每个岗位都有值
140
-                name: qualificationDict.find(item => item.value === position.levelName)?.label || `资质${index + 1}`
140
+                name: position.levelName
141 141
             }))
142 142
 
143 143
 
@@ -145,7 +145,7 @@ export default {
145 145
             const option = {
146 146
                 tooltip: {
147 147
                     trigger: 'item',
148
-                    formatter: function(params) {
148
+                    formatter: function (params) {
149 149
                         return `${params.name}: ${params.value}`;
150 150
                     }
151 151
                 },
@@ -166,7 +166,7 @@ export default {
166 166
                     radius: ['40%', '70%'],
167 167
                     center: ['45%', '50%'],
168 168
                     avoidLabelOverlap: false,
169
-                    
169
+
170 170
                     label: {
171 171
                         show: true,
172 172
                         formatter: '{b}: {c}'
@@ -269,28 +269,29 @@ export default {
269 269
 
270 270
 <style lang="scss" scoped>
271 271
 .content-item {
272
-  display: flex;
273
-  justify-content: space-between;
274
-  align-items: center;
275
-  margin-bottom: 16rpx;
276
-
277
-  &:last-child {
278
-    margin-bottom: 0;
279
-  }
272
+    display: flex;
273
+    justify-content: space-between;
274
+    align-items: center;
275
+    margin-bottom: 16rpx;
276
+
277
+    &:last-child {
278
+        margin-bottom: 0;
279
+    }
280 280
 }
281 281
 
282 282
 .item-label {
283
-  font-size: 28rpx;
284
-  color: #333333;
285
-  font-weight: 500;
286
-  min-width: 120rpx;
283
+    font-size: 28rpx;
284
+    color: #333333;
285
+    font-weight: 500;
286
+    min-width: 120rpx;
287 287
 }
288 288
 
289 289
 .item-value {
290
-  font-size: 28rpx;
291
-  color: #999999;
292
-  font-weight: 500;
290
+    font-size: 28rpx;
291
+    color: #999999;
292
+    font-weight: 500;
293 293
 }
294
+
294 295
 .detail-card {
295 296
 
296 297
     padding: 10rpx 30rpx;
@@ -303,9 +304,7 @@ export default {
303 304
         margin-bottom: 24rpx;
304 305
     }
305 306
 
306
-    .text-layout {
307
-       
308
-    }
307
+    .text-layout {}
309 308
 
310 309
     .chart-section {
311 310
         width: 100%;