detail.vue 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. <template>
  2. <div class="detail-container">
  3. <div class="card content-box">
  4. <div class="detail-header">
  5. <h3>详情</h3>
  6. <el-button text @click="handleClose">
  7. <el-icon><Close /></el-icon>
  8. </el-button>
  9. </div>
  10. <el-form ref="formRef" :model="formData" label-width="140px" label-position="right">
  11. <el-row :gutter="40">
  12. <!-- 左侧列 -->
  13. <el-col :span="12">
  14. <el-form-item label="需求标题" required>
  15. <el-input v-model="formData.requirementTitle" placeholder="请输入" disabled />
  16. </el-form-item>
  17. <el-form-item label="装修类型">
  18. <el-radio-group v-model="formData.renovationType" disabled>
  19. <el-radio :label="1">新房装修</el-radio>
  20. <el-radio :label="2">旧房改造</el-radio>
  21. <el-radio :label="3">局部装修</el-radio>
  22. </el-radio-group>
  23. </el-form-item>
  24. <el-form-item label="房屋面积(㎡)" required>
  25. <el-input v-model="formData.houseArea" placeholder="请输入" disabled />
  26. </el-form-item>
  27. <el-form-item label="装修预算(万元)" required>
  28. <el-input v-model="formData.renovationBudget" placeholder="请输入" disabled />
  29. </el-form-item>
  30. <el-form-item label="详细需求">
  31. <el-input
  32. v-model="formData.detailedRequirement"
  33. type="textarea"
  34. :rows="4"
  35. placeholder="请输入"
  36. disabled
  37. />
  38. </el-form-item>
  39. <el-form-item label="期望装修时间" required>
  40. <el-date-picker
  41. v-model="formData.expectedRenovationTime"
  42. type="date"
  43. placeholder="请选择"
  44. value-format="YYYY-MM-DD"
  45. style="width: 100%"
  46. disabled
  47. />
  48. </el-form-item>
  49. <el-form-item label="上传房屋图纸" required>
  50. <el-upload
  51. v-model:file-list="fileList"
  52. list-type="picture-card"
  53. :disabled="true"
  54. :on-preview="handlePictureCardPreview"
  55. :on-remove="handleRemove"
  56. >
  57. <el-icon><Plus /></el-icon>
  58. </el-upload>
  59. <div class="upload-tip">({{ fileList.length }}/9)</div>
  60. </el-form-item>
  61. <el-form-item label="联系人" required>
  62. <el-input v-model="formData.contactName" placeholder="请输入" disabled />
  63. </el-form-item>
  64. <el-form-item label="联系电话" required>
  65. <el-input v-model="formData.contactPhone" placeholder="请输入" disabled />
  66. </el-form-item>
  67. <el-form-item label="所在城市" required>
  68. <el-input v-model="formData.city" placeholder="请选择" disabled />
  69. </el-form-item>
  70. <el-form-item label="详细地址">
  71. <el-input
  72. v-model="formData.detailedAddress"
  73. type="textarea"
  74. :rows="3"
  75. placeholder="请输入"
  76. disabled
  77. />
  78. </el-form-item>
  79. </el-col>
  80. <!-- 右侧列 -->
  81. <el-col :span="12">
  82. <el-form-item label="提交时间">
  83. <el-input v-model="formData.createdTime" placeholder="请输入" disabled />
  84. </el-form-item>
  85. <el-form-item label="审核状态">
  86. <el-input v-model="auditStatusText" placeholder="请输入" disabled />
  87. </el-form-item>
  88. <el-form-item label="审核时间">
  89. <el-input v-model="formData.updatedTime" placeholder="请输入" disabled />
  90. </el-form-item>
  91. <el-form-item v-if="formData.auditStatus === 2" label="拒绝原因">
  92. <el-input
  93. v-model="formData.rejectionReason"
  94. type="textarea"
  95. :rows="4"
  96. placeholder="请输入"
  97. disabled
  98. />
  99. <div class="form-tip">根据审核状态 对应展示</div>
  100. </el-form-item>
  101. </el-col>
  102. </el-row>
  103. </el-form>
  104. <div class="detail-footer">
  105. <el-button @click="handleClose">取消</el-button>
  106. <el-button type="primary" @click="handleConfirm">确定</el-button>
  107. </div>
  108. </div>
  109. <!-- 图片预览 -->
  110. <el-image-viewer
  111. v-if="imageViewerVisible"
  112. :url-list="imageViewerUrlList"
  113. :initial-index="imageViewerInitialIndex"
  114. @close="imageViewerVisible = false"
  115. />
  116. </div>
  117. </template>
  118. <script setup lang="ts" name="decorationDetail">
  119. import { ref, computed, onMounted, watch } from "vue";
  120. import { useRoute, useRouter } from "vue-router";
  121. import { ElMessage } from "element-plus";
  122. import { Plus, Close } from "@element-plus/icons-vue";
  123. import type { UploadFile } from "element-plus";
  124. import { getDecorationDetail } from "@/api/modules/storeDecoration";
  125. const route = useRoute();
  126. const router = useRouter();
  127. const formRef = ref();
  128. const formData = ref<any>({
  129. requirementTitle: "",
  130. renovationType: 1,
  131. houseArea: "",
  132. renovationBudget: "",
  133. detailedRequirement: "",
  134. expectedRenovationTime: "",
  135. contactName: "",
  136. contactPhone: "",
  137. city: "",
  138. detailedAddress: "",
  139. createdTime: "",
  140. auditStatus: 0,
  141. updatedTime: "",
  142. rejectionReason: "",
  143. attachmentUrls: []
  144. });
  145. const fileList = ref<UploadFile[]>([]);
  146. const imageViewerVisible = ref(false);
  147. const imageViewerUrlList = ref<string[]>([]);
  148. const imageViewerInitialIndex = ref(0);
  149. // 审核状态文本
  150. const auditStatusText = computed(() => {
  151. const statusMap: Record<number, string> = {
  152. 0: "待审核",
  153. 1: "审核通过",
  154. 2: "审核失败"
  155. };
  156. return statusMap[formData.value.auditStatus] || "--";
  157. });
  158. // 获取详情数据
  159. const initData = async () => {
  160. const id = route.query.id;
  161. if (!id) {
  162. handleClose();
  163. return;
  164. }
  165. try {
  166. const res = await getDecorationDetail({ id: id as string });
  167. if (res.code == 200 || res.code == 0) {
  168. const data = res.data || res.data?.data || {};
  169. formData.value = {
  170. requirementTitle: data.requirementTitle || "",
  171. renovationType: data.renovationType || 1,
  172. houseArea: data.houseArea || "",
  173. renovationBudget: data.renovationBudget || "",
  174. detailedRequirement: data.detailedRequirement || "",
  175. expectedRenovationTime: data.expectedRenovationTime || "",
  176. contactName: data.contactName || "",
  177. contactPhone: data.contactPhone || "",
  178. city: data.city || "",
  179. detailedAddress: data.detailedAddress || "",
  180. createdTime: data.createdTime || "",
  181. auditStatus: data.auditStatus ?? 0,
  182. updatedTime: data.updatedTime || "",
  183. rejectionReason: data.rejectionReason || "",
  184. attachmentUrls: data.attachmentUrls || []
  185. };
  186. // 处理附件列表
  187. if (formData.value.attachmentUrls && formData.value.attachmentUrls.length > 0) {
  188. fileList.value = formData.value.attachmentUrls.map((url: string, index: number) => ({
  189. uid: index,
  190. name: `图片${index + 1}`,
  191. url: url,
  192. status: "success"
  193. }));
  194. }
  195. }
  196. } catch (error: any) {
  197. // 静默处理错误,不显示错误提示
  198. console.error("获取详情失败:", error);
  199. }
  200. };
  201. // 图片预览
  202. const handlePictureCardPreview = (file: UploadFile) => {
  203. if (file.url) {
  204. imageViewerUrlList.value = fileList.value.map((item: UploadFile) => item.url || "").filter(Boolean);
  205. imageViewerInitialIndex.value = fileList.value.findIndex((item: UploadFile) => item.uid === file.uid);
  206. imageViewerVisible.value = true;
  207. }
  208. };
  209. // 删除图片(详情页禁用,这里只是占位)
  210. const handleRemove = () => {
  211. // 详情页不允许删除
  212. };
  213. // 关闭页面
  214. const handleClose = () => {
  215. router.go(-1);
  216. };
  217. // 确定按钮
  218. const handleConfirm = () => {
  219. handleClose();
  220. };
  221. // 监听路由变化
  222. watch(
  223. () => route.query.id,
  224. () => {
  225. if (route.query.id) {
  226. initData();
  227. }
  228. },
  229. { immediate: true }
  230. );
  231. onMounted(() => {
  232. if (route.query.id) {
  233. initData();
  234. }
  235. });
  236. </script>
  237. <style lang="scss" scoped>
  238. .detail-container {
  239. width: 100%;
  240. min-height: 100%;
  241. background-color: white;
  242. .content-box {
  243. padding: 20px;
  244. }
  245. .detail-header {
  246. display: flex;
  247. justify-content: space-between;
  248. align-items: center;
  249. margin-bottom: 20px;
  250. padding-bottom: 15px;
  251. border-bottom: 1px solid #ebeef5;
  252. h3 {
  253. margin: 0;
  254. font-size: 18px;
  255. font-weight: 500;
  256. }
  257. }
  258. :deep(.el-form-item) {
  259. margin-bottom: 20px;
  260. }
  261. :deep(.el-radio-group) {
  262. display: flex;
  263. gap: 20px;
  264. }
  265. .upload-tip {
  266. font-size: 12px;
  267. color: #999;
  268. margin-top: 5px;
  269. }
  270. .form-tip {
  271. font-size: 12px;
  272. color: #999;
  273. margin-top: 5px;
  274. text-align: right;
  275. }
  276. .detail-footer {
  277. text-align: center;
  278. padding: 20px 0 0;
  279. margin-top: 20px;
  280. border-top: 1px solid #ebeef5;
  281. }
  282. :deep(.el-upload--picture-card) {
  283. width: 100px;
  284. height: 100px;
  285. }
  286. :deep(.el-upload-list--picture-card .el-upload-list__item) {
  287. width: 100px;
  288. height: 100px;
  289. }
  290. }
  291. </style>