home.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. import plateNumber from '@/components/plate-number/plateNumber.vue';
  2. import { REG_SOURCE } from '@/constants';
  3. import LoginDom from '@/components/Login/Login.vue';
  4. import { mapState } from 'vuex';
  5. const app = {
  6. globalData: {
  7. regSource: '',
  8. },
  9. };
  10. import uni from '@/utils/uniHooks';
  11. // import blueCom from '../components/blue/home.vue';
  12. // import greenCom from '../components/green/home.vue';
  13. // import officeBlueCom from '../components/officeBlue/home.vue';
  14. // import purpleCom from '../components/purple/home.vue';
  15. import { parkingLots, checkOut } from '@/api/parking';
  16. export default {
  17. components: {
  18. plateNumber,
  19. LoginDom,
  20. // blueCom,
  21. // greenCom,
  22. // officeBlueCom,
  23. // purpleCom,
  24. },
  25. data() {
  26. return {
  27. vehicleMgt_content_index: -1, //历史车辆选中
  28. carType: 0, //车辆类型
  29. init_ch: false, // 字体超出隐藏显示
  30. search_price: false, //查询按钮隐藏显示
  31. parkInfoEntity: {},
  32. show_chinese: false, //是否显示汉字键盘
  33. show_allBoard: false, //是否显示英文数字键盘
  34. plate_number: '', //车牌号
  35. description: '', // 车场描述
  36. ind: null,
  37. numArr: ['', '', '', '', '', '', ''],
  38. active: null,
  39. carList: [], // 车辆列表
  40. classifyList: ['燃油车牌', '新能源', '特殊车牌'], // 车牌类型
  41. vehicleNumber: '',
  42. localimgPic: '',
  43. hourMoney: '',
  44. showSq: false,
  45. blueHeadBg: 'parkingFee/fee-head-bg.png',
  46. picUrl: this.$picUrl,
  47. colorAry: ['', '-blue', '-green'],
  48. openId: null,
  49. options: null,
  50. preUrl: '',
  51. // custTypeId: 0,
  52. };
  53. },
  54. computed: {
  55. disabledBtn() {
  56. return this.numArr.findIndex((val) => !val) !== -1;
  57. },
  58. ...mapState({
  59. groupId: (state) => state.groupId,
  60. openid: (state) => state.openid,
  61. mallId: (state) => state.mallId,
  62. kipUserId: (state) => state.kipUserId,
  63. userInfo: (state) => state.userInfo,
  64. member: (state) => state.member,
  65. mobile: (state) => state.mobile,
  66. custTypeId: (state) => state.custTypeId,
  67. }),
  68. },
  69. beforeRouteLeave(to, from, next) {
  70. this.$store.commit('cachedViews/DEL_CACHED_VIEW', to);
  71. next();
  72. },
  73. watch: {
  74. userInfo() {
  75. this.initPage();
  76. },
  77. openid() {
  78. if (this.openid) {
  79. this.getParkInfo();
  80. this.showSq = false;
  81. }
  82. },
  83. },
  84. async created(params) {},
  85. mounted() {
  86. setTimeout(() => {
  87. uni.setNavigationBarTitle({
  88. title: '停车缴费',
  89. });
  90. }, 300);
  91. if (this.openid) {
  92. console.log(939393939393);
  93. this.getParkInfo();
  94. this.showSq = false;
  95. } else {
  96. const regSource = REG_SOURCE.PARKING;
  97. app.globalData.regSource = regSource;
  98. if (this.options?.regSource) {
  99. app.globalData.regSource = REG_SOURCE[this.options?.regSource];
  100. }
  101. if (this.options?.tpName) {
  102. app.globalData.tpName = this.options?.tpName;
  103. }
  104. this.showSq = true;
  105. }
  106. },
  107. methods: {
  108. async initPage() {
  109. // ws()
  110. console.time('time');
  111. const name = {
  112. a: 'label',
  113. c: 'label',
  114. };
  115. // const nameD = Encrypt(JSON.stringify(name))
  116. // this.options = params;
  117. // await this.$onLaunched;
  118. this.localimgPic = this.$staticPicUrl + '/wxminilocalimg/parkingFee/';
  119. // app.globalData.pullVipcode = params.pullVipcode || '';
  120. // app.globalData.mallid = params.mallid || app.globalData.mallid
  121. if (this.userInfo) {
  122. // this.getParkInfo();
  123. return;
  124. // app.globalData.isNewMember = '';
  125. // 场景二维码记录(是否扫码进入)
  126. // app.globalData.paramsScene = {};
  127. // this.$saveSceneQrcodeDetail(
  128. // 'page',
  129. // 'parkingFee',
  130. // '停车缴费',
  131. // '',
  132. // '',
  133. // '',
  134. // ''
  135. // );
  136. }
  137. // 埋点本地化
  138. this.preUrl = uni.getStorageSync('previousUrl');
  139. uni.setStorageSync('previousUrl', '/pages/parkingFee/home.vue');
  140. },
  141. toggleType(carType) {
  142. this.ind = 0;
  143. this.active = 0;
  144. this.carType = carType;
  145. if (carType === 1) {
  146. this.numArr = [
  147. this.numArr[0],
  148. this.numArr[1],
  149. this.numArr[2],
  150. this.numArr[3],
  151. this.numArr[4],
  152. this.numArr[5],
  153. this.numArr[6],
  154. this.numArr[7],
  155. ];
  156. } else {
  157. this.numArr = [
  158. this.numArr[0],
  159. this.numArr[1],
  160. this.numArr[2],
  161. this.numArr[3],
  162. this.numArr[4],
  163. this.numArr[5],
  164. this.numArr[6],
  165. ];
  166. }
  167. },
  168. // 获取停车场信息
  169. getParkInfo: async function () {
  170. uni.showLoading({
  171. title: '加载中',
  172. });
  173. const openid = uni.getStorageSync('openid') || this.openId;
  174. /*let params = {
  175. // mallid: '8a84853b7c91ac5b017c961a9b2a030d',
  176. // groupId: '8a84853b7c91ac5b017c962dab55030e',
  177. mallid: this.mallId,
  178. groupId: this.groupId,
  179. openid: openid,
  180. vipcode: this.member?.vipcode,
  181. };
  182. console.log(342, params);
  183. this.$md(params);
  184. this.$request({
  185. url: this.$baseURL + 'api/1.0/park/parkInfo',
  186. data: params,
  187. method: 'POST',
  188. header: JSON.parse(uni.getStorageSync('handleUser')),
  189. })
  190. .then((res) => {
  191. if (res.data.code === 0) {
  192. const data = res.data.data || {};
  193. this.carList = data.carList;
  194. this.parkInfoEntity = data.parkInfoEntity;
  195. this.hourMoney =
  196. parseFloat(this.parkInfoEntity.needmoney) /
  197. parseFloat(this.parkInfoEntity.tohours);
  198. let reg = /[;;]/g;
  199. this.parkInfoEntity.payinstruction =
  200. this.parkInfoEntity.payinstruction.replace(reg, '\r\n');
  201. this.parkInfoEntity.hourMoney = this.hourMoney;
  202. uni.setStorageSync('parkinfo', JSON.stringify(this.parkInfoEntity));
  203. } else {
  204. uni.showToast({
  205. title: res.data.msg,
  206. duration: 2000,
  207. icon: 'none',
  208. });
  209. }
  210. })
  211. .catch((err) => {
  212. uni.showToast({
  213. title: '网络超时请稍后再试',
  214. duration: 2000,
  215. icon: 'none',
  216. });
  217. console.log(err);
  218. });*/
  219. try {
  220. const res = await parkingLots();
  221. console.log('223,2323', res);
  222. const data = {
  223. "parkName": "杭州停车场",
  224. "parkCode": "hz01",
  225. "carList": [],
  226. "description": "计费基础规则:10元每小时,上不封顶 ;\n线上缴费渠道:CRM小程序 (分会员通道及非会员通道);1\n会员等级减免:铂金卡当日可免费停车4小时,金卡当时可免费停车2小时,银卡无减免 (当日仅限使用1次,可与其它减免共享);\n积分抵扣:1000积分抵扣10元(手动输入抵扣积分);\n消费减免:消费200元可减免2小时,消费400元可减免4小时,消费800元可减免6小时 。仅限会员,当日有效,当日可多次享受该减免,当日最多可享受消费减免6小时。;\n 消费减免举例:;\n (1) 某顾客第一次进场,消费230元 离场时可看到减免2小时的选项,默认为选中;\n (2) 如果顾客未使用减免,顾客第二次进场,消费+270 离场时可看到减免金额提高到4小时;\n 如果顾客使用减免:顾客第二次进场,消费+270 离场时可看到还是只能减免2小时;\n (3) CRM小程序缴费页面停留时长1分钟,1分钟后自动刷新获取最新缴费金额;\n纸质优惠券核销: 顾客在CRM小程序手动扫码获取优惠券金额;\n会员活动及积分兑换优惠 :通过CRM系统获取(详细情况由CRM另行描述)!"
  227. }
  228. // let reg = /[;;]/g;
  229. // this.parkInfoEntity.description = data.description.replace(reg, '\r\n');
  230. this.description = data.description;
  231. // const data = res.data.data || {};
  232. this.carList = data.carList;
  233. // this.parkInfoEntity = data.parkInfoEntity;
  234. // this.hourMoney =
  235. // parseFloat(this.parkInfoEntity.needmoney) /
  236. // parseFloat(this.parkInfoEntity.tohours);
  237. // let reg = /[;;]/g;
  238. // this.parkInfoEntity.payinstruction =
  239. // this.parkInfoEntity.payinstruction.replace(reg, '\r\n');
  240. // this.parkInfoEntity.hourMoney = this.hourMoney;
  241. // uni.setStorageSync('parkinfo', JSON.stringify(this.parkInfoEntity));
  242. // console.log(233, res);
  243. } catch (e) {
  244. console.log(225225, e);
  245. }
  246. // return;
  247. // const data = res.data || {};
  248. // this.carList = data.carList;
  249. // this.parkInfoEntity = data.parkInfoEntity;
  250. // this.hourMoney =
  251. // parseFloat(this.parkInfoEntity.needmoney) /
  252. // parseFloat(this.parkInfoEntity.tohours);
  253. // let reg = /[;;]/g;
  254. // this.parkInfoEntity.payinstruction =
  255. // this.parkInfoEntity.payinstruction.replace(reg, '\r\n');
  256. // this.parkInfoEntity.hourMoney = this.hourMoney;
  257. // uni.setStorageSync('parkinfo', JSON.stringify(this.parkInfoEntity));
  258. },
  259. //缴费说明隐藏显示
  260. top_display() {
  261. this.init_ch = !this.init_ch;
  262. // 缴费说明展开/收起埋点(增加动作参数)
  263. this.sensorsClick('$ClickExpandPaymentInstructions', {
  264. action: this.init_ch ? 'open' : 'close',
  265. redirect_url: '',
  266. cta_itemno: '',
  267. cta_name: '',
  268. });
  269. },
  270. // 埋点方法
  271. sensorsClick(eventName, params) {
  272. let optionsQuery = uni.getStorageSync('options_query');
  273. let fixedParams = {
  274. previous_url: this.preUrl || '',
  275. // 原previous_url: uni.getStorageSync('previousUrl') || ''
  276. // previous_url: 使用sdk预置参数$referrer,
  277. $brand_id: uni.getStorageSync('groupId'),
  278. $location: uni.getStorageSync('mallid'),
  279. $channel: optionsQuery?.channel || '',
  280. // $utm_lbs: this.optionsQuery.utm_lbs || '',
  281. $utm_channel: optionsQuery?.utm_channel || '',
  282. $utm_method: optionsQuery?.utm_method || '',
  283. $utm_source: optionsQuery?.utm_source || '',
  284. $utm_function: optionsQuery?.utm_function || '',
  285. $utm_user: optionsQuery?.utm_user || '',
  286. },
  287. finalParams = Object.assign(fixedParams, params);
  288. this.$sensors.track(eventName, finalParams);
  289. },
  290. // 唤起键盘
  291. clickShowKeyboard(index) {
  292. this.ind = index;
  293. this.active = index;
  294. if (index === 0) {
  295. this.$refs['plateKeyboard'].openKeyboardCN();
  296. } else {
  297. this.$refs['plateKeyboard'].closeKeyboardCN();
  298. this.$refs['plateKeyboard'].openKeyboardEN();
  299. }
  300. },
  301. // 接收子组件数据
  302. updateCarno(val) {
  303. this.numArr = val.numArr;
  304. this.vehicleNumber = this.numArr.join('');
  305. this.active = val.active;
  306. this.ind = val.ind;
  307. },
  308. // 节流函数
  309. throttle(fc, waitTime = 500, imme = true) {
  310. if (imme) {
  311. if (!this.flag) {
  312. this.flag = true;
  313. typeof fc === 'function' && fc();
  314. this.timer = setTimeout(() => {
  315. this.flag = false;
  316. }, waitTime);
  317. }
  318. } else {
  319. if (!this.flag) {
  320. this.flag = true;
  321. this.timer = setTimeout(() => {
  322. this.flag = false;
  323. typeof fc === 'function' && fc();
  324. }, waitTime);
  325. }
  326. }
  327. },
  328. // 校验车牌号
  329. preHandleSearch() {
  330. this.throttle(() => {
  331. this.handleSearch(this.vehicleNumber);
  332. }, 3000);
  333. },
  334. // 历史车牌快速查询
  335. toHandleSearch(carno) {
  336. this.throttle(() => {
  337. this.handleSearch(carno, '$ClickHistoryAndPayment');
  338. }, 3000);
  339. },
  340. // 查询车费信息
  341. async handleSearch(carno, clickEvent = '$ClickQueryAndPayment') {
  342. this.vehicleNumber = carno;
  343. const params = {
  344. carno,
  345. mallid: this.mallId,
  346. openid: this.openid,
  347. vipcode: this.member?.vipcode,
  348. mobile: this.mobile,
  349. groupId: this.groupId,
  350. createuser: 'sys_miniprogram',
  351. };
  352. // 查询缴费按钮埋点
  353. let [carTypeName, redirectUrl, parkTime] = ['ordinary', '', ''];
  354. switch (this.carType) {
  355. case 0:
  356. carTypeName = 'ordinary';
  357. break;
  358. case 1:
  359. carTypeName = 'newEnergy';
  360. break;
  361. case 2:
  362. carTypeName = 'special';
  363. break;
  364. }
  365. // this.sensorsClick(clickEvent, { $car_type: carTypeName })
  366. // TODO: 暂定埋点传参为车牌类型,是否需要其他参数比如车牌号码;埋点位置是否要放在查询接口回调函数中
  367. this.$md(params);
  368. console.log(539, uni.getStorageSync('handleUser'));
  369. try {
  370. const res = await checkOut(carno)
  371. console.log(res)
  372. } catch ( err ) {
  373. console.log('errerrerrerr',err)
  374. }
  375. return
  376. this.$request({
  377. // url: this.$baseURL + 'api/1.0/park/checkCarIsInPark',
  378. url: this.$baseURL + 'api/1.0/park/checkCarIsInParkAndCarFee',
  379. // url: 'http://172.21.90.87:8083/xcrm-api/api/1.0/park/checkCarIsInParkAndCarFee',
  380. data: params,
  381. method: 'POST',
  382. header: JSON.parse(uni.getStorageSync('handleUser')),
  383. timeout: 60000 * 2, // 120S
  384. showLoading: {
  385. title: '加载中',
  386. duration: 0,
  387. },
  388. })
  389. .then((res) => {
  390. // console.log(555555, res);
  391. // ToastObj.clear();
  392. // uni.hideLoading();
  393. if (res.data.code === 0) {
  394. // 清理旧数据
  395. this.parkingFeeDetailInit();
  396. uni.setStorageSync('isReload', '3');
  397. // this.$destroy();
  398. this.$router.push({
  399. path: 'parkingFeeDetail',
  400. query: {
  401. carno,
  402. },
  403. });
  404. parkTime = res.data?.data?.serviceMin;
  405. redirectUrl = '/pages/parkingFee/parkingFeeDetail.vue';
  406. } else if (res.data.code === 1) {
  407. // 当前车辆没有查到账单
  408. this.$router.push({
  409. path: 'parkingFeePayment',
  410. query: {
  411. msg: res.data.msg,
  412. carno,
  413. },
  414. });
  415. redirectUrl = '/pages/parkingFee/parkingFeePayment.vue';
  416. } else if (res.data.code === 2) {
  417. // 月租车
  418. this.$router.push({
  419. path: './parkingFeeHint/parkingFeeHint',
  420. query: {
  421. carno,
  422. },
  423. });
  424. redirectUrl = '/pages/parkingFee/parkingFeeHint/parkingFeeHint.vue';
  425. } else {
  426. uni.showToast({
  427. title: res.data.msg,
  428. duration: 2000,
  429. icon: 'none',
  430. });
  431. }
  432. this.sensorsClick(clickEvent, {
  433. car_type: carTypeName,
  434. redirect_url: redirectUrl,
  435. time: parkTime,
  436. cta_itemno: '',
  437. cta_name: '',
  438. });
  439. })
  440. .catch((err) => {
  441. // uni.hideLoading();
  442. uni.showToast({
  443. title: '网络超时请稍后再试',
  444. duration: 2000,
  445. icon: 'none',
  446. });
  447. console.log(err);
  448. });
  449. },
  450. // 页面初始清空缓存
  451. parkingFeeDetailInit() {
  452. console.log('清理数据');
  453. // 优惠减免(首停、会员、消费)
  454. uni.removeStorageSync('checkedList'); // 选中list
  455. uni.removeStorageSync('checkedTotal'); // 选中count数
  456. uni.removeStorageSync('discountTotal'); // 减免信息(时长、费用)
  457. // 停车减免(优惠、积分、停车券)
  458. uni.removeStorageSync('parkFee');
  459. // 电子券优惠信息
  460. uni.removeStorageSync('checkedCouponList'); // 选中list
  461. uni.removeStorageSync('couponInfo'); // 减免信息(时长、费用)
  462. uni.removeStorageSync('list'); // 电子券list
  463. // 总停车优惠信息(时长、费用)
  464. uni.removeStorageSync('parkingTotal');
  465. // 应缴金额
  466. uni.removeStorageSync('servicefee');
  467. // 订单号
  468. uni.removeStorageSync('orderno');
  469. // 纸质优惠券
  470. uni.removeStorageSync('paperCouponInfo');
  471. // uni.removeStorageSync('isReload');
  472. },
  473. // 车牌号校验
  474. // isVehicleNumber(vehicleNumber) {
  475. // if (vehicleNumber.length == 7) {
  476. // this.vehicleNumber = vehicleNumber.join('')
  477. // var express =
  478. // /^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$/;
  479. // if (!express.test(this.vehicleNumber)) {
  480. // uni.showToast({
  481. // title: '请输入正确的车牌号',
  482. // duration: 2000,
  483. // icon: 'none'
  484. // })
  485. // return false
  486. // }
  487. // return true
  488. // }
  489. // if (vehicleNumber.length == 8) {
  490. // this.vehicleNumber = vehicleNumber.join('')
  491. // var express =
  492. // /^([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[a-zA-Z](([DF]((?![IO])[a-zA-Z0-9](?![IO]))[0-9]{4})|([0-9]{5}[DF]))|[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1})$/;
  493. // if (!express.test(this.vehicleNumber)) {
  494. // uni.showToast({
  495. // title: '请输入正确的车牌号',
  496. // duration: 2000,
  497. // icon: 'none'
  498. // })
  499. // return false
  500. // }
  501. // return true
  502. // }
  503. // },
  504. // 缴费记录
  505. doRouter: function () {
  506. if (this.$store.state.isLogin === '3') {
  507. this.$router.push({ path: 'login' });
  508. return;
  509. }
  510. this.$router.push({ path: 'parkingFeeList' });
  511. this.sensorsClick('$ClickParkRouter', {
  512. cta_itemno: '',
  513. cta_name: '缴费记录',
  514. redirect_url: '/pages/parkingFee/parkingFeeList.vue',
  515. });
  516. },
  517. // 车牌管理
  518. doRouter2: function () {
  519. if (this.$store.state.isLogin === '3') {
  520. this.$router.push({ path: 'login' });
  521. return;
  522. }
  523. uni.removeStorageSync('passLogin');
  524. this.$router.push({ path: 'vehicleManagement' });
  525. this.sensorsClick('$ClickParkRouter', {
  526. cta_itemno: '',
  527. cta_name: '车牌管理',
  528. redirect_url: '/pages/parkingFee/vehicleManagement.vue',
  529. });
  530. },
  531. //停车发票
  532. doRouter1: function () {
  533. if (this.$store.state.isLogin === '3') {
  534. this.$router.push({ path: 'login' });
  535. return;
  536. }
  537. // uni.removeStorageSync('passLogin');
  538. // 北京停车场开票
  539. // if (this.parkInfoEntity.parkMallCode === 3) {
  540. // uni.navigateToMiniProgram({
  541. // appId: this.$etcpAppId,
  542. // path: this.$etcpAppInvoicePath,
  543. // envVersion: 'release',
  544. // })
  545. // return
  546. // }
  547. // this.$router.push({
  548. // path: './parkingReceipt/parkingReceipt',
  549. // })
  550. if (this.$store.state.passLogin) {
  551. }
  552. this.$router.push({ path: 'parkingReceipt' });
  553. this.sensorsClick('$ClickParkRouter', {
  554. cta_itemno: '',
  555. cta_name: '停车发票',
  556. redirect_url: '/pages/parkingFee/parkingReceipt/parkingReceipt.vue',
  557. });
  558. },
  559. //停车券兑换
  560. doRouter3: function () {
  561. // this.$router.push({
  562. // path: '/pages/pointsMall/pointsMall?exchangeTypes=2',
  563. // })
  564. // TODO 跳转到crm的积分商城
  565. // this.$router.push({ path: 'pointsMall?exchangeTypes=2' });
  566. // this.sensorsClick('$ClickParkRouter', {
  567. // cta_itemno: '',
  568. // cta_name: '停车券兑换',
  569. // redirect_url: '/pages/pointsMall/pointsMall.vue',
  570. // });
  571. // uni.navigateTo({
  572. // url: '/pages/pointsMall/pointsMall?exchangeTypes=2',
  573. // })
  574. window.toWXSendMsg({
  575. type: 'toPage',
  576. options: {
  577. fnName: 'navigateTo',
  578. url: '/pages/pointsMall/pointsMall?exchangeTypes=2',
  579. },
  580. });
  581. },
  582. blueComChange(value) {
  583. console.log('blueComChange', value);
  584. },
  585. },
  586. };