lfj-dropdown-box.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  1. <template>
  2. <view class="uni-stat__select" :class="{ 'uni-stat__select_disabled': disabled }">
  3. <view class="uni-stat-box">
  4. <view class="uni-select">
  5. <view class="uni-select__input-box" :style="{ height: multiple ? '100%' : '25px' }" @click="toggleSelector">
  6. <!-- 多选不搜索 -->
  7. <view class="" style="display: flex; flex-wrap: wrap; width: 100%" v-if="multiple && current.length > 0">
  8. <view class="tag-calss" v-for="(item, index) in collapseTags ? current.slice(0, collapseTagsNum) : current" :key="item[map.value]">
  9. <span class="text">{{ item[map.text] }}</span>
  10. <view class="" @click.stop="delItem(item)">
  11. <uni-icons type="clear" style="margin-left: 4px" color="#c0c4cc" />
  12. </view>
  13. </view>
  14. <view v-if="current.length > collapseTagsNum && collapseTags" class="tag-calss">
  15. <span class="text">+{{ current.length - collapseTagsNum }}</span>
  16. </view>
  17. <input
  18. v-if="filterable && !disabled"
  19. @input="inputChange"
  20. class="uni-select__input-text"
  21. type="text"
  22. style="font-size: 12px; height: 52rpx; margin-left: 6px; width: auto"
  23. confirm-type="search"
  24. placeholder="请输入"
  25. @confirm="confirm"
  26. v-model="filterInput"
  27. />
  28. </view>
  29. <view v-else-if="current && current.length > 0 && !showSelector" class="uni-select__input-text">
  30. {{ current }}
  31. </view>
  32. <input
  33. v-else-if="filterable"
  34. :focus="isFocus"
  35. @input="inputChange"
  36. :disabled="disabled"
  37. confirm-type="search"
  38. @confirm="confirm"
  39. class="uni-select__input-text"
  40. type="text"
  41. style="font-size: 12px; position: absolute; z-index: 1"
  42. :placeholder="placeholderOld"
  43. v-model="filterInput"
  44. />
  45. <view v-else class="uni-select__input-text uni-select__input-placeholder">{{ placeholderOld }}</view>
  46. <uni-icons
  47. v-if="(current.length > 0 && clear && !disabled) || (currentArr.length > 0 && clear && !disabled)"
  48. type="clear"
  49. color="#c0c4cc"
  50. size="24"
  51. style="position: absolute; right: 0"
  52. @click="clearVal"
  53. />
  54. <uni-icons
  55. style="right: 0; position: absolute; top: 50%; transform: translate(0, -50%)"
  56. v-else
  57. :type="showSelector ? 'top' : 'bottom'"
  58. size="14"
  59. color="#999"
  60. />
  61. </view>
  62. </view>
  63. </view>
  64. <view class="uni-select--mask" v-if="showSelector" @click="toggleSelector" />
  65. <view class="uni-select__selector" :class="isDown ? 'uni-select__selector__down' : 'uni-select__selector__upwards'" v-if="showSelector">
  66. <view class="uni-popper__arrow"></view>
  67. <view class="popup__selector-scroll">
  68. <view class="popup-scroll-view">
  69. <scroll-view scroll-y="true" class="uni-select__selector-scroll" @scrolltolower="scrolltolower">
  70. <view class="uni-select__selector-empty" style="margin: auto" v-if="filterMixinDatacomResData.length === 0">
  71. <span style="display: inline-block; width: 100%; text-align: center">{{ emptyTips }}</span>
  72. </view>
  73. <view
  74. v-else
  75. :style="{ fontWeight: multiple && currentArr.includes(item[map.value]) ? 'bold' : '' }"
  76. class="scroll_item"
  77. :class="{ scroll_item_disable: item.disable }"
  78. v-for="(item, index) in filterMixinDatacomResData"
  79. :key="index"
  80. @click="change(item)"
  81. >
  82. <span class="scroll_item_text" :style="{ color: multiple && currentArr.includes(item[map.value]) ? '#007aff' : '' }">{{ formatItemName(item) }}</span>
  83. <view class="scroll_item_right">
  84. <span v-if="rightTextShow" :style="{ color: multiple && currentArr.includes(item[map.value]) ? 'rgb(204, 204, 204)' : '' }">
  85. {{ formatItemRightName(item) }}
  86. </span>
  87. <!-- <uni-icons type="checkmarkempty" color="#007aff" /> -->
  88. <uni-icons v-if="multiple && currentArr.includes(item[map.value])" type="checkmarkempty" color="#007aff" />
  89. </view>
  90. </view>
  91. <!-- <uni-load-more v-if="filterMixinDatacomResData.length !== 0 && dropDownLoading" :status="loadStatus"></uni-load-more> -->
  92. <view class="loading_box" v-if="filterMixinDatacomResData.length !== 0 && dropDownLoading">
  93. <view class="wave-loading" v-if="loadStatus == 'loading'">
  94. <span style="--time: 1">l</span>
  95. <span style="--time: 2">o</span>
  96. <span style="--time: 3">a</span>
  97. <span style="--time: 4">d</span>
  98. <span style="--time: 5">i</span>
  99. <span style="--time: 6">n</span>
  100. <span style="--time: 7">g</span>
  101. <span style="--time: 8">.</span>
  102. <span style="--time: 9">.</span>
  103. <span style="--time: 10">.</span>
  104. </view>
  105. <span v-else-if="loadStatus == 'more'">下拉加载更多</span>
  106. <span v-else style="color: #999">无更多数据了</span>
  107. </view>
  108. </scroll-view>
  109. </view>
  110. </view>
  111. </view>
  112. </view>
  113. </template>
  114. <script>
  115. /**
  116. * DataChecklist 数据选择器
  117. * @description 通过数据渲染的下拉框组件
  118. * @tutorial https://uniapp.dcloud.io/component/uniui/uni-data-select
  119. * @property {String} collapseTagsNum 多选时选中值按文字的形式展示的数量
  120. * @property {String} collapseTags 多选时是否将选中值按文字的形式展示
  121. * @property {String} rightSideText 作为 value 唯一标识的键名
  122. * @property {Array} multiple 是否多选
  123. * @property {Array} filterable 是否开启搜索
  124. * @property {Array} localdata 本地数据 ,格式 [{text:'',value:''}]
  125. * @property {Array} map 本地数据 ,格式 {text: 'text', value: 'value', rightText: 'rightText', disable: 'disable'}
  126. * @property {Boolean} clear 是否可以清空已选项
  127. * @property {Boolean} emptyText 没有数据时显示的文字 ,本地数据无效
  128. * @property {String} placeholder 输入框的提示文字
  129. * @property {Boolean} disabled 是否禁用
  130. * @property {Boolean} dropDownLoading 是否开启下拉加载
  131. * @property {Boolean} rightTextShow 是否显示右侧文字
  132. * @property {String} loadStatus 加载更多状态
  133. * @event {Function} change 选中发生变化触发
  134. * @event {Function} lower 触底事件
  135. */
  136. export default {
  137. name: 'lfj-uni-data-select',
  138. props: {
  139. // #ifndef VUE3
  140. value: {
  141. type: [String, Number, Array],
  142. default: ''
  143. },
  144. // #endif
  145. // #ifdef VUE3
  146. modelValue: {
  147. type: [String, Number, Array],
  148. default: ''
  149. },
  150. // #endif
  151. dropDownLoading: {
  152. type: Boolean,
  153. default: false
  154. },
  155. localdata: {
  156. type: Array,
  157. default() {
  158. return [];
  159. }
  160. },
  161. emptyTips: {
  162. type: String,
  163. default: '无选项'
  164. },
  165. placeholder: {
  166. type: String,
  167. default: '请选择'
  168. },
  169. collapseTagsNum: {
  170. type: Number,
  171. default: 1
  172. },
  173. collapseTags: {
  174. type: Boolean,
  175. default: false
  176. },
  177. disabled: {
  178. type: Boolean,
  179. default: false
  180. },
  181. clear: {
  182. type: Boolean,
  183. default: true
  184. },
  185. filterable: {
  186. type: Boolean,
  187. default: false
  188. },
  189. multiple: {
  190. type: Boolean,
  191. default: false
  192. },
  193. rightTextShow: {
  194. type: Boolean,
  195. default: false
  196. },
  197. map: {
  198. type: Object,
  199. default() {
  200. return { text: 'text', value: 'value', rightText: 'rightText', disabled: 'disabled' };
  201. }
  202. },
  203. loadStatus: {
  204. type: String,
  205. default: 'more'
  206. },
  207. // 格式化输出 用法 field="_id as value, version as text, uni_platform as label" format="{label} - {text}"
  208. format: {
  209. type: String,
  210. default: ''
  211. }
  212. },
  213. data() {
  214. return {
  215. windowHeight: 0,
  216. showSelector: false,
  217. mixinDatacomResData: [],
  218. isFocus: false,
  219. placeholderOld: '',
  220. filterInput: '',
  221. // 单选
  222. current: [],
  223. // 多选数据
  224. currentArr: [],
  225. isDown: true //下拉框是否朝下
  226. };
  227. },
  228. watch: {
  229. localdata: {
  230. immediate: true,
  231. handler(val, old) {
  232. if (Array.isArray(val) && old !== val) {
  233. console.log('新数据');
  234. this.mixinDatacomResData = val || [];
  235. }
  236. }
  237. },
  238. valueCom: {
  239. handler(newVal, oldVal) {
  240. this.initDefVal();
  241. },
  242. deep: true,
  243. immediate: true
  244. },
  245. mixinDatacomResData: {
  246. immediate: true,
  247. handler(val) {
  248. if (val.length) {
  249. this.initDefVal();
  250. }
  251. }
  252. }
  253. },
  254. created() {
  255. this.windowHeight = uni.getSystemInfoSync().windowHeight;
  256. this.placeholderOld = this.placeholder;
  257. if (this.multiple) {
  258. // #ifndef VUE3
  259. this.currentArr = this.value || [];
  260. // #endif
  261. // #ifdef VUE3
  262. this.currentArr = this.modelValue || [];
  263. // #endif
  264. if (this.current.length > 0) {
  265. this.current = [];
  266. }
  267. // #ifndef VUE3
  268. if (this.value && this.value.length > 0 && this.filterMixinDatacomResData.length > 0) {
  269. this.current = this.value.map((item) => {
  270. let current = this.mixinDatacomResData.find((e) => e[this.map.value] == item);
  271. return {
  272. ...current
  273. };
  274. });
  275. }
  276. // #endif
  277. // #ifdef VUE3
  278. if (this.modelValue && this.modelValue.length > 0 && this.filterMixinDatacomResData.length > 0) {
  279. this.current = this.modelValue.map((item) => {
  280. let current = this.mixinDatacomResData.find((e) => e[this.map.value] == item);
  281. return {
  282. ...current
  283. };
  284. });
  285. }
  286. // #endif
  287. } else {
  288. // #ifndef VUE3
  289. if (this.value || this.value == 0) {
  290. this.current = this.formatItemName(this.filterMixinDatacomResData.find((e) => e[this.map.value] == this.value));
  291. }
  292. // #endif
  293. // #ifdef VUE3
  294. if (this.modelValue || this.value == 0) {
  295. this.current = this.formatItemName(this.filterMixinDatacomResData.find((e) => e[this.map.value] == this.modelValue));
  296. }
  297. // #endif
  298. }
  299. this.debounceGet = this.debounce(() => {
  300. this.query();
  301. }, 300);
  302. if (this.collection && !this.localdata.length) {
  303. this.debounceGet();
  304. }
  305. },
  306. computed: {
  307. filterMixinDatacomResData() {
  308. if (this.filterable && this.filterInput) {
  309. return this.mixinDatacomResData.filter((e) => e[this.map.text].includes(this.filterInput));
  310. } else {
  311. return this.mixinDatacomResData;
  312. }
  313. },
  314. typePlaceholder() {
  315. const text = {
  316. 'opendb-stat-app-versions': '版本',
  317. 'opendb-app-channels': '渠道',
  318. 'opendb-app-list': '应用'
  319. };
  320. const common = this.placeholder;
  321. const placeholder = text[this.collection];
  322. return placeholder ? common + placeholder : common;
  323. },
  324. valueCom() {
  325. // #ifdef VUE3
  326. return this.modelValue;
  327. // #endif
  328. // #ifndef VUE3
  329. return this.value;
  330. // #endif
  331. }
  332. },
  333. methods: {
  334. getIsDown() {
  335. const query = uni.createSelectorQuery().in(this);
  336. const _this = this;
  337. query
  338. .select('.uni-stat-box')
  339. .boundingClientRect((data) => {
  340. if (_this.windowHeight - data.top - data.height > 220) {
  341. _this.isDown = true;
  342. } else {
  343. _this.isDown = false;
  344. }
  345. })
  346. .exec();
  347. },
  348. // 执行数据库查询
  349. query() {
  350. this.mixinDatacomEasyGet();
  351. },
  352. // 监听查询条件变更事件
  353. onMixinDatacomPropsChange() {
  354. if (this.collection) {
  355. this.debounceGet();
  356. }
  357. },
  358. debounce(fn, time = 100) {
  359. let timer = null;
  360. return function (...args) {
  361. if (timer) clearTimeout(timer);
  362. timer = setTimeout(() => {
  363. fn.apply(this, args);
  364. }, time);
  365. };
  366. },
  367. confirm(e) {
  368. this.$emit('confirm', e);
  369. },
  370. toggleSelector() {
  371. if (this.disabled) {
  372. return;
  373. }
  374. this.getIsDown();
  375. this.showSelector = !this.showSelector;
  376. this.isFocus = this.showSelector;
  377. if (this.filterable && this.current && this.showSelector) {
  378. if (!this.multiple) {
  379. this.placeholderOld = this.current;
  380. // this.filterInput = ""
  381. }
  382. } else if (this.filterable && !this.current && !this.showSelector) {
  383. if (this.placeholderOld != this.placeholder) {
  384. if (!this.multiple) {
  385. this.current = this.placeholderOld;
  386. }
  387. }
  388. }
  389. this.filterInput = '';
  390. },
  391. initDefVal() {
  392. let defValue = '';
  393. if ((this.valueCom || this.valueCom === 0) && !this.isDisabled(this.valueCom)) {
  394. defValue = this.valueCom;
  395. } else {
  396. let strogeValue;
  397. if (this.collection) {
  398. strogeValue = this.getCache();
  399. }
  400. if (strogeValue || strogeValue === 0) {
  401. defValue = strogeValue;
  402. } else {
  403. let defItem = '';
  404. if (this.defItem > 0 && this.defItem <= this.mixinDatacomResData.length) {
  405. defItem = this.mixinDatacomResData[this.defItem - 1][this.dataValue];
  406. }
  407. defValue = defItem;
  408. }
  409. if (defValue || defValue === 0) {
  410. this.emit(defValue);
  411. }
  412. }
  413. if (this.multiple) {
  414. const mixinDatacomResData = this.mixinDatacomResData || [];
  415. if (!defValue) defValue = [];
  416. this.current = defValue.map((item) => {
  417. const current = mixinDatacomResData.find((e) => {
  418. return e[this.map.value] == item;
  419. });
  420. return {
  421. ...current
  422. };
  423. });
  424. this.currentArr = this.current.map((e) => e[this.map.value]);
  425. if (defValue.length < 1) {
  426. this.currentArr = [];
  427. }
  428. } else {
  429. const def = this.mixinDatacomResData.find((item) => item[this.map.value] === defValue);
  430. this.current = def ? this.formatItemName(def) : '';
  431. }
  432. },
  433. /**
  434. * @param {[String, Number]} value
  435. * 判断用户给的 value 是否同时为禁用状态
  436. */
  437. isDisabled(value) {
  438. let isDisabled = false;
  439. this.mixinDatacomResData.forEach((item) => {
  440. if (item[this.dataValue] === value) {
  441. isDisabled = item.disable;
  442. }
  443. });
  444. return isDisabled;
  445. },
  446. inputChange(e) {
  447. this.$emit('inputChange', e.detail.value);
  448. },
  449. scrolltolower(e) {
  450. if (e) {
  451. this.$emit('lower', this.scrolltolower());
  452. }
  453. },
  454. delItem(item) {
  455. if (this.disabled) {
  456. return;
  457. }
  458. if (this.currentArr.includes(item[this.map.value])) {
  459. let index = this.current.findIndex((e) => {
  460. return e[this.map.value] == item[this.map.value];
  461. });
  462. this.current.splice(index, 1);
  463. this.currentArr.splice(index, 1);
  464. this.emit(this.current);
  465. }
  466. },
  467. clearVal() {
  468. if (this.disabled) {
  469. return;
  470. }
  471. if (this.multiple) {
  472. this.current = [];
  473. this.currentArr = [];
  474. this.emit([]);
  475. } else {
  476. this.current = '';
  477. this.currentArr = [];
  478. this.emit('');
  479. }
  480. if (this.collection) {
  481. this.removeCache();
  482. }
  483. this.placeholderOld = this.placeholder;
  484. this.filterInput = '';
  485. },
  486. change(item) {
  487. // 是否禁用
  488. if (!item.disabled) {
  489. // 是否多选
  490. if (this.multiple) {
  491. if (!this.current) {
  492. this.current = [];
  493. }
  494. if (!this.currentArr) {
  495. this.currentArr = [];
  496. }
  497. if (this.currentArr.includes(item[this.map.value])) {
  498. let index = this.current.findIndex((e) => {
  499. return e[this.map.value] == item[this.map.value];
  500. });
  501. this.current.splice(index, 1);
  502. this.currentArr.splice(index, 1);
  503. this.emit(this.current);
  504. } else {
  505. this.current.push(item);
  506. this.currentArr.push(item[this.map.value]);
  507. this.emit(this.current);
  508. }
  509. this.filterInput = '';
  510. } else {
  511. // 单选
  512. this.showSelector = false;
  513. this.current = this.formatItemName(item);
  514. if (this.filterable) {
  515. this.filterInput = item[this.map.text];
  516. }
  517. this.emit(item[this.map.value]);
  518. }
  519. }
  520. },
  521. emit(val) {
  522. // 是否多选
  523. if (this.multiple) {
  524. this.$emit('input', this.currentArr);
  525. this.$emit('update:modelValue', this.currentArr);
  526. const currentArr = this.mixinDatacomResData.filter((item) => this.currentArr.includes(item[this.map.value]));
  527. // console.log(currentArr, '多选数据');
  528. this.$emit('change', currentArr);
  529. } else {
  530. this.$emit('input', val);
  531. this.$emit('update:modelValue', val);
  532. const current = this.mixinDatacomResData.find((item) => val == item[this.map.value]);
  533. // console.log(current, '单选数据');
  534. this.$emit('change', current);
  535. }
  536. if (this.collection) {
  537. this.setCache(val);
  538. }
  539. },
  540. formatItemRightName(item) {
  541. if (!item) {
  542. return ' ';
  543. }
  544. let text = item[this.map.rightText];
  545. let value = item[this.map.value];
  546. let { channel_code } = item;
  547. channel_code = channel_code ? `(${channel_code})` : '';
  548. if (this.format) {
  549. // 格式化输出
  550. let str = '';
  551. str = this.format;
  552. for (let key in item) {
  553. str = str.replace(new RegExp(`{${key}}`, 'g'), item[key]);
  554. }
  555. return str;
  556. } else {
  557. return text ? text : `${channel_code}`;
  558. }
  559. },
  560. formatItemName(item) {
  561. if (!item) {
  562. return '';
  563. }
  564. let text = item[this.map.text];
  565. let value = item[this.map.value];
  566. let { channel_code } = item;
  567. channel_code = channel_code ? `(${channel_code})` : '';
  568. if (this.format) {
  569. // 格式化输出
  570. let str = '';
  571. str = this.format;
  572. for (let key in item) {
  573. str = str.replace(new RegExp(`{${key}}`, 'g'), item[key]);
  574. }
  575. return str;
  576. } else {
  577. return text ? text : `未命名${channel_code}`;
  578. }
  579. },
  580. // 获取当前加载的数据
  581. getLoadData() {
  582. return this.mixinDatacomResData;
  583. },
  584. // 获取当前缓存key
  585. getCurrentCacheKey() {
  586. return this.collection;
  587. },
  588. selClick() {
  589. this.showSelector = !this.showSelector;
  590. }
  591. }
  592. };
  593. </script>
  594. <style lang="scss" scoped>
  595. $uni-box-shadow: 0 1rpx 8rpx 1rpx rgba(32, 34, 36, 0.2);
  596. $uni-base-color: #6a6a6a !default;
  597. $uni-main-color: #333 !default;
  598. $uni-secondary-color: #909399 !default;
  599. $uni-border-3: #e5e5e5;
  600. .uni-stat__select_disabled {
  601. background-color: #f5f7fa;
  602. cursor: not-allowed;
  603. }
  604. .uni-stat__select {
  605. position: relative;
  606. .uni-stat-box {
  607. border: 1px solid rgb(229, 229, 229);
  608. border-radius: 4px;
  609. padding: 10rpx;
  610. min-height: 25px;
  611. display: flex;
  612. align-items: center;
  613. background-color: transparent;
  614. .uni-select {
  615. width: 100%;
  616. height: 100%;
  617. display: flex;
  618. align-items: center;
  619. font-size: 12px;
  620. position: relative;
  621. .uni-select__input-text {
  622. // width: 280px;
  623. width: 90%;
  624. color: $uni-main-color;
  625. white-space: nowrap;
  626. text-overflow: ellipsis;
  627. -o-text-overflow: ellipsis;
  628. overflow: hidden;
  629. }
  630. .uni-select__input-box {
  631. width: 100%;
  632. height: 100%;
  633. position: relative;
  634. /* #ifndef APP-NVUE */
  635. display: flex;
  636. /* #endif */
  637. flex: 1;
  638. flex-direction: row;
  639. align-items: center;
  640. .tag-calss {
  641. font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif;
  642. font-weight: 400;
  643. -webkit-font-smoothing: antialiased;
  644. -webkit-tap-highlight-color: transparent;
  645. font-size: 12px;
  646. border: 1px solid #d9ecff;
  647. border-radius: 4px;
  648. white-space: nowrap;
  649. height: 24px;
  650. padding: 0 4px 0px 8px;
  651. line-height: 22px;
  652. box-sizing: border-box;
  653. margin: 2px 0 2px 6px;
  654. display: flex;
  655. max-width: 100%;
  656. align-items: center;
  657. background-color: #f4f4f5;
  658. border-color: #e9e9eb;
  659. color: #909399;
  660. .text {
  661. font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif;
  662. font-weight: 400;
  663. -webkit-font-smoothing: antialiased;
  664. -webkit-tap-highlight-color: transparent;
  665. font-size: 12px;
  666. white-space: nowrap;
  667. line-height: 22px;
  668. color: #909399;
  669. overflow: hidden;
  670. text-overflow: ellipsis;
  671. }
  672. }
  673. .uni-select__input-placeholder {
  674. color: $uni-base-color;
  675. font-size: 12px;
  676. }
  677. }
  678. }
  679. }
  680. .uni-select__selector {
  681. /* #ifndef APP-NVUE */
  682. box-sizing: border-box;
  683. /* #endif */
  684. position: absolute;
  685. left: 0;
  686. width: 100%;
  687. border-radius: 6px;
  688. z-index: 3;
  689. .popup__selector-scroll {
  690. width: 100%;
  691. // height: 200px;
  692. display: block;
  693. max-height: 208px;
  694. background-color: #ffffff;
  695. box-shadow: $uni-box-shadow;
  696. box-sizing: border-box;
  697. border-radius: 6px;
  698. overflow: hidden;
  699. padding: 4px 0;
  700. .popup-scroll-view {
  701. width: 100%;
  702. .uni-select__selector-scroll {
  703. /* #ifndef APP-NVUE */
  704. max-height: 200px;
  705. box-sizing: border-box;
  706. /* #endif */
  707. }
  708. .scroll_item_disable {
  709. opacity: 0.3;
  710. pointer-events: none;
  711. }
  712. .scroll_item {
  713. padding: 0px 10px;
  714. line-height: 35px;
  715. font-size: 14px;
  716. text-align: center;
  717. display: flex;
  718. justify-content: space-between;
  719. align-items: center;
  720. &:hover {
  721. background-color: #f9f9f9;
  722. }
  723. .scroll_item_right {
  724. color: #ccc;
  725. }
  726. .scroll_item_text {
  727. display: inline-block;
  728. max-width: 50%;
  729. white-space: nowrap;
  730. overflow: hidden;
  731. text-overflow: ellipsis;
  732. }
  733. }
  734. }
  735. }
  736. }
  737. }
  738. .uni-select__selector__down {
  739. top: calc(100% + 12px);
  740. .uni-popper__arrow {
  741. transform: rotateX(0deg);
  742. top: -6px;
  743. }
  744. }
  745. .uni-select__selector__upwards {
  746. bottom: calc(100% + 12px);
  747. .uni-popper__arrow {
  748. transform: rotateX(180deg);
  749. bottom: -6px;
  750. }
  751. }
  752. /* picker 弹出层通用的指示小三角 */
  753. .uni-popper__arrow,
  754. .uni-popper__arrow::after {
  755. position: absolute;
  756. display: block;
  757. width: 0;
  758. height: 0;
  759. border-color: transparent;
  760. border-style: solid;
  761. border-width: 6px;
  762. }
  763. .uni-popper__arrow {
  764. filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
  765. left: 10%;
  766. margin-right: 3px;
  767. border-top-width: 0;
  768. border-bottom-color: #ebeef5;
  769. }
  770. .uni-popper__arrow::after {
  771. content: ' ';
  772. top: 1px;
  773. margin-left: -6px;
  774. border-top-width: 0;
  775. border-bottom-color: #fff;
  776. }
  777. // .uni-select__selector {
  778. // /* #ifndef APP-NVUE */
  779. // box-sizing: border-box;
  780. // /* #endif */
  781. // position: absolute;
  782. // left: 0;
  783. // width: 100%;
  784. // background-color: #ffffff;
  785. // border: 1px solid #ebeef5;
  786. // border-radius: 6px;
  787. // box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  788. // z-index: 3;
  789. // padding: 4px 0;
  790. // }
  791. .loading_box {
  792. display: flex;
  793. justify-content: center;
  794. padding: 20rpx 0;
  795. color: #999;
  796. .wave-loading {
  797. span {
  798. display: inline-block;
  799. font-size: 30rpx;
  800. font-weight: bold;
  801. font-family: 'Courier New', Courier, monospace;
  802. animation: wave-loading 1s ease-in-out infinite;
  803. animation-delay: calc(0.1s * var(--time));
  804. }
  805. }
  806. @keyframes wave-loading {
  807. 0% {
  808. transform: translateY(0rpx);
  809. }
  810. 25% {
  811. transform: translateY(-20rpx);
  812. }
  813. 50%,
  814. 100% {
  815. transform: translateY(0rpx);
  816. }
  817. }
  818. }
  819. .uni-select--mask {
  820. position: fixed;
  821. top: 0;
  822. bottom: 0;
  823. right: 0;
  824. left: 0;
  825. z-index: 2;
  826. }
  827. </style>