From 20e32587ecbab27e4436f2f64a15faa3c89e4f41 Mon Sep 17 00:00:00 2001
From: pyt <626651354@qq.com>
Date: 星期二, 20 五月 2025 21:39:59 +0800
Subject: [PATCH] Merge branch 'master' of http://120.76.84.145:10101/gitblit/r/H5/threeSide

---
 management/src/pages/setting/user/index.jsx                             |  181 ++-
 H5/uni_modules/mumu-recorder/package.json                               |   87 ++
 management/src/pages/appeal-management/service.js                       |   16 
 H5/uni_modules/mumu-recorder/readme.md                                  |  117 ++
 H5/components/voiceInputPopup.vue                                       |  368 ++++++++
 management/src/pages/setting/role/components/addAndEdit.jsx             |    8 
 management/src/pages/logManagement/service.js                           |   15 
 management/src/requestErrorConfig.ts                                    |    2 
 management/src/pages/setting/user/index.less                            |    5 
 management/src/pages/appeal-management/statistics/service.js            |   15 
 H5/pages/supervision/service.js                                         |   22 
 management/src/pages/setting/role/index.jsx                             |    2 
 H5/uni_modules/mumu-recorder/components/mumu-recorder/mumu-recorder.vue |  113 ++
 management/src/pages/appeal-management/statistics/index.jsx             |   42 
 H5/pages/supervision/supervision.vue                                    |   66 
 management/src/pages/party/manage/index.jsx                             |  188 ++-
 H5/package.json                                                         |    5 
 H5/pages/supervision/supervision-progress.vue                           |   24 
 H5/pages/work-detail/work-detail.vue                                    |   20 
 H5/utils/request.js                                                     |    6 
 management/src/pages/logManagement/index.jsx                            |   66 
 management/src/pages/setting/user/components/addAndEdit.jsx             |  699 +++++++--------
 management/src/pages/setting/user/service.js                            |   10 
 H5/pages/add-progress/index.vue                                         |    2 
 H5/uni_modules/mumu-recorder/changelog.md                               |    4 
 management/src/pages/appeal-management/detail.jsx                       |  235 +++++
 H5/manifest.json                                                        |  171 ++-
 H5/pages/supervision/edit-supervision-progress.vue                      |   13 
 management/config/routes.ts                                             |    2 
 H5/pages/Appeal/Appeal.vue                                              |   72 +
 30 files changed, 1,774 insertions(+), 802 deletions(-)

diff --git a/H5/components/voiceInputPopup.vue b/H5/components/voiceInputPopup.vue
index 4737331..b0393ee 100644
--- a/H5/components/voiceInputPopup.vue
+++ b/H5/components/voiceInputPopup.vue
@@ -1,25 +1,32 @@
 <template>
-  <u-popup :show="show" mode="bottom" :closeOnClickOverlay="false" @close="closePopup" zIndex="10071">
+  <u-popup :show="show" mode="bottom" :closeOnClickOverlay="false" @close="closePopup" :zIndex="9999" :overlay="true"
+    :safeAreaInsetBottom="true">
     <view class="voice-popup">
       <view class="header">
         <text class="pl-30">语音输入</text>
         <image src="/static/Appeal/close.png" class="w-34 h-34 mr-30" mode="" @click="closePopup"></image>
       </view>
       <view class="record-anim">
-        <image src="/static/Appeal/step.png" class="w-153 h-119" mode=""  @click="onPlay"></image>
+        <image src="/static/Appeal/step.png" class="w-153 h-119" mode=""></image>
       </view>
       <view class="timer">{{ time }}</view>
       <view class="btns">
-        <image src="/static/Appeal/start.png" class="w-153 h-153 mr-14" mode=""  @click="onPlay"></image>
-        <image src="/static/Appeal/stop.png" class="w-153 h-153 mr-14" mode="" @click="onPause"></image>
+        <image :src="getRecordButtonSrc" class="w-153 h-153 mr-14" mode="" @click="handlerOnCahnger"></image>
         <image src="/static/Appeal/cancel.png" class="w-153 h-153 mr-14" mode="" @click="onStop"></image>
       </view>
     </view>
+    <mumu-recorder ref="mumuRecorder" @success="handlerSuccess" @error="handleError"></mumu-recorder>
   </u-popup>
 </template>
 
 <script>
+import { getSignature } from '../pages/index/service'
+import MumuRecorder from '@/uni_modules/mumu-recorder/components/mumu-recorder/mumu-recorder.vue'
 export default {
+  name: 'VoiceInputPopup',
+  components: {
+    MumuRecorder
+  },
   props: {
     show: {
       type: Boolean,
@@ -29,16 +36,317 @@
   data() {
     return {
       time: '00:00:00',
-      barHeights: [20, 30, 40, 30, 20], // 可做动画
+      isRecording: false,
+      isPaused: false,
+      tempFilePath: '',
+      timer: null,
+      seconds: 0,
+      minutes: 0,
+      hours: 0,
+      recordSegments: [], // 存储录音片段
+      status: false,
+      recorder: null,
+      currentSegment: null // 当前录音片段
     }
   },
+  computed: {
+    getRecordButtonSrc() {
+      if (this.isPaused) {
+        return '/static/Appeal/start.png'
+      }
+      return this.isRecording ? '/static/Appeal/stop.png' : '/static/Appeal/start.png'
+    }
+  },
+  mounted() {
+  },
   methods: {
-    closePopup() {
-      this.$emit('update:show', false)
+    handlerSave() {
+      let tag = document.createElement('a')
+      tag.href = this.recorder.localUrl
+      tag.download = '录音'
+      tag.click()
     },
-    onPlay() {},
-    onPause() {},
-    onStop() {},
+    handlerOnCahnger() {
+      if (!this.isRecording && !this.isPaused) {
+        // 开始新的录音
+        this.startNewRecording()
+      } else if (this.isRecording) {
+        // 暂停当前录音
+        this.pauseRecording()
+      } else if (this.isPaused) {
+        // 继续录音
+        this.resumeRecording()
+      }
+    },
+    startNewRecording() {
+      console.log('开始新的录音')
+      this.isRecording = true
+      this.isPaused = false
+      this.startTimer()
+      this.$refs.mumuRecorder.start()
+    },
+    pauseRecording() {
+      console.log('暂停录音')
+      this.isRecording = false
+      this.isPaused = true
+      this.stopTimer()
+      this.$refs.mumuRecorder.stop()
+    },
+    resumeRecording() {
+      console.log('继续录音')
+      this.isRecording = true
+      this.isPaused = false
+      this.startTimer()
+      this.$refs.mumuRecorder.start()
+    },
+    handlerSuccess(res) {
+      console.log('录音成功回调:', res)
+      this.recorder = res
+      // 保存当前录音片段
+      if (res.localUrl) {
+        console.log('当前录音片段URL:', res.localUrl)
+        console.log('当前已存储的片段数:', this.recordSegments.length)
+        console.log('当前片段:', this.currentSegment)
+        
+        // 只有当当前片段与上一个不同时才添加
+        if (!this.currentSegment || this.currentSegment.url !== res.localUrl) {
+          console.log('添加新的录音片段')
+          this.currentSegment = {
+            url: res.localUrl,
+            data: res.data,
+            duration: this.seconds + this.minutes * 60 + this.hours * 3600
+          }
+          this.recordSegments.push(this.currentSegment)
+          console.log('更新后的片段列表:', this.recordSegments)
+        } else {
+          console.log('跳过重复的录音片段')
+        }
+      }
+    },
+    handlerError(code) {
+      switch (code) {
+        case '101':
+          uni.showModal({
+            content: '当前浏览器版本较低,请更换浏览器使用,推荐在微信中打开。'
+          })
+          break;
+        case '201':
+          uni.showModal({
+            content: '麦克风权限被拒绝,请刷新页面后授权麦克风权限。'
+          })
+          break
+        default:
+          uni.showModal({
+            content: '未知错误,请刷新页面重试'
+          })
+          break
+      }
+    },
+    closePopup() {
+      // 清空录音片段
+      this.recordSegments = []
+      this.currentSegment = null
+      // 重置计时器
+      this.seconds = 0
+      this.minutes = 0
+      this.hours = 0
+      this.updateTimeDisplay()
+      // 关闭弹窗
+      this.$emit('close')
+    },
+    startTimer() {
+      this.stopTimer();
+      this.timer = setInterval(() => {
+        this.seconds++;
+        if (this.seconds >= 60) {
+          this.seconds = 0;
+          this.minutes++;
+          if (this.minutes >= 60) {
+            this.minutes = 0;
+            this.hours++;
+          }
+        }
+        this.updateTimeDisplay();
+      }, 1000);
+    },
+    stopTimer() {
+      if (this.timer) {
+        clearInterval(this.timer);
+        this.timer = null;
+      }
+    },
+    updateTimeDisplay() {
+      this.time = `${String(this.hours).padStart(2, '0')}:${String(this.minutes).padStart(2, '0')}:${String(this.seconds).padStart(2, '0')}`;
+    },
+    // 合并音频文件
+    async mergeAudioFiles(audioUrls) {
+      try {
+        const audioContext = new (window.AudioContext || window.webkitAudioContext)();
+        const audioBuffers = [];
+        
+        // 加载所有音频文件
+        for (const url of audioUrls) {
+          const response = await fetch(url);
+          const arrayBuffer = await response.arrayBuffer();
+          const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
+          audioBuffers.push(audioBuffer);
+        }
+
+        // 计算总时长
+        const totalLength = audioBuffers.reduce((acc, buffer) => acc + buffer.length, 0);
+        
+        // 创建新的音频缓冲区
+        const mergedBuffer = audioContext.createBuffer(
+          audioBuffers[0].numberOfChannels,
+          totalLength,
+          audioBuffers[0].sampleRate
+        );
+
+        // 合并音频数据
+        let offset = 0;
+        for (const buffer of audioBuffers) {
+          for (let channel = 0; channel < buffer.numberOfChannels; channel++) {
+            const channelData = buffer.getChannelData(channel);
+            mergedBuffer.copyToChannel(channelData, channel, offset);
+          }
+          offset += buffer.length;
+        }
+
+        // 将合并后的音频转换为 Blob
+        const wavBlob = await this.audioBufferToWav(mergedBuffer);
+        const mergedUrl = URL.createObjectURL(wavBlob);
+        
+        return mergedUrl;
+      } catch (error) {
+        console.error('合并音频失败:', error);
+        throw error;
+      }
+    },
+
+    // 将 AudioBuffer 转换为 WAV 格式
+    audioBufferToWav(buffer) {
+      const numOfChan = buffer.numberOfChannels;
+      const length = buffer.length * numOfChan * 2;
+      const buffer2 = new ArrayBuffer(44 + length);
+      const view = new DataView(buffer2);
+      const channels = [];
+      let sample;
+      let offset = 0;
+      let pos = 0;
+
+      // 写入 WAV 文件头
+      setUint32(0x46464952);                         // "RIFF"
+      setUint32(36 + length);                        // 文件长度
+      setUint32(0x45564157);                         // "WAVE"
+      setUint32(0x20746d66);                         // "fmt " chunk
+      setUint32(16);                                 // 长度 = 16
+      setUint16(1);                                  // PCM (uncompressed)
+      setUint16(numOfChan);
+      setUint32(buffer.sampleRate);
+      setUint32(buffer.sampleRate * 2 * numOfChan);  // avg. bytes/sec
+      setUint16(numOfChan * 2);                      // block-align
+      setUint16(16);                                 // 16-bit
+      setUint32(0x61746164);                         // "data" - chunk
+      setUint32(length);                             // chunk length
+
+      // 写入音频数据
+      for (let i = 0; i < buffer.numberOfChannels; i++) {
+        channels.push(buffer.getChannelData(i));
+      }
+
+      while (pos < buffer.length) {
+        for (let i = 0; i < numOfChan; i++) {
+          sample = Math.max(-1, Math.min(1, channels[i][pos]));
+          sample = (0.5 + sample < 0 ? sample * 32768 : sample * 32767) | 0;
+          view.setInt16(44 + offset, sample, true);
+          offset += 2;
+        }
+        pos++;
+      }
+
+      return new Blob([buffer2], { type: 'audio/wav' });
+
+      function setUint16(data) {
+        view.setUint16(pos, data, true);
+        pos += 2;
+      }
+
+      function setUint32(data) {
+        view.setUint32(pos, data, true);
+        pos += 4;
+      }
+    },
+
+    // 修改 onStop 方法
+    async onStop() {
+      console.log('停止录音')
+      // 如果正在录音,先停止当前录音
+      if (this.isRecording) {
+        this.$refs.mumuRecorder.stop()
+      }
+      
+      // 停止计时
+      this.stopTimer()
+      
+      // 重置状态
+      this.isRecording = false
+      this.isPaused = false
+      this.currentSegment = null
+      
+      // 处理录音片段
+      if (this.recordSegments.length > 0) {
+        try {
+          uni.showLoading({
+            title: '正在处理音频...'
+          })
+          
+          // 获取所有录音片段的URL
+          const audioUrls = this.recordSegments.map(segment => segment.url)
+          console.log('准备合并的音频片段列表:', audioUrls)
+          console.log('音频片段数量:', audioUrls.length)
+          
+          // 合并音频文件
+          const mergedUrl = await this.mergeAudioFiles(audioUrls)
+          
+          // 创建合并后的音频数据对象
+          const mergedAudioData = {
+            url: this.recordSegments[this.recordSegments.length - 1].url,
+            data: this.recordSegments[this.recordSegments.length - 1].data,
+            duration: this.seconds + this.minutes * 60 + this.hours * 3600
+          }
+          
+          uni.showToast({
+            title: '录制成功',
+            icon: 'success',
+            duration: 2000
+          })
+          
+          setTimeout(() => {
+            this.$emit('submit', mergedAudioData)
+          }, 2000)
+          
+          uni.hideLoading()
+          this.closePopup()
+        } catch (error) {
+          console.error('音频合并失败:', error)
+          uni.hideLoading()
+          uni.showToast({
+            title: '音频合并失败,请重试',
+            icon: 'none',
+            duration: 2000
+          })
+        }
+      } else {
+        uni.showToast({
+          title: '未检测到录音文件',
+          icon: 'none',
+          duration: 2000
+        })
+      }
+    }
+  },
+  beforeDestroy() {
+    this.stopTimer();
   }
 }
 </script>
@@ -48,6 +356,9 @@
   background: #fff;
   border-radius: 24rpx 24rpx 0 0;
   padding: 40rpx 0 30rpx 0;
+  position: relative;
+  z-index: 9999;
+
   .header {
     display: flex;
     justify-content: center;
@@ -56,25 +367,30 @@
     font-size: 32rpx;
     font-weight: bold;
     margin-bottom: 80rpx;
+
     text {
       flex: 1;
       text-align: center;
     }
+
     .u-icon {
       position: absolute;
       right: 30rpx;
       top: 0;
     }
   }
+
   .record-anim {
     display: flex;
     justify-content: center;
     align-items: center;
     margin-bottom: 57rpx;
+
     .bars {
       display: flex;
       align-items: flex-end;
       height: 60rpx;
+
       .bar {
         width: 10rpx;
         margin: 0 4rpx;
@@ -84,26 +400,34 @@
       }
     }
   }
+
   .timer {
     text-align: center;
     font-size: 28rpx;
     color: #888;
-    // margin-bottom: 30rpx;
   }
+
   .btns {
     display: flex;
     justify-content: space-around;
     align-items: center;
-    padding: 40rpx 67rpx 76rpx 67rpx;
-    // .u-button {
-    //   width: 100rpx;
-    //   height: 100rpx;
-    //   border-radius: 50%;
-    //   display: flex;
-    //   justify-content: center;
-    //   align-items: center;
-    //   margin: 0 10rpx;
-    // }
+    padding: 40rpx 67rpx 6rpx 67rpx;
   }
 }
-</style> 
\ No newline at end of file
+
+::v-deep .uni-toast {
+  z-index: 10099 !important;
+}
+
+.uni-sample-toast {
+  z-index: 10099 !important;
+}
+
+::v-deep .uni-toast .uni-sample-toast {
+  z-index: 10099 !important;
+}
+
+/deep/ .u-transition.u-fade-enter-to.u-fade-enter-active {
+  z-index: 997 !important;
+}
+</style>
\ No newline at end of file
diff --git a/H5/manifest.json b/H5/manifest.json
index 1d6f98c..ec80cdc 100644
--- a/H5/manifest.json
+++ b/H5/manifest.json
@@ -1,85 +1,88 @@
 {
-    "name" : "“三个身边”群众工作机制",
-    "appid" : "__UNI__DB035F5",
-    "description" : "",
-    "versionName" : "1.0.0",
-    "versionCode" : "100",
-    "transformPx" : false,
-    /* 5+App特有相关 */
-    "app-plus" : {
-        "usingComponents" : true,
-        "nvueStyleCompiler" : "uni-app",
-        "compilerVersion" : 3,
-        "splashscreen" : {
-            "alwaysShowBeforeRender" : true,
-            "waiting" : true,
-            "autoclose" : true,
-            "delay" : 0
-        },
-        /* 模块配置 */
-        "modules" : {},
-        /* 应用发布信息 */
-        "distribute" : {
-            /* android打包配置 */
-            "android" : {
-                "permissions" : [
-                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
-                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
-                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
-                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
-                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
-                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
-                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
-                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
-                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
-                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
-                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
-                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
-                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
-                    "<uses-feature android:name=\"android.hardware.camera\"/>",
-                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
-                ]
-            },
-            /* ios打包配置 */
-            "ios" : {},
-            /* SDK配置 */
-            "sdkConfigs" : {}
-        }
-    },
-    "sassImplementationName" : "node-sass",
-    /* 快应用特有相关 */
-    "quickapp" : {},
-    /* 小程序特有相关 */
-    "mp-weixin" : {
-        "appid" : "",
-        "setting" : {
-            "urlCheck" : false
-        },
-        "usingComponents" : true
-    },
-    "mp-alipay" : {
-        "usingComponents" : true
-    },
-    "mp-baidu" : {
-        "usingComponents" : true
-    },
-    "mp-toutiao" : {
-        "usingComponents" : true
-    },
-    "uniStatistics" : {
-        "enable" : false
-    },
-    "vueVersion" : "2",
-    "h5" : {
-        "template" : "index.html",
-        "title" : "“三个身边”群众工作机制",
-        "optimization" : {
-            "treeShaking" : {
-                "enable" : false
-            }
-        },
-        "router" : {
-            "base" : "./"
-        }
-    }
-}
+	"name": "“三个身边”群众工作机制",
+	"appid": "__UNI__DB035F5",
+	"description": "",
+	"versionName": "1.0.0",
+	"versionCode": "100",
+	"transformPx": false,
+	/* 5+App特有相关 */
+	"app-plus": {
+		"usingComponents": true,
+		"nvueStyleCompiler": "uni-app",
+		"compilerVersion": 3,
+		"splashscreen": {
+			"alwaysShowBeforeRender": true,
+			"waiting": true,
+			"autoclose": true,
+			"delay": 0
+		},
+		/* 模块配置 */
+		"modules": {},
+		/* 应用发布信息 */
+		"distribute": {
+			/* android打包配置 */
+			"android": {
+				"permissions": [
+					"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+					"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+					"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+					"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+					"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+					"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+					"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+					"<uses-permission android:name=\"android.permission.CAMERA\"/>",
+					"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+					"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+					"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+					"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+					"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+					"<uses-feature android:name=\"android.hardware.camera\"/>",
+					"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+				]
+			},
+			/* ios打包配置 */
+			"ios": {},
+			/* SDK配置 */
+			"sdkConfigs": {}
+		}
+	},
+	"sassImplementationName": "node-sass",
+	/* 快应用特有相关 */
+	"quickapp": {},
+	/* 小程序特有相关 */
+	"mp-weixin": {
+		"appid": "",
+		"setting": {
+			"urlCheck": false
+		},
+		"usingComponents": true
+	},
+	"mp-alipay": {
+		"usingComponents": true
+	},
+	"mp-baidu": {
+		"usingComponents": true
+	},
+	"mp-toutiao": {
+		"usingComponents": true
+	},
+	"uniStatistics": {
+		"enable": false
+	},
+	"vueVersion": "2",
+	"h5": {
+		"template": "index.html",
+		"title": "“三个身边”群众工作机制",
+		"optimization": {
+			"treeShaking": {
+				"enable": false
+			}
+		},
+		"devServer": {
+			"https": true
+		},
+		"router": {
+			"base": "./"
+		}
+	}
+}
\ No newline at end of file
diff --git a/H5/package.json b/H5/package.json
index 13ca88e..997f0f6 100644
--- a/H5/package.json
+++ b/H5/package.json
@@ -1,5 +1,10 @@
 {
   "dependencies": {
     "echarts": "^5.6.0"
+  },
+  "permission": {
+    "scope.record": {
+      "desc": "录音功能需要使用您的录音权限"
+    }
   }
 }
diff --git a/H5/pages/Appeal/Appeal.vue b/H5/pages/Appeal/Appeal.vue
index 9275f7f..dc38ba7 100644
--- a/H5/pages/Appeal/Appeal.vue
+++ b/H5/pages/Appeal/Appeal.vue
@@ -62,7 +62,7 @@
 				<view class="flex a-center j-between">
 					<text class="w-108 fs-27 font-bold mr-85">问题描述</text>
 					<view class="flex a-center" @click="voiceInput">
-
+						<image src="/static/Appeal/yuyin.png" class="w-30 h-30 mr-11" mode=""></image>
 						<text class="fs-23 red">语音输入</text>
 					</view>
 				</view>
@@ -154,9 +154,9 @@
 import config from '@/config/index.js'
 import voiceInputPopup from '@/components/voiceInputPopup.vue'
 import {
-		mapActions,
-		mapState
-	} from "vuex";
+	mapActions,
+	mapState
+} from "vuex";
 
 export default {
 	components: {
@@ -178,14 +178,12 @@
 			detailedAddress: '',
 			descriptionTitle: '',
 			descriptionContent: '',
-			videoContent: [
-				{ url: 'xxx1', playing: false },
-				{ url: 'xxx2', playing: false }
-			],
+			videoContent: [],
 			latitude: '',
 			longitude: '',
 			images: [],
 			videos: [],
+			voiceFile: '',//语音文件多个逗号拼接
 			userInfo: uni.getStorageSync('userInfo'), //个人信息
 			voiceInputShow: false,
 		};
@@ -202,7 +200,7 @@
 		this.getproblem()
 		this.time = dayjs().format('YYYY-MM-DD')
 	},
-	
+
 	methods: {
 		...mapActions(["playRecording", "pausePlaying"]),
 		onPlayRecording(index) {
@@ -224,7 +222,8 @@
 			this.voiceInputShow = false;
 		},
 		submitVoiceInput(e) {
-			this.videoContent.push(e);
+			console.log('eeeeeeeeeeeeeeeeeee', e)
+			this.videoContent.push({ url: e.url, data: e.data, playing: false });
 			this.voiceInputShow = false;
 		},
 		previewImage(index) {
@@ -262,7 +261,55 @@
 				})]
 			}))
 		},
