PageTwo.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. <template>
  2. <view class="page-two-container">
  3. <!-- 上门地址卡片 -->
  4. <view class="card-wrap">
  5. <view class="address-section">
  6. <view class="address-header">
  7. <u-icon name="map" size="36rpx" color="#108cff" class="location-icon" />
  8. <text class="address-title">上门地址</text>
  9. </view>
  10. <view class="address-content">
  11. <text class="address-text">{{ orderDetail.address || '未填写' }}</text>
  12. </view>
  13. </view>
  14. </view>
  15. <!-- 跟进清单卡片 -->
  16. <view class="card-wrap checklist-card">
  17. <view class="checklist-section">
  18. <u-checkbox-group v-model="selectedCheckbox" placement="column">
  19. <!-- 联系师傅 -->
  20. <view class="checklist-item">
  21. <view class="checkbox-text-container">
  22. <u-checkbox name="contactMaster" size="40rpx" color="#108cff" />
  23. <text class="checklist-text">联系师傅</text>
  24. </view>
  25. <u-input
  26. v-if="selectedCheckbox.includes('contactMaster')"
  27. v-model="formData.contactPhone"
  28. placeholder="请输入师傅手机号"
  29. class="checklist-input"
  30. />
  31. </view>
  32. <!-- 师傅拍图技巧 -->
  33. <view class="checklist-item">
  34. <view class="checkbox-text-container">
  35. <u-checkbox name="photoTips" size="40rpx" color="#108cff" />
  36. <text class="checklist-text">师傅拍图技巧</text>
  37. </view>
  38. <u-input
  39. v-if="selectedCheckbox.includes('photoTips')"
  40. v-model="formData.photoTips"
  41. type="textarea"
  42. placeholder="请输入拍图技巧"
  43. rows="3"
  44. class="checklist-textarea"
  45. />
  46. <view v-if="selectedCheckbox.includes('photoTips')" class="upload-btn-container">
  47. <view class="upload-btn" @click="handleUpload('photoTips')">
  48. <u-icon name="camera" size="32rpx" color="#108cff" />
  49. <text class="upload-btn-text">上传图片</text>
  50. </view>
  51. </view>
  52. <view
  53. v-if="selectedCheckbox.includes('photoTips') && photoTipsImages.length > 0"
  54. class="image-list"
  55. >
  56. <view
  57. v-for="(image, index) in photoTipsImages"
  58. :key="index"
  59. class="image-item"
  60. @click="previewPhotoTips(image)"
  61. >
  62. <image :src="image" mode="aspectFill" class="image-thumb" />
  63. </view>
  64. </view>
  65. </view>
  66. <!-- 到达客户面对面 -->
  67. <view class="checklist-item">
  68. <view class="checkbox-text-container">
  69. <u-checkbox name="faceToFace" size="40rpx" color="#108cff" />
  70. <text class="checklist-text">到达客户面对面</text>
  71. </view>
  72. <u-input
  73. v-if="selectedCheckbox.includes('faceToFace')"
  74. v-model="formData.faceToFaceNotes"
  75. type="textarea"
  76. placeholder="请输入备注信息"
  77. rows="3"
  78. class="checklist-textarea"
  79. />
  80. <view v-if="selectedCheckbox.includes('faceToFace')" class="upload-btn-container">
  81. <view class="upload-btn" @click="handleUpload('faceToFace')">
  82. <u-icon name="camera" size="32rpx" color="#108cff" />
  83. <text class="upload-btn-text">上传图片</text>
  84. </view>
  85. </view>
  86. <view
  87. v-if="selectedCheckbox.includes('faceToFace') && faceToFaceImages.length > 0"
  88. class="image-list"
  89. >
  90. <view
  91. v-for="(image, index) in faceToFaceImages"
  92. :key="index"
  93. class="image-item"
  94. @click="previewFaceToFace(image)"
  95. >
  96. <image :src="image" mode="aspectFill" class="image-thumb" />
  97. </view>
  98. </view>
  99. </view>
  100. </u-checkbox-group>
  101. </view>
  102. </view>
  103. <!-- 核准价卡片 -->
  104. <view class="card-wrap price-card">
  105. <view class="price-section">
  106. <view class="price-picker-container">
  107. <view class="quick-actions top-actions">
  108. <view class="quick-btn increase" @click="quickChangePrice(100)">+100</view>
  109. <view class="quick-btn increase" @click="quickChangePrice(1000)">+1000</view>
  110. </view>
  111. <view class="number-box-container">
  112. <view class="price-input-box">
  113. <text class="price-label">核准价</text>
  114. <view class="price-value-wrap">
  115. <text class="yuan-prefix">¥</text>
  116. <input
  117. type="number"
  118. v-model="approvedPrice"
  119. class="price-input"
  120. placeholder="0"
  121. min="0"
  122. @input="onPriceInput"
  123. @blur="saveApprovedPrice"
  124. />
  125. </view>
  126. </view>
  127. </view>
  128. <view class="quick-actions bottom-actions">
  129. <view class="quick-btn decrease" @click="quickChangePrice(-100)">-100</view>
  130. <view class="quick-btn decrease" @click="quickChangePrice(-1000)">-1000</view>
  131. </view>
  132. </view>
  133. </view>
  134. </view>
  135. <!-- 高清细节图卡片 -->
  136. <view class="card-wrap detail-image-card">
  137. <view class="detail-image-section">
  138. <view class="detail-image-header">
  139. <text class="detail-image-title">上传高清细节图(支持多选)</text>
  140. <view class="copy-btn" @click="copyAllDetailImages">
  141. <text>一键保存</text>
  142. </view>
  143. </view>
  144. <view class="detail-image-upload-container">
  145. <view class="detail-image-list">
  146. <view
  147. v-for="(item, index) in detailImages"
  148. :key="`detail-${index}`"
  149. class="detail-image-item"
  150. >
  151. <PicComp
  152. :src="item.fileUrl"
  153. @needPreviewPic="previewImageDetail"
  154. />
  155. <view class="detail-delete-btn" @click="handleDeleteImage(item)">×</view>
  156. </view>
  157. <view
  158. class="detail-upload-btn"
  159. @click="handleUploadImage('detailImages')"
  160. >
  161. <u-icon name="plus" size="40rpx" color="#999" />
  162. </view>
  163. </view>
  164. </view>
  165. </view>
  166. </view>
  167. <!-- 下一步按钮 -->
  168. <u-button
  169. class="next-btn"
  170. @click="handleNext"
  171. type="primary"
  172. size="middle"
  173. >
  174. 下一步
  175. </u-button>
  176. </view>
  177. </template>
  178. <script>
  179. import PicComp from './PicComp.vue'
  180. import imageUpload from '../utils/imageUpload.js'
  181. export default {
  182. name: 'PageTwo',
  183. components: {
  184. PicComp
  185. },
  186. props: {
  187. orderDetail: {
  188. type: Object,
  189. default: () => ({})
  190. },
  191. orderId: {
  192. type: String,
  193. default: ''
  194. },
  195. currentReceipt: {
  196. type: Object,
  197. default: () => ({})
  198. },
  199. followUpList: {
  200. type: Array,
  201. default: () => []
  202. }
  203. },
  204. data() {
  205. return {
  206. selectedCheckbox: [],
  207. formData: {
  208. contactPhone: '',
  209. photoTips: '',
  210. faceToFaceNotes: ''
  211. },
  212. photoTipsImages: [],
  213. faceToFaceImages: [],
  214. approvedPrice: 0,
  215. detailImages: []
  216. }
  217. },
  218. watch: {
  219. currentReceipt: {
  220. handler(newVal) {
  221. if (newVal && newVal.id) {
  222. this.approvedPrice = Number(newVal.sellingPrice) || 0
  223. this.loadDetailImages()
  224. }
  225. },
  226. immediate: true,
  227. deep: true
  228. },
  229. followUpList: {
  230. handler(newVal) {
  231. if (newVal && newVal.length > 0) {
  232. this.checkFollowUpContent(newVal)
  233. }
  234. },
  235. deep: true
  236. }
  237. },
  238. methods: {
  239. /**
  240. * 加载细节图
  241. */
  242. async loadDetailImages() {
  243. if (!this.currentReceipt.id || !this.orderDetail.itemBrand) return
  244. try {
  245. const list = await imageUpload.getFileList(
  246. '2',
  247. '3',
  248. this.currentReceipt.id,
  249. this.orderDetail.itemBrand,
  250. this.currentReceipt.clueId
  251. )
  252. // 按照 fileIds 排序
  253. if (this.currentReceipt.fileIds && list && list.length > 0) {
  254. const sortedIds = this.currentReceipt.fileIds.split(',')
  255. list.sort((a, b) => {
  256. const indexA = sortedIds.indexOf(a.id)
  257. const indexB = sortedIds.indexOf(b.id)
  258. // 如果都不在列表中,保持原顺序
  259. if (indexA === -1 && indexB === -1) return 0
  260. // 如果 a 不在列表中,放到后面
  261. if (indexA === -1) return 1
  262. // 如果 b 不在列表中,放到后面
  263. if (indexB === -1) return -1
  264. // 都在列表中,按 index 排序
  265. return indexA - indexB
  266. })
  267. }
  268. this.detailImages = list || []
  269. } catch (error) {
  270. console.error('加载细节图失败:', error)
  271. }
  272. },
  273. /**
  274. * 检查跟进内容
  275. */
  276. checkFollowUpContent(followUpList) {
  277. const contentList = followUpList.map(item => item.content || '')
  278. contentList.forEach(item => {
  279. if (item.includes('联系师傅') && !this.selectedCheckbox.includes('contactMaster')) {
  280. this.selectedCheckbox.push('contactMaster')
  281. const phone = item.split(';')[1] || ''
  282. this.formData.contactPhone = phone
  283. }
  284. if (item.includes('师傅拍图技巧') && !this.selectedCheckbox.includes('photoTips')) {
  285. this.selectedCheckbox.push('photoTips')
  286. const tips = item.split(';')[1] || ''
  287. this.formData.photoTips = tips
  288. const urls = item.split(';')[2] || ''
  289. this.photoTipsImages = urls.split(',').filter(url => url.trim())
  290. }
  291. if (item.includes('到达客户面对面') && !this.selectedCheckbox.includes('faceToFace')) {
  292. this.selectedCheckbox.push('faceToFace')
  293. const notes = item.split(';')[1] || ''
  294. this.formData.faceToFaceNotes = notes
  295. const urls = item.split(';')[2] || ''
  296. this.faceToFaceImages = urls.split(',').filter(url => url.trim())
  297. }
  298. })
  299. },
  300. /**
  301. * 价格输入处理
  302. */
  303. onPriceInput(e) {
  304. let value = Number(e.detail.value)
  305. if (isNaN(value)) value = 0
  306. value = Math.max(0, value)
  307. this.approvedPrice = value
  308. },
  309. /**
  310. * 快速调整价格
  311. */
  312. async quickChangePrice(amount) {
  313. let newPrice = this.approvedPrice + amount
  314. newPrice = Math.max(0, newPrice)
  315. this.approvedPrice = newPrice
  316. await uni.$u.api.updateReceiptForm({
  317. id: this.currentReceipt.id,
  318. sellingPrice: newPrice
  319. })
  320. this.$emit('price-updated')
  321. },
  322. async saveApprovedPrice() {
  323. await uni.$u.api.updateReceiptForm({
  324. id: this.currentReceipt.id,
  325. sellingPrice: this.approvedPrice
  326. })
  327. this.$emit('price-updated')
  328. },
  329. /**
  330. * 上传图片(跟进清单)
  331. */
  332. async handleUpload(field) {
  333. try {
  334. const filePaths = await imageUpload.chooseImage(9)
  335. const uploadResults = await imageUpload.uploadFiles(filePaths)
  336. const urls = uploadResults.map(item => item.fileUrl)
  337. if (field === 'photoTips') {
  338. this.photoTipsImages = [...this.photoTipsImages, ...urls]
  339. } else if (field === 'faceToFace') {
  340. this.faceToFaceImages = [...this.faceToFaceImages, ...urls]
  341. }
  342. } catch (error) {
  343. console.error('上传失败:', error)
  344. uni.$u.toast('上传失败')
  345. }
  346. },
  347. /**
  348. * 上传细节图
  349. */
  350. async handleUploadImage() {
  351. try {
  352. const filePaths = await imageUpload.chooseImage(9)
  353. const uploadResults = await imageUpload.uploadFiles(filePaths)
  354. await imageUpload.bindOrderFile(
  355. this.currentReceipt.clueId,
  356. this.currentReceipt.id,
  357. '3',
  358. uploadResults
  359. )
  360. await this.loadDetailImages()
  361. // 更新 fileIds
  362. const fileIds = this.detailImages.map(item => item.id).join(',')
  363. await uni.$u.api.updateReceiptForm({
  364. id: this.currentReceipt.id,
  365. fileIds: fileIds
  366. })
  367. this.$emit('update-file-ids', fileIds)
  368. } catch (error) {
  369. console.error('上传失败:', error)
  370. }
  371. },
  372. /**
  373. * 删除图片
  374. */
  375. async handleDeleteImage(item) {
  376. uni.showModal({
  377. title: '提示',
  378. content: '确定要删除这张图片吗?',
  379. success: async (res) => {
  380. if (res.confirm) {
  381. try {
  382. await imageUpload.deleteFile(item.id)
  383. await this.loadDetailImages()
  384. // 更新 fileIds
  385. const fileIds = this.detailImages.map(item => item.id).join(',')
  386. await uni.$u.api.updateReceiptForm({
  387. id: this.currentReceipt.id,
  388. fileIds: fileIds
  389. })
  390. this.$emit('update-file-ids', fileIds)
  391. } catch (error) {
  392. console.error('删除失败:', error)
  393. }
  394. }
  395. }
  396. })
  397. },
  398. /**
  399. * 复制所有细节图
  400. */
  401. async copyAllDetailImages() {
  402. const allUrls = this.detailImages.map(item => item.fileUrl)
  403. if (allUrls.length === 0) {
  404. uni.showToast({
  405. title: '没有图片可复制',
  406. icon: 'none'
  407. })
  408. return
  409. }
  410. uni.showModal({
  411. title: '保存图片',
  412. content: `是否将 ${allUrls.length} 张图片保存到本地相册?`,
  413. confirmText: '保存',
  414. success: (res) => {
  415. if (res.confirm) {
  416. imageUpload.saveImagesToLocal(allUrls)
  417. }
  418. }
  419. })
  420. },
  421. /**
  422. * 预览细节图
  423. */
  424. previewImageDetail(src) {
  425. const urlList = this.detailImages.map(item => item.fileUrl)
  426. uni.previewImage({
  427. urls: urlList,
  428. current: src
  429. })
  430. },
  431. /**
  432. * 预览师傅拍图技巧图片
  433. */
  434. previewPhotoTips(src) {
  435. uni.previewImage({
  436. urls: this.photoTipsImages,
  437. current: src
  438. })
  439. },
  440. /**
  441. * 预览到达客户面对面图片
  442. */
  443. previewFaceToFace(src) {
  444. uni.previewImage({
  445. urls: this.faceToFaceImages,
  446. current: src
  447. })
  448. },
  449. /**
  450. * 下一步
  451. */
  452. async handleNext() {
  453. // 保存核准价
  454. await uni.$u.api.updateReceiptForm({
  455. id: this.currentReceipt.id,
  456. sellingPrice: this.approvedPrice
  457. })
  458. // 保存跟进记录
  459. if (this.selectedCheckbox.includes('contactMaster')) {
  460. await uni.$u.api.addOrderFollow({
  461. orderId: this.orderId,
  462. content: `联系师傅;${this.formData.contactPhone}`
  463. })
  464. }
  465. if (this.selectedCheckbox.includes('photoTips')) {
  466. const urls = this.photoTipsImages.join(',')
  467. await uni.$u.api.addOrderFollow({
  468. orderId: this.orderId,
  469. content: `师傅拍图技巧;${this.formData.photoTips};${urls}`
  470. })
  471. }
  472. if (this.selectedCheckbox.includes('faceToFace')) {
  473. const urls = this.faceToFaceImages.join(',')
  474. await uni.$u.api.addOrderFollow({
  475. orderId: this.orderId,
  476. content: `到达客户面对面;${this.formData.faceToFaceNotes};${urls}`
  477. })
  478. }
  479. this.$emit('next', {
  480. nowPage: 'formTwo',
  481. form: {
  482. approvedPrice: this.approvedPrice,
  483. detailImages: this.detailImages
  484. }
  485. })
  486. }
  487. }
  488. }
  489. </script>
  490. <style scoped lang="scss">
  491. @import '../styles/common.scss';
  492. .page-two-container {
  493. @extend .page-container;
  494. padding-bottom: 100rpx;
  495. }
  496. .address-section {
  497. padding: 20rpx;
  498. }
  499. .checklist-card {
  500. margin-top: 20rpx;
  501. }
  502. .checklist-section {
  503. padding: 20rpx;
  504. }
  505. .checklist-item {
  506. padding: 16rpx 0;
  507. border-bottom: 1rpx solid map-get($colors, border);
  508. &:last-child {
  509. border-bottom: none;
  510. }
  511. }
  512. .checkbox-text-container {
  513. @include flex-center;
  514. margin-bottom: 12rpx;
  515. }
  516. .checklist-text {
  517. @include font-styles;
  518. margin-left: 16rpx;
  519. }
  520. .checklist-input,
  521. .checklist-textarea {
  522. margin-top: 12rpx;
  523. margin-left: 56rpx;
  524. width: calc(100% - 72rpx);
  525. border-radius: 8rpx;
  526. border: 1rpx solid #e5e7eb;
  527. padding: 12rpx 16rpx;
  528. }
  529. .upload-btn-container {
  530. margin-top: 16rpx;
  531. margin-left: 56rpx;
  532. }
  533. .upload-btn {
  534. display: inline-flex;
  535. align-items: center;
  536. gap: 12rpx;
  537. padding: 20rpx 40rpx;
  538. border-radius: 8rpx;
  539. background-color: map-get($colors, bg);
  540. border: 2rpx dashed map-get($colors, primary);
  541. color: map-get($colors, primary);
  542. cursor: pointer;
  543. }
  544. .upload-btn-text {
  545. @include font-styles($size: small, $weight: medium);
  546. }
  547. .image-list {
  548. margin-top: 16rpx;
  549. margin-left: 56rpx;
  550. display: flex;
  551. flex-wrap: wrap;
  552. gap: 16rpx;
  553. }
  554. .image-item {
  555. width: 120rpx;
  556. height: 120rpx;
  557. border-radius: 8rpx;
  558. overflow: hidden;
  559. cursor: pointer;
  560. transition: opacity 0.2s;
  561. &:active {
  562. opacity: 0.7;
  563. }
  564. }
  565. .image-thumb {
  566. width: 100%;
  567. height: 100%;
  568. object-fit: cover;
  569. }
  570. .price-card {
  571. margin-top: 20rpx;
  572. }
  573. .price-section {
  574. padding: 20rpx;
  575. padding-right: 20rpx; /* 整体往左挪,避免被右侧固定导航遮挡 */
  576. }
  577. .price-picker-container {
  578. display: flex;
  579. flex-direction: column;
  580. align-items: center;
  581. padding: 20rpx 0;
  582. }
  583. .quick-actions {
  584. display: flex;
  585. justify-content: center;
  586. gap: 16rpx;
  587. margin: 5rpx 0;
  588. width: 100%;
  589. }
  590. .quick-btn {
  591. flex: 1;
  592. border-radius: 12rpx;
  593. font-size: 36rpx;
  594. padding: 10rpx 0;
  595. text-align: center;
  596. font-weight: 600;
  597. cursor: pointer;
  598. &.increase {
  599. background-color: #e6f7ed;
  600. color: #00b42a;
  601. }
  602. &.decrease {
  603. background-color: #fff1f0;
  604. color: #f53f3f;
  605. }
  606. }
  607. .number-box-container {
  608. display: flex;
  609. align-items: center;
  610. margin: 20rpx 0;
  611. width: 100%;
  612. justify-content: center;
  613. }
  614. .price-input-box {
  615. flex: 1;
  616. max-width: 800rpx;
  617. background-color: #f5f7fa;
  618. border: 2rpx solid #e5e7eb;
  619. border-radius: 12rpx;
  620. padding: 0rpx 24rpx;
  621. display: flex;
  622. align-items: center;
  623. justify-content: space-between;
  624. }
  625. .price-label {
  626. font-size: 30rpx;
  627. font-weight: 700;
  628. min-width: 120rpx;
  629. }
  630. .price-value-wrap {
  631. flex: 1;
  632. display: flex;
  633. align-items: center;
  634. min-width: 0;
  635. }
  636. .yuan-prefix {
  637. font-size: 48rpx;
  638. font-weight: 600;
  639. margin-right: 8rpx;
  640. flex-shrink: 0;
  641. }
  642. .price-input {
  643. flex: 1;
  644. min-width: 0;
  645. border: none;
  646. outline: none;
  647. background-color: transparent;
  648. text-align: left;
  649. font-size: 48rpx;
  650. font-weight: 600;
  651. padding: 0 10rpx 0 0;
  652. }
  653. .detail-image-card {
  654. margin-top: 20rpx;
  655. }
  656. .detail-image-section {
  657. padding: 20rpx;
  658. }
  659. .detail-image-header {
  660. display: flex;
  661. justify-content: space-between;
  662. align-items: center;
  663. margin-bottom: 20rpx;
  664. padding-bottom: 20rpx;
  665. border-bottom: 1rpx solid map-get($colors, border);
  666. }
  667. .detail-image-title {
  668. @include font-styles($size: content, $weight: bold, $color: primary);
  669. }
  670. .copy-btn {
  671. border-radius: 20rpx;
  672. border: 1rpx solid #007AFF;
  673. background-color: transparent;
  674. color: #007AFF;
  675. padding: 0 24rpx;
  676. height: 64rpx;
  677. line-height: 64rpx;
  678. cursor: pointer;
  679. }
  680. .detail-image-list {
  681. display: flex;
  682. flex-wrap: wrap;
  683. gap: 20rpx;
  684. }
  685. .detail-image-item {
  686. position: relative;
  687. width: 200rpx;
  688. height: 200rpx;
  689. }
  690. .detail-delete-btn {
  691. position: absolute;
  692. top: -10rpx;
  693. right: -10rpx;
  694. width: 40rpx;
  695. height: 40rpx;
  696. background-color: #ff4d4f;
  697. color: #fff;
  698. border-radius: 50%;
  699. display: flex;
  700. align-items: center;
  701. justify-content: center;
  702. font-weight: bold;
  703. z-index: 10;
  704. cursor: pointer;
  705. }
  706. .detail-upload-btn {
  707. width: 200rpx;
  708. height: 200rpx;
  709. border: 8rpx dashed #ddd;
  710. border-radius: 30rpx;
  711. display: flex;
  712. align-items: center;
  713. justify-content: center;
  714. background-color: #f9f9f9;
  715. cursor: pointer;
  716. }
  717. .next-btn {
  718. position: fixed;
  719. bottom: 10rpx;
  720. left: 2.5%;
  721. width: 95%;
  722. height: 80rpx;
  723. line-height: 80rpx;
  724. text-align: center;
  725. border-radius: 20rpx;
  726. }
  727. </style>