展品维保小程序前端代码接口
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

690 lines
18 KiB

1 week ago
5 days ago
5 days ago
6 days ago
5 days ago
5 days ago
6 days ago
6 days ago
1 week ago
1 week ago
1 week ago
  1. <template>
  2. <view class="repair-submit">
  3. <!-- 导航栏 -->
  4. <!-- <uv-navbar title="报修提交" :border="false" bg-color="#ffffff" title-color="#333333" /> -->
  5. <!-- 报修基本信息 -->
  6. <view class="repair-info">
  7. <view class="info-header">
  8. <view class="red-line"></view>
  9. <text class="info-title">报修基本信息</text>
  10. </view>
  11. <!-- 报修日期 -->
  12. <view class="form-item" @click="showDatePicker">
  13. <text class="label">报修日期</text>
  14. <view class="select-area">
  15. <text class="value" :class="{ placeholder: !malfunctionDate }">{{ malfunctionDate || '请选择' }}</text>
  16. <uv-icon name="arrow-down" size="18" color="#000"></uv-icon>
  17. </view>
  18. </view>
  19. <!-- 故障紧急程度 -->
  20. <view class="form-item " @click="showUrgencyPicker">
  21. <text class="label">故障紧急程度</text>
  22. <view class="select-area">
  23. <text class="value" :class="{ placeholder: !urgency }">{{ urgency.label || '请选择' }}</text>
  24. <uv-icon name="arrow-down" size="18" color="#000"></uv-icon>
  25. </view>
  26. </view>
  27. <!-- 故障情况 -->
  28. <view class="form-item form-item-header">
  29. <text class="label active">故障情况</text>
  30. </view>
  31. <!-- 故障情况选择 -->
  32. <view class="form-item" @click="showFaultPicker">
  33. <text class="label">故障情况</text>
  34. <view class="select-area">
  35. <text class="value" :class="{ placeholder: !malfunctionStatus }">{{ malfunctionStatus || '请选择' }}</text>
  36. <uv-icon name="arrow-down" size="18" color="#000"></uv-icon>
  37. </view>
  38. </view>
  39. <!-- 故障情况描述 -->
  40. <view class="form-item">
  41. <text class="label">故障情况描述</text>
  42. </view>
  43. <view class="textarea-container">
  44. <uv-textarea
  45. v-model="malfunctionDesc"
  46. placeholder="请对故障情况进行描述"
  47. :maxlength="200"
  48. :show-confirm-bar="false"
  49. height="60"
  50. border="none"
  51. :custom-style="{ backgroundColor: '#f5f5f5' }"
  52. ></uv-textarea>
  53. </view>
  54. <!-- 故障图片 -->
  55. <view class="form-item">
  56. <text class="label">故障图片</text>
  57. </view>
  58. <view class="image-upload">
  59. <view v-for="(img, index) in malfunctionImage" :key="index" class="image-item">
  60. <image :src="img" mode="aspectFill" @click="previewImage(img)"></image>
  61. <view class="delete-btn" @click="deleteImage(index)">
  62. <uv-icon name="close" size="12" color="#fff"></uv-icon>
  63. </view>
  64. </view>
  65. <view class="upload-btn" @click="uploadImage">
  66. <uv-icon name="camera" size="34" color="#C70019"></uv-icon>
  67. </view>
  68. </view>
  69. <!-- 故障首次发生时间 -->
  70. <view class="form-item" @click="showFirstOccurTimePicker">
  71. <text class="label">故障首次发生时间</text>
  72. <view class="select-area">
  73. <text class="value" :class="{ placeholder: !firstDate }">{{ firstDate || '请选择' }}</text>
  74. <uv-icon name="arrow-down" size="18" color="#000"></uv-icon>
  75. </view>
  76. </view>
  77. <!-- 发生频率 -->
  78. <view class="form-item">
  79. <text class="label">发生频率</text>
  80. <view class="radio-options">
  81. <view
  82. v-for="(item, index) in frequencyOptions"
  83. :key="index"
  84. class="radio-item"
  85. :class="{ active: frequency === item.value }"
  86. @click="selectFrequency(item.value)"
  87. >
  88. <view class="radio-dot" :class="{ active: frequency === item.value }"></view>
  89. <text :class="{ active: frequency === item.value }">{{ item.label }}</text>
  90. </view>
  91. </view>
  92. </view>
  93. <!-- 请描述与故障设备发生主要故障的具体条件 -->
  94. <!-- <view class="form-item">
  95. <text class="label">请描述与故障设备发生主要故障的具体条件</text>
  96. </view> -->
  97. <view class="textarea-container">
  98. <uv-textarea
  99. v-model="reason"
  100. placeholder="请填写说明故障发生频率的触发条件"
  101. :maxlength="200"
  102. :show-confirm-bar="false"
  103. height="60"
  104. border="none"
  105. :custom-style="{ backgroundColor: '#f5f5f5' }"
  106. ></uv-textarea>
  107. </view>
  108. <!-- 是否影响使用 -->
  109. <view class="form-item" @click="showImpactPicker">
  110. <text class="label">是否影响使用</text>
  111. <view class="select-area">
  112. <text class="value" :class="{ placeholder: !isAffectUse }">{{ isAffectUse.label || '请选择' }}</text>
  113. <uv-icon name="arrow-down" size="18" color="#000"></uv-icon>
  114. </view>
  115. </view>
  116. <!-- 采取的临时措施 -->
  117. <!-- 故障情况 -->
  118. <view class="form-item form-item-header">
  119. <text class="label active">采取的临时措施</text>
  120. </view>
  121. <!-- <view class="form-item">
  122. <text class="label">是否采取临时措施</text>
  123. </view>
  124. <view class="textarea-container">
  125. <uv-textarea
  126. v-model="malfunctionName"
  127. placeholder="如有采取临时措施请填写措施说明"
  128. :maxlength="200"
  129. :show-confirm-bar="false"
  130. height="60"
  131. border="none"
  132. :custom-style="{ backgroundColor: '#f5f5f5' }"
  133. ></uv-textarea>
  134. </view> -->
  135. <!-- 是否采取的对措施 -->
  136. <view class="form-item">
  137. <text class="label">是否采取临时措施</text>
  138. <view class="radio-options">
  139. <view
  140. class="radio-item"
  141. :class="{ active: isMeasure === '1' }"
  142. @click="selectMeasures('1')"
  143. >
  144. <view class="radio-dot" :class="{ active: isMeasure === '1' }"></view>
  145. <text :class="{ active: isMeasure === '1' }"></text>
  146. </view>
  147. <view
  148. class="radio-item"
  149. :class="{ active: isMeasure === '0' }"
  150. @click="selectMeasures('0')"
  151. >
  152. <view class="radio-dot" :class="{ active: isMeasure === '0' }"></view>
  153. <text :class="{ active: isMeasure === '0' }"></text>
  154. </view>
  155. </view>
  156. </view>
  157. <view class="textarea-container">
  158. <uv-textarea
  159. v-model="malfunctionName"
  160. placeholder="如有采取临时措施请填写措施说明"
  161. :maxlength="200"
  162. :show-confirm-bar="false"
  163. height="60"
  164. border="none"
  165. :custom-style="{ backgroundColor: '#f5f5f5' }"
  166. ></uv-textarea>
  167. </view>
  168. <!-- 是否影响体验 -->
  169. <view class="form-item">
  170. <text class="label">是否影响体验</text>
  171. <view class="radio-options">
  172. <view
  173. class="radio-item"
  174. :class="{ active: isAffectExperience === '1' }"
  175. @click="selectExperience('1')"
  176. >
  177. <view class="radio-dot" :class="{ active: isAffectExperience === '1' }"></view>
  178. <text :class="{ active: isAffectExperience === '1' }"></text>
  179. </view>
  180. <view
  181. class="radio-item"
  182. :class="{ active: isAffectExperience === '0' }"
  183. @click="selectExperience('0')"
  184. >
  185. <view class="radio-dot" :class="{ active: isAffectExperience === '0' }"></view>
  186. <text :class="{ active: isAffectExperience === '0' }"></text>
  187. </view>
  188. </view>
  189. </view>
  190. <!-- 备注 -->
  191. <view class="form-item">
  192. <text class="label">备注</text>
  193. </view>
  194. <view class="textarea-container">
  195. <uv-textarea
  196. v-model="remark"
  197. placeholder="备注"
  198. :maxlength="200"
  199. :show-confirm-bar="false"
  200. height="60"
  201. border="none"
  202. :custom-style="{ backgroundColor: '#f5f5f5' }"
  203. ></uv-textarea>
  204. </view>
  205. </view>
  206. <!-- 提交按钮 -->
  207. <view class="submit-container">
  208. <uv-button
  209. type="primary"
  210. text="立即提交"
  211. :custom-style="{ backgroundColor: '#C70019', borderRadius: '25px' }"
  212. @click="submitRepair"
  213. ></uv-button>
  214. </view>
  215. <!-- 选择器 -->
  216. <uv-picker
  217. confirm-color="#C70019"
  218. ref="urgencyPicker"
  219. :columns="urgencyColumns"
  220. keyName="label"
  221. @confirm="confirmUrgency"
  222. @cancel="cancelUrgency"
  223. ></uv-picker>
  224. <uv-picker
  225. confirm-color="#C70019"
  226. ref="faultPicker"
  227. :columns="faultColumns"
  228. @confirm="confirmFault"
  229. @cancel="cancelFault"
  230. ></uv-picker>
  231. <!-- 故障首次发生时间选择器 -->
  232. <uv-datetime-picker
  233. ref="firstOccurTimePicker"
  234. mode="date"
  235. v-model="firstTime"
  236. confirm-color="#C70019"
  237. @confirm="confirmFirstOccurTime"
  238. ></uv-datetime-picker>
  239. <uv-picker
  240. confirm-color="#C70019"
  241. ref="impactPicker"
  242. :columns="impactColumns"
  243. @confirm="confirmImpact"
  244. @cancel="cancelImpact"
  245. keyName="label"
  246. ></uv-picker>
  247. <!-- 日期选择器 -->
  248. <uv-datetime-picker
  249. confirm-color="#C70019"
  250. ref="datePicker"
  251. v-model="timeValue"
  252. mode="date"
  253. @confirm="confirmDate"
  254. ></uv-datetime-picker>
  255. </view>
  256. </template>
  257. <script>
  258. export default {
  259. data() {
  260. return {
  261. // 表单数据
  262. malfunctionDate: '',
  263. urgency: '',
  264. malfunctionStatus: '',
  265. malfunctionDesc: '',
  266. malfunctionImage: [],
  267. firstDate: '',
  268. frequency: '1',
  269. reason: '',
  270. isAffectUse: '0',
  271. malfunctionName: '',
  272. isMeasure: '0',
  273. isAffectExperience: '0',
  274. remark: '',
  275. showpieceId: '',
  276. timeValue: Number(new Date()),
  277. firstTime: Number(new Date()),
  278. // 频率选项
  279. frequencyOptions: [
  280. { label: '持续性问题', value: '0' },
  281. { label: '间歇性问题', value: '1' }
  282. ],
  283. // 选择器数据
  284. urgencyColumns: [
  285. [
  286. { label: '一般', value: '0' },
  287. { label: '紧急', value: '1'}
  288. ]
  289. ],
  290. faultColumns: [['硬件故障', '软件故障', '网络故障', '其他']],
  291. impactColumns: [[
  292. { label: '是', value: '1' },
  293. { label: '否', value: '0' }
  294. ]],
  295. }
  296. },
  297. methods: {
  298. // 显示日期选择器
  299. showDatePicker() {
  300. this.$refs.datePicker.open()
  301. },
  302. // 确认日期选择
  303. confirmDate(e) {
  304. this.malfunctionDate = this.$utils.formatTime(e.value)
  305. },
  306. // 显示紧急程度选择器
  307. showUrgencyPicker() {
  308. this.$refs.urgencyPicker.open()
  309. },
  310. // 确认紧急程度
  311. confirmUrgency(e) {
  312. this.urgency = e.value[0]
  313. },
  314. // 取消紧急程度选择
  315. cancelUrgency() {
  316. // 取消操作
  317. },
  318. // 显示故障情况选择器
  319. showFaultPicker() {
  320. this.$refs.faultPicker.open()
  321. },
  322. // 确认故障情况
  323. confirmFault(e) {
  324. this.malfunctionStatus = e.value[0]
  325. },
  326. // 取消故障情况选择
  327. cancelFault() {
  328. // 取消操作
  329. },
  330. // 显示故障首次发生时间选择器
  331. showFirstOccurTimePicker() {
  332. this.$refs.firstOccurTimePicker.open()
  333. },
  334. // 确认故障首次发生时间
  335. confirmFirstOccurTime(e) {
  336. this.firstDate = this.$utils.formatTime(e.value)
  337. },
  338. // 显示影响使用选择器
  339. showImpactPicker() {
  340. this.$refs.impactPicker.open()
  341. },
  342. // 确认影响使用
  343. confirmImpact(e) {
  344. this.isAffectUse = e.value[0]
  345. },
  346. // 取消影响使用选择
  347. cancelImpact() {
  348. // 取消操作
  349. },
  350. // 选择频率
  351. selectFrequency(value) {
  352. this.frequency = value
  353. },
  354. // 选择是否采取措施
  355. selectMeasures(value) {
  356. this.isMeasure = value
  357. },
  358. // 选择是否影响体验
  359. selectExperience(value) {
  360. this.isAffectExperience = value
  361. },
  362. // 上传图片
  363. async uploadImage() {
  364. try {
  365. const result = await this.$utils.chooseAndUpload()
  366. if (result && result.success) {
  367. console.log(result);
  368. this.malfunctionImage.push(result.url)
  369. }
  370. } catch (error) {
  371. console.error('头像上传失败:', error)
  372. uni.showToast({
  373. title: '头像上传失败',
  374. icon: 'error'
  375. })
  376. }
  377. },
  378. // 删除图片
  379. deleteImage(index) {
  380. this.malfunctionImage.splice(index, 1)
  381. },
  382. // 预览图片
  383. previewImage(url) {
  384. uni.previewImage({
  385. urls: this.malfunctionImage,
  386. current: url
  387. })
  388. },
  389. // 提交报修
  390. async submitRepair() {
  391. // 表单验证
  392. if (!this.urgency) {
  393. uni.showToast({ title: '请选择故障紧急程度', icon: 'none' })
  394. return
  395. }
  396. if (!this.malfunctionImage.length) {
  397. uni.showToast({ title: '请上传故障图片', icon: 'none' })
  398. return
  399. }
  400. if (!this.malfunctionDesc.trim()) {
  401. uni.showToast({ title: '请填写故障情况描述', icon: 'none' })
  402. return
  403. }
  404. if (!this.firstDate.trim()) {
  405. uni.showToast({ title: '请选择故障首次发生时间', icon: 'none' })
  406. return
  407. }
  408. // 提交数据
  409. const formData = {
  410. showpieceId: this.showpieceId,
  411. malfunctionDate: this.malfunctionDate,
  412. urgency: this.urgency.value,
  413. malfunctionDesc: this.malfunctionStatus + this.malfunctionDesc,
  414. malfunctionImage: this.malfunctionImage.join(','),
  415. firstDate: this.firstDate,
  416. frequency: this.frequency,
  417. reason: this.reason,
  418. isAffectUse: this.isAffectUse.value,
  419. malfunctionName: this.malfunctionName,
  420. isMeasure: this.isMeasure,
  421. isAffectExperience: this.isAffectExperience,
  422. remark: this.remark
  423. }
  424. // console.log('提交数据:', formData)
  425. // uni.showToast({ title: '提交成功', icon: 'success' })
  426. const subRes = await this.$api.exhibit.addMalfunction({...formData})
  427. if (subRes.code === 200) {
  428. uni.showToast({ title: subRes.message})
  429. setTimeout(() => {
  430. uni.navigateBack()
  431. }, 1000)
  432. }else{
  433. uni.showToast({ title: subRes.message, icon: 'none' })
  434. }
  435. }
  436. },
  437. async onLoad(args) {
  438. this.showpieceId = args.id
  439. try {
  440. const listRes = await this.$api.config.queryMalfunctionDescList()
  441. if (listRes.code === 200) {
  442. this.faultColumns = [[...listRes.result.records.map(item => item.malfunction)]]
  443. }
  444. } catch (error) {
  445. uni.showToast({ title: error.message, icon: 'none' })
  446. }
  447. }
  448. }
  449. </script>
  450. <style lang="scss" scoped>
  451. .repair-submit {
  452. min-height: 100vh;
  453. background-color: #f5f5f5;
  454. padding-bottom: 200rpx;
  455. }
  456. .repair-info {
  457. margin: 18rpx;
  458. background: #ffffff;
  459. border-radius: 15rpx;
  460. box-shadow: 0rpx 3rpx 6rpx 0rpx rgba(0,0,0,0.16);
  461. padding: 40rpx;
  462. .info-header {
  463. display: flex;
  464. align-items: center;
  465. margin-bottom: 40rpx;
  466. .red-line {
  467. width: 9rpx;
  468. height: 33rpx;
  469. background-color: $primary-color;
  470. margin-right: 7rpx;
  471. border-radius: 5rpx;
  472. }
  473. .info-title {
  474. font-size: 30rpx;
  475. font-weight: bold;
  476. color: $primary-text-color;
  477. }
  478. }
  479. .form-item-header {
  480. border-bottom: none;
  481. margin-top: 20rpx;
  482. }
  483. .form-item {
  484. display: flex;
  485. align-items: center;
  486. justify-content: space-between;
  487. padding: 24rpx 0;
  488. border-bottom: 2rpx solid #f0f0f0;
  489. &:last-child {
  490. border-bottom: none;
  491. }
  492. .label {
  493. font-size: 30rpx;
  494. color: $primary-text-color;
  495. flex-shrink: 0;
  496. &.active {
  497. font-weight: bold;
  498. }
  499. }
  500. .value {
  501. font-size: 30rpx;
  502. color: $secondary-text-color;
  503. &.placeholder {
  504. color: $secondary-text-color;
  505. }
  506. }
  507. .select-area {
  508. display: flex;
  509. align-items: center;
  510. gap: 16rpx;
  511. }
  512. }
  513. .textarea-container {
  514. // margin: 16rpx 0 32rpx 0;
  515. // background-color: #f5f5f5;
  516. border-radius: 8rpx;
  517. // padding: 16rpx;
  518. }
  519. .image-upload {
  520. display: flex;
  521. flex-wrap: wrap;
  522. gap: 24rpx;
  523. margin: 16rpx 0;
  524. .upload-btn {
  525. width: 160rpx;
  526. height: 160rpx;
  527. border: 2rpx dashed $primary-color;
  528. // border-radius: 8rpx;
  529. display: flex;
  530. align-items: center;
  531. justify-content: center;
  532. background-color: #fff;
  533. }
  534. .image-item {
  535. position: relative;
  536. width: 160rpx;
  537. height: 160rpx;
  538. image {
  539. width: 100%;
  540. height: 100%;
  541. border-radius: 8rpx;
  542. }
  543. .delete-btn {
  544. position: absolute;
  545. top: -12rpx;
  546. right: -12rpx;
  547. width: 40rpx;
  548. height: 40rpx;
  549. background-color: #ff4757;
  550. border-radius: 50%;
  551. display: flex;
  552. align-items: center;
  553. justify-content: center;
  554. }
  555. }
  556. }
  557. .hint-text {
  558. font-size: 24rpx;
  559. color: #999;
  560. margin-top: 16rpx;
  561. }
  562. .form-item .radio-options {
  563. display: flex;
  564. gap: 60rpx;
  565. .radio-item {
  566. display: flex;
  567. align-items: center;
  568. gap: 16rpx;
  569. .radio-dot {
  570. width: 32rpx;
  571. height: 32rpx;
  572. border: 4rpx solid #ddd;
  573. border-radius: 50%;
  574. position: relative;
  575. &.active {
  576. border-color: $primary-color;
  577. color: $primary-color;
  578. &::after {
  579. content: '';
  580. position: absolute;
  581. top: 50%;
  582. left: 50%;
  583. transform: translate(-50%, -50%);
  584. width: 16rpx;
  585. height: 16rpx;
  586. background-color: $primary-color;
  587. border-radius: 50%;
  588. }
  589. }
  590. }
  591. text {
  592. font-size: 30rpx;
  593. color: $secondary-text-color;
  594. &.active {
  595. color: $primary-color;
  596. }
  597. }
  598. }
  599. }
  600. }
  601. .submit-container {
  602. position: fixed;
  603. bottom: 0;
  604. left: 0;
  605. right: 0;
  606. padding: 32rpx;
  607. background-color: #fff;
  608. border-top: 2rpx solid #f0f0f0;
  609. }
  610. </style>