activity-detail-new.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  1. <template>
  2. <view class="page-container">
  3. <!-- 页面滚动区域 -->
  4. <scroll-view class="page-scroll" scroll-y>
  5. <!-- 地块信息卡片 -->
  6. <view class="info-card">
  7. <view class="card-title">
  8. <text>地块信息</text>
  9. </view>
  10. <view class="info-item">
  11. <text class="info-label">地块名称</text>
  12. <text class="info-value">{{ formData.fieldName || '未知' }}</text>
  13. </view>
  14. <view class="info-item">
  15. <text class="info-label">作物名称</text>
  16. <text class="info-value">{{ formData.growCrops || '未知' }}</text>
  17. </view>
  18. <view class="info-item">
  19. <text class="info-label">负责人</text>
  20. <text class="info-value">{{ formData.manager || '未知' }}</text>
  21. </view>
  22. </view>
  23. <!-- 任务填写表单 -->
  24. <view class="form-card">
  25. <view class="card-title">
  26. <text>任务信息</text>
  27. </view>
  28. <!-- 任务名称 -->
  29. <view class="form-item">
  30. <view class="form-label required">任务名称</view>
  31. <input
  32. v-model="formData.taskName"
  33. placeholder="请输入任务名称,例如:水稻田施肥"
  34. :disabled="pageMode === 'view'"
  35. class="form-input"
  36. />
  37. </view>
  38. <!-- 任务类型 -->
  39. <view class="form-item" @click="pageMode !== 'view' && showTaskTypeSelector()">
  40. <view class="form-label required">任务类型</view>
  41. <view class="select-wrapper">
  42. <!-- <input
  43. :value="formData.typeName"
  44. :placeholder="dictLoading ? '加载中...' : '请选择任务类型'"
  45. readonly
  46. class="form-input select-input"
  47. /> -->
  48. <view class="form-input select-input">
  49. {{ formData.typeName || (dictLoading ? '加载中...' : '请选择任务类型') }}
  50. </view>
  51. <view v-if="pageMode !== 'view'" class="select-arrow">
  52. <text>▼</text>
  53. </view>
  54. </view>
  55. </view>
  56. <!-- 执行时间 -->
  57. <view class="form-item" @click="pageMode !== 'view' && selectExecuteTime()">
  58. <view class="form-label required">执行时间</view>
  59. <view class="select-wrapper">
  60. <!-- <input
  61. :value="formattedExecuteTime"
  62. placeholder="请选择任务计划时间"
  63. readonly
  64. class="form-input select-input"
  65. readonly
  66. /> -->
  67. <view class="form-input select-input">
  68. {{ formattedExecuteTime || '请选择任务计划时间' }}
  69. </view>
  70. <view v-if="pageMode !== 'view'" class="select-arrow">
  71. <text>选择</text>
  72. </view>
  73. </view>
  74. </view>
  75. <!-- 负责人选择 -->
  76. <view class="form-item" @click="pageMode !== 'view' && showUserSelector()">
  77. <view class="form-label required">负责人</view>
  78. <view class="select-wrapper">
  79. <!-- <input
  80. :value="formData.assigneeName"
  81. placeholder="请选择负责人"
  82. readonly
  83. class="form-input select-input"
  84. /> -->
  85. <view class="form-input select-input">
  86. {{ formData.assigneeName || '请选择负责人' }}
  87. </view>
  88. <view v-if="pageMode !== 'view'" class="select-arrow">
  89. <text>选择</text>
  90. </view>
  91. </view>
  92. </view>
  93. <!-- 任务说明 -->
  94. <view class="form-item">
  95. <view class="form-label">任务说明</view>
  96. <textarea
  97. v-model="formData.remark"
  98. placeholder="请输入任务要点,例如:每亩用肥20kg"
  99. :disabled="pageMode === 'view'"
  100. class="form-textarea"
  101. maxlength="200"
  102. ></textarea>
  103. <view class="char-count">{{ (formData.remark || '').length }}/200</view>
  104. </view>
  105. <!-- 任务完成情况 -->
  106. <view class="section-divider"></view>
  107. <view class="section-title">
  108. <text>任务完成情况</text>
  109. </view>
  110. <!-- 完成状态选择 - 新建和编辑模式 -->
  111. <view class="form-item" v-if="pageMode === 'create' || pageMode === 'edit'">
  112. <view class="form-label">完成状态</view>
  113. <view class="radio-group">
  114. <view
  115. class="radio-item"
  116. v-for="(item, index) in completionStatusOptions"
  117. :key="index"
  118. @click="selectCompletionStatus(item.value)"
  119. >
  120. <view class="radio-circle" :class="{'radio-checked': formData.completionStatus === item.value}">
  121. <view v-if="formData.completionStatus === item.value" class="radio-dot"></view>
  122. </view>
  123. <text class="radio-label">{{ item.label }}</text>
  124. </view>
  125. </view>
  126. </view>
  127. <!-- 查看模式显示完成状态 -->
  128. <view class="form-item" v-if="pageMode === 'view'">
  129. <view class="form-label">完成状态</view>
  130. <view class="status-completed">
  131. <text class="status-icon">✓</text>
  132. <text>已完成</text>
  133. </view>
  134. </view>
  135. <!-- 完成时间 -->
  136. <view class="form-item" v-if="formData.completionStatus === '1'">
  137. <view class="form-label" :class="{'required': (pageMode === 'create' || pageMode === 'edit') && formData.completionStatus === '1'}">完成时间</view>
  138. <view class="select-wrapper" @click="(pageMode === 'create' || pageMode === 'edit') && formData.completionStatus === '1' && selectCompletionTime()">
  139. <!-- <input
  140. :value="formattedCompletionTime"
  141. placeholder="请选择实际完成时间"
  142. readonly
  143. class="form-input select-input"
  144. /> -->
  145. <view class="form-input select-input">
  146. {{ formattedCompletionTime || '请选择实际完成时间' }}
  147. </view>
  148. <view v-if="(pageMode === 'create' || pageMode === 'edit') && formData.completionStatus === '1'" class="select-arrow">
  149. <text>选择</text>
  150. </view>
  151. </view>
  152. </view>
  153. <!-- 完成说明 -->
  154. <view class="form-item" v-if="formData.completionStatus === '1'">
  155. <view class="form-label" :class="{'required': (pageMode === 'create' || pageMode === 'edit') && formData.completionStatus === '1'}">完成说明</view>
  156. <textarea
  157. v-model="formData.completionDesc"
  158. placeholder="请输入完成说明,例如:已完成并拍照记录"
  159. :disabled="pageMode === 'view'"
  160. class="form-textarea"
  161. maxlength="300"
  162. ></textarea>
  163. <view class="char-count">{{ (formData.completionDesc || '').length }}/300</view>
  164. <view class="form-error" v-if="formErrors.completionDesc">
  165. {{ formErrors.completionDesc }}
  166. </view>
  167. </view>
  168. <!-- 现场图片 -->
  169. <view class="form-item" v-if="formData.completionStatus === '1'">
  170. <view class="form-label">现场图片</view>
  171. <!-- 新建和编辑模式 -->
  172. <view v-if="pageMode === 'create' || pageMode === 'edit'" class="image-upload">
  173. <view class="image-list">
  174. <view
  175. class="image-preview"
  176. v-for="(item, index) in formData.images"
  177. :key="index"
  178. @click="previewImage(item, index)"
  179. >
  180. <!-- <image :src="getImageUrl(item)" mode="aspectFill"/> -->
  181. <image :src="item.url" mode="aspectFill"/>
  182. <view class="delete-btn" @click.stop="deletePic(index)">
  183. <text>×</text>
  184. </view>
  185. </view>
  186. <view
  187. v-if="formData.images.length < 6"
  188. class="upload-btn"
  189. @click="chooseImage"
  190. >
  191. <text class="upload-icon">+</text>
  192. <text class="upload-text">添加图片</text>
  193. </view>
  194. </view>
  195. <view class="upload-tip">最多可上传6张图片</view>
  196. </view>
  197. <!-- 查看模式 -->
  198. <view v-else-if="pageMode === 'view' && formData.images && formData.images.length > 0" class="image-view">
  199. <view class="image-list">
  200. <view
  201. class="image-preview"
  202. v-for="(item, index) in formData.images"
  203. :key="index"
  204. @click="previewImage(item, index)"
  205. >
  206. <!-- <image :src="getImageUrl(item)" mode="aspectFill"/> -->
  207. <image :src="item.url" mode="aspectFill"/>
  208. </view>
  209. </view>
  210. </view>
  211. <!-- 无图片提示 -->
  212. <view v-else class="no-images">
  213. <text>暂无图片</text>
  214. </view>
  215. </view>
  216. </view>
  217. <!-- 底部占位 -->
  218. <view class="bottom-safe"></view>
  219. </scroll-view>
  220. <!-- 底部提交按钮 -->
  221. <view class="footer-safe" v-if="pageMode !== 'view'">
  222. <view class="footer-content">
  223. <button
  224. class="submit-button"
  225. :class="{'loading': isSubmitting}"
  226. @click="submitForm"
  227. :disabled="isSubmitting"
  228. >
  229. {{ isSubmitting ? '提交中...' : submitButtonText }}
  230. </button>
  231. </view>
  232. </view>
  233. <!-- 遮罩层 -->
  234. <view v-if="showTaskTypePicker || showDateTimeSelector || showUserPicker" class="picker-mask" @click="closePickers"></view>
  235. <!-- 任务类型选择弹窗 -->
  236. <view v-if="showTaskTypePicker" class="picker-popup">
  237. <view class="picker-header">
  238. <text class="picker-cancel" @click="showTaskTypePicker = false">取消</text>
  239. <text class="picker-title">选择任务类型</text>
  240. <text class="picker-confirm" @click="confirmTaskType">确定</text>
  241. </view>
  242. <view class="picker-content">
  243. <view v-if="dictLoading" class="picker-loading">
  244. <text>加载中...</text>
  245. </view>
  246. <view
  247. v-else
  248. class="picker-item"
  249. v-for="(item, index) in taskTypeOptions"
  250. :key="index"
  251. :class="{'selected': tempTaskTypeIndex === index}"
  252. @click="tempTaskTypeIndex = index"
  253. >
  254. <text>{{ item.dictLabel }}</text>
  255. <text v-if="tempTaskTypeIndex === index" class="check-mark">✓</text>
  256. </view>
  257. </view>
  258. </view>
  259. <!-- 用户选择弹窗 -->
  260. <view v-if="showUserPicker" class="picker-popup">
  261. <view class="picker-header">
  262. <text class="picker-cancel" @click="showUserPicker = false">取消</text>
  263. <text class="picker-title">选择负责人</text>
  264. <text class="picker-confirm" @click="confirmUser">确定</text>
  265. </view>
  266. <view class="picker-content">
  267. <view v-if="usersLoading" class="picker-loading">
  268. <text>加载中...</text>
  269. </view>
  270. <view v-else-if="userList.length === 0" class="picker-empty">
  271. <text>暂无可选负责人</text>
  272. </view>
  273. <view
  274. v-else
  275. class="picker-item"
  276. v-for="(user, index) in userList"
  277. :key="user.userId"
  278. :class="{'selected': tempUserIndex === index}"
  279. @click="tempUserIndex = index"
  280. >
  281. <text>{{ user.userName }}</text>
  282. <text v-if="tempUserIndex === index" class="check-mark">✓</text>
  283. </view>
  284. </view>
  285. </view>
  286. <!-- 日期时间选择弹窗 -->
  287. <view v-if="showDateTimeSelector" class="picker-popup datetime-picker">
  288. <view class="picker-header">
  289. <text class="picker-cancel" @click="cancelDateTime">取消</text>
  290. <text class="picker-title">选择时间</text>
  291. <text class="picker-confirm" @click="confirmDateTime">确定</text>
  292. </view>
  293. <view class="datetime-picker-content">
  294. <picker-view
  295. class="datetime-picker-view"
  296. :value="dateTimePickerValue"
  297. @change="onDateTimePickerChange"
  298. :indicator-style="'height: 80rpx;'"
  299. :mask-style="'background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0.6)), linear-gradient(0deg, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0.6));'"
  300. >
  301. <picker-view-column>
  302. <view class="picker-view-item" v-for="(item, index) in dateTimePickerRange[0]" :key="'year-'+index">
  303. <text class="picker-item-text">{{ item }}</text>
  304. </view>
  305. </picker-view-column>
  306. <picker-view-column>
  307. <view class="picker-view-item" v-for="(item, index) in dateTimePickerRange[1]" :key="'month-'+index">
  308. <text class="picker-item-text">{{ item }}</text>
  309. </view>
  310. </picker-view-column>
  311. <picker-view-column>
  312. <view class="picker-view-item" v-for="(item, index) in dateTimePickerRange[2]" :key="'day-'+index">
  313. <text class="picker-item-text">{{ item }}</text>
  314. </view>
  315. </picker-view-column>
  316. <picker-view-column>
  317. <view class="picker-view-item" v-for="(item, index) in dateTimePickerRange[3]" :key="'hour-'+index">
  318. <text class="picker-item-text">{{ item }}</text>
  319. </view>
  320. </picker-view-column>
  321. <picker-view-column>
  322. <view class="picker-view-item" v-for="(item, index) in dateTimePickerRange[4]" :key="'min-'+index">
  323. <text class="picker-item-text">{{ item }}</text>
  324. </view>
  325. </picker-view-column>
  326. </picker-view>
  327. </view>
  328. </view>
  329. </view>
  330. </template>
  331. <script setup>
  332. import { ref, reactive, computed } from 'vue'
  333. import api from "@/config/api.js";
  334. import { getAgriculturalTasksById, addAgriculturalTask, updateAgriculturalTask } from '@/api/services/activity.js';
  335. import { getUsersByPlotId, getUserInfo } from '@/api/services/user.js';
  336. import { useDict } from '@/utils/composables/useDict';
  337. import storage from "@/utils/storage.js";
  338. // 使用字典组合式函数
  339. const { dictData, dictLoading, loadDict } = useDict(['task_type', 'task_status'])
  340. // 响应式数据
  341. </script>
  342. <style scoped>
  343. .page-container {
  344. height: 100vh;
  345. background-color: #F5F5F5;
  346. display: flex;
  347. flex-direction: column;
  348. }
  349. .page-scroll {
  350. flex: 1;
  351. overflow: hidden;
  352. }
  353. /* 地块基础信息卡片 */
  354. .info-card {
  355. background: #F9F9F9;
  356. margin: 24rpx;
  357. padding: 24rpx;
  358. border-radius: 8rpx;
  359. border: 1rpx solid #E5E5E5;
  360. }
  361. .card-title {
  362. font-size: 30rpx;
  363. font-weight: 600;
  364. color: #333333;
  365. margin-bottom: 16rpx;
  366. padding-bottom: 12rpx;
  367. border-bottom: 1rpx solid #E5E5E5;
  368. }
  369. .info-item {
  370. display: flex;
  371. justify-content: space-between;
  372. align-items: center;
  373. margin-bottom: 12rpx;
  374. padding: 8rpx 0;
  375. }
  376. .info-item:last-child {
  377. margin-bottom: 0;
  378. }
  379. .info-label {
  380. font-size: 28rpx;
  381. color: #666666;
  382. flex-shrink: 0;
  383. }
  384. .info-value {
  385. font-size: 28rpx;
  386. color: #333333;
  387. font-weight: 500;
  388. }
  389. /* 任务填写表单 */
  390. .form-card {
  391. background: #FFFFFF;
  392. margin: 0 24rpx 24rpx;
  393. padding: 24rpx;
  394. border-radius: 8rpx;
  395. border: 1rpx solid #E5E5E5;
  396. }
  397. .section-divider {
  398. height: 1rpx;
  399. background: #F0F0F0;
  400. margin: 32rpx 0 24rpx;
  401. }
  402. .section-title {
  403. font-size: 30rpx;
  404. font-weight: 600;
  405. color: #333333;
  406. margin-bottom: 16rpx;
  407. padding-bottom: 12rpx;
  408. border-bottom: 1rpx solid #F0F0F0;
  409. }
  410. .form-item {
  411. margin-bottom: 24rpx;
  412. }
  413. .form-item:last-child {
  414. margin-bottom: 0;
  415. }
  416. .form-label {
  417. font-size: 28rpx;
  418. color: #333333;
  419. margin-bottom: 12rpx;
  420. font-weight: 500;
  421. }
  422. .form-label.required::before {
  423. content: '*';
  424. color: #FF6B6B;
  425. margin-right: 4rpx;
  426. }
  427. .form-input {
  428. width: 100%;
  429. line-height: 80rpx;
  430. height: 80rpx;
  431. background: #F8F8F8;
  432. border: 1rpx solid #E5E5E5;
  433. border-radius: 8rpx;
  434. padding: 0 16rpx;
  435. font-size: 28rpx;
  436. color: #333333;
  437. box-sizing: border-box;
  438. }
  439. .form-input:focus {
  440. background: #FFFFFF;
  441. border-color: #3BB44A;
  442. }
  443. .form-input::placeholder {
  444. color: #CCCCCC;
  445. }
  446. .form-input:disabled {
  447. background: #F8F8F8;
  448. color: #999999;
  449. }
  450. .select-wrapper {
  451. position: relative;
  452. width: 100%;
  453. }
  454. .select-input {
  455. cursor: pointer;
  456. }
  457. .select-arrow {
  458. position: absolute;
  459. right: 16rpx;
  460. top: 50%;
  461. transform: translateY(-50%);
  462. color: #999999;
  463. font-size: 20rpx;
  464. pointer-events: none;
  465. }
  466. .form-textarea {
  467. width: 100%;
  468. min-height: 120rpx;
  469. background: #F8F8F8;
  470. border: 1rpx solid #E5E5E5;
  471. border-radius: 8rpx;
  472. padding: 16rpx;
  473. font-size: 28rpx;
  474. color: #333333;
  475. box-sizing: border-box;
  476. resize: none;
  477. line-height: 1.5;
  478. }
  479. .form-textarea:focus {
  480. background: #FFFFFF;
  481. border-color: #3BB44A;
  482. }
  483. .form-textarea::placeholder {
  484. color: #CCCCCC;
  485. }
  486. .form-textarea:disabled {
  487. background: #F8F8F8;
  488. color: #999999;
  489. }
  490. .char-count {
  491. font-size: 24rpx;
  492. color: #CCCCCC;
  493. text-align: right;
  494. margin-top: 8rpx;
  495. }
  496. .form-error {
  497. font-size: 24rpx;
  498. color: #FF6B6B;
  499. margin-top: 8rpx;
  500. }
  501. /* 单选按钮样式 */
  502. .radio-group {
  503. display: flex;
  504. gap: 32rpx;
  505. }
  506. .radio-item {
  507. display: flex;
  508. align-items: center;
  509. cursor: pointer;
  510. }
  511. .radio-circle {
  512. width: 32rpx;
  513. height: 32rpx;
  514. border: 2rpx solid #CCCCCC;
  515. border-radius: 50%;
  516. display: flex;
  517. align-items: center;
  518. justify-content: center;
  519. margin-right: 8rpx;
  520. }
  521. .radio-circle.radio-checked {
  522. border-color: #3BB44A;
  523. background-color: #3BB44A;
  524. }
  525. .radio-dot {
  526. width: 12rpx;
  527. height: 12rpx;
  528. background-color: #FFFFFF;
  529. border-radius: 50%;
  530. }
  531. .radio-label {
  532. font-size: 28rpx;
  533. color: #333333;
  534. }
  535. /* 完成状态样式 */
  536. .status-completed {
  537. display: flex;
  538. align-items: center;
  539. color: #3BB44A;
  540. font-size: 28rpx;
  541. }
  542. .status-icon {
  543. width: 32rpx;
  544. height: 32rpx;
  545. background: #3BB44A;
  546. color: #FFFFFF;
  547. border-radius: 50%;
  548. display: flex;
  549. align-items: center;
  550. justify-content: center;
  551. margin-right: 8rpx;
  552. font-size: 20rpx;
  553. line-height: 1;
  554. }
  555. /* 图片上传样式 */
  556. .image-upload, .image-view {
  557. width: 100%;
  558. }
  559. .image-list {
  560. display: flex;
  561. flex-wrap: wrap;
  562. gap: 16rpx;
  563. }
  564. .image-preview {
  565. position: relative;
  566. width: 160rpx;
  567. height: 160rpx;
  568. border-radius: 8rpx;
  569. overflow: hidden;
  570. background: #F5F5F5;
  571. }
  572. .image-preview image {
  573. width: 100%;
  574. height: 100%;
  575. }
  576. .delete-btn {
  577. position: absolute;
  578. top: -6rpx;
  579. right: -6rpx;
  580. width: 32rpx;
  581. height: 32rpx;
  582. background: rgba(0, 0, 0, 0.6);
  583. color: #FFFFFF;
  584. border-radius: 50%;
  585. display: flex;
  586. align-items: center;
  587. justify-content: center;
  588. font-size: 20rpx;
  589. line-height: 1;
  590. }
  591. .upload-btn {
  592. width: 160rpx;
  593. height: 160rpx;
  594. background: #F8F8F8;
  595. border: 2rpx dashed #DDDDDD;
  596. border-radius: 8rpx;
  597. display: flex;
  598. flex-direction: column;
  599. align-items: center;
  600. justify-content: center;
  601. }
  602. .upload-icon {
  603. font-size: 32rpx;
  604. margin-bottom: 8rpx;
  605. color: #999999;
  606. }
  607. .upload-text {
  608. font-size: 24rpx;
  609. color: #999999;
  610. }
  611. .upload-tip {
  612. font-size: 24rpx;
  613. color: #999999;
  614. margin-top: 12rpx;
  615. }
  616. .no-images {
  617. padding: 40rpx 0;
  618. text-align: center;
  619. color: #CCCCCC;
  620. font-size: 28rpx;
  621. }
  622. /* 底部安全区域 */
  623. .bottom-safe {
  624. height: 120rpx;
  625. }
  626. .footer-safe {
  627. background: #FFFFFF;
  628. border-top: 1rpx solid #E5E5E5;
  629. padding-bottom: constant(safe-area-inset-bottom);
  630. padding-bottom: env(safe-area-inset-bottom);
  631. }
  632. .footer-content {
  633. padding: 24rpx;
  634. }
  635. .submit-button {
  636. width: 100%;
  637. height: 88rpx;
  638. background: #3BB44A;
  639. color: #FFFFFF;
  640. border: none;
  641. border-radius: 8rpx;
  642. font-size: 32rpx;
  643. font-weight: 600;
  644. display: flex;
  645. align-items: center;
  646. justify-content: center;
  647. }
  648. .submit-button:active {
  649. background: #2D8C3C;
  650. }
  651. .submit-button:disabled,
  652. .submit-button.loading {
  653. background: #CCCCCC;
  654. }
  655. /* 选择器弹窗样式 */
  656. .picker-mask {
  657. position: fixed;
  658. top: 0;
  659. left: 0;
  660. width: 100%;
  661. height: 100%;
  662. background: rgba(0, 0, 0, 0.5);
  663. z-index: 999;
  664. }
  665. .picker-popup {
  666. position: fixed;
  667. bottom: 0;
  668. left: 0;
  669. width: 100%;
  670. background: #FFFFFF;
  671. border-radius: 16rpx 16rpx 0 0;
  672. z-index: 1000;
  673. padding-bottom: constant(safe-area-inset-bottom);
  674. padding-bottom: env(safe-area-inset-bottom);
  675. }
  676. .picker-header {
  677. display: flex;
  678. justify-content: space-between;
  679. align-items: center;
  680. padding: 24rpx;
  681. border-bottom: 1rpx solid #E5E5E5;
  682. }
  683. .picker-cancel, .picker-confirm {
  684. font-size: 30rpx;
  685. color: #3BB44A;
  686. }
  687. .picker-title {
  688. font-size: 32rpx;
  689. font-weight: 600;
  690. color: #333333;
  691. }
  692. .picker-content {
  693. max-height: 400rpx;
  694. overflow-y: auto;
  695. }
  696. .picker-item {
  697. display: flex;
  698. justify-content: space-between;
  699. align-items: center;
  700. padding: 24rpx;
  701. border-bottom: 1rpx solid #F0F0F0;
  702. font-size: 30rpx;
  703. color: #333333;
  704. }
  705. .picker-item.selected {
  706. color: #3BB44A;
  707. }
  708. .picker-item:last-child {
  709. border-bottom: none;
  710. }
  711. .check-mark {
  712. color: #3BB44A;
  713. font-size: 28rpx;
  714. }
  715. /* 日期时间选择器样式 */
  716. .datetime-picker {
  717. height: 60vh;
  718. }
  719. .datetime-picker-content {
  720. height: calc(100% - 100rpx);
  721. padding: 0;
  722. }
  723. .datetime-picker-view {
  724. width: 100%;
  725. height: 100%;
  726. }
  727. .picker-view-item {
  728. display: flex;
  729. align-items: center;
  730. justify-content: center;
  731. height: 80rpx;
  732. font-size: 32rpx;
  733. color: #333333;
  734. }
  735. .picker-item-text {
  736. font-size: 32rpx;
  737. color: #333333;
  738. line-height: 80rpx;
  739. height: 80rpx;
  740. text-align: center;
  741. }
  742. /* 添加加载中样式 */
  743. .picker-loading {
  744. display: flex;
  745. justify-content: center;
  746. align-items: center;
  747. padding: 30rpx 0;
  748. color: #999;
  749. font-size: 28rpx;
  750. }
  751. .picker-empty {
  752. padding: 30rpx 0;
  753. text-align: center;
  754. color: #CCCCCC;
  755. font-size: 28rpx;
  756. }
  757. </style>