uni-data-select.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856
  1. <template>
  2. <view class="uni-stat__select">
  3. <span v-if="label" class="uni-label-text hide-on-phone">{{ label + ':' }}</span>
  4. <view class="uni-stat-box" :class="{ 'uni-stat__actived': current }">
  5. <view class="uni-select"
  6. :class="{ 'uni-select--disabled': disabled, 'uni-select--wrap': shouldWrap, 'border-default': mode == 'default', 'border-bottom': mode == 'underline' }">
  7. <view class="uni-select__input-box" @click="toggleSelector"
  8. :class="{ 'uni-select__input-box--wrap': shouldWrap }">
  9. <view v-if="slotSelected" class="slot-content padding-top-bottom"
  10. :class="{ 'uni-select__input-text--wrap': shouldWrap }">
  11. <slot name="selected" :selectedItems="getSelectedItems()"></slot>
  12. </view>
  13. <template v-else>
  14. <view v-if="textShow" class="uni-select__input-text"
  15. :class="{ 'uni-select__input-text--wrap': shouldWrap }">
  16. <view class="padding-top-bottom" :class="'align-' + align">{{ textShow }}</view>
  17. </view>
  18. <view v-else class="uni-select__input-text uni-select__input-placeholder"
  19. :class="'align-' + align">{{ typePlaceholder }}</view>
  20. </template>
  21. <view key="clear-button" v-if="!hideRight && shouldShowClear && clear && !disabled"
  22. @click.stop="clearVal">
  23. <uni-icons type="clear" color="#c0c4cc" size="24" />
  24. </view>
  25. <view key="arrow-button" v-else-if="!hideRight">
  26. <uni-icons :type="showSelector ? 'top' : 'bottom'" size="14" color="#999" />
  27. </view>
  28. </view>
  29. <view class="uni-select--mask" v-if="showSelector" @click="toggleSelector" />
  30. <view class="uni-select__selector" :style="getOffsetByPlacement" v-if="showSelector">
  31. <view :class="placement == 'bottom' ? 'uni-popper__arrow_bottom' : 'uni-popper__arrow_top'"></view>
  32. <scroll-view scroll-y="true" class="uni-select__selector-scroll">
  33. <template v-if="slotEmpty && mixinDatacomResData.length === 0">
  34. <view class="uni-select__selector-empty">
  35. <slot name="empty" :empty="emptyTips"></slot>
  36. </view>
  37. </template>
  38. <template v-else>
  39. <view v-if="mixinDatacomResData.length === 0" class="uni-select__selector-empty">
  40. <text>{{ emptyTips }}</text>
  41. </view>
  42. </template>
  43. <template v-if="slotOption">
  44. <view v-for="(itemData, index) in mixinDatacomResData" :key="index"
  45. @click="change(itemData)">
  46. <slot name="option" :item="itemData"
  47. :itemSelected="multiple ? getCurrentValues().includes(itemData.value) : getCurrentValues() == itemData.value">
  48. </slot>
  49. </view>
  50. </template>
  51. <template v-else>
  52. <view v-if="!multiple && mixinDatacomResData.length > 0"
  53. :class="{ 'uni-select__selector-item': true, 'uni-select__selector-item--actived': item.value === modelValue }"
  54. class="" v-for="(item, index) in mixinDatacomResData" :key="index"
  55. @click="change(item)">
  56. <text :class="{ 'uni-select__selector__disabled': item.disable }">{{
  57. formatItemName(item) }}</text>
  58. </view>
  59. <view v-if="multiple && mixinDatacomResData.length > 0">
  60. <checkbox-group @change="checkBoxChange">
  61. <label class="uni-select__selector-item"
  62. v-for="(item, index) in mixinDatacomResData" :key="index">
  63. <checkbox :value="index + ''" :checked="getCurrentValues().includes(item.value)"
  64. :disabled="item.disable"></checkbox>
  65. <view :class="{ 'uni-select__selector__disabled': item.disable }">
  66. {{ formatItemName(item) }}</view>
  67. </label>
  68. </checkbox-group>
  69. </view>
  70. </template>
  71. </scroll-view>
  72. </view>
  73. </view>
  74. </view>
  75. </view>
  76. </template>
  77. <script>
  78. /**
  79. * DataChecklist 数据选择器
  80. * @description 通过数据渲染的下拉框组件
  81. * @tutorial https://uniapp.dcloud.io/component/uniui/uni-data-select
  82. * @property {String|Array} value 默认值,多选时为数组
  83. * @property {Array} localdata 本地数据 ,格式 [{text:'',value:''}]
  84. * @property {Boolean} clear 是否可以清空已选项
  85. * @property {Boolean} emptyText 没有数据时显示的文字 ,本地数据无效
  86. * @property {String} label 左侧标题
  87. * @property {String} placeholder 输入框的提示文字
  88. * @property {Boolean} disabled 是否禁用
  89. * @property {Boolean} multiple 是否多选模式
  90. * @property {Boolean} wrap 是否允许选中文本换行显示
  91. * @property {String} placement 弹出位置
  92. * @value top 顶部弹出
  93. * @value bottom 底部弹出(default)
  94. * @property {String} align 选择文字的位置
  95. * @value left 显示左侧
  96. * @value center 显示中间
  97. * @value right 显示 右侧
  98. * @property {Boolean} hideRight 是否隐藏右侧按钮
  99. * @property {String} mode 边框样式
  100. * @value default 四周边框
  101. * @value underline 下边框
  102. * @value none 无边框
  103. * @event {Function} change 选中发生变化触发
  104. * @event {Function} open 选择框开启时触发
  105. * @event {Function} close 选择框关闭时触发
  106. * @event {Function} clear 点击清除按钮之后触发
  107. */
  108. export default {
  109. name: "uni-data-select",
  110. mixins: [uniCloud.mixinDatacom || {}],
  111. emits: [
  112. 'open',
  113. 'close',
  114. 'update:modelValue',
  115. 'input',
  116. 'clear',
  117. 'change'
  118. ],
  119. model: {
  120. prop: 'modelValue',
  121. event: 'update:modelValue'
  122. },
  123. options: {
  124. // #ifdef MP-TOUTIAO
  125. virtualHost: false,
  126. // #endif
  127. // #ifndef MP-TOUTIAO
  128. virtualHost: true
  129. // #endif
  130. },
  131. props: {
  132. localdata: {
  133. type: Array,
  134. default() {
  135. return []
  136. }
  137. },
  138. value: {
  139. type: [String, Number, Array],
  140. default: undefined
  141. },
  142. modelValue: {
  143. type: [String, Number, Array],
  144. default: undefined
  145. },
  146. label: {
  147. type: String,
  148. default: ''
  149. },
  150. placeholder: {
  151. type: String,
  152. default: '请选择'
  153. },
  154. emptyTips: {
  155. type: String,
  156. default: '无选项'
  157. },
  158. clear: {
  159. type: Boolean,
  160. default: true
  161. },
  162. defItem: {
  163. type: Number,
  164. default: 0
  165. },
  166. disabled: {
  167. type: Boolean,
  168. default: false
  169. },
  170. // 格式化输出 用法 field="_id as value, version as text, uni_platform as label" format="{label} - {text}"
  171. format: {
  172. type: String,
  173. default: ''
  174. },
  175. placement: {
  176. type: String,
  177. default: 'bottom'
  178. },
  179. multiple: {
  180. type: Boolean,
  181. default: false
  182. },
  183. wrap: {
  184. type: Boolean,
  185. default: false
  186. },
  187. align: {
  188. type: String,
  189. default: "left"
  190. },
  191. hideRight: {
  192. type: Boolean,
  193. default: false
  194. },
  195. mode: {
  196. type: String,
  197. default: 'default'
  198. }
  199. },
  200. data() {
  201. return {
  202. showSelector: false,
  203. current: '',
  204. mixinDatacomResData: [],
  205. apps: [],
  206. channels: [],
  207. cacheKey: "uni-data-select-lastSelectedValue",
  208. };
  209. },
  210. created() {
  211. this.debounceGet = this.debounce(() => {
  212. this.query();
  213. }, 300);
  214. if (this.collection && !this.localdata.length) {
  215. this.debounceGet();
  216. }
  217. },
  218. computed: {
  219. typePlaceholder() {
  220. const text = {
  221. 'opendb-stat-app-versions': '版本',
  222. 'opendb-app-channels': '渠道',
  223. 'opendb-app-list': '应用'
  224. }
  225. const common = this.placeholder
  226. const placeholder = text[this.collection]
  227. return placeholder ?
  228. common + placeholder :
  229. common
  230. },
  231. valueCom() {
  232. if (this.value === undefined && this.modelValue !== undefined) return this.modelValue
  233. if (this.modelValue === undefined && this.value !== undefined) return this.value
  234. if (this.value === undefined && this.modelValue === undefined) return undefined
  235. return this.value
  236. },
  237. textShow() {
  238. // 长文本显示
  239. if (this.multiple) {
  240. const currentValues = this.getCurrentValues();
  241. if (Array.isArray(currentValues) && currentValues.length > 0) {
  242. const selectedItems = this.mixinDatacomResData.filter(item => currentValues.includes(item.value));
  243. return selectedItems.map(item => this.formatItemName(item)).join(', ');
  244. } else {
  245. return ''; // 空数组时返回空字符串,显示占位符
  246. }
  247. } else {
  248. return this.current;
  249. }
  250. },
  251. shouldShowClear() {
  252. if (this.multiple) {
  253. const currentValues = this.getCurrentValues();
  254. return Array.isArray(currentValues) && currentValues.length > 0;
  255. } else {
  256. return !!this.current;
  257. }
  258. },
  259. shouldWrap() {
  260. // 只有在多选模式、开启换行、且有内容时才应用换行样式
  261. return this.multiple && this.wrap && !!this.textShow;
  262. },
  263. getOffsetByPlacement() {
  264. switch (this.placement) {
  265. case 'top':
  266. return "bottom:calc(100% + 12px);";
  267. case 'bottom':
  268. return "top:calc(100% + 12px);";
  269. }
  270. },
  271. slotSelected() {
  272. // #ifdef VUE2
  273. return this.$scopedSlots ? this.$scopedSlots.selected : false
  274. // #endif
  275. // #ifdef VUE3
  276. return this.$slots ? this.$slots.selected : false
  277. // #endif
  278. },
  279. slotEmpty() {
  280. // #ifdef VUE2
  281. return this.$scopedSlots ? this.$scopedSlots.empty : false
  282. // #endif
  283. // #ifdef VUE3
  284. return this.$slots ? this.$slots.empty : false
  285. // #endif
  286. },
  287. slotOption() {
  288. // #ifdef VUE2
  289. return this.$scopedSlots ? this.$scopedSlots.option : false
  290. // #endif
  291. // #ifdef VUE3
  292. return this.$slots ? this.$slots.option : false
  293. // #endif
  294. }
  295. },
  296. watch: {
  297. showSelector: {
  298. handler(val, old) {
  299. val ? this.$emit('open') : this.$emit('close')
  300. }
  301. },
  302. localdata: {
  303. immediate: true,
  304. handler(val, old) {
  305. if (Array.isArray(val) && old !== val) {
  306. this.mixinDatacomResData = val
  307. }
  308. }
  309. },
  310. valueCom(val, old) {
  311. this.initDefVal()
  312. },
  313. mixinDatacomResData: {
  314. immediate: true,
  315. handler(val) {
  316. if (val.length) {
  317. this.initDefVal()
  318. }
  319. }
  320. },
  321. },
  322. methods: {
  323. getSelectedItems() {
  324. const currentValues = this.getCurrentValues();
  325. let _minxData = this.mixinDatacomResData
  326. // #ifdef MP-WEIXIN || MP-TOUTIAO
  327. _minxData = JSON.parse(JSON.stringify(this.mixinDatacomResData))
  328. // #endif
  329. if (this.multiple) {
  330. return _minxData.filter(item => currentValues.includes(item.value)) || [];
  331. } else {
  332. return _minxData.filter(item => item.value === currentValues) || [];
  333. }
  334. },
  335. debounce(fn, time = 100) {
  336. let timer = null
  337. return function (...args) {
  338. if (timer) clearTimeout(timer)
  339. timer = setTimeout(() => {
  340. fn.apply(this, args)
  341. }, time)
  342. }
  343. },
  344. // 检查项目是否已选中
  345. isSelected(item) {
  346. if (this.multiple) {
  347. const currentValues = this.getCurrentValues();
  348. return Array.isArray(currentValues) && currentValues.includes(item.value);
  349. } else {
  350. return this.getCurrentValues() === item.value;
  351. }
  352. },
  353. // 获取当前选中的值
  354. getCurrentValues() {
  355. if (this.multiple) {
  356. return Array.isArray(this.valueCom) ? this.valueCom : (this.valueCom ? [this.valueCom] : []);
  357. } else {
  358. return this.valueCom;
  359. }
  360. },
  361. // 执行数据库查询
  362. query() {
  363. this.mixinDatacomEasyGet();
  364. },
  365. // 监听查询条件变更事件
  366. onMixinDatacomPropsChange() {
  367. if (this.collection) {
  368. this.debounceGet();
  369. }
  370. },
  371. initDefVal() {
  372. let defValue = this.multiple ? [] : undefined
  373. if ((this.valueCom !== undefined && this.valueCom !== null) && !this.isDisabled(this.valueCom)) {
  374. defValue = this.valueCom
  375. } else {
  376. let strogeValue
  377. if (this.collection) {
  378. strogeValue = this.getCache()
  379. }
  380. if (strogeValue || strogeValue === 0) {
  381. defValue = strogeValue
  382. } else {
  383. let defItem = this.multiple ? [] : undefined
  384. if (this.defItem > 0 && this.defItem <= this.mixinDatacomResData.length) {
  385. defItem = this.multiple ? [this.mixinDatacomResData[this.defItem - 1].value] : this.mixinDatacomResData[this.defItem - 1].value
  386. }
  387. defValue = defItem
  388. }
  389. if (defValue !== '' && defValue !== undefined && defValue !== null && (!this.multiple || (Array.isArray(defValue) && defValue.length > 0))) {
  390. this.emit(defValue)
  391. }
  392. }
  393. if (this.multiple) {
  394. const selectedValues = Array.isArray(defValue) ? defValue : (defValue !== undefined ? [defValue] : []);
  395. const selectedItems = this.mixinDatacomResData.filter(item => selectedValues.includes(item.value));
  396. this.current = selectedItems.map(item => this.formatItemName(item));
  397. } else {
  398. const def = defValue !== undefined ? this.mixinDatacomResData.find(item => item.value === defValue) : null
  399. this.current = def ? this.formatItemName(def) : ''
  400. }
  401. },
  402. /**
  403. * @param {[String, Number, Array]} value
  404. * 判断用户给的 value 是否同时为禁用状态
  405. */
  406. isDisabled(value) {
  407. if (Array.isArray(value)) {
  408. // 对于数组,如果任意一个值被禁用,则认为整体被禁用
  409. return value.some(val => {
  410. return this.mixinDatacomResData.some(item => item.value === val && item.disable);
  411. });
  412. } else {
  413. let isDisabled = false;
  414. this.mixinDatacomResData.forEach(item => {
  415. if (item.value === value) {
  416. isDisabled = item.disable
  417. }
  418. })
  419. return isDisabled;
  420. }
  421. },
  422. clearVal() {
  423. const emptyValue = this.multiple ? [] : '';
  424. this.emit(emptyValue)
  425. this.current = this.multiple ? [] : ''
  426. if (this.collection) {
  427. this.removeCache()
  428. }
  429. this.$emit('clear')
  430. },
  431. checkBoxChange(res) {
  432. let range = res.detail.value
  433. let currentValues = range && range.length > 0 ? range.map((item) => {
  434. const index = parseInt(item, 10);
  435. if (isNaN(index)) {
  436. console.error(`无效索引: ${item}`);
  437. }
  438. if (index < 0 || index >= this.mixinDatacomResData.length) {
  439. console.error(`索引越界: ${index}`);
  440. }
  441. return this.mixinDatacomResData[index].value;
  442. }) : []
  443. const selectedItems = this.mixinDatacomResData.filter(dataItem => currentValues.includes(dataItem.value));
  444. this.current = selectedItems.map(dataItem => this.formatItemName(dataItem));
  445. this.emit(currentValues);
  446. },
  447. change(item) {
  448. if (!item.disable) {
  449. if (this.multiple) {
  450. // 多选模式
  451. let currentValues = this.getCurrentValues();
  452. if (!Array.isArray(currentValues)) {
  453. currentValues = currentValues ? [currentValues] : [];
  454. }
  455. const itemValue = item.value;
  456. const index = currentValues.indexOf(itemValue);
  457. if (index > -1) {
  458. currentValues.splice(index, 1);
  459. } else {
  460. currentValues.push(itemValue);
  461. }
  462. const selectedItems = this.mixinDatacomResData.filter(dataItem => currentValues.includes(dataItem.value));
  463. this.current = selectedItems.map(dataItem => this.formatItemName(dataItem));
  464. this.emit(currentValues);
  465. } else {
  466. // 单选模式
  467. this.showSelector = false
  468. this.current = this.formatItemName(item)
  469. this.emit(item.value)
  470. }
  471. }
  472. },
  473. emit(val) {
  474. this.$emit('input', val)
  475. this.$emit('update:modelValue', val)
  476. this.$emit('change', val)
  477. if (this.collection) {
  478. this.setCache(val);
  479. }
  480. },
  481. toggleSelector() {
  482. if (this.disabled) {
  483. return
  484. }
  485. this.showSelector = !this.showSelector
  486. },
  487. formatItemName(item) {
  488. let {
  489. text,
  490. value,
  491. channel_code
  492. } = item
  493. channel_code = channel_code ? `(${channel_code})` : ''
  494. if (this.format) {
  495. // 格式化输出
  496. let str = "";
  497. str = this.format;
  498. for (let key in item) {
  499. str = str.replace(new RegExp(`{${key}}`, "g"), item[key]);
  500. }
  501. return str;
  502. } else {
  503. return this.collection.indexOf('app-list') > 0 ?
  504. `${text}(${value})` :
  505. (
  506. text ?
  507. text :
  508. `未命名${channel_code}`
  509. )
  510. }
  511. },
  512. // 获取当前加载的数据
  513. getLoadData() {
  514. return this.mixinDatacomResData;
  515. },
  516. // 获取当前缓存key
  517. getCurrentCacheKey() {
  518. return this.collection;
  519. },
  520. // 获取缓存
  521. getCache(name = this.getCurrentCacheKey()) {
  522. let cacheData = uni.getStorageSync(this.cacheKey) || {};
  523. return cacheData[name];
  524. },
  525. // 设置缓存
  526. setCache(value, name = this.getCurrentCacheKey()) {
  527. let cacheData = uni.getStorageSync(this.cacheKey) || {};
  528. cacheData[name] = value;
  529. uni.setStorageSync(this.cacheKey, cacheData);
  530. },
  531. // 删除缓存
  532. removeCache(name = this.getCurrentCacheKey()) {
  533. let cacheData = uni.getStorageSync(this.cacheKey) || {};
  534. delete cacheData[name];
  535. uni.setStorageSync(this.cacheKey, cacheData);
  536. },
  537. }
  538. }
  539. </script>
  540. <style lang="scss">
  541. $uni-base-color: #6a6a6a !default;
  542. $uni-main-color: #333 !default;
  543. $uni-secondary-color: #909399 !default;
  544. $uni-border-3: #e5e5e5;
  545. $uni-primary: #2979ff !default;
  546. $uni-success: #4cd964 !default;
  547. $uni-warning: #f0ad4e !default;
  548. $uni-error: #dd524d !default;
  549. $uni-info: #909399 !default;
  550. /* #ifndef APP-NVUE */
  551. @media screen and (max-width: 500px) {
  552. .hide-on-phone {
  553. display: none;
  554. }
  555. }
  556. /* #endif */
  557. .uni-stat__select {
  558. display: flex;
  559. align-items: center;
  560. // padding: 15px;
  561. /* #ifdef H5 */
  562. cursor: pointer;
  563. /* #endif */
  564. width: 100%;
  565. flex: 1;
  566. box-sizing: border-box;
  567. }
  568. .uni-stat-box {
  569. background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important;
  570. width: 100%;
  571. flex: 1;
  572. }
  573. .uni-stat__actived {
  574. width: 100%;
  575. flex: 1;
  576. // outline: 1px solid #2979ff;
  577. }
  578. .uni-label-text {
  579. font-size: 14px;
  580. font-weight: bold;
  581. color: $uni-base-color;
  582. margin: auto 0;
  583. margin-right: 5px;
  584. }
  585. .border-bottom {
  586. border-bottom: solid 1px $uni-border-3;
  587. }
  588. .border-default {
  589. border: 1px solid $uni-border-3;
  590. }
  591. .uni-select {
  592. font-size: 14px;
  593. box-sizing: border-box;
  594. border-radius: 4px;
  595. padding: 0 5px;
  596. padding-left: 10px;
  597. position: relative;
  598. /* #ifndef APP-NVUE */
  599. display: flex;
  600. user-select: none;
  601. /* #endif */
  602. flex-direction: row;
  603. align-items: center;
  604. width: 100%;
  605. flex: 1;
  606. min-height: 35px;
  607. &--disabled {
  608. background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important;
  609. cursor: not-allowed;
  610. }
  611. &--wrap {
  612. height: auto;
  613. min-height: 35px;
  614. // align-items: flex-start;
  615. }
  616. }
  617. .uni-select__label {
  618. font-size: 16px;
  619. // line-height: 22px;
  620. height: 35px;
  621. padding-right: 10px;
  622. color: $uni-secondary-color;
  623. }
  624. .uni-select__input-box {
  625. // height: 35px;
  626. width: 0px;
  627. position: relative;
  628. /* #ifndef APP-NVUE */
  629. display: flex;
  630. /* #endif */
  631. flex: 1;
  632. flex-direction: row;
  633. align-items: center;
  634. &--wrap {
  635. .uni-select__input-text {
  636. margin-right: 8px;
  637. }
  638. }
  639. .padding-top-bottom {
  640. padding-top: 5px;
  641. padding-bottom: 5px;
  642. }
  643. .slot-content {
  644. width: 100%;
  645. display: flex;
  646. flex-direction: row;
  647. flex-wrap: wrap;
  648. }
  649. }
  650. .uni-select__input {
  651. flex: 1;
  652. font-size: 14px;
  653. height: 22px;
  654. line-height: 22px;
  655. }
  656. .uni-select__input-plac {
  657. font-size: 14px;
  658. color: $uni-secondary-color;
  659. }
  660. .uni-select__selector {
  661. /* #ifndef APP-NVUE */
  662. box-sizing: border-box;
  663. /* #endif */
  664. position: absolute;
  665. left: 0;
  666. width: 100%;
  667. background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important;
  668. border: 1px solid #EBEEF5;
  669. border-radius: 6px;
  670. box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  671. z-index: 1111;
  672. padding: 4px 0;
  673. }
  674. .uni-select__selector-scroll {
  675. /* #ifndef APP-NVUE */
  676. max-height: 200px;
  677. box-sizing: border-box;
  678. /* #endif */
  679. }
  680. /* #ifdef H5 */
  681. @media (min-width: 768px) {
  682. .uni-select__selector-scroll {
  683. max-height: 600px;
  684. }
  685. }
  686. /* #endif */
  687. .uni-select__selector-empty,
  688. .uni-select__selector-item {
  689. /* #ifndef APP-NVUE */
  690. display: flex;
  691. cursor: pointer;
  692. /* #endif */
  693. flex-direction: row;
  694. align-items: center;
  695. line-height: 35px;
  696. font-size: 14px;
  697. /* border-bottom: solid 1px $uni-border-3; */
  698. padding: 0px 10px;
  699. }
  700. .uni-select__selector-item--actived {
  701. background-color: rgba(var(--bs-secondary-color-rgb), var(--bs-bg-opacity)) !important;
  702. }
  703. .uni-select__selector-item-check {
  704. margin-left: auto;
  705. }
  706. .uni-select__selector-empty:last-child,
  707. .uni-select__selector-item:last-child {
  708. /* #ifndef APP-NVUE */
  709. border-bottom: none;
  710. /* #endif */
  711. }
  712. .uni-select__selector__disabled {
  713. opacity: 0.4;
  714. cursor: default;
  715. }
  716. /* picker 弹出层通用的指示小三角 */
  717. .uni-popper__arrow_bottom,
  718. .uni-popper__arrow_bottom::after,
  719. .uni-popper__arrow_top,
  720. .uni-popper__arrow_top::after {
  721. position: absolute;
  722. display: block;
  723. width: 0;
  724. height: 0;
  725. border-color: transparent;
  726. border-style: solid;
  727. border-width: 6px;
  728. }
  729. .uni-popper__arrow_bottom {
  730. filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
  731. top: -6px;
  732. left: 10%;
  733. margin-right: 3px;
  734. border-top-width: 0;
  735. border-bottom-color: #EBEEF5;
  736. }
  737. .uni-popper__arrow_bottom::after {
  738. content: " ";
  739. top: 1px;
  740. margin-left: -6px;
  741. border-top-width: 0;
  742. border-bottom-color: #fff;
  743. }
  744. .uni-popper__arrow_top {
  745. filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
  746. bottom: -6px;
  747. left: 10%;
  748. margin-right: 3px;
  749. border-bottom-width: 0;
  750. border-top-color: #EBEEF5;
  751. }
  752. .uni-popper__arrow_top::after {
  753. content: " ";
  754. bottom: 1px;
  755. margin-left: -6px;
  756. border-bottom-width: 0;
  757. border-top-color: #fff;
  758. }
  759. .uni-select__input-text {
  760. // width: 280px;
  761. width: 100%;
  762. color: $uni-main-color;
  763. white-space: nowrap;
  764. text-overflow: ellipsis;
  765. -o-text-overflow: ellipsis;
  766. overflow: hidden;
  767. &--wrap {
  768. white-space: normal;
  769. text-overflow: initial;
  770. -o-text-overflow: initial;
  771. overflow: visible;
  772. word-wrap: break-word;
  773. word-break: break-all;
  774. // line-height: 1.5;
  775. }
  776. }
  777. .uni-select__input-placeholder {
  778. color: $uni-base-color;
  779. font-size: 12px;
  780. margin: 1px 0;
  781. }
  782. .uni-select--mask {
  783. position: fixed;
  784. top: 0;
  785. bottom: 0;
  786. right: 0;
  787. left: 0;
  788. z-index: 2;
  789. }
  790. .align-left {
  791. text-align: left;
  792. }
  793. .align-center {
  794. text-align: center;
  795. }
  796. .align-right {
  797. text-align: right;
  798. }
  799. </style>