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

638 lines
18 KiB

  1. <template>
  2. <view class="container">
  3. <view class="header">
  4. <!-- 大Tab维修记录/保养记录 -->
  5. <view class="main-tabs">
  6. <view
  7. class="tab-item"
  8. :class="{ active: activeMainTab === 'repair' }"
  9. @click="switchMainTab('repair')"
  10. >
  11. <text class="tab-text">维修记录</text>
  12. <view class="tab-underline" v-if="activeMainTab === 'repair'"></view>
  13. </view>
  14. <view
  15. class="tab-item"
  16. :class="{ active: activeMainTab === 'maintain' }"
  17. @click="switchMainTab('maintain')"
  18. >
  19. <text class="tab-text">保养记录</text>
  20. <view class="tab-underline" v-if="activeMainTab === 'maintain'"></view>
  21. </view>
  22. </view>
  23. <!-- 筛选按钮区域 -->
  24. <view class="picker-buttons">
  25. <view class="picker-btn" :class="{ active: selectedTime }" @click="showTimePicker" >
  26. <text class="btn-text">{{ selectedTime || '时间' }}</text>
  27. <text class="arrow-icon"></text>
  28. </view>
  29. <view class="picker-btn" :class="{ active: selectedPerson }" @click="showPersonPicker" >
  30. <text class="btn-text">{{ selectedPerson || '人员' }}</text>
  31. <text class="arrow-icon"></text>
  32. </view>
  33. </view>
  34. </view>
  35. <!-- 时间选择器 -->
  36. <uv-picker
  37. ref="timePicker"
  38. :columns="timeColumns"
  39. @confirm="onTimeConfirm"
  40. @cancel="onTimeCancel"
  41. title="选择时间范围"
  42. confirmColor="#C70019"
  43. ></uv-picker>
  44. <!-- 人员选择器 -->
  45. <uv-picker
  46. ref="personPicker"
  47. :columns="personColumns"
  48. @confirm="onPersonConfirm"
  49. @cancel="onPersonCancel"
  50. title="选择人员"
  51. confirmColor="#C70019"
  52. ></uv-picker>
  53. <!-- 内容区域 -->
  54. <view class="content-area">
  55. <!-- 记录item -->
  56. <view class="record-item" v-for="(record, index) in list" :key="index">
  57. <!-- 维修记录 -->
  58. <template v-if="activeMainTab === 'repair'">
  59. <!-- 基本信息 -->
  60. <view class="info-row">
  61. <text class="label">维修人</text>
  62. <text class="value">{{ record.repairPerson }}</text>
  63. </view>
  64. <view class="info-row">
  65. <text class="label">联系方式</text>
  66. <text class="value">{{ record.contactPhone }}</text>
  67. </view>
  68. <view class="info-row">
  69. <text class="label">维修日期</text>
  70. <text class="value">{{ record.repairDate }}</text>
  71. </view>
  72. <view class="info-row">
  73. <text class="label">处理内容</text>
  74. </view>
  75. <!-- 处理内容文本区域 -->
  76. <view class="content-text">
  77. <text>{{ record.processContent }}</text>
  78. </view>
  79. <!-- 上传图片 -->
  80. <view class="info-row" v-if="!record.isCollapsed">
  81. <text class="label">上传图片</text>
  82. </view>
  83. <view class="image-container" v-if="!record.isCollapsed">
  84. <image class="uploaded-image" :src="record.uploadImage" mode="aspectFill"></image>
  85. </view>
  86. <!-- 是否产生费用 -->
  87. <view class="info-row">
  88. <text class="label">是否产生费用</text>
  89. <text class="value red-text">{{ record.hasCost }}</text>
  90. </view>
  91. </template>
  92. <!-- 保养记录 -->
  93. <template v-else>
  94. <!-- 基本信息 -->
  95. <view class="info-row">
  96. <text class="label">保养人</text>
  97. <text class="value">{{ record.maintainPerson }}</text>
  98. </view>
  99. <view class="info-row">
  100. <text class="label">保养日期</text>
  101. <text class="value">{{ record.maintainDate }}</text>
  102. </view>
  103. <view class="info-row">
  104. <text class="label">保养前状态</text>
  105. </view>
  106. <!-- 保养前状态文本区域 -->
  107. <view class="content-text">
  108. <text>{{ record.beforeStatus }}</text>
  109. </view>
  110. <!-- 保养前图片 -->
  111. <view class="image-container" v-if="!record.isCollapsed">
  112. <image
  113. class="uploaded-image"
  114. v-for="(img, imgIndex) in record.beforeImages"
  115. :key="imgIndex"
  116. :src="img"
  117. mode="aspectFill"
  118. ></image>
  119. </view>
  120. <view class="info-row" v-if="!record.isCollapsed">
  121. <text class="label">保养后状态</text>
  122. </view>
  123. <!-- 保养后状态文本区域 -->
  124. <view class="content-text" v-if="!record.isCollapsed">
  125. <text>{{ record.afterStatus }}</text>
  126. </view>
  127. <!-- 保养后图片 -->
  128. <view class="image-container" v-if="!record.isCollapsed">
  129. <image
  130. class="uploaded-image"
  131. v-for="(img, imgIndex) in record.afterImages"
  132. :key="'after-' + imgIndex"
  133. :src="img"
  134. mode="aspectFill"
  135. ></image>
  136. </view>
  137. <!-- 是否产生费用 -->
  138. <view class="info-row" v-if="!record.isCollapsed">
  139. <text class="label">是否产生费用</text>
  140. <text class="value red-text">{{ record.hasCost }}</text>
  141. </view>
  142. </template>
  143. <!-- 查看全部按钮收起状态时显示 -->
  144. <!-- <view class="view-all-btn" v-if="record.isCollapsed" @click="toggleCollapse(index)">
  145. <text class="view-all-text">查看全部</text>
  146. <text class="view-all-icon"></text>
  147. </view> -->
  148. <!-- 产生费用 -->
  149. <view class="info-row" v-if="!record.isCollapsed">
  150. <text class="label">产生费用</text>
  151. <text class="value red-text">{{ record.totalCost }}</text>
  152. </view>
  153. <!-- 费用详情表格 -->
  154. <view class="cost-table" v-if="!record.isCollapsed">
  155. <view class="table-header">
  156. <text class="header-cell">费用名称</text>
  157. <text class="header-cell">数量</text>
  158. <text class="header-cell">金额</text>
  159. </view>
  160. <view class="table-row" v-for="(item, index) in record.costDetails" :key="index">
  161. <text class="cell">{{ item.name }}</text>
  162. <text class="cell">{{ item.quantity }}</text>
  163. <text class="cell">{{ item.amount }}</text>
  164. </view>
  165. </view>
  166. <!-- 维修记录特有字段 -->
  167. <template v-if="activeMainTab === 'repair'">
  168. <!-- 问题是否解决 -->
  169. <view class="info-row" v-if="!record.isCollapsed">
  170. <text class="label">问题是否解决</text>
  171. <text class="value red-text">{{ record.isResolved }}</text>
  172. </view>
  173. <!-- 备注 -->
  174. <view class="info-row" v-if="!record.isCollapsed">
  175. <text class="label">备注</text>
  176. </view>
  177. <!-- 备注文本区域 -->
  178. <view class="content-text" v-if="!record.isCollapsed">
  179. <text>{{ record.remark }}</text>
  180. </view>
  181. </template>
  182. <!-- 保养记录特有字段 -->
  183. <template v-else>
  184. <!-- 附件信息 -->
  185. <view class="info-row" v-if="!record.isCollapsed">
  186. <text class="label">附件信息</text>
  187. </view>
  188. <!-- 附件信息文本区域 -->
  189. <view class="content-text" v-if="!record.isCollapsed">
  190. <text>{{ record.attachmentInfo }}</text>
  191. </view>
  192. <!-- 附件图片 -->
  193. <view class="image-container" v-if="!record.isCollapsed">
  194. <image class="uploaded-image" :src="record.attachmentImage" mode="aspectFill"></image>
  195. </view>
  196. <!-- 保养备注 -->
  197. <view class="info-row" v-if="!record.isCollapsed">
  198. <text class="label">备注</text>
  199. </view>
  200. <!-- 保养备注文本区域 -->
  201. <view class="content-text" v-if="!record.isCollapsed">
  202. <text>{{ record.maintainRemark }}</text>
  203. </view>
  204. </template>
  205. <!-- 收起按钮 -->
  206. <view class="collapse-btn" @click="toggleCollapse(index)">
  207. <text class="collapse-text">{{ record.isCollapsed ? '查看全部' : '收起' }}</text>
  208. <text class="collapse-icon">{{ record.isCollapsed ? '▼' : '▲' }}</text>
  209. </view>
  210. </view>
  211. </view>
  212. </view>
  213. </template>
  214. <script>
  215. export default {
  216. data() {
  217. return {
  218. activeMainTab: 'repair', // 当前激活的主Tab
  219. activeFilter: 0, // 当前激活的筛选器
  220. filterOptions: [
  221. { name: '时间' },
  222. { name: '人员' }
  223. ],
  224. selectedTime: '', // 选中的时间
  225. selectedPerson: '', // 选中的人员
  226. timeColumns: [
  227. ['今天', '昨天', '本周', '本月', '上月', '自定义']
  228. ],
  229. personColumns: [
  230. ['张三', '李四', '王五', '赵六', '钱七', '孙八']
  231. ],
  232. // 维修记录数据
  233. repairData: [
  234. {
  235. repairPerson: '李华',
  236. contactPhone: '15845623255',
  237. repairDate: '2025-08-14',
  238. processContent: '文字内容文字内容文字内容',
  239. uploadImage: '/static/商城_商品2.png',
  240. hasCost: '是',
  241. totalCost: '300.00',
  242. costDetails: [
  243. { name: '天然粘胶剂', quantity: '2', amount: '100.00' },
  244. { name: '达玛树脂', quantity: '1', amount: '200.00' }
  245. ],
  246. isResolved: '是',
  247. remark: '文字内容',
  248. isCollapsed: true // 控制收起状态
  249. },
  250. {
  251. repairPerson: '李华',
  252. contactPhone: '15845623255',
  253. repairDate: '2025-08-14',
  254. processContent: '文字内容文字内容文字内容',
  255. uploadImage: '/static/商城_商品2.png',
  256. hasCost: '是',
  257. totalCost: '300.00',
  258. costDetails: [
  259. { name: '天然粘胶剂', quantity: '2', amount: '100.00' },
  260. { name: '达玛树脂', quantity: '1', amount: '200.00' }
  261. ],
  262. isResolved: '是',
  263. remark: '文字内容',
  264. isCollapsed: true // 控制收起状态
  265. },
  266. ],
  267. // 保养记录数据
  268. maintainData: [
  269. {
  270. maintainPerson: '李华',
  271. maintainDate: '2025-08-19',
  272. beforeStatus: '文字内容文字内容文字内容',
  273. beforeImages: ['/static/商城_商品2.png', '/static/商城_商品2.png'],
  274. afterStatus: '文字内容文字内容文字内容',
  275. afterImages: ['/static/商城_商品2.png', '/static/商城_商品2.png'],
  276. hasCost: '是',
  277. totalCost: '300.00',
  278. costDetails: [
  279. { name: '天然粘胶剂', quantity: '2', amount: '100.00' },
  280. { name: '达玛树脂', quantity: '1', amount: '200.00' }
  281. ],
  282. attachmentInfo: '附件信息',
  283. maintainRemark: '文字内容',
  284. attachmentImage: '/static/商城_商品2.png',
  285. isCollapsed: true // 控制收起状态
  286. },
  287. {
  288. maintainPerson: '李华',
  289. maintainDate: '2025-08-19',
  290. beforeStatus: '文字内容文字内容文字内容',
  291. beforeImages: ['/static/商城_商品2.png', '/static/商城_商品2.png'],
  292. afterStatus: '文字内容文字内容文字内容',
  293. afterImages: ['/static/商城_商品2.png', '/static/商城_商品2.png'],
  294. hasCost: '是',
  295. totalCost: '300.00',
  296. costDetails: [
  297. { name: '天然粘胶剂', quantity: '2', amount: '100.00' },
  298. { name: '达玛树脂', quantity: '1', amount: '200.00' }
  299. ],
  300. attachmentInfo: '附件信息',
  301. maintainRemark: '文字内容',
  302. attachmentImage: '/static/商城_商品2.png',
  303. isCollapsed: true // 控制收起状态
  304. }
  305. ]
  306. }
  307. },
  308. computed: {
  309. list() {
  310. return this.activeMainTab === 'repair' ? this.repairData : this.maintainData
  311. },
  312. contentText() {
  313. const tabText = this.activeMainTab === 'repair' ? '维修' : '保养'
  314. const filterText = this.filterOptions[this.activeFilter].name
  315. let selectedText = ''
  316. if (this.activeFilter === 0 && this.selectedTime) {
  317. selectedText = ` - ${this.selectedTime}`
  318. } else if (this.activeFilter === 1 && this.selectedPerson) {
  319. selectedText = ` - ${this.selectedPerson}`
  320. }
  321. return `${tabText}记录 - 按${filterText}筛选${selectedText}`
  322. }
  323. },
  324. methods: {
  325. switchMainTab(tab) {
  326. this.activeMainTab = tab
  327. },
  328. onFilterChange(index) {
  329. this.activeFilter = index
  330. // 切换筛选器时清空选择
  331. this.selectedTime = ''
  332. this.selectedPerson = ''
  333. },
  334. showTimePicker() {
  335. this.$refs.timePicker.open()
  336. },
  337. showPersonPicker() {
  338. this.$refs.personPicker.open()
  339. },
  340. onTimeConfirm(value) {
  341. this.selectedTime = value.value[0]
  342. console.log('选择的时间:', value)
  343. },
  344. onTimeCancel() {
  345. console.log('取消选择时间')
  346. },
  347. onPersonConfirm(value) {
  348. this.selectedPerson = value.value[0]
  349. console.log('选择的人员:', value)
  350. },
  351. onPersonCancel() {
  352. console.log('取消选择人员')
  353. },
  354. toggleCollapse(index) {
  355. if (this.activeMainTab === 'repair') {
  356. this.repairData[index].isCollapsed = !this.repairData[index].isCollapsed
  357. console.log('收起/展开费用详情', this.repairData[index].isCollapsed)
  358. } else {
  359. this.maintainData[index].isCollapsed = !this.maintainData[index].isCollapsed
  360. console.log('收起/展开费用详情', this.maintainData[index].isCollapsed)
  361. }
  362. }
  363. }
  364. }
  365. </script>
  366. <style lang="scss" scoped>
  367. .container {
  368. background-color: #f5f5f5;
  369. min-height: 100vh;
  370. }
  371. .header{
  372. padding: 16rpx 39rpx 23rpx;
  373. background: #fff;
  374. }
  375. .main-tabs {
  376. display: flex;
  377. margin-bottom: 48rpx;
  378. // border-bottom: 2rpx solid #f0f0f0;
  379. .tab-item {
  380. flex: 1;
  381. position: relative;
  382. padding: 13rpx 0;
  383. text-align: center;
  384. .tab-text {
  385. font-size: 28rpx;
  386. color: $secondary-text-color;
  387. font-weight: 400;
  388. transition: all 0.3s ease;
  389. }
  390. &.active {
  391. .tab-text {
  392. color: $primary-color;
  393. // font-weight: 600;
  394. }
  395. }
  396. .tab-underline {
  397. position: absolute;
  398. bottom: 0;
  399. left: 50%;
  400. transform: translateX(-50%);
  401. width: 60rpx;
  402. height: 4rpx;
  403. background-color: $primary-color;
  404. border-radius: 2rpx;
  405. }
  406. }
  407. }
  408. .filter-section {
  409. margin-bottom: 32rpx;
  410. }
  411. .picker-buttons {
  412. // margin-bottom: 32rpx;
  413. display: flex;
  414. gap: 55rpx;
  415. .picker-btn {
  416. display: flex;
  417. align-items: center;
  418. justify-content: flex-start;
  419. padding: 0;
  420. background-color: transparent;
  421. color: $primary-text-color;
  422. &.active {
  423. color: $primary-color;
  424. }
  425. .btn-text {
  426. font-size: 28rpx;
  427. // color: $primary-color;
  428. margin-right: 10rpx;
  429. }
  430. .arrow-icon {
  431. font-size: 20rpx;
  432. // color: $primary-color;
  433. }
  434. }
  435. }
  436. .content-area {
  437. padding: 22rpx 29rpx;
  438. .record-item {
  439. background: #fff;
  440. border-radius: 16rpx;
  441. padding: 29rpx;
  442. margin-bottom: 37rpx;
  443. border-radius: 15rpx;
  444. box-shadow: 0 3rpx 6rpx 0rpx rgba(0,0,0,0.16);
  445. .info-row {
  446. display: flex;
  447. justify-content: space-between;
  448. align-items: flex-start;
  449. margin-bottom: 38rpx;
  450. .label {
  451. font-size: 28rpx;
  452. color: $primary-text-color;
  453. // font-weight: 400;
  454. flex-shrink: 0;
  455. }
  456. .value {
  457. font-size: 28rpx;
  458. color: $primary-text-color;
  459. text-align: right;
  460. flex: 1;
  461. margin-left: 32rpx;
  462. &.red-text {
  463. color: $primary-color;
  464. }
  465. }
  466. }
  467. .content-text {
  468. background: #f5f5f5;
  469. border-radius: 15rpx;
  470. padding: 24rpx;
  471. margin-bottom: 24rpx;
  472. min-height: 120rpx;
  473. text {
  474. font-size: 28rpx;
  475. color: $primary-text-color;
  476. line-height: 1.5;
  477. }
  478. }
  479. .image-container {
  480. margin-bottom: 29rpx;
  481. .uploaded-image {
  482. width: 157rpx;
  483. height: 157rpx;
  484. // border-radius: 8rpx;
  485. }
  486. }
  487. .cost-table {
  488. margin-bottom: 24rpx;
  489. .table-header {
  490. display: flex;
  491. // background: #f8f8f8;
  492. // border-radius: 8rpx 8rpx 0 0;
  493. padding: 30rpx 0;
  494. justify-content: space-between;
  495. .header-cell {
  496. flex: 1;
  497. font-size: 30rpx;
  498. color: $secondary-text-color;
  499. &:nth-child(1) {
  500. text-align: left;
  501. }
  502. &:nth-child(2) {
  503. text-align: center;
  504. }
  505. &:nth-child(3) {
  506. text-align: right;
  507. }
  508. // font-weight: 500;
  509. }
  510. }
  511. .table-row {
  512. display: flex;
  513. border-bottom: 1rpx solid #f0f0f0;
  514. padding: 30rpx 0;
  515. // justify-content: space-between;
  516. .cell {
  517. flex: 1;
  518. font-size: 30rpx;
  519. color: $primary-text-color;
  520. &:nth-child(1) {
  521. text-align: left;
  522. }
  523. &:nth-child(2) {
  524. text-align: center;
  525. }
  526. &:nth-child(3) {
  527. text-align: right;
  528. }
  529. }
  530. // .cell:first-child {
  531. // text-align: center;
  532. // }
  533. }
  534. }
  535. .view-all-btn {
  536. display: flex;
  537. justify-content: center;
  538. align-items: center;
  539. padding: 16rpx 0;
  540. margin-top: 16rpx;
  541. .view-all-text {
  542. font-size: 26rpx;
  543. color: $primary-color;
  544. margin-right: 8rpx;
  545. }
  546. .view-all-icon {
  547. font-size: 20rpx;
  548. color: $primary-color;
  549. }
  550. }
  551. .collapse-btn {
  552. display: flex;
  553. justify-content: center;
  554. align-items: center;
  555. padding: 16rpx 0;
  556. margin-top: 16rpx;
  557. .collapse-text {
  558. font-size: 26rpx;
  559. color: $primary-color;
  560. margin-right: 8rpx;
  561. }
  562. .collapse-icon {
  563. font-size: 20rpx;
  564. color: $primary-color;
  565. }
  566. }
  567. }
  568. }
  569. </style>