currentDetails.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. <template>
  2. <view class="bg-[#f5f7fa] min-h-screen pb-[40rpx]">
  3. <!-- 基本信息 -->
  4. <view class="bg-white rounded-[12rpx] mx-[20rpx] mb-[20rpx] p-[30rpx]">
  5. <view class="text-[32rpx] font-bold mb-[30rpx]">基本信息</view>
  6. <view v-if="loading" class="py-[50rpx] text-center text-[28rpx] text-[#999]">加载中...</view>
  7. <view v-else-if="dictLoadError" class="py-[50rpx] text-center text-[28rpx] text-[#f56c6c]">
  8. <view>数据加载失败</view>
  9. <view class="text-[24rpx] mt-[10rpx]" @click="reloadDictData">点击重新加载</view>
  10. </view>
  11. <view v-else>
  12. <view class="flex items-center mb-[30rpx]">
  13. <view class="text-[30rpx] text-[#333] w-[200rpx]">承包方姓名</view>
  14. <view class="flex-1 text-right text-[30rpx]">{{ editForm.cbfmc || '未填写' }}</view>
  15. </view>
  16. <view class="flex justify-between items-center mb-[30rpx]">
  17. <view class="text-[30rpx] text-[#666]">承包方编码</view>
  18. <view class="text-[30rpx] text-[#333]">{{ farmerInfo?.cbfbm || '未填写' }}</view>
  19. </view>
  20. <view class="flex items-center mb-[30rpx]">
  21. <view class="text-[30rpx] text-[#333] w-[200rpx]">证件类型</view>
  22. <view class="flex-1 text-right text-[30rpx]">{{ getDictLabel('idType', editForm.zjlx) || '未选择' }}
  23. </view>
  24. </view>
  25. <view class="flex items-center mb-[30rpx]">
  26. <view class="text-[30rpx] text-[#333] w-[200rpx]">证件号码</view>
  27. <view class="flex-1 text-right text-[30rpx]">{{ editForm.cbfzjhm || '未填写' }}</view>
  28. </view>
  29. <view class="flex items-center mb-[30rpx]">
  30. <view class="text-[30rpx] text-[#333] w-[200rpx]">承包方类型</view>
  31. <view class="flex-1 text-right text-[30rpx]">
  32. {{ getDictLabel('farmerType', editForm.cbflx) || '未选择' }}
  33. </view>
  34. </view>
  35. <view class="flex items-center mb-[30rpx]">
  36. <view class="text-[30rpx] text-[#333] w-[200rpx]">联系电话</view>
  37. <view class="flex-1 text-right text-[30rpx]">{{ editForm.lxdh || '未填写' }}</view>
  38. </view>
  39. <view class="flex items-center mb-[30rpx]">
  40. <view class="text-[30rpx] text-[#666] w-[200rpx]">邮政编码</view>
  41. <view class="flex-1 text-right text-[30rpx]">{{ editForm.yzbm || '未填写' }}</view>
  42. </view>
  43. <view class="flex items-start mb-[20rpx]">
  44. <view class="text-[30rpx] text-[#333] w-[200rpx] pt-[10rpx]">承包方地址</view>
  45. <view class="flex-1 text-[30rpx] leading-[1.6]">{{ editForm.cbfdz || '未填写' }}</view>
  46. </view>
  47. </view>
  48. </view>
  49. <!-- 家庭成员 -->
  50. <!-- <view class="bg-white rounded-[12rpx] mx-[20rpx] mb-[20rpx] p-[30rpx]">
  51. <view class="text-[32rpx] font-bold mb-[30rpx]">家庭成员</view>
  52. <view class="text-[30rpx] text-[#333] mb-[20rpx]">家庭成员信息({{ familyMembers.length }})</view>
  53. <view v-for="(item, index) in familyMembers" :key="index"
  54. class="bg-[#f8f9fa] rounded-[12rpx] p-[20rpx] mb-[20rpx]">
  55. <view v-if="hasStatus(item.bizStatus)" class="status-text mb-[10rpx]">
  56. 状态:<text
  57. :class="formatStatus(item.bizStatus).className">{{ formatStatus(item.bizStatus).text }}</text>
  58. </view>
  59. <view>
  60. <view class="text-[30rpx] text-[#333] mb-[10rpx]">
  61. {{ item.cyxm }}&nbsp;&nbsp;&nbsp;&nbsp;{{ getDictLabel('cyxb', item.cyxb) }}&nbsp;&nbsp;&nbsp;&nbsp;{{ getDictLabel('yhzgx', item.yhzgx) }}
  62. </view>
  63. <view class="text-[32rpx] text-[#666] mt-[10rpx]">{{ item.cyzjhm }}</view>
  64. </view>
  65. </view>
  66. </view> -->
  67. <!-- 地块信息 -->
  68. <view class="bg-white rounded-[12rpx] mx-[20rpx] mb-[20rpx] p-[30rpx]">
  69. <view class="text-[32rpx] font-bold mb-[30rpx]">地块信息</view>
  70. <view class="text-[28rpx] text-[#666] mb-[20rpx]">地块数量&nbsp;&nbsp;{{ landList.length }}&nbsp;&nbsp;块</view>
  71. <view v-for="(item, index) in landList" :key="index"
  72. class="bg-[#f8f9fa] rounded-[12rpx] p-[20rpx] mb-[20rpx]" @click="jumpplotDetails(item)">
  73. <view v-if="hasStatus(item.dkTemp?.bizStatus)" class="status-text mb-[10rpx]">
  74. 状态:<text
  75. :class="formatStatus(item.dkTemp?.bizStatus).className">{{ formatStatus(item.dkTemp?.bizStatus).text }}</text>
  76. </view>
  77. <view class="flex justify-between items-center mb-[10rpx]">
  78. <view class="text-[30rpx] text-[#007aff] flex items-center">
  79. <view>{{ item.dkTemp?.dkbm ? item.dkTemp.dkbm.slice(-5) : '' }}</view>
  80. <view class="ml-[20rpx]">{{ item.dkTemp?.dkmc || '' }}</view>
  81. <view class="ml-[20rpx]">{{ item.cbdkxxTemp?.htmjm || 0 }}亩</view>
  82. </view>
  83. <view class="text-[28rpx] text-[#007aff]" @click.stop="handleViewLandPosition(item)">地块位置</view>
  84. </view>
  85. <view class="text-[32rpx] text-[#666] mb-[5rpx] flex">
  86. <view>地块东至:{{ item.dkTemp?.dkdz || '无' }}</view>
  87. <view class="ml-[100rpx]">地块西至:{{ item.dkTemp?.dkxz || '无' }}</view>
  88. </view>
  89. <view class="text-[32rpx] text-[#666] flex mt-[20rpx]">
  90. <view>地块南至:{{ item.dkTemp?.dknz || '无' }}</view>
  91. <view class="ml-[100rpx]">地块北至:{{ item.dkTemp?.dkbz || '无' }}</view>
  92. </view>
  93. </view>
  94. </view>
  95. <!-- 附件 -->
  96. <view class="bg-white rounded-[12rpx] mx-[20rpx] mb-[20rpx] p-[30rpx]">
  97. <view class="flex justify-between items-center">
  98. <view class="text-[32rpx] font-bold">附件信息</view>
  99. <view class="text-[28rpx] text-[#007aff]" @click="handleUploadAttachment">
  100. {{ attachmentList.length > 0 ? `已上传 ${attachmentList.length} 个` : '暂无附件' }}
  101. </view>
  102. </view>
  103. </view>
  104. <!-- 审核按钮 -->
  105. <view class="dialog-footer" v-if="displayType === 'Auditing'">
  106. <view class="dialog-btn dialog-btn-cancel" @click.stop="showAuditModal(2)">驳回</view>
  107. <view class="dialog-btn dialog-btn-next" @click.stop="showAuditModal(1)">通过</view>
  108. </view>
  109. </view>
  110. </template>
  111. <script setup lang="ts">
  112. import { ref } from 'vue'
  113. import { onLoad } from '@dcloudio/uni-app';
  114. // @ts-ignore
  115. import { getfarmerLoginData, getDictData, getCbfjtcyData, getCbfdkxxData, getdkxxxxData, getCbfAddDkxxData } from '@/api/farmerApi.js';
  116. import { submitbatchSubmitList, submitbatchVillageAuditList, investigatordksubmit } from '@/api/SubmitApi.js';
  117. const loading = ref(false);
  118. const dictLoadError = ref(false);
  119. const displayType = ref('');
  120. const farmerInfo = ref(null);
  121. const dictData = ref({ idType: [], farmerType: [], cyxb: [], yhzgx: [] });
  122. const editForm = ref({ cbfmc: '', zjlx: '', cbfzjhm: '', cbflx: '', lxdh: '', yzbm: '', cbfdz: '' });
  123. const familyMembers = ref([]);
  124. const landList = ref([]);
  125. const attachmentList = ref([]);
  126. const submittype = ref(null)
  127. // 判断是否需要提交
  128. const hasStatus = (status) => {
  129. return status === 1 || status === 2 || status === '1' || status === '2';
  130. };
  131. // 状态文本
  132. const formatStatus = (status) => {
  133. const num = Number(status);
  134. switch (num) {
  135. case 1: return { text: '新增数据', className: 'status-add' };
  136. case 2: return { text: '修改数据', className: 'status-edit' };
  137. default: return { text: '', className: '' };
  138. }
  139. };
  140. // 字典
  141. const transformDictFormat = (originalDict) => {
  142. if (!originalDict || typeof originalDict !== 'object') return [];
  143. return Object.entries(originalDict).map(([key, value]) => ({ value: String(key), label: String(value) }));
  144. };
  145. const getDictLabel = (dictType, value) => {
  146. if (!value || !dictData.value[dictType]?.length) return '未知';
  147. const item = dictData.value[dictType].find(item => String(item.value) === String(value));
  148. return item?.label || '未知';
  149. };
  150. // 加载
  151. const loadDictData = async () => {
  152. try {
  153. dictLoadError.value = false;
  154. const [resFarmer, resIdType, resCyxb, resYhzgx] = await Promise.all([
  155. getDictData('dic_cbflx'), getDictData('dic_zjlx'), getDictData('dic_xb'), getDictData('dic_yhzgx')
  156. ]);
  157. dictData.value.farmerType = transformDictFormat(resFarmer.data);
  158. dictData.value.idType = transformDictFormat(resIdType.data);
  159. dictData.value.cyxb = transformDictFormat(resCyxb.data);
  160. dictData.value.yhzgx = transformDictFormat(resYhzgx.data);
  161. } catch (e) { dictLoadError.value = true; }
  162. };
  163. const reloadDictData = async () => {
  164. loading.value = true;
  165. await loadDictData();
  166. loading.value = false;
  167. };
  168. // 清空本地数据(提交成功后)
  169. const clearLocalMapData = () => {
  170. try {
  171. uni.removeStorageSync('LOCAL_STORAGE_KEY')
  172. } catch (e) {
  173. console.error('清空本地数据失败')
  174. }
  175. }
  176. const getTotal = async (cbfbm) => {
  177. try {
  178. const res = await getfarmerLoginData({ cbfbm });
  179. if (res.data?.length) {
  180. const info = res.data[0];
  181. farmerInfo.value = info;
  182. editForm.value = {
  183. cbfmc: info.cbfmc || '', zjlx: info.cbfzjlx || '', cbfzjhm: info.cbfzjhm || '',
  184. cbflx: info.cbflx || '', lxdh: info.lxdh || '', yzbm: info.yzbm || '', cbfdz: info.cbfdz || ''
  185. };
  186. }
  187. } catch (e) { }
  188. };
  189. const getcbfjtcyTotal = async (cbfbm) => {
  190. try {
  191. const res = await getCbfjtcyData({ cbfbm });
  192. if (res.data) familyMembers.value = res.data;
  193. } catch (e) { }
  194. };
  195. const getcbfDkxxTotal = async (cbfbm) => {
  196. try {
  197. const res = await getCbfAddDkxxData({ cbfbm });
  198. if (!res.data?.length) return;
  199. landList.value = res.data;
  200. } catch (e) { }
  201. };
  202. // ====================== 核心优化:弹出审核意见框 ======================
  203. const showAuditModal = (type) => {
  204. // 自定义弹窗(高度更高、输入区域更大)
  205. uni.showModal({
  206. title: type === 1 ? '确认通过' : '确认驳回',
  207. editable: true,
  208. placeholderText: type === 2 ? '请输入驳回原因(必填)' : '请输入审核意见(选填)',
  209. success: async (res) => {
  210. if (!res.confirm) return;
  211. const content = res.content?.trim() || '';
  212. // 驳回时必须填写意见
  213. if (type === 2 && !content) {
  214. uni.showToast({ title: '驳回必须填写原因', icon: 'none' });
  215. return;
  216. }
  217. // 通过时可以不填
  218. if(submittype.value === 'official'){
  219. await doSubmitAudit(type, content);
  220. }else if(submittype.value === 'investigator'){
  221. await investigatorSubmitAudit(type, content);
  222. }
  223. clearLocalMapData(); // 提交成功 → 清空本地
  224. }
  225. });
  226. };
  227. // 执行提交(两个接口都能成功 ✅)
  228. const doSubmitAudit = async (type, opinion) => {
  229. try {
  230. // 家庭成员:把 id 转 数字!!!
  231. const fbfbmArray = familyMembers.value
  232. .filter(item => hasStatus(item?.bizStatus))
  233. .map(item => Number(item?.id)) // 🔥 这里必须转数字
  234. .filter(Boolean);
  235. // 地块正常
  236. const landListArray = landList.value
  237. .filter(item => hasStatus(item.dkTemp?.bizStatus))
  238. .map(item => item.dkTemp?.bsm)
  239. .filter(Boolean);
  240. // 两个接口都传对象格式(完全一样)
  241. const JtcyPostData = {
  242. ids: fbfbmArray,
  243. type: type,
  244. opinion: opinion
  245. };
  246. const DkxxPostDat = {
  247. bsms: landListArray,
  248. type: type,
  249. opinion: opinion
  250. };
  251. // 提交
  252. await submitbatchVillageAuditList(DkxxPostDat);
  253. await submitbatchSubmitList(JtcyPostData);
  254. uni.showToast({ title: '提交成功', icon: 'success' });
  255. setTimeout(() => {
  256. uni.navigateBack({
  257. success: () => {
  258. const pages = getCurrentPages();
  259. const prevPage = pages[pages.length - 1];
  260. if (prevPage && typeof prevPage.onLoad === 'function') {
  261. prevPage.onLoad(prevPage.options);
  262. }
  263. }
  264. });
  265. }, 1500);
  266. } catch (e) {
  267. console.error(e);
  268. uni.showToast({ title: '提交失败', icon: 'none' });
  269. }
  270. };
  271. // 执行提交(两个接口都能成功 ✅)
  272. const investigatorSubmitAudit = async (type, opinion) => {
  273. try {
  274. // 地块正常
  275. const landListArray = landList.value
  276. .filter(item => hasStatus(item.dkTemp?.bizStatus))
  277. .map(item => item.dkTemp?.bsm)
  278. .filter(Boolean);
  279. const DkxxPostDat = {
  280. bsms: landListArray,
  281. type: type,
  282. opinion: opinion
  283. };
  284. // 提交
  285. await investigatordksubmit(DkxxPostDat);
  286. uni.showToast({ title: '提交成功', icon: 'success' });
  287. setTimeout(() => {
  288. uni.navigateBack({
  289. success: () => {
  290. const pages = getCurrentPages();
  291. const prevPage = pages[pages.length - 1];
  292. if (prevPage && typeof prevPage.onLoad === 'function') {
  293. prevPage.onLoad(prevPage.options);
  294. }
  295. }
  296. });
  297. }, 1500);
  298. } catch (e) {
  299. console.error(e);
  300. uni.showToast({ title: '提交失败', icon: 'none' });
  301. }
  302. };
  303. // 附件
  304. const handleUploadAttachment = () => {
  305. uni.chooseImage({ count: 5, success: res => attachmentList.value.push(...res.tempFilePaths) });
  306. };
  307. // 地块位置
  308. const handleViewLandPosition = (item) => {
  309. if (!item?.dkTemp.dkbm) { uni.showToast({ title: '地块编码不存在', icon: 'none' }); return; }
  310. uni.navigateTo({ url: `/pages/land/landPosition?code=${item.dkTemp.dkbm}` });
  311. };
  312. // 详情
  313. const jumpplotDetails = (item) => {
  314. console.log(item)
  315. if (!item?.dkTemp.dkbm) { uni.showToast({ title: '地块编码不存在', icon: 'none' }); return; }
  316. uni.navigateTo({ url: `/pages/investigator/Households/plotDetails?code=${item.dkTemp.dkbm}` });
  317. };
  318. onLoad(async (options) => {
  319. submittype.value = options.typedifference;
  320. console.log(123321,options.typedifference,JSON.parse(decodeURIComponent(options.groupInfo)))
  321. loading.value = true;
  322. displayType.value = options.type || '';
  323. await loadDictData();
  324. if (options.groupInfo) {
  325. try {
  326. const info = JSON.parse(decodeURIComponent(options.groupInfo));
  327. if (info.cbfbm) {
  328. await getTotal(info.cbfbm);
  329. await getcbfjtcyTotal(info.cbfbm);
  330. await getcbfDkxxTotal(info.cbfbm);
  331. }
  332. } catch (e) { }
  333. }
  334. loading.value = false;
  335. });
  336. </script>
  337. <style lang="scss" scoped>
  338. page {
  339. background-color: #f5f7fa;
  340. }
  341. .dialog-footer {
  342. display: flex;
  343. padding: 20rpx 30rpx 30rpx;
  344. gap: 20rpx;
  345. }
  346. .dialog-btn {
  347. flex: 1;
  348. height: 80rpx;
  349. border-radius: 40rpx;
  350. display: flex;
  351. align-items: center;
  352. justify-content: center;
  353. font-size: 32rpx;
  354. }
  355. .dialog-btn-cancel {
  356. background: #e5e5e5;
  357. color: #666;
  358. }
  359. .dialog-btn-next {
  360. background: #409eff;
  361. color: #fff;
  362. }
  363. .status-text {
  364. font-size: 28rpx;
  365. color: #333;
  366. margin-bottom: 10rpx;
  367. }
  368. .status-add {
  369. color: #00b42a;
  370. font-weight: 500;
  371. }
  372. .status-edit {
  373. color: #1677ff;
  374. font-weight: 500;
  375. }
  376. /* 全局修改弹窗输入框高度(更高更大) */
  377. :deep(.uni-modal-input) {
  378. height: 80rpx !important;
  379. font-size: 28rpx !important;
  380. padding: 10rpx 15rpx !important;
  381. }
  382. :deep(.uni-modal) {
  383. min-height: 380rpx !important;
  384. }
  385. </style>