選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

vehicle-details.vue 16KB

1ヶ月前
4週間前
1ヶ月前
4週間前
1ヶ月前
3週間前
1ヶ月前
3週間前
1ヶ月前
4週間前
1ヶ月前
4週間前
1ヶ月前
4週間前
1ヶ月前
4週間前
1ヶ月前
4週間前
1ヶ月前
4週間前
1ヶ月前
4週間前
1ヶ月前
4週間前
1ヶ月前
1ヶ月前
3週間前
1ヶ月前
3週間前
1ヶ月前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. <template>
  2. <view class="vehicle-details-container">
  3. <!-- 车辆基本信息 -->
  4. <view class="vehicle-info-section">
  5. <view class="info-item">
  6. <text class="label">车牌号</text>
  7. <text class="value">{{ vehicleInfo.vehiclePlate }}</text>
  8. </view>
  9. <view class="info-item">
  10. <text class="label">车牌颜色</text>
  11. <text class="value">{{
  12. getVehiclePlateColor(vehicleInfo.vehiclePlateColor)
  13. }}</text>
  14. </view>
  15. <view class="info-item">
  16. <text class="label">车辆所有人信息</text>
  17. <text class="value">{{ vehicleInfo.ownerName }}</text>
  18. </view>
  19. <view class="info-item">
  20. <text class="label">车辆所有人证件类型</text>
  21. <!-- <text class="value">{{ vehicleInfo.ownerIdType }}</text> -->
  22. <text class="value">{{ getCodeName('ID_TYPE',vehicleInfo.ownerIdType) }}</text>
  23. </view>
  24. <view class="info-item">
  25. <text class="label">车辆所有人证件号码</text>
  26. <text class="value">{{ vehicleInfo.ownerIdNum }}</text>
  27. </view>
  28. <view class="info-item">
  29. <text class="label">车辆所有人电话</text>
  30. <text class="value">{{ vehicleInfo.ownerTel }}</text>
  31. </view>
  32. <!-- <view class="info-item">
  33. <text class="label">车辆号码</text>
  34. <text class="value">{{ vehicleInfo.vehicleId }}</text>
  35. </view> -->
  36. <view class="info-item">
  37. <text class="label">行驶证车辆类型</text>
  38. <text class="value">{{ vehicleInfo.vehicleType }}</text>
  39. </view>
  40. <view class="info-item">
  41. <text class="label">车辆识别号</text>
  42. <text class="value">{{ vehicleInfo.vin }}</text>
  43. </view>
  44. <view class="info-item">
  45. <text class="label">发动机号码</text>
  46. <text class="value">{{ vehicleInfo.engineNum }}</text>
  47. </view>
  48. <view class="info-item">
  49. <text class="label">车辆收费类型</text>
  50. <text class="value">{{ getCodeName('VEHICLE_TYPE',vehicleInfo.type) }}</text>
  51. </view>
  52. <view class="info-item">
  53. <text class="label">核定载人数</text>
  54. <text class="value">{{ vehicleInfo.approvedCount }}</text>
  55. </view>
  56. <view class="info-item">
  57. <text class="label">总质量</text>
  58. <text class="value">{{ vehicleInfo.totalMass }}kg</text>
  59. </view>
  60. <view class="info-item">
  61. <text class="label">整备质量</text>
  62. <text class="value">{{ vehicleInfo.maintenaceMass }}kg</text>
  63. </view>
  64. <view class="info-item">
  65. <text class="label">核定载质量</text>
  66. <text class="value">{{ vehicleInfo.permittedWeight }}kg</text>
  67. </view>
  68. <view class="info-item">
  69. <text class="label">外廊尺寸</text>
  70. <text class="value">{{ vehicleInfo.vehicleDimensions }}</text>
  71. </view>
  72. <view class="info-item">
  73. <text class="label">准牵引总质量</text>
  74. <text class="value">{{ vehicleInfo.permittedTowWeight }}Kg</text>
  75. </view>
  76. <view class="info-item">
  77. <text class="label">车轮数</text>
  78. <text class="value">{{ vehicleInfo.vehicleWheelCount }}</text>
  79. </view>
  80. <view class="info-item">
  81. <text class="label">车轴数</text>
  82. <text class="value">{{ vehicleInfo.axleCount }}</text>
  83. </view>
  84. <view class="info-item">
  85. <text class="label">车辆使用性质</text>
  86. <text class="value">{{ getCodeName('USE_USER_TYPE',vehicleInfo.useUserType) }}</text>
  87. </view>
  88. <!-- 行驶证图片 -->
  89. <view class="license-section">
  90. <view class="license-item">
  91. <text class="license-title">行驶证主页</text>
  92. <view class="license-image-container">
  93. <image
  94. v-if="vehicleInfo.vehPosImgUrl"
  95. :src="getImageUrl(vehicleInfo.vehPosImgUrl)"
  96. class="license-image"
  97. mode="aspectFit"
  98. @click="previewImage(getImageUrl(vehicleInfo.vehPosImgUrl))"
  99. />
  100. <view v-else class="license-placeholder">
  101. <text class="placeholder-text">暂无图片</text>
  102. </view>
  103. </view>
  104. </view>
  105. <view class="license-item">
  106. <text class="license-title">行驶证副页</text>
  107. <view class="license-image-container">
  108. <image
  109. v-if="vehicleInfo.vehNegImgUrl"
  110. :src="getImageUrl(vehicleInfo.vehNegImgUrl)"
  111. class="license-image"
  112. mode="aspectFit"
  113. @click="previewImage(getImageUrl(vehicleInfo.vehNegImgUrl))"
  114. />
  115. <view v-else class="license-placeholder">
  116. <text class="placeholder-text">暂无图片</text>
  117. </view>
  118. </view>
  119. </view>
  120. </view>
  121. <!-- 车身照和车头照 -->
  122. <view class="license-section">
  123. <view class="license-item">
  124. <text class="license-title">车头照</text>
  125. <view class="license-image-container">
  126. <image
  127. v-if="vehicleInfo.vehBodyUrl"
  128. :src="getImageUrl(vehicleInfo.vehBodyUrl)"
  129. class="license-image"
  130. mode="aspectFit"
  131. @click="previewImage(getImageUrl(vehicleInfo.vehBodyUrl))"
  132. />
  133. <view v-else class="license-placeholder">
  134. <text class="placeholder-text">暂无图片</text>
  135. </view>
  136. </view>
  137. </view>
  138. <!-- <view class="license-item">
  139. <text class="license-title">车头照</text>
  140. <view class="license-image-container">
  141. <image
  142. v-if="vehicleInfo.proxyUrl"
  143. :src="getImageUrl(vehicleInfo.proxyUrl)"
  144. class="license-image"
  145. mode="aspectFit"
  146. @click="previewImage(getImageUrl(vehicleInfo.proxyUrl))"
  147. />
  148. <view v-else class="license-placeholder">
  149. <text class="placeholder-text">暂无图片</text>
  150. </view>
  151. </view>
  152. </view> -->
  153. </view>
  154. </view>
  155. <!-- 底部按钮 -->
  156. <view class="bottom-actions">
  157. <button class="submit-btn" @click="changeVehicleInfo">车辆信息变更</button>
  158. </view>
  159. </view>
  160. </template>
  161. <script lang="ts" setup>
  162. import { reactive, ref } from "vue";
  163. import { onLoad } from "@dcloudio/uni-app";
  164. import { getVehiclePlateColor } from "@/datas/vehiclePlateColor";
  165. import { vehicleInfoView } from "@/utils/network/api.js";
  166. import { requestNew } from "@/utils/network/request.js";
  167. import { fileURL } from "@/datas/fileURL.js";
  168. // import { getItem } from "@/utils/storage";
  169. import {
  170. getCodeName
  171. } from "@/datas/queryKey.js";
  172. import { queryKey } from "@/utils/network/api.js";
  173. import { setItem, getItem } from "@/utils/storage";
  174. // 响应式数据
  175. const vehicleInfo = reactive({
  176. vehiclePlate: '',
  177. vehiclePlateColor: 0,
  178. vehPosImgUrl: '',
  179. vehNegImgUrl: '',
  180. ownerName: '',
  181. ownerIdType: '',
  182. ownerIdNum: '',
  183. ownerTel: '',
  184. vin: '',
  185. vehicleId: '',
  186. vehicleType: '',
  187. engineNum: '',
  188. type: '',
  189. approvedCount: 0,
  190. totalMass: 0,
  191. maintenaceMass: 0,
  192. permittedWeight: 0,
  193. vehicleDimensions: '',
  194. permittedTowWeight: 0,
  195. vehicleWheelCount: 0,
  196. axleCount: 0,
  197. useCharacter: '',
  198. vehBodyUrl: '',
  199. proxyUrl: ''
  200. });
  201. const plateNumber = ref(["贵", "Z", "M", "J", "U", "7", "0"]);
  202. const currentInputIndex = ref(0);
  203. const selectedColor = ref("blue");
  204. // 确保字典数据已加载
  205. const ensureDictData = () => {
  206. const dictData = getItem('key');
  207. if (!dictData) {
  208. // 如果字典数据不存在,先加载字典数据
  209. const options = {
  210. type: 2,
  211. data: {},
  212. method: "POST",
  213. };
  214. return requestNew(queryKey, options).then((res) => {
  215. console.log("加载字典数据", res);
  216. // 处理字典接口返回的两种数据结构
  217. const dictData = res.dictTypeAndItem || res;
  218. setItem('key', dictData);
  219. return dictData;
  220. });
  221. }
  222. return Promise.resolve(dictData);
  223. };
  224. // 页面加载
  225. onLoad((options) => {
  226. console.log("车辆详情页面参数:", options);
  227. uni.setNavigationBarTitle({
  228. title: "车辆详情",
  229. });
  230. if (options.id) {
  231. // 确保字典数据已加载后再获取车辆详情
  232. ensureDictData().then(() => {
  233. getVehicleDetails(options.id);
  234. });
  235. } else {
  236. uni.showToast({
  237. title: "缺少车辆ID参数",
  238. icon: "none",
  239. });
  240. }
  241. });
  242. // 获取车辆详情
  243. const getVehicleDetails = (id: string) => {
  244. const options = {
  245. type: 2,
  246. data: {
  247. vehicleId: id,
  248. },
  249. method: "POST",
  250. showLoading: true,
  251. };
  252. requestNew(vehicleInfoView, options)
  253. .then((res) => {
  254. console.log("车辆详情接口返回:", res);
  255. if (res) {
  256. // 将接口返回的数据赋值给vehicleInfo
  257. Object.assign(vehicleInfo, res);
  258. console.log(vehicleInfo, 'vehicleInfo');
  259. } else {
  260. uni.showToast({
  261. title: res?.message || "获取车辆信息失败",
  262. icon: "none",
  263. });
  264. }
  265. })
  266. .catch((err) => {
  267. console.error("获取车辆详情失败:", err);
  268. uni.showToast({
  269. title: "获取车辆信息失败",
  270. icon: "none",
  271. });
  272. });
  273. };
  274. // 处理图片URL
  275. const getImageUrl = (url: string) => {
  276. if (!url) return '';
  277. // 如果已经是完整URL,直接返回
  278. if (url.startsWith('http://') || url.startsWith('https://')) {
  279. return url;
  280. }
  281. // 从fileURL中删除default-bucket/后缀,然后拼上url
  282. const baseUrl = fileURL.replace('/default-bucket/', '');
  283. return `${baseUrl}/${url}`;
  284. };
  285. // 预览图片
  286. const previewImage = (url: string) => {
  287. if (url) {
  288. uni.previewImage({
  289. urls: [url],
  290. current: url,
  291. });
  292. }
  293. };
  294. // 聚焦输入框
  295. const focusInput = (index: number) => {
  296. currentInputIndex.value = index;
  297. };
  298. // 添加新车牌
  299. const addNewPlate = () => {
  300. uni.showToast({
  301. title: "添加新车牌功能",
  302. icon: "none",
  303. });
  304. };
  305. // 选择车牌颜色
  306. const selectColor = (color: string) => {
  307. selectedColor.value = color;
  308. };
  309. // 选择图片
  310. const chooseImage = () => {
  311. uni.chooseImage({
  312. count: 1,
  313. sizeType: ["compressed"],
  314. sourceType: ["album", "camera"],
  315. success: (res) => {
  316. vehicleInfo.proxyUrl = res.tempFilePaths[0];
  317. },
  318. });
  319. };
  320. // 下一步
  321. const nextStep = () => {
  322. uni.showToast({
  323. title: "下一步功能",
  324. icon: "none",
  325. });
  326. };
  327. // 车辆信息变更
  328. const changeVehicleInfo = () => {
  329. uni.navigateTo({
  330. url: `/subpackage/personal-center/vehicle-change/vehicle-change-choiceType?vehicleId=${vehicleInfo.vehicleId}&vehiclePlate=${vehicleInfo.vehiclePlate}`,
  331. });
  332. };
  333. </script>
  334. <style lang="scss" scoped>
  335. .vehicle-details-container {
  336. min-height: 100vh;
  337. background-color: #f5f5f5;
  338. padding-bottom: 200rpx;
  339. }
  340. .header {
  341. background-color: #fff;
  342. padding: 30rpx;
  343. text-align: center;
  344. border-bottom: 1rpx solid #eee;
  345. .title {
  346. font-size: 36rpx;
  347. font-weight: bold;
  348. color: #333;
  349. }
  350. }
  351. .vehicle-info-section {
  352. background-color: #fff;
  353. margin: 20rpx;
  354. border-radius: 12rpx;
  355. padding: 30rpx;
  356. .info-item {
  357. display: flex;
  358. justify-content: space-between;
  359. align-items: center;
  360. padding: 20rpx 0;
  361. border-bottom: 1rpx solid #f0f0f0;
  362. &:last-child {
  363. border-bottom: none;
  364. }
  365. .label {
  366. font-size: 28rpx;
  367. color: #666;
  368. // flex: 0;
  369. }
  370. .value {
  371. font-size: 28rpx;
  372. color: #333;
  373. // flex: 1;
  374. text-align: right;
  375. }
  376. }
  377. }
  378. .license-section {
  379. background-color: #fff;
  380. margin: 20rpx;
  381. border-radius: 12rpx;
  382. padding: 30rpx;
  383. .license-item {
  384. margin-bottom: 30rpx;
  385. &:last-child {
  386. margin-bottom: 0;
  387. }
  388. .license-title {
  389. font-size: 28rpx;
  390. color: #333;
  391. margin-bottom: 20rpx;
  392. display: block;
  393. }
  394. .license-image-container {
  395. width: 100%;
  396. height: 300rpx;
  397. border: 2rpx dashed #ddd;
  398. border-radius: 8rpx;
  399. display: flex;
  400. align-items: center;
  401. justify-content: center;
  402. .license-image {
  403. width: 100%;
  404. height: 100%;
  405. border-radius: 8rpx;
  406. }
  407. .license-placeholder {
  408. display: flex;
  409. align-items: center;
  410. justify-content: center;
  411. width: 100%;
  412. height: 100%;
  413. .placeholder-text {
  414. color: #999;
  415. font-size: 26rpx;
  416. }
  417. }
  418. }
  419. }
  420. }
  421. .plate-selection-section {
  422. background-color: #fff;
  423. margin: 20rpx;
  424. border-radius: 12rpx;
  425. padding: 30rpx;
  426. .plate-header {
  427. margin-bottom: 30rpx;
  428. .plate-title {
  429. font-size: 32rpx;
  430. color: #333;
  431. font-weight: bold;
  432. }
  433. }
  434. .plate-input-section {
  435. margin-bottom: 30rpx;
  436. .input-label {
  437. font-size: 28rpx;
  438. color: #666;
  439. margin-bottom: 20rpx;
  440. display: block;
  441. }
  442. .plate-input-container {
  443. display: flex;
  444. align-items: center;
  445. gap: 10rpx;
  446. .plate-char-input {
  447. width: 80rpx;
  448. height: 80rpx;
  449. border: 2rpx solid #ddd;
  450. border-radius: 8rpx;
  451. display: flex;
  452. align-items: center;
  453. justify-content: center;
  454. background-color: #fff;
  455. &.active {
  456. border-color: #007aff;
  457. background-color: #f0f8ff;
  458. }
  459. .plate-char {
  460. font-size: 32rpx;
  461. color: #333;
  462. font-weight: bold;
  463. }
  464. }
  465. .plate-add-btn {
  466. width: 80rpx;
  467. height: 80rpx;
  468. border: 2rpx solid #ddd;
  469. border-radius: 8rpx;
  470. display: flex;
  471. flex-direction: column;
  472. align-items: center;
  473. justify-content: center;
  474. background-color: #fff;
  475. .add-icon {
  476. font-size: 24rpx;
  477. color: #007aff;
  478. font-weight: bold;
  479. }
  480. .add-text {
  481. font-size: 20rpx;
  482. color: #007aff;
  483. }
  484. }
  485. }
  486. }
  487. .plate-color-section {
  488. .color-label {
  489. font-size: 28rpx;
  490. color: #666;
  491. margin-bottom: 20rpx;
  492. display: block;
  493. }
  494. .color-options {
  495. display: flex;
  496. gap: 20rpx;
  497. .color-option {
  498. flex: 1;
  499. height: 80rpx;
  500. border-radius: 8rpx;
  501. display: flex;
  502. align-items: center;
  503. justify-content: center;
  504. border: 2rpx solid transparent;
  505. &.blue {
  506. background: linear-gradient(135deg, #007aff, #0056b3);
  507. &.active {
  508. border-color: #007aff;
  509. box-shadow: 0 0 10rpx rgba(0, 122, 255, 0.3);
  510. }
  511. }
  512. &.green {
  513. background: linear-gradient(135deg, #34c759, #28a745);
  514. &.active {
  515. border-color: #34c759;
  516. box-shadow: 0 0 10rpx rgba(52, 199, 89, 0.3);
  517. }
  518. }
  519. .color-text {
  520. color: #fff;
  521. font-size: 28rpx;
  522. font-weight: bold;
  523. }
  524. }
  525. }
  526. }
  527. }
  528. .front-photo-section {
  529. background-color: #fff;
  530. margin: 20rpx;
  531. border-radius: 12rpx;
  532. padding: 30rpx;
  533. .photo-title {
  534. font-size: 28rpx;
  535. color: #333;
  536. margin-bottom: 20rpx;
  537. display: block;
  538. }
  539. .photo-container {
  540. width: 100%;
  541. height: 400rpx;
  542. border: 2rpx dashed #ddd;
  543. border-radius: 8rpx;
  544. display: flex;
  545. align-items: center;
  546. justify-content: center;
  547. .front-photo {
  548. width: 100%;
  549. height: 100%;
  550. border-radius: 8rpx;
  551. }
  552. .photo-placeholder {
  553. display: flex;
  554. align-items: center;
  555. justify-content: center;
  556. width: 100%;
  557. height: 100%;
  558. .placeholder-text {
  559. color: #999;
  560. font-size: 26rpx;
  561. }
  562. }
  563. }
  564. }
  565. .bottom-actions {
  566. position: fixed;
  567. bottom: 0;
  568. left: 0;
  569. right: 0;
  570. background-color: #fff;
  571. padding: 30rpx;
  572. border-top: 1rpx solid #eee;
  573. display: flex;
  574. flex-direction: column;
  575. gap: 20rpx;
  576. .next-btn {
  577. background: linear-gradient(135deg, #007aff, #0056b3);
  578. color: #fff;
  579. border: none;
  580. border-radius: 12rpx;
  581. height: 88rpx;
  582. font-size: 32rpx;
  583. font-weight: bold;
  584. }
  585. .submit-btn {
  586. width:90%;
  587. background: linear-gradient(to bottom, #1e3a8a, #1e1e1e);
  588. color: #fff;
  589. border: none;
  590. border-radius: 50rpx;
  591. height: 88rpx;
  592. font-size: 32rpx;
  593. font-weight: bold;
  594. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.3);
  595. position: relative;
  596. &::before {
  597. content: "";
  598. position: absolute;
  599. top: 0;
  600. left: 0;
  601. right: 0;
  602. height: 2rpx;
  603. background: linear-gradient(to right, #60a5fa, #93c5fd);
  604. border-radius: 50rpx 50rpx 0 0;
  605. }
  606. &::after {
  607. content: "";
  608. position: absolute;
  609. bottom: 0;
  610. left: 0;
  611. right: 0;
  612. height: 2rpx;
  613. background: #000;
  614. border-radius: 0 0 50rpx 50rpx;
  615. }
  616. }
  617. }
  618. </style>