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.
 
 
 
 
 
 

464 lines
20 KiB

  1. <template>
  2. <view class="mpvue-picker">
  3. <view :class="{'pickerMask':showPicker}" @click="maskClick" catchtouchmove="true"></view>
  4. <view class="mpvue-picker-content " :class="{'mpvue-picker-view-show':showPicker}">
  5. <view class="mpvue-picker__hd" catchtouchmove="true">
  6. <view class="mpvue-picker__action" @click="pickerCancel">Huỷ</view>
  7. <view class="mpvue-picker__action" :style="{color:themeColor}" @click="pickerConfirm">Xác nhận</view>
  8. </view>
  9. <!-- 单列 -->
  10. <picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue" @change="pickerChange" v-if="mode==='selector' && pickerValueSingleArray.length > 0">
  11. <block>
  12. <picker-view-column>
  13. <view class="picker-item" v-for="(item,index) in pickerValueSingleArray" :key="index">{{item.label}}</view>
  14. </picker-view-column>
  15. </block>
  16. </picker-view>
  17. <!-- 时间选择器 -->
  18. <picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue" @change="pickerChange" v-if="mode==='timeSelector'">
  19. <block>
  20. <picker-view-column>
  21. <view class="picker-item" v-for="(item,index) in pickerValueHour" :key="index">{{item.label}}</view>
  22. </picker-view-column>
  23. <picker-view-column>
  24. <view class="picker-item" v-for="(item,index) in pickerValueMinute" :key="index">{{item.label}}</view>
  25. </picker-view-column>
  26. </block>
  27. </picker-view>
  28. <!-- 多列选择 -->
  29. <picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue" @change="pickerChange" v-if="mode==='multiSelector'">
  30. <block v-for="(n,index) in pickerValueMulArray.length" :key="index">
  31. <picker-view-column>
  32. <view class="picker-item" v-for="(item,index1) in pickerValueMulArray[n]" :key="index1">{{item.label}}</view>
  33. </picker-view-column>
  34. </block>
  35. </picker-view>
  36. <!-- 二级联动 -->
  37. <picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue" @change="pickerChangeMul" v-if="mode==='multiLinkageSelector' && deepLength===2">
  38. <block>
  39. <picker-view-column>
  40. <view class="picker-item" v-for="(item,index) in pickerValueMulTwoOne" :key="index">{{item.label}}</view>
  41. </picker-view-column>
  42. <picker-view-column>
  43. <view class="picker-item" v-for="(item,index) in pickerValueMulTwoTwo" :key="index">{{item.label}}</view>
  44. </picker-view-column>
  45. </block>
  46. </picker-view>
  47. <!-- 三级联动 -->
  48. <picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue" @change="pickerChangeMul" v-if="mode==='multiLinkageSelector' && deepLength===3">
  49. <block>
  50. <picker-view-column>
  51. <view class="picker-item" v-for="(item,index) in pickerValueMulThreeOne" :key="index">{{item.label}}</view>
  52. </picker-view-column>
  53. <picker-view-column>
  54. <view class="picker-item" v-for="(item,index) in pickerValueMulThreeTwo" :key="index">{{item.label}}</view>
  55. </picker-view-column>
  56. <picker-view-column>
  57. <view class="picker-item" v-for="(item,index) in pickerValueMulThreeThree" :key="index">{{item.label}}</view>
  58. </picker-view-column>
  59. </block>
  60. </picker-view>
  61. </view>
  62. </view>
  63. </template>
  64. <script>
  65. export default {
  66. data() {
  67. return {
  68. pickerChangeValue: [],
  69. pickerValue: [],
  70. pickerValueArrayChange: true,
  71. modeChange: false,
  72. pickerValueSingleArray: [],
  73. pickerValueHour: [],
  74. pickerValueMinute: [],
  75. pickerValueMulArray: [],
  76. pickerValueMulTwoOne: [],
  77. pickerValueMulTwoTwo: [],
  78. pickerValueMulThreeOne: [],
  79. pickerValueMulThreeTwo: [],
  80. pickerValueMulThreeThree: [],
  81. /* 是否显示控件 */
  82. showPicker: false,
  83. };
  84. },
  85. props: {
  86. /* mode */
  87. mode: {
  88. type: String,
  89. default: 'selector'
  90. },
  91. /* picker 数值 */
  92. pickerValueArray: {
  93. type: Array,
  94. default(){
  95. return []
  96. }
  97. },
  98. /* 默认值 */
  99. pickerValueDefault: {
  100. type: Array,
  101. default(){
  102. return []
  103. }
  104. },
  105. /* 几级联动 */
  106. deepLength: {
  107. type: Number,
  108. default: 2
  109. },
  110. /* 主题色 */
  111. themeColor: String
  112. },
  113. watch: {
  114. pickerValueArray(oldVal, newVal) {
  115. this.pickerValueArrayChange = true;
  116. },
  117. mode(oldVal, newVal) {
  118. this.modeChange = true;
  119. },
  120. pickerValueArray(val){
  121. this.initPicker(val);
  122. }
  123. },
  124. methods: {
  125. initPicker(valueArray) {
  126. let pickerValueArray = valueArray;
  127. this.pickerValue = this.pickerValueDefault;
  128. // 初始化多级联动
  129. if (this.mode === 'selector') {
  130. this.pickerValueSingleArray = valueArray;
  131. } else if (this.mode === 'timeSelector') {
  132. this.modeChange = false;
  133. let hourArray = [];
  134. let minuteArray = [];
  135. for (let i = 0; i < 24; i++) {
  136. hourArray.push({
  137. value: i,
  138. label: i > 9 ? `${i} 时` : `0${i} 时`
  139. });
  140. }
  141. for (let i = 0; i < 60; i++) {
  142. minuteArray.push({
  143. value: i,
  144. label: i > 9 ? `${i} 分` : `0${i} 分`
  145. });
  146. }
  147. this.pickerValueHour = hourArray;
  148. this.pickerValueMinute = minuteArray;
  149. } else if (this.mode === 'multiSelector') {
  150. this.pickerValueMulArray = valueArray;
  151. } else if (this.mode === 'multiLinkageSelector' && this.deepLength === 2) {
  152. // 两级联动
  153. let pickerValueMulTwoOne = [];
  154. let pickerValueMulTwoTwo = [];
  155. // 第一列
  156. for (let i = 0, length = pickerValueArray.length; i < length; i++) {
  157. pickerValueMulTwoOne.push(pickerValueArray[i]);
  158. }
  159. // 渲染第二列
  160. // 如果有设定的默认值
  161. if (this.pickerValueDefault.length === 2) {
  162. let num = this.pickerValueDefault[0];
  163. for (
  164. let i = 0, length = pickerValueArray[num].children.length; i < length; i++
  165. ) {
  166. pickerValueMulTwoTwo.push(pickerValueArray[num].children[i]);
  167. }
  168. } else {
  169. for (
  170. let i = 0, length = pickerValueArray[0].children.length; i < length; i++
  171. ) {
  172. pickerValueMulTwoTwo.push(pickerValueArray[0].children[i]);
  173. }
  174. }
  175. this.pickerValueMulTwoOne = pickerValueMulTwoOne;
  176. this.pickerValueMulTwoTwo = pickerValueMulTwoTwo;
  177. } else if (
  178. this.mode === 'multiLinkageSelector' &&
  179. this.deepLength === 3
  180. ) {
  181. let pickerValueMulThreeOne = [];
  182. let pickerValueMulThreeTwo = [];
  183. let pickerValueMulThreeThree = [];
  184. // 第一列
  185. for (let i = 0, length = pickerValueArray.length; i < length; i++) {
  186. pickerValueMulThreeOne.push(pickerValueArray[i]);
  187. }
  188. // 渲染第二列
  189. this.pickerValueDefault =
  190. this.pickerValueDefault.length === 3 ?
  191. this.pickerValueDefault :
  192. [0, 0, 0];
  193. if (this.pickerValueDefault.length === 3) {
  194. let num = this.pickerValueDefault[0];
  195. for (
  196. let i = 0, length = pickerValueArray[num].children.length; i < length; i++
  197. ) {
  198. pickerValueMulThreeTwo.push(pickerValueArray[num].children[i]);
  199. }
  200. // 第三列
  201. let numSecond = this.pickerValueDefault[1];
  202. for (let i = 0, length = pickerValueArray[num].children[numSecond].children.length; i < length; i++) {
  203. pickerValueMulThreeThree.push(
  204. pickerValueArray[num].children[numSecond].children[i]
  205. );
  206. }
  207. }
  208. this.pickerValueMulThreeOne = pickerValueMulThreeOne;
  209. this.pickerValueMulThreeTwo = pickerValueMulThreeTwo;
  210. this.pickerValueMulThreeThree = pickerValueMulThreeThree;
  211. }
  212. },
  213. show() {
  214. setTimeout(() => {
  215. if (this.pickerValueArrayChange || this.modeChange) {
  216. this.initPicker(this.pickerValueArray);
  217. this.showPicker = true;
  218. this.pickerValueArrayChange = false;
  219. this.modeChange = false;
  220. } else {
  221. this.showPicker = true;
  222. }
  223. }, 0);
  224. },
  225. maskClick() {
  226. this.pickerCancel();
  227. },
  228. pickerCancel() {
  229. this.showPicker = false;
  230. this._initPickerVale();
  231. let pickObj = {
  232. index: this.pickerValue,
  233. value: this._getPickerLabelAndValue(this.pickerValue, this.mode).value,
  234. label: this._getPickerLabelAndValue(this.pickerValue, this.mode).label
  235. };
  236. this.$emit('onCancel', pickObj);
  237. },
  238. pickerConfirm(e) {
  239. this.showPicker = false;
  240. this._initPickerVale();
  241. let pickObj = {
  242. index: this.pickerValue,
  243. value: this._getPickerLabelAndValue(this.pickerValue, this.mode).value,
  244. label: this._getPickerLabelAndValue(this.pickerValue, this.mode).label
  245. };
  246. this.$emit('onConfirm', pickObj);
  247. },
  248. showPickerView() {
  249. this.showPicker = true;
  250. },
  251. pickerChange(e) {
  252. this.pickerValue = e.mp.detail.value;
  253. let pickObj = {
  254. index: this.pickerValue,
  255. value: this._getPickerLabelAndValue(this.pickerValue, this.mode).value,
  256. label: this._getPickerLabelAndValue(this.pickerValue, this.mode).label
  257. };
  258. this.$emit('onChange', pickObj);
  259. },
  260. pickerChangeMul(e) {
  261. if (this.deepLength === 2) {
  262. let pickerValueArray = this.pickerValueArray;
  263. let changeValue = e.mp.detail.value;
  264. // 处理第一列滚动
  265. if (changeValue[0] !== this.pickerValue[0]) {
  266. let pickerValueMulTwoTwo = [];
  267. // 第一列滚动第二列数据更新
  268. for (let i = 0, length = pickerValueArray[changeValue[0]].children.length; i < length; i++) {
  269. pickerValueMulTwoTwo.push(pickerValueArray[changeValue[0]].children[i]);
  270. }
  271. this.pickerValueMulTwoTwo = pickerValueMulTwoTwo;
  272. // 第二列初始化为 0
  273. changeValue[1] = 0;
  274. }
  275. this.pickerValue = changeValue;
  276. } else if (this.deepLength === 3) {
  277. let pickerValueArray = this.pickerValueArray;
  278. let changeValue = e.mp.detail.value;
  279. let pickerValueMulThreeTwo = [];
  280. let pickerValueMulThreeThree = [];
  281. // 重新渲染第二列
  282. // 如果是第一列滚动
  283. if (changeValue[0] !== this.pickerValue[0]) {
  284. this.pickerValueMulThreeTwo = [];
  285. for (let i = 0, length = pickerValueArray[changeValue[0]].children.length; i < length; i++) {
  286. pickerValueMulThreeTwo.push(pickerValueArray[changeValue[0]].children[i]);
  287. }
  288. // 重新渲染第三列
  289. for (let i = 0, length = pickerValueArray[changeValue[0]].children[0].children.length; i <
  290. length; i++) {
  291. pickerValueMulThreeThree.push(pickerValueArray[changeValue[0]].children[0].children[i]);
  292. }
  293. changeValue[1] = 0;
  294. changeValue[2] = 0;
  295. this.pickerValueMulThreeTwo = pickerValueMulThreeTwo;
  296. this.pickerValueMulThreeThree = pickerValueMulThreeThree;
  297. } else if (changeValue[1] !== this.pickerValue[1]) {
  298. // 第二列滚动
  299. // 重新渲染第三列
  300. this.pickerValueMulThreeThree = [];
  301. pickerValueMulThreeTwo = this.pickerValueMulThreeTwo;
  302. for (let i = 0, length = pickerValueArray[changeValue[0]].children[changeValue[1]].children.length; i <
  303. length; i++) {
  304. pickerValueMulThreeThree.push(pickerValueArray[changeValue[0]].children[changeValue[1]].children[
  305. i]);
  306. }
  307. changeValue[2] = 0;
  308. this.pickerValueMulThreeThree = pickerValueMulThreeThree;
  309. }
  310. this.pickerValue = changeValue;
  311. }
  312. let pickObj = {
  313. index: this.pickerValue,
  314. value: this._getPickerLabelAndValue(this.pickerValue, this.mode).value,
  315. label: this._getPickerLabelAndValue(this.pickerValue, this.mode).label
  316. };
  317. this.$emit('onChange', pickObj);
  318. },
  319. // 获取 pxikerLabel
  320. _getPickerLabelAndValue(value, mode) {
  321. let pickerLable;
  322. let pickerGetValue = [];
  323. // selector
  324. if (mode === 'selector') {
  325. pickerLable = this.pickerValueSingleArray[value].label;
  326. pickerGetValue.push(this.pickerValueSingleArray[value].value);
  327. } else if (mode === 'timeSelector') {
  328. pickerLable = `${this.pickerValueHour[value[0]].label}-${this.pickerValueMinute[value[1]].label}`;
  329. pickerGetValue.push(this.pickerValueHour[value[0]].value);
  330. pickerGetValue.push(this.pickerValueHour[value[1]].value);
  331. } else if (mode === 'multiSelector') {
  332. for (let i = 0; i < value.length; i++) {
  333. if (i > 0) {
  334. pickerLable += this.pickerValueMulArray[i][value[i]].label + (i === value.length - 1 ? '' :
  335. '-');
  336. } else {
  337. pickerLable = this.pickerValueMulArray[i][value[i]].label + '-';
  338. }
  339. pickerGetValue.push(this.pickerValueMulArray[i][value[i]].value);
  340. }
  341. } else if (mode === 'multiLinkageSelector') {
  342. /* eslint-disable indent */
  343. pickerLable =
  344. this.deepLength === 2 ?
  345. `${this.pickerValueMulTwoOne[value[0]].label}-${this.pickerValueMulTwoTwo[value[1]].label}` :
  346. `${this.pickerValueMulThreeOne[value[0]].label}-${this.pickerValueMulThreeTwo[value[1]].label}-${this.pickerValueMulThreeThree[value[2]].label}`;
  347. if (this.deepLength === 2) {
  348. pickerGetValue.push(this.pickerValueMulTwoOne[value[0]].value);
  349. pickerGetValue.push(this.pickerValueMulTwoTwo[value[1]].value);
  350. } else {
  351. pickerGetValue.push(this.pickerValueMulThreeOne[value[0]].value);
  352. pickerGetValue.push(this.pickerValueMulThreeTwo[value[1]].value);
  353. pickerGetValue.push(this.pickerValueMulThreeThree[value[2]].value);
  354. }
  355. /* eslint-enable indent */
  356. }
  357. return {
  358. label: pickerLable,
  359. value: pickerGetValue
  360. };
  361. },
  362. // 初始化 pickerValue 默认值
  363. _initPickerVale() {
  364. if (this.pickerValue.length === 0) {
  365. if (this.mode === 'selector') {
  366. this.pickerValue = [0];
  367. } else if (this.mode === 'multiSelector') {
  368. this.pickerValue = new Int8Array(this.pickerValueArray.length);
  369. } else if (
  370. this.mode === 'multiLinkageSelector' &&
  371. this.deepLength === 2
  372. ) {
  373. this.pickerValue = [0, 0];
  374. } else if (
  375. this.mode === 'multiLinkageSelector' &&
  376. this.deepLength === 3
  377. ) {
  378. this.pickerValue = [0, 0, 0];
  379. }
  380. }
  381. }
  382. }
  383. };
  384. </script>
  385. <style>
  386. .pickerMask {
  387. position: fixed;
  388. z-index: 1000;
  389. top: 0;
  390. right: 0;
  391. left: 0;
  392. bottom: 0;
  393. background: rgba(0, 0, 0, 0.6);
  394. }
  395. .mpvue-picker-content {
  396. position: fixed;
  397. bottom: 0;
  398. left: 0;
  399. width: 100%;
  400. transition: all 0.3s ease;
  401. transform: translateY(100%);
  402. z-index: 3000;
  403. }
  404. .mpvue-picker-view-show {
  405. transform: translateY(0);
  406. }
  407. .mpvue-picker__hd {
  408. display: flex;
  409. padding: 9px 15px;
  410. background-color: #fff;
  411. position: relative;
  412. text-align: center;
  413. font-size: 17px;
  414. }
  415. .mpvue-picker__hd:after {
  416. content: ' ';
  417. position: absolute;
  418. left: 0;
  419. bottom: 0;
  420. right: 0;
  421. height: 1px;
  422. border-bottom: 1px solid #e5e5e5;
  423. color: #e5e5e5;
  424. transform-origin: 0 100%;
  425. transform: scaleY(0.5);
  426. }
  427. .mpvue-picker__action {
  428. display: block;
  429. flex: 1;
  430. color: #1aad19;
  431. }
  432. .mpvue-picker__action:first-child {
  433. text-align: left;
  434. color: #888;
  435. }
  436. .mpvue-picker__action:last-child {
  437. text-align: right;
  438. }
  439. .picker-item {
  440. text-align: center;
  441. line-height: 40px;
  442. font-size: 16px;
  443. }
  444. .mpvue-picker-view {
  445. position: relative;
  446. bottom: 0;
  447. left: 0;
  448. width: 100%;
  449. height: 238px;
  450. background-color: rgba(255, 255, 255, 1);
  451. }
  452. </style>