-		submit(type) {
+		async submit(type) {
+			if (this.videoContent.length > 0) {
+				uni.showLoading({
+					title: '正在上传语音文件...'
+				});
+
+				const uploadPromises = this.videoContent.map(item => {
+					return new Promise((resolve, reject) => {
+						console.log('item.data', item.data)
+						uni.uploadFile({
+							url: config.imageUrl,
+							file: item.data,
+							name: 'file',
+							// fileType: 'audio/mpeg',
+							// filePath: item.url,
+							// name: 'file',
+							header: {
+								'Content-Type': 'multipart/form-data',
+								'Authorization': uni.getStorageSync('token')
+							},
+							success: (uploadFileRes) => {
+								const response = JSON.parse(uploadFileRes.data);
+								if (response.code === 200) {
+									resolve(response.data);
+								} else {
+									reject(new Error('上传失败'));
+								}
+							},
+							fail: (error) => {
+								reject(error);
+							}
+						});
+					});
+				});
+
+				try {
+					const uploadedUrls = await Promise.all(uploadPromises);
+					this.voiceFile = uploadedUrls.join(',');
+					console.log('this.voiceFile', this.voiceFile)
+					uni.hideLoading();
+				} catch (error) {
+					uni.hideLoading();
+					uni.showToast({
+						title: '语音文件上传失败',
+						icon: 'error'
+					});
+					return;
+				}
+			}
 			const preciseRegex = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/;
 			if (!this.time) {
 				uni.showToast({
@@ -308,6 +355,7 @@
 				})
 				return
 			}
+
 			const data = {
 				time: this.time,
 				problemType: this.problemType,
@@ -320,6 +368,7 @@
 				descriptionContent: this.descriptionContent,
 				images: this.images.join(','),
 				videos: this.videos.join(','),
+				voiceFile: this.voiceFile,
 			}
 			// 问题上报
 			if (type == 1) {
@@ -382,6 +431,7 @@
 				success: (res) => {
 
 					uni.showLoading()
+					console.log('res.tempFilePaths[0]', res.tempFilePaths[0])
 					uni.uploadFile({
 						url: config.imageUrl,
 						filePath: res.tempFilePaths[0],
diff --git a/H5/pages/add-progress/index.vue b/H5/pages/add-progress/index.vue
index a94cd59..58bc82d 100644
--- a/H5/pages/add-progress/index.vue
+++ b/H5/pages/add-progress/index.vue
@@ -236,7 +236,7 @@
 								timeout: 1000 * 45,
 								name: 'file',
 								header: {
-									Authorization: cuni.getStorageSync('token')
+									Authorization: uni.getStorageSync('token')
 								},
 								success: (res) => {
 									if (JSON.parse(res.data).code == 200) {
diff --git a/H5/pages/supervision/edit-supervision-progress.vue b/H5/pages/supervision/edit-supervision-progress.vue
index 4cc0ced..18a6bac 100644
--- a/H5/pages/supervision/edit-supervision-progress.vue
+++ b/H5/pages/supervision/edit-supervision-progress.vue
@@ -74,7 +74,7 @@
 			</view>
 		</view>
 		<view @click.stop="submit" class="mt-38 fs-35 lh-96 br-48 txt-center font-bold bgcolor6 color4 fixed"
-			style="width: calc(100% - 62rpx);bottom: calc(env(safe-area-inset-bottom) + 10rpx);">确认添加</view>
+			style="width: calc(100% - 62rpx);bottom: calc(env(safe-area-inset-bottom) + 10rpx);">确认</view>
 		<view class="btn-box"></view>
 		<view class="safe-box"></view>
 	</view>
@@ -82,7 +82,7 @@
 
 <script>
 	import {
-		saveProcess,
+		editProgress,
 		getComplaintDetail
 	} from './service'
 	import config from '@/config/index.js'
@@ -97,10 +97,16 @@
 				video: [],
 				againCklicFlag: true,
 				rulsFlag: false,
+				progressId: ''
 			}
 		},
 		onLoad(params) {
 			this.complaintId = params.id
+			this.describe = JSON.parse(params.data).describe
+			this.progressId = JSON.parse(params.data).id
+			this.video = JSON.parse(params.data).video.split(',')
+			this.imgUrls = JSON.parse(params.data).imgUrl.split(',')
+			this.localImageUrls = JSON.parse(params.data).imgUrl.split(',')
 			getComplaintDetail({
 				id: params.id
 			}).then(res => {
@@ -122,12 +128,13 @@
 					})
 				}
 				let obj = {
+					id: this.progressId,
 					complaintId: this.complaintId,
 					describe: this.describe,
 					imgUrl: this.imgUrls.join(','),
 					video: this.video.join(',')
 				}
-				saveProcess(obj).then(res => {
+				editProgress(obj).then(res => {
 					if (res.code == 200) {
 						uni.showToast({
 							title: '提交成功',
diff --git a/H5/pages/supervision/service.js b/H5/pages/supervision/service.js
index b9cb14f..bea37fd 100644
--- a/H5/pages/supervision/service.js
+++ b/H5/pages/supervision/service.js
@@ -1,11 +1,25 @@
 import request from '@/utils/request.js'
 
-// 工单列表
-export const getList = (params) => {
-	return request.post(`/api/huacheng-sangeshenbian/applet/complaint/list`, params)
+// 处理记录
+export const getProcessingList = (data) => {
+	return request.post(`/api/huacheng-sangeshenbian/applet/supervise/processing-record-page`, data)
+}
+// 问题驳回池
+export const getRejectList = (data) => {
+	return request.post(`/api/huacheng-sangeshenbian/applet/supervise/reject-record-page`, data)
 }
 
-// 工单详情
+// 详情
 export const getComplaintDetail = (params) => {
 	return request.get('/api/huacheng-sangeshenbian/applet/complaint/detail', params)
+}
+
+// 编辑办理进度
+export const editProgress = (params) => {
+	return request.put('/api/huacheng-sangeshenbian/applet/complaint-progress/edit', params)
+}
+
+// 删除办理进度
+export const delProgress = (id) => {
+	return request.delete(`/api/huacheng-sangeshenbian/applet/complaint-progress/${id}`)
 }
\ No newline at end of file
diff --git a/H5/pages/supervision/supervision-progress.vue b/H5/pages/supervision/supervision-progress.vue
index b0a7520..fc44a39 100644
--- a/H5/pages/supervision/supervision-progress.vue
+++ b/H5/pages/supervision/supervision-progress.vue
@@ -99,7 +99,8 @@
 <script>
 	import dayjs from '../../uni_modules/uview-ui/libs/util/dayjs'
 	import {
-		getComplaintDetail
+		getComplaintDetail,
+		delProgress
 	} from './service'
 	export default {
 		data() {
@@ -129,7 +130,6 @@
 			getComplaintDetail({
 				id: this.id
 			}).then(res => {
-
 				this.info = {
 					...res.data
 				}
@@ -137,7 +137,23 @@
 		},
 		methods: {
 			deleteProgress() {
-
+				delProgress(this.row.id).then(res => {
+					uni.showToast({
+						icon: 'none',
+						mask: true,
+						title: '删除成功'
+					})
+					this.$refs.customPopup.show = false
+					setTimeout(() => {
+						getComplaintDetail({
+							id: this.id
+						}).then(res => {
+							this.info = {
+								...res.data
+							}
+						})
+					}, 1500)
+				})
 			},
 			toDelete(item) {
 				this.row = item
@@ -145,7 +161,7 @@
 			},
 			toEdit(item) {
 				uni.navigateTo({
-					url: `/pages/supervision/edit-supervision-progress?id=${this.id}`
+					url: `/pages/supervision/edit-supervision-progress?id=${this.id}&data=${JSON.stringify(item)}`
 				})
 			},
 			callPhone(phoneNumber) {
diff --git a/H5/pages/supervision/supervision.vue b/H5/pages/supervision/supervision.vue
index a55d20b..8e72eae 100644
--- a/H5/pages/supervision/supervision.vue
+++ b/H5/pages/supervision/supervision.vue
@@ -2,25 +2,23 @@
 	<view class="content">
 		<view class="bgColor2 shadow1 pb-19" style="position: sticky;top: 0;z-index: 999;">
 			<view class="h-96 flex a-center fs-27  j-between txt-center  font-w400 color1">
-				<view @click="changeType('1')" class="flex1 bgColor2 relative"
-					:class="searchParams.type == '1' && 'color2 font-bold'">
+				<view @click="changeType(1)" class="flex1 bgColor2 relative" :class="type == 1 && 'color2 font-bold'">
 					<view class="relative zIndex1000">
 						处理记录
 					</view>
-					<view v-if="searchParams.type == '1'" class="bgColor1"></view>
+					<view v-if="type == 1" class="bgColor1"></view>
 				</view>
-				<view @click="changeType('2')" class="flex1 bgColor2 relative"
-					:class="searchParams.type == '2' && 'color2 font-bold'">
+				<view @click="changeType(2)" class="flex1 bgColor2 relative" :class="type == 2 && 'color2 font-bold'">
 					<view class="relative zIndex1000">
 						问题驳回池
 					</view>
-					<view v-if="searchParams.type == '2'" class="bgColor1"></view>
+					<view v-if="type == 2" class="bgColor1"></view>
 				</view>
 			</view>
 			<view class="flex a-center j-between mx-27 pl-38 border2">
 				<view class="flex a-center flex1">
 					<image src="../../static/search.png" mode="widthFix" class="w-31 h-31 shrink0 mr-13" />
-					<input v-model="searchParams.searchStr" class="fs-27 flex1" placeholder="输入姓名、联系电话关键字搜索" />
+					<input v-model="searchParams.keyword" class="fs-27 flex1" placeholder="输入姓名、联系电话关键字搜索" />
 				</view>
 				<view @click="searchList" class="fs-23 lh-69 txt-center px-29 br-48 my-4 mx-4 bgcolor88">搜索</view>
 			</view>
@@ -101,18 +99,18 @@
 				<view class="mt-31 border1">
 					<view class="left"></view>
 					<view class="right"></view>
-					<view v-if="searchParams.type == '1'">
+					<view v-if="type == 1">
 						<view class="flex a-center j-between lh-38 mt-29 ml-38 mr-23 fs-27">
 							<view>添加办理进度数</view>
-							<view class="font-bold">10</view>
+							<view class="font-bold">{{item.progressCount}}</view>
 						</view>
 						<view class="flex a-center j-between lh-38 mt-29 ml-38 mr-23 fs-27">
 							<view>已下派次数</view>
-							<view class="font-bold">10</view>
+							<view class="font-bold">{{item.assignmentCount}}</view>
 						</view>
 						<view class="flex a-center j-between lh-38 mt-29 ml-38 mr-23 fs-27">
 							<view>已上报次数</view>
-							<view class="font-bold">10</view>
+							<view class="font-bold">{{item.reportCount}}</view>
 						</view>
 						<view class="flex a-center j-between lh-38 mt-29 ml-38 mr-23 fs-27">
 							<view>创建时间</view>
@@ -122,31 +120,32 @@
 					<view v-else>
 						<view class="flex a-center j-between lh-38 mt-29 ml-38 mr-23 fs-27">
 							<view>申请时间</view>
-							<view class="font-bold">2025-09-09 11:09:09</view>
+							<view class="font-bold">{{ item.applyTime | formatTime }}</view>
 						</view>
 						<view class="flex a-center j-between lh-38 mt-29 ml-38 mr-23 fs-27">
 							<view>申请人</view>
 							<view class="flex a-center">
-								<view class="font-bold">李雷 13987654321</view>
-								<image @click.stop="callPhone(item.contactNumber)" src="../../static/tell.png"
+								<view class="font-bold">{{item.reporter}} {{item.reporterPhone}}</view>
+								<image @click.stop="callPhone(item.reporterPhone)" src="../../static/tell.png"
 									class="w-58 h-58 shrink0 ml-19" />
 							</view>
 						</view>
 						<view class="flex a-center j-between lh-38 mt-29 ml-38 mr-23 fs-27">
 							<view>审批时间</view>
-							<view class="font-bold">2025-09-09 11:09:09</view>
+							<view class="font-bold">{{ item.auditTime | formatTime }}</view>
 						</view>
 						<view class="flex a-center j-between lh-38 mt-29 ml-38 mr-23 fs-27">
 							<view>审批人</view>
 							<view class="flex a-center">
-								<view class="font-bold">李雷 13987654321</view>
-								<image @click.stop="callPhone(item.contactNumber)" src="../../static/tell.png"
+								<view class="font-bold">{{item.auditorName}} {{item.auditorPhone}}</view>
+								<image @click.stop="callPhone(item.auditorPhone)" src="../../static/tell.png"
 									class="w-58 h-58 shrink0 ml-19" />
 							</view>
 						</view>
-						<view class="flex a-center j-between lh-38 mt-29 ml-38 mr-23 fs-27">
+						<view class="flex j-between lh-38 mt-29 ml-38 mr-23 fs-27">
 							<view class="shrink0">驳回理由</view>
-							<view style="max-width: 458rpx; text-align: right;font-weight: bold;">不同意当前申请不同意当前申请不同意当前申请
+							<view style="max-width: 458rpx; text-align: right;font-weight: bold;">
+								{{item.rejectReason}}
 							</view>
 						</view>
 					</view>
@@ -160,17 +159,17 @@
 <script>
 	import dayjs from '@/uni_modules/uview-ui/libs/util/dayjs.js'
 	import {
-		getList
+		getProcessingList,
+		getRejectList
 	} from './service.js'
 	export default {
 		data() {
 			return {
-				active: 1,
+				type: 1,
 				searchParams: {
 					pageNum: 1,
 					pageSize: 10,
-					type: '1',
-					searchStr: ''
+					keyword: ''
 				},
 				list: [],
 				status: 'loadMore',
@@ -185,7 +184,7 @@
 					'6': '上级驳回',
 					'7': '延期待审核',
 					'8': '已办结'
-				}
+				},
 			}
 		},
 		onReachBottom() {
@@ -220,6 +219,14 @@
 		},
 		methods: {
 			searchList() {
+				if (this.searchParams.keyword == '') {
+					uni.showToast({
+						title: '请输入关键字搜索',
+						icon: 'none',
+						mask: true
+					})
+					return
+				}
 				this.searchParams.pageNum = 1
 				this.fetchList(this.searchParams, (e) => {
 					this.list = e.records || []
@@ -242,24 +249,19 @@
 			},
 			fetchList(params, callback) {
 				if (this.status == 'loading') return
-				this.status = 'loading'
-				getList(params).then(res => {
+				this.status = 'loading';
+				[getProcessingList, getRejectList][this.type - 1](params).then(res => {
 					if (res.code == 200) {
-						res.data.records.map(item => {
-							if (item.images) {
-								item.images = item.images.split(',')
-							}
-						})
 						callback(res.data)
 					}
 				})
 			},
 			// 切换状态筛选
 			changeType(type) {
+				this.type = type
 				this.searchParams = {
 					pageNum: 1,
 					pageSize: 10,
-					type, //全部:不传,上报待审核:0,正在办理:1, 办结:2
 				}
 				this.fetchList(this.searchParams, (e) => {
 					this.list = e.records || []
diff --git a/H5/pages/work-detail/work-detail.vue b/H5/pages/work-detail/work-detail.vue
index f0d15bd..a3bdef8 100644
--- a/H5/pages/work-detail/work-detail.vue
+++ b/H5/pages/work-detail/work-detail.vue
@@ -165,9 +165,9 @@
 			<!-- 问题描述 -->
 			<view class="problem">
 				<view class="title">问题描述</view>
-				<view v-for="(item,index) in 2" :key="index"
+				<view v-for="(item,index) in getVoiceFile(orderInfo.voiceFile)" :key="index"
 					class="flex a-center j-between py-17 px-19 br-8 bgcolor1 mb-19">
-					<view class="fs-27 lh-38">语音名字</view>
+					<view class="fs-27 lh-38">语音名字{{(index + 1) | numToWords}}</view>
 					<image v-if="!playFlag" @click.stop="playRecording(item)" src="../../static/24gf-playCircle@2x.png"
 						class="w-27 h-27 shrink0" />
 					<image v-else @click.stop="pausePlaying" src="../../static/pausePlaying.png"
@@ -432,6 +432,18 @@
 			formatTime(val) {
 				if (!val) return ''
 				return dayjs(val).format('YYYY-MM-DD HH:mm:ss')
+			},
+			numToWords(val) {
+				const words = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
+				// 处理 0-10
+				if (val >= 0 && val <= 10) return words[val];
+				// 处理 11-99
+				if (val > 10 && val < 100) {
+					const ten = Math.floor(val / 10);
+					const unit = val % 10;
+					return `${ten > 1 ? words[ten] : ''}十${unit > 0 ? words[unit] : ''}`;
+				}
+				return val; // 超过99返回原数字
 			}
 		},
 		onShow() {
@@ -454,6 +466,10 @@
 		},
 		methods: {
 			...mapActions(["playRecording", "pausePlaying"]),
+			getVoiceFile(voiceFile) {
+				if (!voiceFile || voiceFile.length == 0) return []
+				return voiceFile.split(',')
+			},
 			callPhone(phoneNumber) {
 				uni.makePhoneCall({
 					phoneNumber
diff --git a/H5/uni_modules/mumu-recorder/changelog.md b/H5/uni_modules/mumu-recorder/changelog.md
new file mode 100644
index 0000000..eb2c332
--- /dev/null
+++ b/H5/uni_modules/mumu-recorder/changelog.md
@@ -0,0 +1,4 @@
+## 1.0.1(2022-06-11)
+修复苹果手机在微信中无法获取音频长度问题
+## 1.0.0(2022-06-10)
+版本上线
diff --git a/H5/uni_modules/mumu-recorder/components/mumu-recorder/mumu-recorder.vue b/H5/uni_modules/mumu-recorder/components/mumu-recorder/mumu-recorder.vue
new file mode 100644
index 0000000..b890c7d
--- /dev/null
+++ b/H5/uni_modules/mumu-recorder/components/mumu-recorder/mumu-recorder.vue
@@ -0,0 +1,113 @@
+<template>
+	<view class="recorder">
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				isUserMedia: false,
+				stream: null,
+				audio: null,
+				recorder: null,
+				chunks: [],
+				startTime: 0
+			}
+		},
+		mounted() {
+			/**
+			 * 	error 事件的返回状态
+			 * 	100: 请在HTTPS环境中使用
+			 * 	101: 浏览器不支持
+			 *  201: 用户拒绝授权
+			 *  500: 未知错误
+			 * */
+			if (origin.indexOf('https') === -1) {
+				this.$emit('error', '100')
+				throw '请在 https 环境中使用本插件。'
+			}
+			if (!navigator.mediaDevices || !window.MediaRecorder) {
+				this.$emit('error', '101')
+				throw '当前浏览器不支持'
+			}
+
+			this.getRecorderManager()
+		},
+		methods: {
+			getRecorderManager() {
+				this.audio = document.createElement('audio')
+				navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
+					this.isUserMedia = true
+					stream.getTracks().forEach((track) => {
+						track.stop()
+					})
+				}).catch(err => {
+					this.onErrorHandler(err)
+				})
+			},
+			start() {
+				if (!this.isUserMedia) return console.log('设备不支持')
+
+				navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
+					this.startTime = new Date().getTime()
+					this.stream = stream
+					this.recorder = new MediaRecorder(stream)
+					this.recorder.ondataavailable = this.getRecordingData
+					this.recorder.onstop = this.saveRecordingData
+					this.recorder.start()
+				}).catch(err => {
+					this.onErrorHandler(err)
+				})
+			},
+			stop() {
+				this.recorder.stop()
+				this.stream.getTracks().forEach((track) => {
+					track.stop()
+				})
+			},
+			getRecordingData(e) {
+				this.chunks.push(e.data)
+			},
+			saveRecordingData() {
+				const blob = new Blob(this.chunks, { 'type': 'audio/mpeg' }),
+					localUrl = URL.createObjectURL(blob)
+
+				const endTime = new Date().getTime()
+
+				let duration = (endTime - this.startTime).toString().split('')
+				duration.splice(duration.length - 2)
+				duration.splice(duration.length - 1, 0, '.')
+				duration = parseFloat(duration.join(''))
+
+				const recorder = {
+					data: blob,
+					duration: duration,
+					localUrl: localUrl
+				}
+				this.$emit('success', recorder)
+			},
+			onErrorHandler(err) {
+				console.log(err)
+				if (err.name === 'NotAllowedError') {
+					this.$emit('error', '201')
+					throw '用户拒绝了当前的浏览器实例的访问请求'
+				}
+
+				if (err.name === 'NotReadableError') {
+					this.$emit('error', '101')
+					throw '当前浏览器不支持'
+				}
+
+				this.$emit('error', '500')
+				throw '调用失败,原因不详'
+
+			}
+		},
+		destroyed() {
+			this.stop()
+		}
+	}
+</script>
+<style>
+</style>
diff --git a/H5/uni_modules/mumu-recorder/package.json b/H5/uni_modules/mumu-recorder/package.json
new file mode 100644
index 0000000..00d5e90
--- /dev/null
+++ b/H5/uni_modules/mumu-recorder/package.json
@@ -0,0 +1,87 @@
+{
+  "id": "mumu-recorder",
+  "displayName": "h5录音组件,调用H5原生功能使用麦克风进行录音",
+  "version": "1.0.1",
+  "description": "演示案例中模仿了微信的长按发送语音,与普通录音demo。",
+  "keywords": [
+    "录音",
+    "麦克风",
+    "模仿微信"
+],
+  "repository": "",
+  "engines": {
+    "HBuilderX": "^3.1.0"
+  },
+  "dcloudext": {
+    "category": [
+        "前端组件",
+        "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "麦克风"
+    },
+    "npmurl": ""
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "Vue": {
+          "vue2": "y",
+          "vue3": "y"
+        },
+        "App": {
+          "app-vue": "n",
+          "app-nvue": "n"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "n",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "u",
+          "阿里": "u",
+          "百度": "u",
+          "字节跳动": "u",
+          "QQ": "u",
+          "钉钉": "u",
+          "快手": "u",
+          "飞书": "u",
+          "京东": "u",
+          "小红书": "u"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/H5/uni_modules/mumu-recorder/readme.md b/H5/uni_modules/mumu-recorder/readme.md
new file mode 100644
index 0000000..1f888e5
--- /dev/null
+++ b/H5/uni_modules/mumu-recorder/readme.md
@@ -0,0 +1,117 @@
+## 插件简绍
+
+### 实现原理
+
+> 通过 navigator.mediaDevices.getUserMedia(需要https环境) 这个api调用麦克风,获取到到音频流数据。
+>
+> 通过 MediaRecorder 这个构造函数对音频流进行接收,完成录制后会返回一个存储`Blob`内容的录制数据。
+
+
+### 使用环境
+
+需要https环境才能使用,本地测试可以在 manifest.json  中点击源码展示,找到h5 ,添加:"devServer" : { "https" : true}
+
+**请勿使用 UC浏览器 与 夸克等阿里旗下的浏览器,发现他们使用的内核都较低,无法正常获取音频流,并且都有对接音频流截取的插件,导致无法正常获取音频流的数据。在微信中可以正常使用,推荐在微信内打开演示案例 **
+
+需要https环境才能使用!!!
+
+需要https环境才能使用!!!
+
+需要https环境才能使用!!!
+
+### 插件使用
+
+**插件已支持 uni_modules 支持组件easycom,以下代码演示的是普通使用**
+
+``` html
+<!-- HTML -->
+	<view>
+    <audio :src='recorder.localUrl' v-if='recorder' name='本地录音' controls="true"></audio>
+    <view @click='handlerOnCahnger'>
+			{{!status?'开始录音':'结束录音'}}
+		</view>
+		<mumu-recorder ref='recorder' @success='handlerSuccess' @error='handlerError'></mumu-recorder>
+	</view>
+```
+
+``` javascript
+// js
+	import MumuRecorder from '@/uni_modules/mumu-recorder/components/mumu-recorder/mumu-recorder.vue'
+	export default {
+		components: { MumuRecorder },
+		data() {
+			return {
+				status: false,
+				recorder: null
+			}
+		},
+		onLoad() {
+
+		},
+		methods: {
+			handlerSave() {
+				let tag = document.createElement('a')
+				tag.href = this.recorder.localUrl
+				tag.download = '录音'
+				tag.click()
+			},
+			handlerOnCahnger() {
+				if (this.status) {
+					this.$refs.recorder.stop()
+				} else {
+					this.$refs.recorder.start()
+				}
+				this.status = !this.status
+			},
+			handlerSuccess(res) {
+				console.log(res)
+				this.recorder = res
+			},
+			handlerError(code) {
+				switch (code) {
+					case '101':
+						uni.showModal({
+							content: '当前浏览器版本较低,请更换浏览器使用,推荐在微信中打开。'
+						})
+						break;
+					case '201':
+						uni.showModal({
+							content: '麦克风权限被拒绝,请刷新页面后授权麦克风权限。'
+						})
+						break
+					default:
+						uni.showModal({
+							content: '未知错误,请刷新页面重试'
+						})
+						break
+				}
+			}
+		}
+	}
+```
+
+### 相关API
+
+##### 组件内部方法($refs 调用)
+
+| 方法名 | 说明     | 参数 |
+| ------ | -------- | ---- |
+| start  | 开始录音 | 无   |
+| stop   | 结束录音 | 无   |
+
+
+
+##### 事件(Events)
+
+| 事件名  | 说明                 | 回调参数                                                     |
+| ------- | -------------------- | ------------------------------------------------------------ |
+| success | 停止录音后调用此事件 | 返回录音数据,是一个对象<br />{ data: 音频的 blob 数据,上传请使用这个			<br />duration: 当前音频长度<br/>localUrl: 当前音频的本地链接,可直接通过 audio 标签进行播放 } |
+| error   | 组件内部发生错误     | 错误码:<100 当前不是https环境> <101 浏览器不支持> <201 麦克风权限被拒绝> <500  未知错误> |
+
+### 案例演示
+
+![enter description here](https://h5plugin.mumudev.top/public/recorder/qrcode.png)
+
+## 支持作者
+
+![支持作者](https://student.mumudev.top/wxMP.jpg)
\ No newline at end of file
diff --git a/H5/utils/request.js b/H5/utils/request.js
index 52fceac..765290c 100644
--- a/H5/utils/request.js
+++ b/H5/utils/request.js
@@ -19,9 +19,9 @@
 
 	return new Promise(function(resolve, reject) {
 		let token = uni.getStorageSync('token')
-		// token =
-		// 	'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOjE2MjA0LCJ0eXBlIjoxLCJleHAiOjE3NDM1NTY3NzYsImNyZWF0ZWQiOjE3NDIyNjA3NzY2NTR9.SAmdlprtz_Z1cNSNB4ANYsKJFC7E7Jfxo6XbT9vpbO6zHBpTRfq_oyp9UlDQtHNiYgv-MuyqCBPw1-x88C_-8A'
-		// uni.setStorageSync('token', token)
+		token =
+			'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOjE4OTU1MjI1Nzk1MDcwODEyMTgsInR5cGUiOjEsImV4cCI6MTc0Nzk4MzIyMiwiY3JlYXRlZCI6MTc0NjY4NzIyMjAxMX0.pmUfTkxkbBirDMbnMR1IaLsbSiiwHc366_yyAetCzTOWYxTNgmQlmvw26_W62NHLOebB_ZAEgZsPvkJcaLOoPg'
+		uni.setStorageSync('token', token)
 		let header = {
 			'content-type': type ? 'application/x-www-form-urlencoded;charset=UTF-8' : 'application/json',
 			'Authorization': token,
diff --git a/management/config/routes.ts b/management/config/routes.ts
index 67a18dc..0bba9d2 100644
--- a/management/config/routes.ts
+++ b/management/config/routes.ts
@@ -52,7 +52,7 @@
         access: '/system_setting/position_management',
       },
       {
-        name: '角色管理',
+        name: '权限管理',
         path: '/setting/role',
         component: './setting/role',
         access: '/system_setting/role_management',
diff --git a/management/src/pages/appeal-management/detail.jsx b/management/src/pages/appeal-management/detail.jsx
index e8d4ae5..950943f 100644
--- a/management/src/pages/appeal-management/detail.jsx
+++ b/management/src/pages/appeal-management/detail.jsx
@@ -1,13 +1,14 @@
 import { buildProTableDataSource, sendRequest, showDelConfirm } from '@/utils/antdUtils';
 import { PageContainer, ProTable } from '@ant-design/pro-components';
-import { Button, Card, Select, Space, Descriptions, Divider, Steps, message } from 'antd';
+import { Button, Card, Select, Space, Descriptions, Divider, Steps, message, Modal, Form, Input, Upload, Popconfirm } from 'antd';
 import { useRef, useState, useEffect } from 'react';
 import { Access, useAccess } from 'umi'
 import { history, useLocation } from "@umijs/max"
-import { getDetail } from './service';
+import { getDetail, editProgress, deleteProgress } from './service';
 import moment from 'moment';
 import './index.less';
-import {downLoad } from '@/utils/utils';
+import {downLoad, customRequest } from '@/utils/utils';
+import { PlusOutlined } from '@ant-design/icons';
 
 const Account = () => {
     const actionRef = useRef();
@@ -16,6 +17,22 @@
     const [detail, setDetail] = useState({});
     const searchParams = new URLSearchParams(useLocation().search);
     const id = searchParams.get('id');
+    const [editModalVisible, setEditModalVisible] = useState(false);
+    const [editProgressData, setEditProgressData] = useState(null);
+    const [editForm] = Form.useForm();
+    const [loading, setLoading] = useState(false);
+    const [imgFileList, setImgFileList] = useState([]);
+    const [videoFileList, setVideoFileList] = useState([]);
+    const [previewVisible, setPreviewVisible] = useState(false);
+    const [previewImage, setPreviewImage] = useState('');
+    const [previewType, setPreviewType] = useState('image'); // 'image' or 'video'
+    const uploadConfig = {
+        name: 'file',
+        action: 'https://huacheng.psciio.com/api/huacheng-communitybackstage/communitypartybuilding/uploadimage',
+        headers: {
+            Authorization: 'Bearer ' + localStorage.getItem('token'),
+        },
+    };
 
     useEffect(() => {
         getDetail({ id: id }).then((res) => {
@@ -111,6 +128,117 @@
             span: 4,
         },
     ];
+
+    // 上传前校验
+    const beforeUpload = (file) => {
+        return new Promise((resolve, reject) => {
+            if (file.name.includes(',')) {
+                message.warning('上传文件不能包含英文逗号(,)');
+                return Upload.LIST_IGNORE;
+            }
+            setLoading(true);
+            resolve(file);
+        });
+    };
+
+    // 图片上传change
+    const handleImgChange = ({ file, fileList: newFileList }) => {
+        if (file.status === 'error' || (file.status === 'done' && file.response && file.response.code !== 200)) {
+            setLoading(false);
+            setImgFileList([]);
+            message.error('上传失败');
+            editForm.setFieldValue('imgUrl', []);
+            return;
+        }
+        if (file.status === 'done' && file.response && file.response.code === 200) {
+            setLoading(false);
+            message.success('上传成功');
+        }
+        let urls = newFileList.map(item => {
+            if (item.status === 'done' && item.response && item.response.data) {
+                item.url = item.response.data;
+            }
+            return item.url || item.url;
+        }).filter(Boolean);
+        setImgFileList(newFileList);
+        editForm.setFieldValue('imgUrl', urls);
+    };
+
+    // 视频上传change
+    const handleVideoChange = ({ file, fileList: newFileList }) => {
+        if (file.status === 'error' || (file.status === 'done' && file.response && file.response.code !== 200)) {
+            setLoading(false);
+            setVideoFileList([]);
+            message.error('上传失败');
+            editForm.setFieldValue('videoUrl', []);
+            return;
+        }
+        if (file.status === 'done' && file.response && file.response.code === 200) {
+            setLoading(false);
+            message.success('上传成功');
+        }
+        let urls = newFileList.map(item => {
+            if (item.status === 'done' && item.response && item.response.data) {
+                item.url = item.response.data;
+            }
+            return item.url || item.url;
+        }).filter(Boolean);
+        setVideoFileList(newFileList);
+        editForm.setFieldValue('videoUrl', urls);
+    };
+
+    // 办理进度编辑提交
+    const handleEditProgress = async () => {
+        try {
+            setLoading(true);
+            console.log('editProgressData', editProgressData);
+            
+            const values = await editForm.validateFields();
+            await editProgress({
+                complaintId: id,
+                describe: values.describe,
+                id: editProgressData.id,
+                imgUrl: (values.imgUrl || []).join(','),
+                video: (values.videoUrl || []).join(',')
+            });
+            message.success('编辑成功');
+            setEditModalVisible(false);
+            getDetail({ id }).then((res) => setDetail(res.data));
+        } catch (e) {
+            // 校验或请求失败
+        } finally {
+            setLoading(false);
+        }
+    };
+
+    // 办理进度删除
+    const handleDeleteProgress = async (progressId) => {
+        try {
+            await deleteProgress({ id: progressId });
+            message.success('删除成功');
+            getDetail({ id }).then((res) => setDetail(res.data));
+        } catch (e) {
+            message.error('删除失败');
+        }
+    };
+
+    // 在弹窗打开时同步 fileList
+    useEffect(() => {
+        if (editModalVisible && editProgressData) {
+            setImgFileList((editProgressData.imgUrl ? editProgressData.imgUrl.split(',') : []).map((url, idx) => ({ uid: idx, url, status: 'done' })));
+            setVideoFileList((editProgressData.video ? editProgressData.video.split(',') : []).map((url, idx) => ({ uid: idx, url, status: 'done' })));
+            editForm.setFieldsValue({
+                describe: editProgressData.describe,
+                imgUrl: editProgressData.imgUrl ? editProgressData.imgUrl.split(',') : [],
+                videoUrl: editProgressData.video ? editProgressData.video.split(',') : [],
+            });
+        }
+        if (!editModalVisible) {
+            setImgFileList([]);
+            setVideoFileList([]);
+        }
+    }, [editModalVisible, editProgressData]);
+
     return (
         <div>
             <PageContainer className={'appeal-management-detail'} header={{ breadcrumb: {} }} title="述求详情" >
@@ -121,22 +249,34 @@
                         <Descriptions title="办理进度" column={1}>
                             {detail.complaintProgresses?.length > 0 ? detail.complaintProgresses.map((item, index) => (
                                 <Descriptions.Item key={index}>
-                                    <Card style={{ width: '800px' }} title={item.createByName} extra={moment(item.createTime).format('YYYY-MM-DD HH:mm:ss')}>
+                                    <Card style={{ width: '800px', position: 'relative' }} title={item.createByName} extra={moment(item.createTime).format('YYYY-MM-DD HH:mm:ss')}>
                                         <Descriptions column={1} >
-                                            <Descriptions.Item>
-                                                {item.describe}
-                                            </Descriptions.Item>
+                                            <Descriptions.Item>{item.describe}</Descriptions.Item>
                                             <Descriptions.Item label={'上传图片'}>
-                                                {item.imgUrl && (item.imgUrl || '').split(',').map((item, index) => (
-                                                    <img width={80} style={{ marginRight: '10px' }} height={80} src={item} key={index} alt="example" />
+                                                {item.imgUrl && (item.imgUrl || '').split(',').map((img, idx) => (
+                                                    <img width={80} style={{ marginRight: '10px' }} height={80} src={img} key={idx} alt="example" />
                                                 ))}
                                             </Descriptions.Item>
                                             <Descriptions.Item label={'上传视频'}>
-                                                {item.videoUrl && (item.videoUrl || '').split(',').map((item, index) => (
-                                                    <video width={280} style={{ marginRight: '10px' }} src={item} key={index} controls></video>
+                                                {item.video && item.video.split(',').map((video, idx) => (
+                                                    <video width={280} style={{ marginRight: '10px' }} src={video} key={idx} controls></video>
                                                 ))}
                                             </Descriptions.Item>
                                         </Descriptions>
+                                        <div style={{ position: 'absolute', right: 24, bottom: 16 }}>
+                                            <Button size="small" type="primary" style={{ marginRight: 8 }} onClick={() => {
+                                                setEditProgressData(item);
+                                                setEditModalVisible(true);
+                                                editForm.setFieldsValue({
+                                                    describe: item.describe,
+                                                    imgUrl: item.imgUrl ? item.imgUrl.split(',') : [],
+                                                    videoUrl: item.video ? item.video.split(',') : [],
+                                                });
+                                            }}>编辑</Button>
+                                            <Popconfirm title="确定要删除该办理进度吗?" onConfirm={() => handleDeleteProgress(item.id)} okText="确定" cancelText="取消">
+                                                <Button size="small" danger>删除</Button>
+                                            </Popconfirm>
+                                        </div>
                                     </Card>
                                 </Descriptions.Item>
                             )) : <Descriptions.Item span={4} >暂无办理进度</Descriptions.Item>}
@@ -252,7 +392,80 @@
                     </div>
                 </Card>
 
+                <Modal
+                    title="编辑办理进度"
+                    open={editModalVisible}
+                    onCancel={() => setEditModalVisible(false)}
+                    onOk={handleEditProgress}
+                    confirmLoading={loading}
+                    destroyOnClose
+                    width={600}
+                >
+                    <Form form={editForm} layout="vertical" initialValues={{ describe: '', imgUrl: [], videoUrl: [] }}>
+                        <Form.Item name="describe" label="办理进度描述" rules={[{ required: true, message: '请输入办理进度描述' }]}> 
+                            <Input.TextArea rows={4} maxLength={500} showCount />
+                        </Form.Item>
+                        <Form.Item name="imgUrl" label="图片:">
+                            <Upload
+                                {...uploadConfig}
+                                listType="picture-card"
+                                maxCount={9}
+                                beforeUpload={beforeUpload}
+                                onChange={handleImgChange}
+                                onRemove={() => {
+                                    setImgFileList([]);
+                                    editForm.setFieldValue('imgUrl', []);
+                                }}
+                                showUploadList={{ showPreviewIcon: true }}
+                                accept="image/*"
+                                fileList={imgFileList}
+                                onPreview={file => {
+                                    setPreviewType('image');
+                                    setPreviewImage(file.url || file.thumbUrl);
+                                    setPreviewVisible(true);
+                                }}
+                            >
+                                {imgFileList.length < 9 && <PlusOutlined />}
+                            </Upload>
+                        </Form.Item>
+                        <Form.Item name="videoUrl" label="视频:">
+                            <Upload
+                                {...uploadConfig}
+                                listType="picture-card"
+                                maxCount={9}
+                                beforeUpload={beforeUpload}
+                                onChange={handleVideoChange}
+                                onRemove={() => {
+                                    setVideoFileList([]);
+                                    editForm.setFieldValue('videoUrl', []);
+                                }}
+                                showUploadList={{ showPreviewIcon: true }}
+                                accept="video/*"
+                                fileList={videoFileList}
+                                onPreview={file => {
+                                    setPreviewType('video');
+                                    setPreviewImage(file.url || file.thumbUrl);
+                                    setPreviewVisible(true);
+                                }}
+                            >
+                                {videoFileList.length < 9 && <PlusOutlined />}
+                            </Upload>
+                        </Form.Item>
+                    </Form>
+                </Modal>
 
+                <Modal
+                    open={previewVisible}
+                    footer={null}
+                    onCancel={() => setPreviewVisible(false)}
+                    width={previewType === 'video' ? 800 : 600}
+                >
+                    {previewType === 'image' ? (
+                        <img alt="预览" style={{ width: '100%' }} src={previewImage} />
+                    ) : (
+                        <video style={{ width: '100%' }} src={previewImage} controls autoPlay />
+                    )}
+                </Modal>
             </PageContainer>
         </div>
     );
diff --git a/management/src/pages/appeal-management/service.js b/management/src/pages/appeal-management/service.js
index efdd37d..832c5b8 100644
--- a/management/src/pages/appeal-management/service.js
+++ b/management/src/pages/appeal-management/service.js
@@ -15,3 +15,19 @@
         data
     });
 }
+
+//编辑办理进度
+export const editProgress = async (data) => {
+    return request(`/api/huacheng-sangeshenbian/complaint/update-progress`, {
+        method: 'POST',
+        data
+    });
+}
+
+//删除办理进度
+export const deleteProgress = async (data) => {
+    return request(`/api/huacheng-sangeshenbian/complaint/del-progress/${data.id}`, {
+        method: 'DELETE',
+        data
+    });
+}
diff --git a/management/src/pages/appeal-management/statistics/index.jsx b/management/src/pages/appeal-management/statistics/index.jsx
index 85e061f..cc99e94 100644
--- a/management/src/pages/appeal-management/statistics/index.jsx
+++ b/management/src/pages/appeal-management/statistics/index.jsx
@@ -7,14 +7,12 @@
 import { getList } from './service';
 
 const Account = () => {
-    const actionRef = useRef();
     const access = useAccess();
-    const formRef = useRef();
 
     const columns = [
         {
             title: '述求号',
-            dataIndex: 'reportUserName',
+            dataIndex: 'serialNumber',
             order: 8,
         },
         {
@@ -29,30 +27,30 @@
         },
         {
             title: '申请人',
-            dataIndex: 'name',
+            dataIndex: 'applyUserName',
             order: 5,
         },
         {
             title: '申请时间',
-            dataIndex: 'name',
+            dataIndex: 'applyTime',
             hideInTable: true,
             valueType: 'dateRange',
             order: 3,
         },
         {
             title: '审批时间',
-            dataIndex: 'name',
+            dataIndex: 'examineTime',
             valueType: 'dateRange',
             order: 2,
         },
         {
             title: '审批人',
-            dataIndex: 'name',
+            dataIndex: 'examineUserName',
             order: 4,
         },
         {
             title: '驳回理由',
-            dataIndex: 'contactNumber',
+            dataIndex: 'remark',
             hideInSearch: true,
         },
         {
@@ -64,11 +62,13 @@
                 1: '延期办理',
                 2: '超时办理',
                 3: '已办结',
-                4: '上报待审核',
+                4: '群众撤销',
+                5: '上报待审核',
+                6: '上级驳回',
+                7: '延期待审核',
+                8: '已评价',
+                9: '延期驳回',
             },
-            render: (text, record) => {
-                return Number(record.status) == 0 ? '正在办理' : record.status == 1 ? '延期办理' : record.status == 2 ? '超时办理' : record.status == 3 ? '已办结' : record.status == 4 ? '上报待审核' : '已办结';
-            }
         },
         {
             title: '操作',
@@ -102,20 +102,16 @@
             >
                 <ProTable
                     rowKey="id"
-                    actionRef={actionRef}
                     columns={columns}
-                    formRef={formRef}
                     request={async (params) => {
-
-                        if (params.time && params.time.length > 0) {
-                            params.startTime = moment(params.time[0]).format('YYYY-MM-DD HH:mm:ss');
-                            params.endTime = moment(params.time[1]).format('YYYY-MM-DD 23:59:59');
-                            delete params.time
-                        } else {
-                            delete params.startTime
-                            delete params.endTime
+                        if (params.applyTime && params.applyTime.length > 0) {
+                            params.applyTime = moment(params.applyTime[0]).format('YYYY-MM-DD') +
+                                ' - ' + moment(params.applyTime[1]).format('YYYY-MM-DD')
                         }
-
+                        if (params.examineTime && params.examineTime.length > 0) {
+                            params.examineTime = moment(params.examineTime[0]).format('YYYY-MM-DD') +
+                                ' - ' + moment(params.examineTime[1]).format('YYYY-MM-DD')
+                        }
 
                         return buildProTableDataSource(getList, params);
                     }}
diff --git a/management/src/pages/appeal-management/statistics/service.js b/management/src/pages/appeal-management/statistics/service.js
index efdd37d..9d4db84 100644
--- a/management/src/pages/appeal-management/statistics/service.js
+++ b/management/src/pages/appeal-management/statistics/service.js
@@ -1,17 +1,8 @@
 import { request } from '@umijs/max';
 
-// 获取诉求列表
-export const getList = async (data) => {
-    return request(`/api/huacheng-sangeshenbian/complaint/page`, {
-        method: 'POST',
-        data
-    });
-}
-
-// 获取述求详情
-export const getDetail = async (data) => {
-    return request(`/api/huacheng-sangeshenbian/complaint/detail/${data.id}`, {
+export const getList = async (params) => {
+    return request(`/api/huacheng-sangeshenbian/complaint-reject/list`, {
         method: 'GET',
-        data
+        params
     });
 }
diff --git a/management/src/pages/logManagement/index.jsx b/management/src/pages/logManagement/index.jsx
index 9df7999..3a05a6b 100644
--- a/management/src/pages/logManagement/index.jsx
+++ b/management/src/pages/logManagement/index.jsx
@@ -14,24 +14,24 @@
     const columns = [
         {
             title: '操作时间',
-            dataIndex: 'name',
+            dataIndex: 'createTime',
             hideInTable: true,
             valueType: 'dateRange',
             order: 1,
         },
         {
             title: '操作用户',
-            dataIndex: 'reportUserName',
+            dataIndex: 'operatorName',
             order: 5,
         },
         {
             title: '联系电话',
-            dataIndex: 'reportUserName',
+            dataIndex: 'operatorPhone',
             order: 4,
         },
         {
             title: '操作类型',
-            dataIndex: 'reportUserPhone',
+            dataIndex: 'operatorCategory',
             order: 3,
             valueEnum: {
                 1: '登录',
@@ -48,45 +48,41 @@
         },
         {
             title: '对象名称',
-            dataIndex: 'name',
+            dataIndex: 'targetName',
             hideInSearch: true,
         },
         {
             title: '所在IP',
-            dataIndex: 'name',
+            dataIndex: 'ip',
             order: 2,
         },
     ];
     return (
-        <div>
-            <PageContainer header={{
-                breadcrumb: {},
-            }}
-                title={'日志记录'}
-            >
-                <ProTable
-                    rowKey="id"
-                    actionRef={actionRef}
-                    columns={columns}
-                    formRef={formRef}
-                    request={async (params) => {
-                        if (params.time && params.time.length > 0) {
-                            params.startTime = moment(params.time[0]).format('YYYY-MM-DD HH:mm:ss');
-                            params.endTime = moment(params.time[1]).format('YYYY-MM-DD 23:59:59');
-                            delete params.time
-                        } else {
-                            delete params.startTime
-                            delete params.endTime
-                        }
-
-
-                        return buildProTableDataSource(getList, params);
-                    }}
-                    search={{ labelWidth: 'auto', defaultCollapsed: false }}
-                />
-            </PageContainer>
-        </div>
+        <PageContainer header={{
+            breadcrumb: {},
+        }}
+            title={'日志记录'}
+        >
+            <ProTable
+                rowKey="id"
+                actionRef={actionRef}
+                columns={columns}
+                formRef={formRef}
+                request={async (params) => {
+                    if (params.time && params.time.length > 0) {
+                        params.startTime = moment(params.time[0]).format('YYYY-MM-DD HH:mm:ss');
+                        params.endTime = moment(params.time[1]).format('YYYY-MM-DD 23:59:59');
+                        delete params.time
+                    } else {
+                        delete params.startTime
+                        delete params.endTime
+                    }
+                    return buildProTableDataSource(getList, params);
+                }}
+                search={{ labelWidth: 'auto', defaultCollapsed: false }}
+            />
+        </PageContainer>
     );
 };
 
-export default Account;
+export default Account;
\ No newline at end of file
diff --git a/management/src/pages/logManagement/service.js b/management/src/pages/logManagement/service.js
index efdd37d..73f1726 100644
--- a/management/src/pages/logManagement/service.js
+++ b/management/src/pages/logManagement/service.js
@@ -1,17 +1,8 @@
 import { request } from '@umijs/max';
 
-// 获取诉求列表
-export const getList = async (data) => {
-    return request(`/api/huacheng-sangeshenbian/complaint/page`, {
-        method: 'POST',
-        data
-    });
-}
-
-// 获取述求详情
-export const getDetail = async (data) => {
-    return request(`/api/huacheng-sangeshenbian/complaint/detail/${data.id}`, {
+export const getList = async (params) => {
+    return request(`/api/huacheng-sangeshenbian/system-log/list`, {
         method: 'GET',
-        data
+        params
     });
 }
diff --git a/management/src/pages/party/manage/index.jsx b/management/src/pages/party/manage/index.jsx
index 7edb3d1..f5a39dd 100644
--- a/management/src/pages/party/manage/index.jsx
+++ b/management/src/pages/party/manage/index.jsx
@@ -66,6 +66,18 @@
       }
     },
     {
+      title: '创建时间',
+      dataIndex: 'createTime',
+      sorter: true,
+      hideInSearch: true,
+    },
+    {
+      title: '更新时间',
+      dataIndex: 'updateTime',
+      sorter: true,
+      hideInSearch: true,
+    },
+    {
       title: '状态',
       dataIndex: 'freezeStatus',
       valueEnum: {
@@ -75,80 +87,84 @@
       }
     },
     {
+      title: '身份证号',
+      dataIndex: 'idNumber',
+    },
+    {
       title: '操作',
       hideInSearch: true,
       render: (text, record) => {
         return (
           <Space>
             <Access accessible={access['/party_member/edit']}>
-            <Button
-              type="link"
-              onClick={() => {
-                history.push(`/party/manage/add?type=edit&id=${record.id}`)
-              }}
-            >
-              编辑
-            </Button>
-            </Access>
-            <Access accessible={access['/party_member/del']}>
-            <Button
-              type="link"
-              onClick={() => {
-                showDelConfirm(async () => {
-                  let status = await sendRequest(deleteBanner, {id:record.id})
-                  if (status) {
-                    actionRef.current.reload();
-                  }
-                }, '确认删除所选信息吗?');
-              }}
-            >
-              删除
-            </Button>
-            </Access>
-            <Access accessible={access['/party_member/detail']}>
-            <Button
-              type="link"
-              onClick={() => {
-                history.push(`/party/manage/add?detail=true&id=${record.id}`)
-              }}
-            >
-              查看详情
-            </Button>
-            </Access>
-            <Access accessible={access['/party_member/freeze']}>
-            {record.freezeStatus == 0 && (
               <Button
                 type="link"
                 onClick={() => {
-                  showDelConfirm1(async () => {
-                    let status = await sendRequest(freeze, { id: record.id })
+                  history.push(`/party/manage/add?type=edit&id=${record.id}`)
+                }}
+              >
+                编辑
+              </Button>
+            </Access>
+            <Access accessible={access['/party_member/del']}>
+              <Button
+                type="link"
+                onClick={() => {
+                  showDelConfirm(async () => {
+                    let status = await sendRequest(deleteBanner, { id: record.id })
                     if (status) {
                       actionRef.current.reload();
                     }
-                  }, '确认冻结该党员信息吗?', '冻结', '', '确认冻结该党员信息吗?');
+                  }, '确认删除所选信息吗?');
                 }}
               >
-                冻结
+                删除
               </Button>
-            )}
+            </Access>
+            <Access accessible={access['/party_member/detail']}>
+              <Button
+                type="link"
+                onClick={() => {
+                  history.push(`/party/manage/add?detail=true&id=${record.id}`)
+                }}
+              >
+                查看详情
+              </Button>
+            </Access>
+            <Access accessible={access['/party_member/freeze']}>
+              {record.freezeStatus == 0 && (
+                <Button
+                  type="link"
+                  onClick={() => {
+                    showDelConfirm1(async () => {
+                      let status = await sendRequest(freeze, { id: record.id })
+                      if (status) {
+                        actionRef.current.reload();
+                      }
+                    }, '确认冻结该党员信息吗?', '冻结', '', '确认冻结该党员信息吗?');
+                  }}
+                >
+                  冻结
+                </Button>
+              )}
 
             </Access>
             <Access accessible={access['/party_member/freeze']}>
-            {record.freezeStatus == 1 && (
-              <Button
-                type="link"
-                onClick={() => {
-                  showDelConfirm1(async () => {
-                    let status = await sendRequest(freeze, { id: record.id })
-                    if (status) {
-                      actionRef.current.reload();
-                    }
-                  }, '确认解冻该党员信息吗?', '解冻', '', '确认解冻该党员信息吗?');
-                }}
-              >
-                解冻
-              </Button>
-            )}
+              {record.freezeStatus == 1 && (
+                <Button
+                  type="link"
+                  onClick={() => {
+                    showDelConfirm1(async () => {
+                      let status = await sendRequest(freeze, { id: record.id })
+                      if (status) {
+                        actionRef.current.reload();
+                      }
+                    }, '确认解冻该党员信息吗?', '解冻', '', '确认解冻该党员信息吗?');
+                  }}
+                >
+                  解冻
+                </Button>
+              )}
 
             </Access>
           </Space >
@@ -175,7 +191,15 @@
           showQuickJumper: true,
           defaultPageSize: 10,
         }}
-        request={(params) => {
+        request={(params, sorter) => {
+          console.log('weqweqeqwe', sorter);
+          if (sorter.createTime) {
+            params.createTimeSort = sorter.createTime === 'ascend' ? 2 : 1;
+          }
+          if (sorter.updateTime) {
+            params.updateTimeSort = sorter.updateTime === 'ascend' ? 2 : 1;
+          }
+          
           params.communityId = params.community ? params.community[params.community.length - 1] : ''
           params.auditStatus = 1
           setExcelParams(() => params)
@@ -184,35 +208,35 @@
         toolBarRender={(action, selectRows) => [
           <Space>
             <Access accessible={access['/party_member/add']}>
-            <Button
-              type="primary"
-              onClick={() => {
-                history.push('/party/manage/add?type=add')
-              }}
-            >
-              添加
-            </Button>
+              <Button
+                type="primary"
+                onClick={() => {
+                  history.push('/party/manage/add?type=add')
+                }}
+              >
+                添加
+              </Button>
             </Access>
             <Access accessible={access['/party_member/export']}>
-            <Button
-              type="primary"
-              onClick={() => {
-                exportExcell('党员列表', excelParams, '/api/huacheng-sangeshenbian/party-member/export')
-              }}
-            >
-              导出
-            </Button>
+              <Button
+                type="primary"
+                onClick={() => {
+                  exportExcell('党员列表', excelParams, '/api/huacheng-sangeshenbian/party-member/export')
+                }}
+              >
+                导出
+              </Button>
             </Access>
             <Access accessible={access['/party_member/import']}>
-            <Button
-              type="primary"
-              onClick={() => {
-                handleModalExport(true)
-                modalExportRef.current.clean()
-              }}
-            >
-              导入
-            </Button>
+              <Button
+                type="primary"
+                onClick={() => {
+                  handleModalExport(true)
+                  modalExportRef.current.clean()
+                }}
+              >
+                导入
+              </Button>
             </Access>
           </Space>
         ]}
diff --git a/management/src/pages/setting/role/components/addAndEdit.jsx b/management/src/pages/setting/role/components/addAndEdit.jsx
index ad2a7a4..d8b2284 100644
--- a/management/src/pages/setting/role/components/addAndEdit.jsx
+++ b/management/src/pages/setting/role/components/addAndEdit.jsx
@@ -128,7 +128,7 @@
             getContainer={false}
             width="20%"
             destroyOnClose
-            title={detailType ? '角色详情' : data.id ? '编辑角色' : '添加角色'}
+            title={detailType ? '权限详情' : data.id ? '编辑权限' : '添加权限'}
             open={visible}
             onCancel={() => onCancel(false)}
             afterClose={() => {
@@ -150,10 +150,10 @@
             <Form layout="horizontal" {...formItemLayout} form={form} scrollToFirstError>
                 <Form.Item
                     name="name"
-                    label="角色名称"
-                    rules={[{ required: true, message: '请输入角色名称' }]}
+                    label="权限名称"
+                    rules={[{ required: true, message: '请输入权限名称' }]}
                 >
-                    <Input disabled={detailType} placeholder='请输入角色名称' />
+                    <Input disabled={detailType} placeholder='请输入权限名称' />
                 </Form.Item>
                 <Form.Item
                     name="tree"
diff --git a/management/src/pages/setting/role/index.jsx b/management/src/pages/setting/role/index.jsx
index 630cbc7..46a4693 100644
--- a/management/src/pages/setting/role/index.jsx
+++ b/management/src/pages/setting/role/index.jsx
@@ -14,7 +14,7 @@
 
     const columns = [
         {
-            title: '角色名称',
+            title: '权限名称',
             dataIndex: 'name',
         },
         {
diff --git a/management/src/pages/setting/user/components/addAndEdit.jsx b/management/src/pages/setting/user/components/addAndEdit.jsx
index fb5e4ef..9bc2cb8 100644
--- a/management/src/pages/setting/user/components/addAndEdit.jsx
+++ b/management/src/pages/setting/user/components/addAndEdit.jsx
@@ -1,7 +1,9 @@
-import { Form, Input, Modal, Tree, Button, Spin, Row, Col, Select, Radio, Cascader } from 'antd';
+import { Form, Input, Modal, Tree, Button, Spin, Row, Col, Select, Radio, Cascader, Card } from 'antd';
 import { forwardRef, useImperativeHandle, useState } from 'react';
 import { useEffect } from 'react';
-import { getDepartmentList, systemPostList, systemRoleList, getSystemUserInfo, getCityList, addSystemUserInfo, editSystemUserInfo } from '../service';
+import { DeleteOutlined } from '@ant-design/icons';
+import '../index.less'
+import { getDepartmentList, systemPostList, systemRoleList, getSystemUserInfo, getCityList, addSystemUserInfo, editSystemUserInfo, getCascaderData } from '../service';
 import CryptoJS from 'crypto-js';
 const formItemLayout = {
     labelCol: { span: 8 },
@@ -27,7 +29,10 @@
     //所属角色
     const [roleList, setRoleList] = useState([])
     //账号层级
-    const [levelList, setLevelList] = useState([{ name: '市级账号', value: 1 }, { name: '区县账号', value: 2 }, { name: '街道账号', value: 3 }, { name: '社区账号', value: 4 }, { name: '党员账号', value: 5 }])
+    const [levelList, setLevelList] = useState([])
+
+    //级联数据
+    const [cascaderData, setCascaderData] = useState([])
     //选择的层级
     const [activeLevel, setActiveLevel] = useState('')
     //所属区县
@@ -37,11 +42,11 @@
     const [streetList, setStreetList] = useState([])
     const [activeStreet, setActiveStreet] = useState({})
     //所属社区
-    const [communityList, setCommunityList] = useState([])
     const [activeCommunity, setActiveCommunity] = useState({})
 
-
-
+    const [accountLevels, setAccountLevels] = useState([
+        { area: [], isDiscipline: 0, options: [] }
+    ]);
 
     useEffect(() => {
         // 获取单位
@@ -51,63 +56,14 @@
     useImperativeHandle(ref, () => {
         return {
             refreshData: (data, companyList) => {
-                getCountyList()
+                getCascaderDatas()
                 setOneCompanyList(() => companyList)
-                console.log('companyList', companyList)
-
                 systemPostList({ pageNum: 1, pageSize: 10000 }).then(res => {
                     setPositionList(() => res.data.records)
                 })
                 systemRoleList({ pageNum: 1, pageSize: 10000 }).then(res => {
                     setRoleList(() => res.data.records)
                 })
-                // 权限判断
-                let adminInfo = JSON.parse(localStorage.getItem('userInfo'))
-                setAdminLevel(() => adminInfo.accountLevel)
-                switch (adminInfo.accountLevel) {
-                    case 1:
-                        setLevelList(() => [{ name: '市级账号', value: 1 }, { name: '区县账号', value: 2 }, { name: '街道账号', value: 3 }, { name: '社区账号', value: 4 }, { name: '党员账号', value: 5 }])
-                        break;
-                    case 2:
-                        getStreetList(adminInfo.districtsCode)
-                        setLevelList(() => [{ name: '区县账号', value: 2 }, { name: '街道账号', value: 3 }, { name: '社区账号', value: 4 }, { name: '党员账号', value: 5 }])
-                        this.$nextTick(() => {
-                            form.setFieldsValue({ districtsCode: adminInfo.districtsCode })
-                        })
-
-                        break;
-                    case 3:
-                        getStreetList(adminInfo.districtsCode)
-                        getcommunityList(adminInfo.streetId)
-                        setLevelList(() => [{ name: '街道账号', value: 3 }, { name: '社区账号', value: 4 }, { name: '党员账号', value: 5 }])
-                        form.setFieldsValue({ districtsCode: adminInfo.districtsCode })
-                        form.setFieldsValue({ streetId: adminInfo.streetId })
-                        break;
-                    case 4:
-                        getStreetList(adminInfo.districtsCode)
-                        getcommunityList(adminInfo.streetId)
-                        setLevelList(() => [{ name: '社区账号', value: 4 }, { name: '党员账号', value: 5 }])
-                        // this.$nextTick(() => {
-                        form.setFieldsValue({ districtsCode: adminInfo.districtsCode })
-                        form.setFieldsValue({ streetId: adminInfo.streetId })
-                        form.setFieldsValue({ communityId: adminInfo.communityId * 1 })
-                        // })
-
-
-                        break;
-                    case 5:
-                        getStreetList(adminInfo.districtsCode)
-                        getcommunityList(adminInfo.streetId)
-                        setLevelList(() => [{ name: '党员账号', value: 5 }])
-                        form.setFieldsValue({ districtsCode: adminInfo.districtsCode })
-                        form.setFieldsValue({ streetId: adminInfo.streetId })
-                        form.setFieldsValue({ communityId: adminInfo.communityId * 1 })
-                        break;
-                    default:
-                        break;
-                }
-
-
 
                 if (data.id) {
                     getInfo(data.id)
@@ -128,9 +84,51 @@
     // 保存
     const okHandle = () => {
         form.validateFields().then((values) => {
-            if(values.password){
+            // 校验accountLevels必填
+            if (!accountLevels.length || accountLevels.some(item => !item.area || item.area.length === 0)) {
+                if (window?.antd?.message?.error) {
+                    window.antd.message.error('请完整选择账号所属层级区域!');
+                } else {
+                    alert('请完整选择账号所属层级区域!');
+                }
+                return;
+            }
+            // 打印提交时的accountLevels数组
+            console.log('提交时的accountLevels:', accountLevels);
+            // 组装 systemUserLevels,严格按照接口字段,优先用原始字段
+            const systemUserLevels = accountLevels.map(item => {
+                // Get the first selected option's id as the level
+                const firstSelectedOption = item.selectedOptions?.[0];
+                const level = firstSelectedOption?.id || item.level || '';
+                
+                // 判断不同级别(假设市级别id为1,区县级别id为2,街道级别id为3,社区级别id为4)
+                const isCityLevel = level === '1';
+                const isDistrictLevel = level === '2';
+                const isStreetLevel = level === '3';
+                const isCommunityLevel = level === '4';
+                
+                return {
+                    // 市级别:所有下级字段为空
+                    // 区县级别:街道和社区字段为空
+                    // 街道级别:社区字段为空
+                    // 社区级别:不做处理
+                    community: (isCityLevel || isDistrictLevel || isStreetLevel) ? '' : (item.community || item.selectedOptions?.[3]?.name || ''),
+                    communityId: (isCityLevel || isDistrictLevel || isStreetLevel) ? '' : (item.communityId || item.selectedOptions?.[3]?.id || ''),
+                    districts: isCityLevel ? '' : (item.districts || item.selectedOptions?.[1]?.name || ''),
+                    districtsCode: isCityLevel ? '' : (item.districtsCode || item.selectedOptions?.[1]?.id || ''),
+                    id: item.id || '', // 编辑时可用
+                    level: level, // Use the determined level value
+                    status: 1,
+                    street: (isCityLevel || isDistrictLevel) ? '' : (item.street || item.selectedOptions?.[2]?.name || ''),
+                    streetId: (isCityLevel || isDistrictLevel) ? '' : (item.streetId || item.selectedOptions?.[2]?.id || ''),
+                    superviseFlag: typeof item.isDiscipline === 'number' ? item.isDiscipline : (item.isDiscipline ? 1 : 0),
+                    // systemUserId: 可选,如有需要补充
+                };
+            });
+            values.systemUserLevels = systemUserLevels;
+            if (values.password) {
                 values.password = CryptoJS.MD5(values.password).toString();
-            }else{
+            } else {
                 delete values.password
             }
             if (values.DepartmentId) {
@@ -144,54 +142,73 @@
                 onUpdate(values)
             } else {
                 onSave(values);
+                setAccountLevels([{ area: [], isDiscipline: 0, options: [] }]); // 清空
             }
         });
     };
-    const getCountyList = (id) => {
-        getCityList({ id: '510400', tier: 2 }).then(res => {
-            setCountyList(() => res.data)
-        })
-    }
-    const getStreetList = (id) => {
-        getCityList({ id: id, tier: 3 }).then(res => {
-            setStreetList(() => res.data)
-        })
-    }
-    const getcommunityList = (id) => {
-        getCityList({ id: id, tier: 4 }).then(res => {
-            setCommunityList(() => res.data)
-        })
-    }
-    const changeCountry = (value, label) => {
-        setActiveCounty(label)
-        getStreetList(value)
-        form.setFieldsValue({ streetId: '', communityId: '' })
-        setActiveCommunity({ name: '', id: '' })
-        setActiveStreet({ name: '', id: '' })
 
+    // 获取级联数据
+    const getCascaderDatas = () => {
+        getCascaderData().then(res => {
+            // 处理级联数据
+            const processedData = res.data.map(item => {
+                // 根据第一级类型处理数据
+                if (item.children) {
+                    // 区县级别
+                    if (item.id == 2) { // 假设type=2表示区县
+                        // 只保留第一级children
+                        item.children = item.children.map(child => {
+                            const { children, ...childWithoutChildren } = child;
+                            return childWithoutChildren;
+                        });
+                    }
+                    // 街道级别
+                    else if (item.id == 3) { // 假设type=3表示街道
+                        // 保留区县和街道两级
+                        item.children = item.children.map(child => {
+                            if (child.children) {
+                                child.children = child.children.map(street => {
+                                    const { children, ...streetWithoutChildren } = street;
+                                    return streetWithoutChildren;
+                                });
+                            }
+                            return child;
+                        });
+                    }
+                    // 社区级别
+                    else if (item.id == 4) { // 假设type=4表示社区
+                        // 保留所有层级数据
+                        return item;
+                    }
+                }
+                return item;
+            });
+
+            let arr = JSON.parse(JSON.stringify(processedData))
+            let accountLevels = localStorage.getItem('userInfo')
+            let accountLevel = JSON.parse(accountLevels).accountLevel
+            if (accountLevel == 2) {
+                arr = arr.filter(item => item.id != 1)
+            } else if (accountLevel == 3) {
+                arr = arr.filter(item => item.id != 1 && item.id != 2)
+            } else if (accountLevel == 4) {
+                arr = arr.filter(item => item.id != 1 && item.id != 2 && item.id != 3)
+            }
+            setCascaderData(() => arr);
+        });
     }
-    const changeStreet = (value, label) => {
-        setActiveStreet(label)
-        getcommunityList(value)
-        form.setFieldsValue({ communityId: '' })
-        setActiveCommunity({ name: '', id: '' })
-    }
-    const changeCommunity = (value, label) => {
-        setActiveCommunity(label)
-    }
+
+
+
+
+
+
+
+
+
+
     const getInfo = (id) => {
         getSystemUserInfo(id).then(res => {
-            if (res.data.districtsCode) {
-                setActiveStreet({ name: res.data.districts, id: res.data.districtsCode })
-                getStreetList(res.data.districtsCode)
-            }
-            if (res.data.streetId) {
-                setActiveCounty({ name: res.data.street, id: res.data.streetId })
-                getcommunityList(res.data.streetId)
-            }
-            if (res.data.communityId) {
-                setActiveCommunity({ name: res.data.community, id: res.data.communityId })
-            }
             // delete res.data.password
 
             let departmentId = []
@@ -208,8 +225,89 @@
                 departmentId.push(res.data.fourDepartmentId)
             }
             res.data.DepartmentId = departmentId
-            console.log('departmentId', departmentId)
             setActiveLevel(() => res.data.accountLevel)
+
+            // 先获取级联数据再回显
+            getCascaderData().then(cascadeRes => {
+                // 处理级联数据
+                const processedData = cascadeRes.data.map(item => {
+                    // 根据第一级类型处理数据
+                    if (item.children) {
+                        // 区县级别
+                        if (item.id == 2) { // 假设type=2表示区县
+                            // 只保留第一级children
+                            item.children = item.children.map(child => {
+                                const { children, ...childWithoutChildren } = child;
+                                return childWithoutChildren;
+                            });
+                        }
+                        // 街道级别
+                        else if (item.id == 3) { // 假设type=3表示街道
+                            // 保留区县和街道两级
+                            item.children = item.children.map(child => {
+                                if (child.children) {
+                                    child.children = child.children.map(street => {
+                                        const { children, ...streetWithoutChildren } = street;
+                                        return streetWithoutChildren;
+                                    });
+                                }
+                                return child;
+                            });
+                        }
+                        // 社区级别
+                        else if (item.id == 4) { // 假设type=4表示社区
+                            // 保留所有层级数据
+                            return item;
+                        }
+                    }
+                    return item;
+                });
+
+                let arr = JSON.parse(JSON.stringify(processedData))
+                let accountLevels = localStorage.getItem('userInfo')
+                let accountLevel = JSON.parse(accountLevels).accountLevel
+                if (accountLevel == 2) {
+                    arr = arr.filter(item => item.id != 1)
+                } else if (accountLevel == 3) {
+                    arr = arr.filter(item => item.id != 1 && item.id != 2)
+                } else if (accountLevel == 4) {
+                    arr = arr.filter(item => item.id != 1 && item.id != 2 && item.id != 3)
+                }
+                setCascaderData(() => arr);
+
+                // 回显accountLevels,area始终为4级,id类型统一
+                if (res.data.systemUserLevels && Array.isArray(res.data.systemUserLevels)) {
+                    const newAccountLevels = res.data.systemUserLevels.map(level => {
+                        const toId = v => (v === undefined || v === null) ? undefined : String(v);
+                        const area = [
+                            toId(level.level),
+                            toId(level.twoLevelId || level.districtsCode),
+                            toId(level.threeLevelId || level.streetId),
+                            toId(level.fourLevelId || level.communityId)
+                        ].filter(v => v !== undefined && v !== null && v !== '');
+                        return {
+                            area,
+                            isDiscipline: Number(level.superviseFlag) === 1 ? 1 : 0,
+                            options: [],
+                            selectedOptions: [
+                                level.level ? { id: toId(level.level), name: '' } : undefined,
+                                level.twoLevelName ? { id: toId(level.twoLevelId), name: level.twoLevelName } : undefined,
+                                level.threeLevelName ? { id: toId(level.threeLevelId), name: level.threeLevelName } : undefined,
+                                level.fourLevelName ? { id: toId(level.fourLevelId), name: level.fourLevelName } : undefined,
+                            ].filter(Boolean),
+                            level: toId(level.level) || '',
+                            community: level.community || '',
+                            communityId: level.communityId || '',
+                            districts: level.districts || '',
+                            districtsCode: level.districtsCode || '',
+                            id: level.id || '',
+                            street: level.street || '',
+                            streetId: level.streetId || '',
+                        };
+                    });
+                    setAccountLevels(newAccountLevels.length ? newAccountLevels : [{ area: [], isDiscipline: 0, options: [], level: '', community: '', communityId: '', districts: '', districtsCode: '', id: '', street: '', streetId: '' }]);
+                }
+            });
 
             form.setFieldsValue({ ...res.data, password: '' })
         })
@@ -235,13 +333,32 @@
         return false
     }
 
+    // 动态添加账号层级项
+    const addAccountLevel = () => {
+        setAccountLevels([...accountLevels, { area: [], isDiscipline: 0, options: [] }]);
+    };
+    // 删除账号层级项
+    const removeAccountLevel = (idx) => {
+        if (accountLevels.length === 1) return;
+        setAccountLevels(accountLevels.filter((_, i) => i !== idx));
+    };
+    // 纪检委单选变更
+    const handleDisciplineChange = (e, idx) => {
+        setAccountLevels(levels => {
+            const newLevels = [...levels];
+            newLevels[idx].isDiscipline = e.target.value;
+            return newLevels;
+        });
+    };
+
     return (
         <Modal
             getContainer={false}
-            width="65%"
+            width="75%"
             destroyOnClose
             title={data.type == 'detail' ? '人员详情' : data.type == 'edit' ? '编辑人员' : '添加人员'}
             open={visible}
+            className='addAndEditModal'
             onCancel={() => onCancel(false)}
             afterClose={() => {
                 form.resetFields()
@@ -258,8 +375,8 @@
                     <Button key="back" onClick={() => onCancel(false)}>关闭</Button>
             }
         >
-            <Form layout="horizontal" {...formItemLayout} form={form} scrollToFirstError>
-                <Row>
+            <Form layout="horizontal" form={form} scrollToFirstError labelCol={{ span: 6 }} wrapperCol={{ span: 20 }}>
+                <Row gutter={16}>
                     <Col span={8}>
                         <Form.Item
                             name="name"
@@ -269,90 +386,6 @@
                             <Input disabled={data.type == 'detail'} placeholder='请输入人员姓名' />
                         </Form.Item>
                     </Col>
-                </Row>
-                <Row>
-                    <Col span={16}>
-                        <Form.Item
-                            name="DepartmentId"
-                            label="所属单位"
-                            labelCol={{ span: 4 }}
-                            rules={[{ required: true, message: '请选择所属单位' }]}
-                        >
-                            {/* <Select
-                                key="searchSelect"
-                                allowClear
-                                disabled={data.type == 'detail'}
-                                placeholder="请选择"
-                                options={oneCompanyList}
-                                fieldNames={{ label: 'name', value: 'id' }}
-                                filterOption={false}
-                            >
-                            </Select > */}
-                            <Cascader
-                                changeSelect
-                                options={oneCompanyList}
-                                fieldNames={{ value: 'key', label: 'name' }}
-                                placeholder="请选择"
-                                // displayRender={(label) => label[label.length - 1]}
-                                changeOnSelect={true}
-                            />
-                        </Form.Item>
-                    </Col>
-                    {/* <Col span={8}>
-                        <Form.Item
-                            name="twoDepartmentId"
-                            label="所属二级单位"
-                        >
-                            <Select
-                                key="searchSelect"
-                                allowClear
-                                disabled={data.type == 'detail'}
-                                placeholder="请选择"
-                                options={twoCompanyList}
-                                fieldNames={{ label: 'name', value: 'id' }}
-                                filterOption={false}
-                            >
-                            </Select >
-                        </Form.Item>
-                    </Col>
-                    <Col span={8}>
-                        <Form.Item
-                            name="threeDepartmentId"
-                            label="所属三级单位"
-                        >
-                            <Select
-                                key="searchSelect"
-                                allowClear
-                                disabled={data.type == 'detail'}
-                                placeholder="请选择"
-                                options={threeCompanyList}
-                                fieldNames={{ label: 'name', value: 'id' }}
-                                filterOption={false}
-                            >
-                            </Select >
-                        </Form.Item>
-                    </Col> */}
-                </Row>
-                {/* <Row>
-                    <Col span={8}>
-                        <Form.Item
-                            name="fourDepartmentId"
-                            label="所属四级单位"
-                        >
-                            <Select
-                                key="searchSelect"
-                                allowClear
-                                disabled={data.type == 'detail'}
-                                placeholder="请选择"
-                                options={fourCompanyList}
-                                fieldNames={{ label: 'name', value: 'id' }}
-                                filterOption={false}
-                            >
-                            </Select >
-                        </Form.Item>
-                    </Col>
-                </Row> */}
-                <Row>
                     <Col span={8}>
                         <Form.Item
                             name="systemPostId"
@@ -360,197 +393,120 @@
                             rules={[{ required: true, message: '请选择所属职位' }]}
                         >
                             <Select
-                                key="searchSelect"
                                 allowClear
                                 disabled={data.type == 'detail'}
                                 placeholder="请选择"
                                 options={positionList}
                                 fieldNames={{ label: 'name', value: 'id' }}
                                 filterOption={false}
-                            >
-                            </Select >
+                            />
                         </Form.Item>
                     </Col>
                     <Col span={8}>
                         <Form.Item
                             name="systemRoleId"
-                            label="所属角色"
-                            rules={[{ required: true, message: '请选择所属角色' }]}
+                            label="后台权限"
+                            rules={[{ required: true, message: '请选择后台权限' }]}
                         >
                             <Select
-                                key="searchSelect"
                                 allowClear
                                 disabled={data.type == 'detail'}
                                 placeholder="请选择"
                                 options={roleList}
                                 fieldNames={{ label: 'name', value: 'id' }}
                                 filterOption={false}
-                            >
-                            </Select >
+                            />
                         </Form.Item>
                     </Col>
                 </Row>
-                <Row>
+                <Row gutter={16}>
+                    <Col span={24}>
+                        <Form.Item
+                            label="账号所属层级"
+                            colon={true}
+                            required
+                            labelCol={{ span: 2 }}
+                            wrapperCol={{ span: 12 }}
+                            style={{ marginBottom: 0 }}
+                        >
+                            <Button type={'primary'} onClick={addAccountLevel} style={{ marginBottom: 8 }}>添加</Button>
+                            {accountLevels.map((item, idx) => (
+                                <Card key={idx} style={{ marginBottom: 8 }} size='small' >
+                                    <div style={{ display: 'flex', alignItems: 'center' }}>
+                                        <Cascader
+                                            style={{ width: 320, marginRight: 16 }}
+                                            placeholder="请选择区域"
+                                            options={cascaderData}
+                                            fieldNames={{ label: 'name', value: 'id' }}
+                                            value={item.area}
+                                            onChange={(value, selectedOptions) => {
+                                                setAccountLevels(levels => {
+                                                    const newLevels = [...levels];
+                                                    newLevels[idx] = {
+                                                        ...newLevels[idx],
+                                                        area: value,
+                                                        selectedOptions: selectedOptions,
+                                                        // 清空原有数据,确保新选择的数据生效
+                                                        community: '',
+                                                        communityId: '',
+                                                        districts: '',
+                                                        districtsCode: '',
+                                                        street: '',
+                                                        streetId: '',
+                                                        level: selectedOptions?.[0]?.id || ''
+                                                    };
+                                                    return newLevels;
+                                                });
+                                            }}
+                                        />
+
+                                        <div style={{ marginLeft: 16, marginTop: 22 }}>
+                                            <span style={{ marginRight: 8 }}>是否为纪检委账号:</span>
+                                            <Radio.Group
+                                                style={{ marginRight: 16 }}
+                                                value={item.isDiscipline ?? 0}
+                                                onChange={e => handleDisciplineChange(e, idx)}
+                                                options={[
+                                                    { label: '否', value: 0 },
+                                                    { label: '是', value: 1 }
+                                                ]}
+                                            />
+                                        </div>
+
+                                        {idx > 0 && <DeleteOutlined style={{ marginRight: 16 }} onClick={() => removeAccountLevel(idx)} disabled={accountLevels.length === 1} />}
+
+                                    </div>
+                                </Card>
+                            ))}
+                        </Form.Item>
+                    </Col>
+                </Row>
+                <Row gutter={16}>
                     <Col span={8}>
                         <Form.Item
-                            name="accountLevel"
-                            label="账号层级"
-                            rules={[{ required: true, message: '请选择账号层级' }]}
-                        >
-                            <Select
-                                key="searchSelect"
-                                allowClear
-                                onChange={(e) => setActiveLevel(e)}
-                                disabled={data.type == 'detail'}
-                                placeholder="请选择"
-                                options={levelList}
-                                fieldNames={{ label: 'name', value: 'value' }}
-                            // filterOption={false}
-                            >
-                            </Select >
-                        </Form.Item>
-                    </Col>
-                    <Col span={16}>
-                        <Form.Item
-                            label="是否管理员"
-                            labelCol={{ span: 4 }}
-                            wrapperCol={{ span: 20 }}
-                            style={{ marginBottom: 0 }}
-                        >
-                            <div style={{ display: "flex", flex: 1 }}>
-                                <Form.Item
-                                    name="isAdmin"
-                                    rules={[{ required: true, message: '是否管理员' }]}
-                                >
-                                    <Radio.Group
-                                        disabled={data.type == 'detail'}
-                                        // style={style}
-                                        // onChange={onChange}
-                                        // value={value}
-                                        options={[{ value: 0, label: '否', }, { value: 1, label: '是', },
-
-                                        ]}
-                                    />
-                                </Form.Item>
-                                <div style={{ fontSize: '12px', color: "rgba(0,0,0,0.5)", marginLeft: "10px" }}>管理员主要用于接收实现临期提醒,以及上级端登录</div>
-                            </div>
-                        </Form.Item>
-                    </Col>
-                </Row>
-                {activeLevel != 1 && (
-                    <Row>
-                        {[2, 3, 4, 5].includes(activeLevel) && (
-                            <Col span={8}>
-                                <Form.Item
-                                    name="districtsCode"
-                                    label="所属区县"
-                                    rules={[{ required: true, message: '请选择所属区县' }]}
-                                >
-                                    {/* <Select
-                                // onChange={changeCountry}
-                                // value={activeCounty}
-                                placeholder="请选择"
-                                options={levelList}
-                                fieldNames={{ label: 'name', value: 'id' }}
-                            >
-                            </Select > */}
-                                    <Select
-                                        key="searchSelect"
-                                        allowClear
-                                        disabled={data.type == 'detail' || [2, 3, 4, 5].includes(adminLevel)}
-                                        onChange={changeCountry}
-                                        value={activeCounty.id}
-                                        placeholder="请选择"
-                                        options={countyList}
-                                        fieldNames={{ label: 'name', value: 'id' }}
-                                    // filterOption={false}
-                                    >
-                                    </Select >
-                                </Form.Item>
-                            </Col>
-                        )}
-                        {[3, 4, 5].includes(activeLevel) && (
-                            <Col span={8}>
-                                <Form.Item
-                                    name="streetId"
-                                    label="所属街道"
-                                    rules={[{ required: true, message: '请选择所属街道' }]}
-                                >
-                                    <Select
-                                        onChange={changeStreet}
-                                        disabled={!activeCounty || data.type == 'detail' || [3, 4, 5].includes(adminLevel)}
-                                        key="searchSelect"
-                                        allowClear
-                                        value={activeStreet.id}
-                                        placeholder="请选择"
-                                        options={streetList}
-                                        fieldNames={{ label: 'name', value: 'id' }}
-                                    >
-                                    </Select >
-                                </Form.Item>
-                            </Col>
-                        )}
-
-                        {[4, 5].includes(activeLevel) && (
-                            <Col span={8}>
-                                <Form.Item
-                                    name="communityId"
-                                    label="所属社区"
-                                    rules={[{ required: true, message: '请选择所属社区' }]}
-                                >
-                                    <Select
-                                        onChange={changeCommunity}
-                                        disabled={!activeStreet || data.type == 'detail' || [4, 5].includes(adminLevel)}
-                                        key="searchSelect"
-                                        allowClear
-                                        value={activeCommunity.id}
-                                        placeholder="请选择"
-                                        options={communityList}
-                                        fieldNames={{ label: 'name', value: 'id' }}
-                                    >
-                                    </Select >
-                                </Form.Item>
-                            </Col>
-                        )}
-                    </Row>
-                )}
-
-                <Row>
-                    <Col span={16}>
-                        <Form.Item
                             label="联系方式"
-                            required
-                            labelCol={{ span: 4 }}
-                            wrapperCol={{ span: 20 }}
-                            style={{ marginBottom: 0 }}
+                            name="phone"
+                            extra={'联系方式将作为登录账号使用'}
+                            rules={[{
+                                validator: (rule, value) => {
+                                    return new Promise((resolve, reject) => {
+                                        if (!value) {
+                                            reject('请输入联系方式');
+                                        }
+                                        const phoneRegex = /^((\+86)?(13|14|15|16|17|18|19)[0-9]{9})|((\+86)?(0[0-9]{2,3})?([2-9][0-9]{6,7}))$/;
+                                        if (!phoneRegex.test(value)) {
+                                            reject('请输入正确的电话号码');
+                                        }
+                                        resolve('');
+                                    });
+                                },
+                            }]}
                         >
-                            <div style={{ display: "flex", flex: 1 }}>
-                                <Form.Item
-                                    name="phone"
-
-                                    rules={[{
-                                        validator: (rule, value) => {
-                                            return new Promise((resolve, reject) => {
-                                                if (!value) {
-                                                    reject('请输入联系方式');
-                                                }
-                                                const phoneRegex = /^((\+86)?(13|14|15|16|17|18|19)[0-9]{9})|((\+86)?(0[0-9]{2,3})?([2-9][0-9]{6,7}))$/;
-                                                if (!phoneRegex.test(value)) {
-                                                    reject('请输入正确的电话号码');
-                                                }
-                                                resolve('');
-                                            });
-                                        },
-                                    }]}
-                                >
-                                    <Input disabled={data.type == 'detail'} placeholder='请输入联系方式' />
-                                </Form.Item>
-                                <div style={{ fontSize: '12px', color: "rgba(0,0,0,0.5)", marginLeft: "10px" }}>联系方式将作为登录账号使用</div>
-                            </div>
+                            <Input disabled={data.type == 'detail'} placeholder='请输入联系方式' />
                         </Form.Item>
                     </Col>
                 </Row>
-                <Row>
+                <Row gutter={16}>
                     <Col span={8}>
                         <Form.Item
                             required={data.type == 'add'}
@@ -574,39 +530,32 @@
                             <Input.Password disabled={data.type == 'detail'} placeholder='请输入' />
                         </Form.Item>
                     </Col>
-                    <Col span={16}>
+                </Row>
+                <Row gutter={16}>
+                    <Col span={8}>
                         <Form.Item
                             label="确认密码"
+                            name="surePassword"
+                            extra={'密码需要包含大小写字母,数字和特殊符号,且长度为8位以上'}
                             required={data.type == 'add'}
-                            labelCol={{ span: 4 }}
-                            wrapperCol={{ span: 20 }}
-                            style={{ marginBottom: 0 }}
+                            rules={[{
+                                validator: (rule, value) => {
+                                    return new Promise((resolve, reject) => {
+                                        if (!value && data.type == 'add') {
+                                            reject('请再次输入新密码');
+                                        }
+                                        if (value != form.getFieldValue('password') && data.type == 'add') {
+                                            reject('两次密码请保持一致');
+                                        }
+                                        resolve('');
+                                    });
+                                },
+                            }]}
                         >
-                            <div style={{ display: "flex", flex: 1 }}>
-                                <Form.Item
-                                    name="surePassword"
-                                    rules={[{
-                                        validator: (rule, value) => {
-                                            return new Promise((resolve, reject) => {
-                                                if (!value && data.type == 'add') {
-                                                    reject('请再次输入新密码');
-                                                }
-                                                if (value != form.getFieldValue('password') && data.type == 'add') {
-                                                    reject('两次密码请保持一致');
-                                                }
-                                                resolve('');
-                                            });
-                                        },
-                                    },]}
-                                >
-                                    <Input.Password disabled={data.type == 'detail'} placeholder='请输入' />
-                                </Form.Item>
-                                <div style={{ fontSize: '12px', color: "rgba(0,0,0,0.5)", marginLeft: "10px" }}>密码需要包含大小写字母,数字和特殊符号,且长度为8位以上</div>
-                            </div>
+                            <Input.Password disabled={data.type == 'detail'} placeholder='请输入' />
                         </Form.Item>
                     </Col>
                 </Row>
-
 
             </Form>
             <Spin spinning={spinning} fullscreen />
diff --git a/management/src/pages/setting/user/index.jsx b/management/src/pages/setting/user/index.jsx
index d159be5..c0ab038 100644
--- a/management/src/pages/setting/user/index.jsx
+++ b/management/src/pages/setting/user/index.jsx
@@ -1,7 +1,7 @@
 import { buildProTableDataSource, sendRequest, showDelConfirm, showConfirm } from '@/utils/antdUtils';
 import { DeleteOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons';
-import { PageContainer, ProFormText, ProTable, QueryFilter } from '@ant-design/pro-components';
-import { Button, Cascader, Col, Menu, Row, Select, Space } from 'antd';
+import { PageContainer, ProFormText, ProTable, QueryFilter, ProFormSelect } from '@ant-design/pro-components';
+import { Button, Cascader, Col, Menu, Row, Select, Space, Form } from 'antd';
 import { useEffect, useRef, useState } from 'react';
 import { Access, useAccess } from 'umi';
 import AddAndEdit from './components/addAndEdit';
@@ -21,6 +21,7 @@
 } from './service';
 
 const Role = () => {
+  const [form] = Form.useForm();
   const actionRef = useRef();
   const addViewRef = useRef();
   const addViewRef1 = useRef();
@@ -48,7 +49,7 @@
         }}
       >
         <span>{item.name}</span>
-        <div>
+        {/* <div>
           {item.tier < 4 && (
             <Access accessible={access['/system_setting/unit_management/add']}>
               <PlusOutlined
@@ -82,31 +83,40 @@
               }}
             />
           </Access>
-        </div>
+        </div> */}
       </div >
     );
   };
-  const renderMenuItems = (items) => {
+  const renderMenuItems = (items, level = 0) => {
     return items.map((item) => {
       if (item.children && item.children.length > 0) {
         return (
           <SubMenu
             key={item.key}
             title={node(item)}
-            onTitleClick={(item) => {
-              setUnitId(item.key);
-              actionRef.current.reload();
+            onTitleClick={(e) => {
+              if (e && e.domEvent) {
+                e.domEvent.stopPropagation();
+              }
+              setUnitId(item.id);
+              const values = form.getFieldsValue();
+              actionRef.current.reload(values);
             }}
           >
-            {renderMenuItems(item.children)}
+            {renderMenuItems(item.children, level + 1)}
           </SubMenu>
         );
       }
       return (
         <Menu.Item
-          onClick={(item) => {
-            setUnitId(item.key);
-            actionRef.current.reload();
+          onClick={(e) => {
+            if (e && e.domEvent) {
+              e.domEvent.stopPropagation();
+            }
+            const itemId = item.id || item.key;
+            setUnitId(itemId);
+            const values = form.getFieldsValue();
+            actionRef.current.reload(values);
           }}
           key={item.key}
         >
@@ -120,6 +130,8 @@
       if (res.code == 200 && res.data) {
         const traverseItems = (items) => {
           return items.map((item) => {
+            if (!item.id) {
+            }
             item.key = item.id;
             item.title = '1';
             if (item.child && item.child.length > 0) {
@@ -128,7 +140,8 @@
             return item;
           });
         };
-        setItems(traverseItems(res.data));
+        const processedItems = traverseItems(res.data);
+        setItems(processedItems);
       }
     });
   };
@@ -141,50 +154,50 @@
       title: '联系方式',
       dataIndex: 'phone',
     },
-    {
-      title: '所在单位',
-      dataIndex: 'departmentName',
-      hideInSearch: true,
-      renderFormItem: () => {
-        return (
-          <Cascader
-            options={items}
-            fieldNames={{ value: 'key', label: 'name' }}
-            placeholder="请选择"
-            displayRender={(label) => label[label.length - 1]}
-            changeOnSelect={true}
-          />
-        );
-      },
-    },
-    {
-      hideInTable: true,
-      title: '所在单位',
-      dataIndex: 'departmentId',
-      renderFormItem: () => {
-        return (
-          <Cascader
-            options={items}
-            fieldNames={{ value: 'key', label: 'name' }}
-            placeholder="请选择"
-            displayRender={(label) => label[label.length - 1]}
-            changeOnSelect={true}
-          />
-        );
-      },
-    },
+    // {
+    //   title: '所在单位',
+    //   dataIndex: 'departmentName',
+    //   hideInSearch: true,
+    //   renderFormItem: () => {
+    //     return (
+    //       <Cascader
+    //         options={items}
+    //         fieldNames={{ value: 'key', label: 'name' }}
+    //         placeholder="请选择"
+    //         displayRender={(label) => label[label.length - 1]}
+    //         changeOnSelect={true}
+    //       />
+    //     );
+    //   },
+    // },
+    // {
+    //   hideInTable: true,
+    //   title: '所属权限',
+    //   dataIndex: 'departmentId',
+    //   renderFormItem: () => {
+    //     return (
+    //       <Cascader
+    //         options={items}
+    //         fieldNames={{ value: 'key', label: 'name' }}
+    //         placeholder="请选择"
+    //         displayRender={(label) => label[label.length - 1]}
+    //         changeOnSelect={true}
+    //       />
+    //     );
+    //   },
+    // },
     {
       title: '所属职位',
       dataIndex: 'systemPostName',
       hideInSearch: true,
     },
     {
-      title: '所属角色',
+      title: '后台权限',
       dataIndex: 'systemRoleName',
       hideInSearch: true,
     },
     {
-      title: '所属角色',
+      title: '所属权限',
       dataIndex: 'systemRoleId',
       hideInTable: true,
       renderFormItem: () => {
@@ -201,31 +214,24 @@
       },
     },
     {
-      title: '账号层级',
+      title: '账号所属层级',
       dataIndex: 'accountLevel',
       // (1=市级账号,2=区县账号,3=街道账号,4=社区账号)
       render: (text, record) => {
-        let role = '';
-        switch (record.accountLevel) {
-          case 1:
-            role = '市';
-            break;
-          case 2:
-            role = '区县';
-            break;
-          case 3:
-            role = '街道';
-            break;
-          case 4:
-            role = '社区';
-            break;
-          case 5:
-            role = '党员';
-            break;
-          default:
-            role = '';
-        }
-        return role;
+        record.list.length>0&&record.list.map(item=>{
+          item.str = ''
+          if(item.level==1){
+           item.str = '市'
+          }else if(item.level==2){
+           item.str = '区县' + '/' + item.districts
+          }else if(item.level==3){
+            item.str = '街道' + '/' + item.districts + '/' + item.street
+          }else{
+            item.str = '社区' + '/' + item.districts + '/' + item.street + '/' + item.community
+          }
+          return item.str;
+        })
+        return record.list.map(item=>item.str).join('、');
       },
       valueEnum: {
         1: '市',
@@ -265,7 +271,7 @@
               <Access accessible={access['/system_setting/people_management/edit']}>
                 <a
                   onClick={() => {
-                    addViewRef.current.refreshData({ ...record, type: 'edit' },items);
+                    addViewRef.current.refreshData({ ...record, type: 'edit' }, items);
                     handleModalVisibles(true);
                   }}
                 >
@@ -292,7 +298,7 @@
             <Access accessible={access['/system_setting/people_management/detail']}>
               <a
                 onClick={() => {
-                  addViewRef.current.refreshData({ ...record, type: 'detail' },items);
+                  addViewRef.current.refreshData({ ...record, type: 'detail' }, items);
                   handleModalVisibles(true);
                 }}
               >
@@ -302,7 +308,7 @@
             <Access accessible={access['/system_setting/people_management/freeze']}>
               <a
                 onClick={() => {
-                  showConfirm(`确认${record.status === 1 ? '冻结' : '解冻'}该人员吗?`,'', async () => {
+                  showConfirm(`确认${record.status === 1 ? '冻结' : '解冻'}该人员吗?`, '', async () => {
                     let status = await sendRequest(
                       record.status === 1 ? freezeApi : unfreezeApi,
                       record.id,
@@ -331,6 +337,8 @@
     >
       <div style={{ background: '#fff' }}>
         <QueryFilter
+          form={form}
+          labelWidth={100}
           onReset={(values) => {
             fetchUnit(values);
             setUnitId('');
@@ -342,14 +350,21 @@
             actionRef.current.reload();
           }}
         >
-          <ProFormText name="name" label="单位名称" />
+          <ProFormText name="name" label="组织结构名称" />
+          <ProFormSelect name="type" label="筛选维度" options={[{
+            label: '当前组织结构',
+            value: 1,
+          }, {
+            label: '当前及下级组织结构',
+            value: 2,
+          }]} />
         </QueryFilter>
       </div>
       <Row style={{ marginTop: 20, background: '#fff' }}>
         <Col span={4}>
           <Space style={{ margin: '10px 0' }}>
-            <span style={{ margin: '0 27px' }}>单位管理</span>
-            <Button
+            <span style={{ margin: '0 27px' }}>组织结构</span>
+            {/* <Button
               type="primary"
               onClick={() => {
                 addViewRef1.current.refreshData({});
@@ -357,10 +372,17 @@
               }}
             >
               添加
-            </Button>
+            </Button> */}
           </Space>
 
-          <Menu mode="inline">{renderMenuItems(items)}</Menu>
+          <Menu 
+            mode="inline"
+            onClick={({ key, domEvent }) => {
+              domEvent.stopPropagation();
+            }}
+          >
+            {renderMenuItems(items)}
+          </Menu>
         </Col>
         <Col span={20} style={{ minHeight: 650 }}>
           <ProTable
@@ -385,6 +407,9 @@
               if (params.departmentId) {
                 obj.departmentId = params.departmentId[params.departmentId.length - 1];
               }
+              if (form.getFieldValue('type')) {
+                obj.type = form.getFieldValue('type');
+              }
               return buildProTableDataSource(getList, obj);
             }}
             toolBarRender={(action, selectRows) => [
@@ -393,7 +418,7 @@
                   <Button
                     type="primary"
                     onClick={() => {
-                      addViewRef.current.refreshData({ type: 'add', unitId : unitId  },items);
+                      addViewRef.current.refreshData({ type: 'add', unitId: unitId }, items);
                       handleModalVisibles(true);
                     }}
                   >
diff --git a/management/src/pages/setting/user/index.less b/management/src/pages/setting/user/index.less
new file mode 100644
index 0000000..17eba53
--- /dev/null
+++ b/management/src/pages/setting/user/index.less
@@ -0,0 +1,5 @@
+.addAndEditModal{
+    .ant-modal-body{
+        padding: 0 !important;
+    }   
+}
\ No newline at end of file
diff --git a/management/src/pages/setting/user/service.js b/management/src/pages/setting/user/service.js
index d300fa1..ae7691e 100644
--- a/management/src/pages/setting/user/service.js
+++ b/management/src/pages/setting/user/service.js
@@ -134,4 +134,12 @@
     return request(`/api/huacheng-sangeshenbian/systemUser/unfreeze/${id}`, {
         method: 'PUT',
     });
-}
\ No newline at end of file
+}
+
+
+//获取级联数据
+export const getCascaderData = async (data) => {
+    return request(`/api/huacheng-sangeshenbian/systemUser/getAdministrativeDivisionTwo`, {
+        method: 'GET',
+    });
+}
diff --git a/management/src/requestErrorConfig.ts b/management/src/requestErrorConfig.ts
index 10d9de4..cf32d48 100644
--- a/management/src/requestErrorConfig.ts
+++ b/management/src/requestErrorConfig.ts
@@ -26,7 +26,7 @@
  * @doc https://umijs.org/docs/max/request#配置
  */
 export const errorConfig: RequestConfig = {
-  baseURL: BASE_URL,
+  // baseURL: BASE_URL,
 
   // 请求拦截器
   requestInterceptors: [

--
Gitblit v1.7.1