展品维保小程序前端代码接口
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.

1060 lines
28 KiB

5 days ago
5 days ago
1 week ago
5 days ago
5 days ago
5 days ago
1 week ago
1 week ago
5 days ago
1 week ago
1 week ago
6 days ago
6 days ago
6 days ago
6 days ago
5 days ago
  1. <template>
  2. <view class="maintain-submit">
  3. <!-- 修改状态 -->
  4. <view class="status-item">
  5. <!-- 维修状态和状态选择 -->
  6. <view class="status-row">
  7. <text class="status-label">维修状态</text>
  8. <view class="status-select" @click="showStatusPicker">
  9. <text class="status-value" :class="{ placeholder: !selectedStatus }">{{ selectedStatus || '故障中' }}</text>
  10. <uv-icon name="arrow-down" size="18" color="#000"></uv-icon>
  11. </view>
  12. </view>
  13. <!-- 修改状态按钮 -->
  14. <button class="status-btn" :class="{ active: statusType === 'modify' }" @click="modifyStatus">
  15. <text class="status-text">修改状态</text>
  16. </button>
  17. </view>
  18. <!-- 保修基本信息 -->
  19. <view class="repair-info">
  20. <view class="info-header">
  21. <view class="red-line"></view>
  22. <text class="info-title">报修基本信息</text>
  23. </view>
  24. <!-- 报修日期 -->
  25. <view class="form-item">
  26. <text class="label">报修日期</text>
  27. <text class="value">{{ repairData.malfunctionDate }}</text>
  28. </view>
  29. <!-- 故障紧急程度 -->
  30. <view class="form-item">
  31. <text class="label">故障紧急程度</text>
  32. <text class="value">{{ repairData.urgency === '1' ? '紧急' : '一般' }}</text>
  33. </view>
  34. <!-- 故障情况描述 -->
  35. <view class="form-item">
  36. <text class="label">故障情况描述</text>
  37. </view>
  38. <!-- 故障情况描述文本区域 -->
  39. <view class="content-text">
  40. <uv-textarea
  41. v-model="repairData.malfunctionDesc"
  42. placeholder="展品故障描述"
  43. :maxlength="200"
  44. :show-confirm-bar="false"
  45. height="60"
  46. border="none"
  47. disabled
  48. :textStyle="{ color: '#000' }"
  49. :custom-style="{ backgroundColor: '#f5f5f5' }"
  50. ></uv-textarea>
  51. </view>
  52. <!-- 故障图片 -->
  53. <view class="form-item" v-if="!isCollapsed">
  54. <text class="label">故障图片</text>
  55. </view>
  56. <view class="image-container" v-if="!isCollapsed">
  57. <image
  58. class="uploaded-image"
  59. v-for="(img, index) in getImageList(repairData.malfunctionImage)"
  60. :key="index"
  61. :src="img.trim()"
  62. mode="aspectFill"
  63. @click="previewImage(img.trim())"
  64. ></image>
  65. </view>
  66. <!-- 故障首次发生时间 -->
  67. <view class="form-item" v-if="!isCollapsed">
  68. <text class="label">故障首次发生时间</text>
  69. <text class="value">{{ repairData.firstDate }}</text>
  70. </view>
  71. <!-- 发生频率 -->
  72. <view class="form-item" v-if="!isCollapsed">
  73. <text class="label">发生频率</text>
  74. <text class="value red-text">{{ repairData.frequency === '1' ? '间歇性问题' : '持续性问题' }}</text>
  75. </view>
  76. <!-- 故障发生频率的触发条件 -->
  77. <view class="content-text" v-if="!isCollapsed">
  78. <uv-textarea
  79. v-model="repairData.reason"
  80. placeholder="故障发生频率的触发条件"
  81. :maxlength="200"
  82. :show-confirm-bar="false"
  83. height="60"
  84. border="none"
  85. disabled
  86. :textStyle="{ color: '#000' }"
  87. :custom-style="{ backgroundColor: '#f5f5f5' }"
  88. ></uv-textarea>
  89. </view>
  90. <!-- 是否影响使用 -->
  91. <view class="form-item" v-if="!isCollapsed">
  92. <text class="label">是否影响使用</text>
  93. <text class="value red-text">{{ repairData.isAffectUse === '1' ? '是' : '否' }}</text>
  94. </view>
  95. <!-- 是否采取临时措施 -->
  96. <view class="form-item" v-if="!isCollapsed">
  97. <text class="label">是否采取临时措施</text>
  98. <text class="value red-text">{{ repairData.isMeasure === '1' ? '是' : '否' }}</text>
  99. </view>
  100. <!-- 如有采取临时措施请填写措施说明 -->
  101. <view class="content-text" v-if="!isCollapsed">
  102. <uv-textarea
  103. v-model="repairData.measureDesc"
  104. placeholder="如果有采取临时措施请填写措施说明"
  105. :maxlength="200"
  106. :show-confirm-bar="false"
  107. height="60"
  108. border="none"
  109. disabled
  110. :textStyle="{ color: '#000' }"
  111. :custom-style="{ backgroundColor: '#f5f5f5' }"
  112. ></uv-textarea>
  113. </view>
  114. <!-- 是否影响体验 -->
  115. <view class="form-item" v-if="!isCollapsed">
  116. <text class="label">是否影响体验</text>
  117. <text class="value red-text">{{ repairData.isAffectExperience === '1' ? '是' : '否' }}</text>
  118. </view>
  119. <view class="form-item" v-if="!isCollapsed">
  120. <text class="label">备注</text>
  121. </view>
  122. <!-- 备注 -->
  123. <view class="content-text" v-if="!isCollapsed">
  124. <uv-textarea
  125. v-model="repairData.remark"
  126. placeholder="备注"
  127. :maxlength="200"
  128. :show-confirm-bar="false"
  129. height="60"
  130. border="none"
  131. disabled
  132. :textStyle="{ color: '#000' }"
  133. :custom-style="{ backgroundColor: '#f5f5f5' }"
  134. ></uv-textarea>
  135. </view>
  136. <!-- 查看全部/收起按钮 -->
  137. <view class="collapse-btn" @click="toggleCollapse">
  138. <text class="collapse-text">{{ isCollapsed ? '查看全部' : '收起' }}</text>
  139. <text class="collapse-icon">{{ isCollapsed ? '▼' : '▲' }}</text>
  140. </view>
  141. </view>
  142. <!-- 处理内容 -->
  143. <view class="process-content">
  144. <view class="info-header">
  145. <view class="red-line"></view>
  146. <text class="info-title">处理内容</text>
  147. </view>
  148. <!-- 维修人 -->
  149. <view class="form-item">
  150. <text class="label">维修人</text>
  151. <view class="input-area" >
  152. <input
  153. v-model="processData.repairName"
  154. placeholder="请填写"
  155. class="input-field"
  156. ref="maintainerInput"
  157. />
  158. </view>
  159. </view>
  160. <!-- 联系方式 -->
  161. <view class="form-item">
  162. <text class="label">联系方式</text>
  163. <view class="input-area" >
  164. <input
  165. v-model="processData.phone"
  166. placeholder="请填写"
  167. class="input-field"
  168. ref="maintainerInput"
  169. />
  170. </view>
  171. </view>
  172. <!-- 维修日期 -->
  173. <view class="form-item" @click="showDatePicker">
  174. <text class="label">维修日期</text>
  175. <view class="select-area">
  176. <text class="value" :class="{ placeholder: !processData.repairDate }">{{ processData.repairDate || '请选择' }}</text>
  177. <uv-icon name="arrow-down" size="18" color="#000"></uv-icon>
  178. </view>
  179. </view>
  180. <!-- 处理内容 -->
  181. <view class="form-item">
  182. <text class="label">处理内容</text>
  183. </view>
  184. <view class="textarea-container">
  185. <uv-textarea
  186. v-model="processData.content"
  187. placeholder="请输入处理内容"
  188. :maxlength="200"
  189. :show-confirm-bar="false"
  190. height="60"
  191. border="none"
  192. :textStyle="{ color: '#000' }"
  193. :custom-style="{ backgroundColor: '#f5f5f5' }"
  194. ></uv-textarea>
  195. </view>
  196. <!-- 上传图片 -->
  197. <view class="form-item">
  198. <text class="label">上传图片</text>
  199. </view>
  200. <view class="image-upload">
  201. <view v-for="(img, index) in getImageList(processData.image)" :key="index" class="image-item">
  202. <image :src="img.trim()" mode="aspectFill" @click="previewImage(img.trim())"></image>
  203. <view class="delete-btn" @click="deleteImage(index)">
  204. <uv-icon name="close" size="12" color="#fff"></uv-icon>
  205. </view>
  206. </view>
  207. <view class="upload-btn" @click="uploadImage">
  208. <uv-icon name="camera" size="34" color="#C70019"></uv-icon>
  209. </view>
  210. </view>
  211. <!-- 是否产生费用 -->
  212. <view class="form-item">
  213. <text class="label">是否产生费用</text>
  214. <view class="radio-options">
  215. <view
  216. class="radio-item"
  217. :class="{ active: processData.isExpend === '1' }"
  218. @click="selectCost('1')"
  219. >
  220. <view class="radio-dot" :class="{ active: processData.isExpend === '1' }"></view>
  221. <text :class="{ active: processData.isExpend === '1' }"></text>
  222. </view>
  223. <view
  224. class="radio-item"
  225. :class="{ active: processData.isExpend === '0' }"
  226. @click="selectCost('0')"
  227. >
  228. <view class="radio-dot" :class="{ active: processData.isExpend === '0' }"></view>
  229. <text :class="{ active: processData.isExpend === '0' }"></text>
  230. </view>
  231. </view>
  232. </view>
  233. <!-- 产生费用 -->
  234. <view class="form-item" v-if="processData.isExpend === '1'">
  235. <text class="label">产生费用</text>
  236. <view class="input-area" >
  237. <input
  238. v-model="amount"
  239. placeholder="请输入费用"
  240. disabled
  241. class="input-field"
  242. ref="maintainerInput"
  243. />
  244. </view>
  245. </view>
  246. <!-- 费用详情表格 -->
  247. <view class="cost-table" v-if="processData.isExpend === '1'">
  248. <view class="table-header">
  249. <text class="header-cell">费用名称</text>
  250. <text class="header-cell">数量</text>
  251. <text class="header-cell">金额</text>
  252. <text class="header-cell"></text>
  253. </view>
  254. <view class="table-row" v-for="(item, index) in processData.costDetails" :key="index">
  255. <view class="cell-input">
  256. <uv-input
  257. v-model="item.name"
  258. placeholder="费用名称"
  259. border="none"
  260. :custom-style="{ backgroundColor: 'transparent', fontSize: '28rpx' }"
  261. ></uv-input>
  262. </view>
  263. <view class="cell-input">
  264. <uv-input
  265. v-model="item.quantity"
  266. placeholder="数量"
  267. border="none"
  268. :custom-style="{ backgroundColor: 'transparent', fontSize: '28rpx' }"
  269. ></uv-input>
  270. </view>
  271. <view class="cell-input">
  272. <uv-input
  273. v-model="item.amount"
  274. placeholder="金额"
  275. border="none"
  276. :custom-style="{ backgroundColor: 'transparent', fontSize: '28rpx' }"
  277. ></uv-input>
  278. </view>
  279. <view class="cell-action">
  280. <view class="action-btn delete-btn" @click="deleteCostItem(index)" v-if="processData.costDetails.length > 1">
  281. <uv-icon name="close" size="14" color="#fff"></uv-icon>
  282. </view>
  283. <view class="action-btn add-btn" @click="addCostItem" v-if="index === processData.costDetails.length - 1">
  284. <uv-icon name="plus" size="14" color="#fff"></uv-icon>
  285. </view>
  286. </view>
  287. </view>
  288. </view>
  289. <!-- 问题是否解决 -->
  290. <view class="form-item">
  291. <text class="label">问题是否解决</text>
  292. <view class="radio-options">
  293. <view
  294. class="radio-item"
  295. :class="{ active: processData.isFix === '1' }"
  296. @click="selectResolved('1')"
  297. >
  298. <view class="radio-dot" :class="{ active: processData.isFix === '1' }"></view>
  299. <text :class="{ active: processData.isFix === '1' }"></text>
  300. </view>
  301. <view
  302. class="radio-item"
  303. :class="{ active: processData.isFix === '0' }"
  304. @click="selectResolved('0')"
  305. >
  306. <view class="radio-dot" :class="{ active: processData.isFix === '0' }"></view>
  307. <text :class="{ active: processData.isFix === '0' }"></text>
  308. </view>
  309. </view>
  310. </view>
  311. <!-- 备注 -->
  312. <view class="form-item">
  313. <text class="label">备注</text>
  314. </view>
  315. <view class="textarea-container">
  316. <uv-textarea
  317. v-model="processData.remark"
  318. placeholder="备注"
  319. :maxlength="200"
  320. :show-confirm-bar="false"
  321. height="60"
  322. border="none"
  323. :custom-style="{ backgroundColor: '#f5f5f5' }"
  324. ></uv-textarea>
  325. </view>
  326. <!-- 立即维修按钮 -->
  327. <view class="repair-btn-container">
  328. <uv-button
  329. type="primary"
  330. text="立即维修"
  331. :custom-style="{ backgroundColor: '#C70019', borderRadius: '25px' }"
  332. @click="startRepair"
  333. ></uv-button>
  334. </view>
  335. </view>
  336. <!-- 日期选择器 -->
  337. <uv-datetime-picker
  338. confirm-color="#C70019"
  339. ref="datePicker"
  340. v-model="timeValue"
  341. mode="date"
  342. @confirm="confirmDate"
  343. ></uv-datetime-picker>
  344. </view>
  345. </template>
  346. <script>
  347. export default {
  348. data() {
  349. return {
  350. timeValue: Number(new Date()),
  351. statusType: 'modify',
  352. selectedStatus: '故障中',
  353. isCollapsed: true,
  354. id: '',
  355. showpieceId: '',
  356. // 映射表
  357. statusMap: {
  358. '故障中': '0',
  359. '维修中': '1',
  360. '已解决': '2'
  361. },
  362. // 要有一个相反的引射表
  363. reverseStatusMap: {
  364. '0': '故障中',
  365. '1': '维修中',
  366. '2': '已解决'
  367. },
  368. // 报修基本信息(只读)
  369. repairData: {
  370. malfunctionDate: '2025-08-28', // 从接口 malfunctionDate 字段获取
  371. urgency: '0', // 从接口 urgency 字段映射:0-一般,1-紧急,2-非常紧急
  372. malfunctionDesc: '故障描述', // 从接口 malfunctionDesc 字段获取
  373. malfunctionImage: '', // 从接口 malfunctionImage 字段获取(字符串格式,多张图片用逗号分隔)
  374. firstDate: '2025-08-27', // 从接口 firstDate 字段获取
  375. frequency: '0', // 从接口 frequency 字段映射:0-偶发性,1-持续性
  376. reason: '发生频率触发条件', // 从接口 reason 字段获取
  377. isAffectUse: '0', // 从接口 isAffectUse 字段映射:0-否,1-是
  378. isMeasure: '0', // 从接口 isMeasure 字段映射:0-否,1-是
  379. measureDesc: '措施说明', // 从接口 measureDesc 字段获取
  380. isAffectExperience: '0', // 从接口 isAffectExperience 字段映射:0-否,1-是
  381. remark: '备注', // 从接口 remark 字段获取
  382. status: '0', // 从接口 status 字段获取
  383. },
  384. // 处理内容(可编辑)
  385. processData: {
  386. repairName: '',
  387. phone: '',
  388. repairDate: '',
  389. content: '',
  390. image: '',
  391. isExpend: '0',
  392. costDetails: [
  393. { name: '', quantity: '', amount: '' }
  394. ],
  395. isFix: '0',
  396. remark: ''
  397. },
  398. }
  399. },
  400. computed: {
  401. // 计算总金额
  402. amount() {
  403. return this.processData.costDetails.reduce((sum, item) => {
  404. return sum + (Number(item.quantity) * parseFloat(item.amount || 0))
  405. }, 0)
  406. }
  407. },
  408. async onShow(){
  409. await this.getRepairDetail()
  410. },
  411. onLoad(args){
  412. this.id = args.id
  413. this.showpieceId = args.showpieceId
  414. },
  415. methods: {
  416. // 修改状态
  417. async modifyStatus(){
  418. const res = await this.$api.exhibit.updateMalfunction({
  419. id: this.id,
  420. status: this.statusMap[this.selectedStatus]
  421. })
  422. if (res.code === 200) {
  423. uni.showToast({
  424. title: '修改成功',
  425. icon: 'success'
  426. })
  427. }
  428. },
  429. // 获取报修详情
  430. async getRepairDetail() {
  431. const queryRes = await this.$api.exhibit.queryMalfunctionById({
  432. malfunctionId: this.id
  433. })
  434. if (queryRes.code === 200) {
  435. this.repairData = queryRes.result
  436. // 状态字段反引射表
  437. this.selectedStatus = this.reverseStatusMap[this.repairData.status]
  438. }
  439. },
  440. // 立即维修
  441. async startRepair() {
  442. // 验证必填项
  443. if (!this.processData.repairName) {
  444. uni.showToast({
  445. title: '请输入维修人',
  446. icon: 'none'
  447. })
  448. return
  449. }
  450. if (!this.processData.phone) {
  451. uni.showToast({
  452. title: '请输入联系方式',
  453. icon: 'none'
  454. })
  455. return
  456. }
  457. if (!this.processData.repairDate) {
  458. uni.showToast({
  459. title: '请选择维修日期',
  460. icon: 'none'
  461. })
  462. return
  463. }
  464. if (!this.processData.content) {
  465. uni.showToast({
  466. title: '请输入处理内容',
  467. icon: 'none'
  468. })
  469. return
  470. }
  471. if (this.processData.isFix === null) {
  472. uni.showToast({
  473. title: '请选择问题是否解决',
  474. icon: 'none'
  475. })
  476. return
  477. }
  478. if (this.processData.isExpend === '1') {
  479. // 如果总金额为0则没有消费信息
  480. if (!this.amount) {
  481. uni.showToast({
  482. title: '请添加费用明细',
  483. icon: 'none'
  484. })
  485. return
  486. }
  487. }else {
  488. }
  489. const tempData = {...this.processData}
  490. delete tempData.costDetails
  491. const tempDataList = [...this.processData.costDetails]
  492. if (this.processData.isExpend === '1') {
  493. tempData.expenseList = tempDataList.map(item => `${item.name},${item.quantity},${item.amount}`).join(';')
  494. }else {
  495. delete tempData.expenseList
  496. }
  497. const submitRes = await this.$api.exhibit.addRepair({
  498. showpieceId: this.showpieceId,
  499. ...tempData,
  500. amount: this.amount
  501. })
  502. if (submitRes.code === 200) {
  503. uni.showToast({
  504. title: submitRes.message,
  505. icon: 'none'
  506. })
  507. setTimeout(() => {
  508. uni.navigateBack({
  509. delta: 1
  510. })
  511. }, 400)
  512. }else {
  513. uni.showToast({
  514. title: submitRes.message,
  515. icon: 'none'
  516. })
  517. }
  518. },
  519. // 获取图片列表
  520. getImageList(imageStr) {
  521. if (!imageStr || typeof imageStr !== 'string') {
  522. return []
  523. }
  524. return imageStr.split(',').filter(img => img && img.trim())
  525. },
  526. // 切换折叠状态
  527. toggleCollapse() {
  528. this.isCollapsed = !this.isCollapsed
  529. },
  530. // 预览图片
  531. previewImage(img) {
  532. uni.previewImage({
  533. urls: [img],
  534. current: img
  535. })
  536. },
  537. // 显示日期选择器
  538. showDatePicker() {
  539. this.$refs.datePicker.open()
  540. },
  541. // 确认日期
  542. confirmDate(e) {
  543. this.processData.repairDate = this.$utils.formatTime(e.value)
  544. },
  545. // 上传图片
  546. async uploadImage() {
  547. try {
  548. const result = await this.$utils.chooseAndUpload()
  549. if (result && result.success) {
  550. console.log(result);
  551. // 将新图片URL添加到字符串中
  552. if (this.processData.image) {
  553. this.processData.image += ',' + result.url
  554. } else {
  555. this.processData.image = result.url
  556. }
  557. }
  558. } catch (error) {
  559. console.error('图片上传失败:', error)
  560. uni.showToast({
  561. title: '图片上传失败',
  562. icon: 'error'
  563. })
  564. }
  565. },
  566. // 删除图片
  567. deleteImage(index) {
  568. const imageList = this.getImageList(this.processData.image)
  569. imageList.splice(index, 1)
  570. this.processData.image = imageList.join(',')
  571. },
  572. // 选择是否产生费用
  573. selectCost(value) {
  574. this.processData.isExpend = value
  575. if (!value) {
  576. this.processData.amount = 0
  577. this.processData.costDetails = [{ name: '', quantity: '', amount: '' }]
  578. }
  579. },
  580. // 添加费用项
  581. addCostItem() {
  582. this.processData.costDetails.push({ name: '', quantity: '', amount: '' })
  583. },
  584. // 删除费用项
  585. deleteCostItem(index) {
  586. this.processData.costDetails.splice(index, 1)
  587. },
  588. // 选择问题是否解决
  589. selectResolved(value) {
  590. this.processData.isFix = value
  591. },
  592. // 显示状态选择器
  593. showStatusPicker() {
  594. uni.showActionSheet({
  595. itemList: ['故障中', '维修中', '已解决'],
  596. success: (res) => {
  597. const statusList = ['故障中', '维修中', '已解决']
  598. this.selectedStatus = statusList[res.tapIndex]
  599. }
  600. })
  601. },
  602. }
  603. }
  604. </script>
  605. <style lang="scss" scoped>
  606. .maintain-submit {
  607. min-height: 100vh;
  608. background-color: #f5f5f5;
  609. padding-bottom: 200rpx;
  610. }
  611. // 修改状态
  612. .status-item {
  613. margin: 18rpx;
  614. background: #ffffff;
  615. border-radius: 15rpx;
  616. box-shadow: 0rpx 3rpx 6rpx 0rpx rgba(0,0,0,0.16);
  617. padding: 20rpx 40rpx;
  618. .status-row {
  619. display: flex;
  620. align-items: center;
  621. justify-content: space-between;
  622. margin-bottom: 24rpx;
  623. .status-label {
  624. font-size: 30rpx;
  625. color: $primary-text-color;
  626. // font-weight: bold;
  627. }
  628. .status-select {
  629. display: flex;
  630. align-items: center;
  631. gap: 23rpx;
  632. padding: 12rpx 24rpx;
  633. // background-color: #f5f5f5;
  634. border-radius: 8rpx;
  635. // min-width: 200rpx;
  636. justify-content: space-between;
  637. .status-value {
  638. font-size: 28rpx;
  639. color: $primary-text-color;
  640. &.placeholder {
  641. color: $secondary-text-color;
  642. }
  643. }
  644. }
  645. }
  646. .status-btn {
  647. display: flex;
  648. align-items: center;
  649. justify-content: center;
  650. // padding: 16rpx 32rpx;
  651. // border: 2rpx solid #ddd;
  652. border-radius: full;
  653. background-color: #fff;
  654. width: 419rpx;
  655. height: 78rpx;
  656. border-radius: 39rpx;
  657. &.active {
  658. border-color: $primary-color;
  659. background-color: $primary-color;
  660. .status-text {
  661. color: #fff;
  662. }
  663. }
  664. .status-text {
  665. font-size: 30rpx;
  666. color: $secondary-text-color;
  667. }
  668. }
  669. }
  670. // 报修基本信息和处理内容通用样式
  671. .repair-info, .process-content {
  672. margin: 18rpx;
  673. background: #ffffff;
  674. border-radius: 15rpx;
  675. box-shadow: 0rpx 3rpx 6rpx 0rpx rgba(0,0,0,0.16);
  676. padding: 30rpx;
  677. .info-header {
  678. display: flex;
  679. align-items: center;
  680. margin-bottom: 40rpx;
  681. .red-line {
  682. width: 9rpx;
  683. height: 33rpx;
  684. background-color: $primary-color;
  685. margin-right: 7rpx;
  686. border-radius: 5rpx;
  687. }
  688. .info-title {
  689. font-size: 30rpx;
  690. font-weight: bold;
  691. color: $primary-text-color;
  692. }
  693. }
  694. .form-item {
  695. display: flex;
  696. align-items: center;
  697. justify-content: space-between;
  698. padding: 18rpx 0;
  699. border-bottom: 2rpx solid #f0f0f0;
  700. &:last-child {
  701. border-bottom: none;
  702. }
  703. .input-area {
  704. flex: 1;
  705. // background-color: #f5f5f5;
  706. border-radius: 8rpx;
  707. padding: 2rpx 24rpx;
  708. margin-left: 24rpx;
  709. .input-field {
  710. width: 100%;
  711. font-size: 30rpx;
  712. color: $primary-text-color;
  713. background: transparent;
  714. border: none;
  715. outline: none;
  716. text-align: right;
  717. &::placeholder {
  718. color: $secondary-text-color;
  719. }
  720. }
  721. }
  722. .label {
  723. font-size: 30rpx;
  724. color: $primary-text-color;
  725. flex-shrink: 0;
  726. &.active {
  727. font-weight: bold;
  728. }
  729. }
  730. .value {
  731. font-size: 30rpx;
  732. color: $primary-text-color;
  733. &.placeholder {
  734. color: $secondary-text-color;
  735. }
  736. &.red-text {
  737. color: $primary-color;
  738. }
  739. }
  740. .select-area {
  741. display: flex;
  742. align-items: center;
  743. gap: 16rpx;
  744. }
  745. }
  746. .content-text {
  747. // padding: 16rpx 0;
  748. margin-bottom: 16rpx;
  749. text {
  750. font-size: 30rpx;
  751. color: $secondary-text-color;
  752. line-height: 1.5;
  753. }
  754. }
  755. .image-container {
  756. display: flex;
  757. flex-wrap: wrap;
  758. gap: 24rpx;
  759. margin: 16rpx 0;
  760. .uploaded-image {
  761. width: 160rpx;
  762. height: 160rpx;
  763. // border-radius: 8rpx;
  764. }
  765. }
  766. .collapse-btn {
  767. display: flex;
  768. align-items: center;
  769. justify-content: center;
  770. gap: 16rpx;
  771. padding: 30rpx 0 0;
  772. margin-top: 16rpx;
  773. border-top: 2rpx solid #f0f0f0;
  774. .collapse-text {
  775. font-size: 28rpx;
  776. color: $primary-color;
  777. }
  778. .collapse-icon {
  779. font-size: 24rpx;
  780. color: $primary-color;
  781. }
  782. }
  783. }
  784. // 处理内容特有样式
  785. .process-content {
  786. .textarea-container {
  787. margin: 16rpx 0;
  788. background-color: #f5f5f5;
  789. border-radius: 8rpx;
  790. padding: 8rpx 16rpx;
  791. }
  792. .image-upload {
  793. display: flex;
  794. flex-wrap: wrap;
  795. gap: 24rpx;
  796. margin: 16rpx 0;
  797. .upload-btn {
  798. width: 160rpx;
  799. height: 160rpx;
  800. border: 2rpx dashed $primary-color;
  801. display: flex;
  802. align-items: center;
  803. justify-content: center;
  804. background-color: #fff;
  805. border-radius: 8rpx;
  806. }
  807. .image-item {
  808. position: relative;
  809. width: 160rpx;
  810. height: 160rpx;
  811. image {
  812. width: 100%;
  813. height: 100%;
  814. border-radius: 8rpx;
  815. }
  816. .delete-btn {
  817. position: absolute;
  818. top: -12rpx;
  819. right: -12rpx;
  820. width: 40rpx;
  821. height: 40rpx;
  822. background-color: #ff4757;
  823. border-radius: 50%;
  824. display: flex;
  825. align-items: center;
  826. justify-content: center;
  827. }
  828. }
  829. }
  830. .radio-options {
  831. display: flex;
  832. gap: 80rpx;
  833. .radio-item {
  834. display: flex;
  835. align-items: center;
  836. gap: 16rpx;
  837. .radio-dot {
  838. width: 32rpx;
  839. height: 32rpx;
  840. border: 4rpx solid #ddd;
  841. border-radius: 50%;
  842. position: relative;
  843. &.active {
  844. border-color: $primary-color;
  845. &::after {
  846. content: '';
  847. position: absolute;
  848. top: 50%;
  849. left: 50%;
  850. transform: translate(-50%, -50%);
  851. width: 16rpx;
  852. height: 16rpx;
  853. background-color: $primary-color;
  854. border-radius: 50%;
  855. }
  856. }
  857. }
  858. text {
  859. font-size: 30rpx;
  860. color: $secondary-text-color;
  861. &.active {
  862. color: $primary-color;
  863. }
  864. }
  865. }
  866. }
  867. // 费用表格样式
  868. .cost-table {
  869. margin: 16rpx 0;
  870. border: 2rpx solid #f0f0f0;
  871. border-radius: 8rpx;
  872. overflow: hidden;
  873. .table-header {
  874. display: flex;
  875. background-color: #f8f8f8;
  876. .header-cell {
  877. flex: 1;
  878. padding: 24rpx 16rpx;
  879. font-size: 28rpx;
  880. font-weight: bold;
  881. color: $primary-text-color;
  882. text-align: left;
  883. border-right: 2rpx solid #f0f0f0;
  884. &:first-child {
  885. flex: 2;
  886. text-align: left;
  887. }
  888. &:last-child {
  889. border-right: none;
  890. }
  891. }
  892. }
  893. .table-row {
  894. display: flex;
  895. border-top: 2rpx solid #f0f0f0;
  896. .cell-input {
  897. flex: 1;
  898. padding: 8rpx;
  899. border-right: 2rpx solid #f0f0f0;
  900. &:first-child {
  901. flex: 2;
  902. }
  903. &:last-child {
  904. border-right: none;
  905. }
  906. }
  907. .cell-action {
  908. width: 120rpx;
  909. display: flex;
  910. align-items: center;
  911. justify-content: center;
  912. gap: 8rpx;
  913. padding: 8rpx;
  914. .action-btn {
  915. width: 36rpx;
  916. height: 36rpx;
  917. padding: 4rpx;
  918. border-radius: 50%;
  919. display: flex;
  920. align-items: center;
  921. justify-content: center;
  922. &.add-btn {
  923. background-color: #1a9c10;
  924. }
  925. &.delete-btn {
  926. background-color: $primary-color;
  927. }
  928. }
  929. }
  930. }
  931. }
  932. // 立即维修按钮
  933. .repair-btn-container {
  934. margin-top: 40rpx;
  935. padding-top: 32rpx;
  936. border-top: 2rpx solid #f0f0f0;
  937. }
  938. }
  939. </style>