地块存在老数据与新数据的两种返回字段数据代码.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  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.dkDetail?.bizStatus)" class="status-text mb-[10rpx]">
  74. 状态:<text
  75. :class="formatStatus(item.dkDetail?.bizStatus).className">{{ formatStatus(item.dkDetail?.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.dkDetail?.dkbm ? item.dkDetail.dkbm.slice(-5) : '' }}</view>
  80. <view class="ml-[20rpx]">{{ item.dkDetail?.dkmc || '' }}</view>
  81. <view class="ml-[20rpx]">{{ item.dkDetail?.scmjm || 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.dkDetail?.dkdz || '无' }}</view>
  87. <view class="ml-[100rpx]">地块西至:{{ item.dkDetail?.dkxz || '无' }}</view>
  88. </view>
  89. <view class="text-[32rpx] text-[#666] flex mt-[20rpx]">
  90. <view>地块南至:{{ item.dkDetail?.dknz || '无' }}</view>
  91. <view class="ml-[100rpx]">地块北至:{{ item.dkDetail?.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 } 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. const getTotal = async (cbfbm) => {
  169. try {
  170. const res = await getfarmerLoginData({ cbfbm });
  171. if (res.data?.length) {
  172. const info = res.data[0];
  173. farmerInfo.value = info;
  174. editForm.value = {
  175. cbfmc: info.cbfmc || '', zjlx: info.cbfzjlx || '', cbfzjhm: info.cbfzjhm || '',
  176. cbflx: info.cbflx || '', lxdh: info.lxdh || '', yzbm: info.yzbm || '', cbfdz: info.cbfdz || ''
  177. };
  178. }
  179. } catch (e) { }
  180. };
  181. const getcbfjtcyTotal = async (cbfbm) => {
  182. try {
  183. const res = await getCbfjtcyData({ cbfbm });
  184. if (res.data) familyMembers.value = res.data;
  185. } catch (e) { }
  186. };
  187. const getcbfDkxxTotal = async (cbfbm) => {
  188. try {
  189. const res = await getCbfdkxxData({ cbfbm });
  190. if (!res.data?.length) return;
  191. const list = [...res.data];
  192. for (let i = 0; i < list.length; i++) {
  193. if (list[i].dkbm) {
  194. const dk = await getdkxxxxData({ dkbm: list[i].dkbm });
  195. list[i].dkDetail = dk.data[0]?.dk || dk.data[0]?.dkTemp || {};
  196. }
  197. }
  198. landList.value = list;
  199. } catch (e) { }
  200. };
  201. // ====================== 核心优化:弹出审核意见框 ======================
  202. const showAuditModal = (type) => {
  203. // 自定义弹窗(高度更高、输入区域更大)
  204. uni.showModal({
  205. title: type === 1 ? '确认通过' : '确认驳回',
  206. editable: true,
  207. placeholderText: type === 2 ? '请输入驳回原因(必填)' : '请输入审核意见(选填)',
  208. success: async (res) => {
  209. if (!res.confirm) return;
  210. const content = res.content?.trim() || '';
  211. // 驳回时必须填写意见
  212. if (type === 2 && !content) {
  213. uni.showToast({ title: '驳回必须填写原因', icon: 'none' });
  214. return;
  215. }
  216. // 通过时可以不填
  217. if(submittype.value === 'official'){
  218. await doSubmitAudit(type, content);
  219. }else if(submittype.value === 'investigator'){
  220. await investigatorSubmitAudit(type, content);
  221. }
  222. }
  223. });
  224. };
  225. // 执行提交(两个接口都能成功 ✅)
  226. const doSubmitAudit = async (type, opinion) => {
  227. try {
  228. // 家庭成员:把 id 转 数字!!!
  229. const fbfbmArray = familyMembers.value
  230. .filter(item => hasStatus(item?.bizStatus))
  231. .map(item => Number(item?.id)) // 🔥 这里必须转数字
  232. .filter(Boolean);
  233. // 地块正常
  234. const landListArray = landList.value
  235. .filter(item => hasStatus(item.dkDetail?.bizStatus))
  236. .map(item => item.dkDetail?.bsm)
  237. .filter(Boolean);
  238. // 两个接口都传对象格式(完全一样)
  239. const JtcyPostData = {
  240. ids: fbfbmArray,
  241. type: type,
  242. opinion: opinion
  243. };
  244. const DkxxPostDat = {
  245. bsms: landListArray,
  246. type: type,
  247. opinion: opinion
  248. };
  249. // 提交
  250. await submitbatchVillageAuditList(DkxxPostDat);
  251. await submitbatchSubmitList(JtcyPostData);
  252. uni.showToast({ title: '提交成功', icon: 'success' });
  253. setTimeout(() => {
  254. uni.navigateBack({
  255. success: () => {
  256. const pages = getCurrentPages();
  257. const prevPage = pages[pages.length - 1];
  258. if (prevPage && typeof prevPage.onLoad === 'function') {
  259. prevPage.onLoad(prevPage.options);
  260. }
  261. }
  262. });
  263. }, 1500);
  264. } catch (e) {
  265. console.error(e);
  266. uni.showToast({ title: '提交失败', icon: 'none' });
  267. }
  268. };
  269. // 执行提交(两个接口都能成功 ✅)
  270. const investigatorSubmitAudit = async (type, opinion) => {
  271. try {
  272. // 地块正常
  273. const landListArray = landList.value
  274. .filter(item => hasStatus(item.dkDetail?.bizStatus))
  275. .map(item => item.dkDetail?.bsm)
  276. .filter(Boolean);
  277. const DkxxPostDat = {
  278. bsms: landListArray,
  279. type: type,
  280. opinion: opinion
  281. };
  282. // 提交
  283. await investigatordksubmit(DkxxPostDat);
  284. uni.showToast({ title: '提交成功', icon: 'success' });
  285. setTimeout(() => {
  286. uni.navigateBack({
  287. success: () => {
  288. const pages = getCurrentPages();
  289. const prevPage = pages[pages.length - 1];
  290. if (prevPage && typeof prevPage.onLoad === 'function') {
  291. prevPage.onLoad(prevPage.options);
  292. }
  293. }
  294. });
  295. }, 1500);
  296. } catch (e) {
  297. console.error(e);
  298. uni.showToast({ title: '提交失败', icon: 'none' });
  299. }
  300. };
  301. // 附件
  302. const handleUploadAttachment = () => {
  303. uni.chooseImage({ count: 5, success: res => attachmentList.value.push(...res.tempFilePaths) });
  304. };
  305. // 地块位置
  306. const handleViewLandPosition = (item) => {
  307. if (!item?.dkbm) { uni.showToast({ title: '地块编码不存在', icon: 'none' }); return; }
  308. uni.navigateTo({ url: `/pages/land/landPosition?code=${item.dkbm}` });
  309. };
  310. // 详情
  311. const jumpplotDetails = (item) => {
  312. if (!item?.dkbm) { uni.showToast({ title: '地块编码不存在', icon: 'none' }); return; }
  313. uni.navigateTo({ url: `/pages/investigator/Households/plotDetails?code=${item.dkbm}` });
  314. };
  315. onLoad(async (options) => {
  316. submittype.value = options.typedifference;
  317. console.log(123321,options.typedifference,JSON.parse(decodeURIComponent(options.groupInfo)))
  318. loading.value = true;
  319. displayType.value = options.type || '';
  320. await loadDictData();
  321. if (options.groupInfo) {
  322. try {
  323. const info = JSON.parse(decodeURIComponent(options.groupInfo));
  324. if (info.cbfbm) {
  325. await getTotal(info.cbfbm);
  326. await getcbfjtcyTotal(info.cbfbm);
  327. await getcbfDkxxTotal(info.cbfbm);
  328. }
  329. } catch (e) { }
  330. }
  331. loading.value = false;
  332. });
  333. </script>
  334. <style lang="scss" scoped>
  335. page {
  336. background-color: #f5f7fa;
  337. }
  338. .dialog-footer {
  339. display: flex;
  340. padding: 20rpx 30rpx 30rpx;
  341. gap: 20rpx;
  342. }
  343. .dialog-btn {
  344. flex: 1;
  345. height: 80rpx;
  346. border-radius: 40rpx;
  347. display: flex;
  348. align-items: center;
  349. justify-content: center;
  350. font-size: 32rpx;
  351. }
  352. .dialog-btn-cancel {
  353. background: #e5e5e5;
  354. color: #666;
  355. }
  356. .dialog-btn-next {
  357. background: #409eff;
  358. color: #fff;
  359. }
  360. .status-text {
  361. font-size: 28rpx;
  362. color: #333;
  363. margin-bottom: 10rpx;
  364. }
  365. .status-add {
  366. color: #00b42a;
  367. font-weight: 500;
  368. }
  369. .status-edit {
  370. color: #1677ff;
  371. font-weight: 500;
  372. }
  373. /* 全局修改弹窗输入框高度(更高更大) */
  374. :deep(.uni-modal-input) {
  375. height: 80rpx !important;
  376. font-size: 28rpx !important;
  377. padding: 10rpx 15rpx !important;
  378. }
  379. :deep(.uni-modal) {
  380. min-height: 380rpx !important;
  381. }
  382. </style>