select-cy.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. <template>
  2. <view class="uni-select-cy" :style="{'z-index':zindex}">
  3. <view class="uni-select-cy-select" :class="{ active: active }" @click.stop="handleSelect">
  4. <!-- 禁用mask -->
  5. <view class="uni-disabled" v-if="disabled"></view>
  6. <!-- 清空 -->
  7. <view class="close-icon close-postion" v-if="realValue.length && !active && !disabled && showClearIcon">
  8. <text @click.stop="handleRemove(null)"></text>
  9. </view>
  10. <!-- 显示框 -->
  11. <view class="uni-select-multiple" v-show="realValue.length">
  12. <view class="uni-select-multiple-item" v-for="(item, index) in realValue" :key="index">
  13. <view class="uni-select-multiple-item-row">
  14. {{ item }}
  15. </view>
  16. <view class="close-icon" v-if="showValueClear"><text @click.stop="handleRemove(index)"></text>
  17. </view>
  18. </view>
  19. </view>
  20. <!-- 为空时的显示文案 -->
  21. <view v-if="realValue.length == 0&&showplaceholder">{{ placeholder }}</view>
  22. <!-- 禁用图标 -->
  23. <view class="uni-select-cy-icon" :class="{ disabled: disabled }"><text></text></view>
  24. </view>
  25. <!-- 下拉选项 -->
  26. <scroll-view class="uni-select-cy-options" :scroll-y="true" v-show="active" @scrolltolower="scrolltolower">
  27. <template>
  28. <view class="uni-select-cy-item" :class="{ active: realValue.includes(item[svalue]) }"
  29. v-for="(item, index) in options" :key="index" @click.stop="handleChange(index, item)">
  30. {{ item[slabel] }}
  31. </view>
  32. </template>
  33. </scroll-view>
  34. </view>
  35. </template>
  36. <script>
  37. export default {
  38. name: 'select-cy',
  39. props: {
  40. //是否显示全部清空按钮
  41. showClearIcon: {
  42. type: Boolean,
  43. default: false
  44. },
  45. //是否显示单个删除
  46. showValueClear: {
  47. type: Boolean,
  48. default: true
  49. },
  50. zindex: {
  51. type: Number,
  52. default: 999
  53. },
  54. //禁用组件
  55. disabled: {
  56. type: Boolean,
  57. default: false
  58. },
  59. options: {
  60. type: Array,
  61. default () {
  62. return [];
  63. }
  64. },
  65. value: {
  66. type: Array,
  67. default () {
  68. return [];
  69. }
  70. },
  71. placeholder: {
  72. type: String,
  73. default: '请选择'
  74. },
  75. showplaceholder: {
  76. type: Boolean,
  77. default: true
  78. },
  79. slabel: {
  80. type: String,
  81. default: 'label'
  82. },
  83. svalue: {
  84. type: String,
  85. default: 'value'
  86. },
  87. // 是否开启分页
  88. isPaging:{
  89. type: Boolean,
  90. default: false
  91. }
  92. },
  93. data() {
  94. return {
  95. active: false, //组件是否激活,
  96. changevalue: [], //搜索框同步
  97. realValue: []
  98. };
  99. },
  100. watch:{
  101. value(){
  102. //初始化
  103. this.init();
  104. }
  105. },
  106. methods: {
  107. close() {
  108. this.active = false
  109. },
  110. init() {
  111. if (this.value.length > 0) {
  112. this.changevalue = this.options.map(item => {
  113. this.value.forEach(i => {
  114. if (item[this.svalue] == i[this.svalue]) {
  115. return item;
  116. }
  117. });
  118. });
  119. this.realValue = this.value;
  120. } else {
  121. this.changevalue = [];
  122. this.realValue = [];
  123. }
  124. },
  125. scrolltolower(){
  126. if(this.isPaging){
  127. this.$emit('scrolltolower')
  128. }
  129. },
  130. //点击展示选项
  131. handleSelect() {
  132. if (this.disabled) return;
  133. this.active = !this.active;
  134. },
  135. //移除数据
  136. handleRemove(index) {
  137. if (index === null) {
  138. this.realValue = [];
  139. this.changevalue = [];
  140. } else {
  141. this.realValue.splice(index, 1);
  142. this.changevalue.splice(index, 1);
  143. }
  144. this.$emit('change', this.changevalue, this.realValue);
  145. },
  146. //点击组件列
  147. handleChange(index, item) {
  148. let arrIndex = this.realValue.indexOf(item[this.svalue]);
  149. if (arrIndex > -1) {
  150. this.changevalue.splice(arrIndex, 1);
  151. this.realValue.splice(arrIndex, 1);
  152. } else {
  153. this.changevalue.push(item);
  154. this.realValue.push(item[this.svalue]);
  155. }
  156. console.log(this.realValue, 'this.realValue')
  157. this.$emit('change', this.changevalue, this.realValue);
  158. }
  159. }
  160. };
  161. </script>
  162. <style lang="scss" scoped>
  163. .uni-select-cy {
  164. position: relative;
  165. z-index: 999;
  166. .uni-select-mask {
  167. width: 100%;
  168. height: 100%;
  169. }
  170. /* 删除按钮样式*/
  171. .close-icon {
  172. height: 100%;
  173. width: 15px;
  174. display: flex;
  175. align-items: center;
  176. justify-content: center;
  177. z-index: 3;
  178. cursor: pointer;
  179. text {
  180. position: relative;
  181. background: #fff;
  182. width: 13px;
  183. height: 13px;
  184. border-radius: 50%;
  185. border: 1px solid #bbb;
  186. &::before,
  187. &::after {
  188. content: "";
  189. position: absolute;
  190. left: 20%;
  191. top: 50%;
  192. height: 1px;
  193. width: 60%;
  194. transform: rotate(45deg);
  195. background-color: #bbb;
  196. }
  197. &::after {
  198. transform: rotate(-45deg);
  199. }
  200. }
  201. }
  202. //所有清空的定位
  203. .close-postion {
  204. position: absolute;
  205. right: 35px;
  206. top: 0;
  207. height: 100%;
  208. width: 15px;
  209. }
  210. /* 多选盒子 */
  211. .uni-select-multiple {
  212. overflow-x: auto;
  213. display: flex;
  214. flex: 1;
  215. width: 0;
  216. flex-wrap: nowrap;
  217. .uni-select-multiple-item {
  218. background: #bbb;
  219. margin-right: 5rpx;
  220. padding: 2rpx 4rpx;
  221. border-radius: 4rpx;
  222. color: #fff;
  223. display: flex;
  224. flex: 0 0 140rpx;
  225. .uni-select-multiple-item-row{
  226. flex: 1;
  227. overflow: hidden;
  228. text-overflow: ellipsis;
  229. white-space: nowrap;
  230. }
  231. }
  232. }
  233. // select部分
  234. .uni-select-cy-select {
  235. user-select: none;
  236. position: relative;
  237. z-index: 3;
  238. height: 36px;
  239. padding: 0 30px 0 10px;
  240. box-sizing: border-box;
  241. border-radius: 4px;
  242. border: 1px solid rgb(229, 229, 229);
  243. display: flex;
  244. align-items: center;
  245. font-size: 14px;
  246. color: #999;
  247. flex-wrap: nowrap;
  248. .uni-disabled {
  249. position: absolute;
  250. left: 0;
  251. width: 100%;
  252. height: 100%;
  253. z-index: 19;
  254. cursor: no-drop;
  255. background: rgba(255, 255, 255, .5);
  256. }
  257. .uni-select-cy-input {
  258. font-size: 14px;
  259. color: #999;
  260. display: block;
  261. width: 96%;
  262. overflow: hidden;
  263. text-overflow: ellipsis;
  264. white-space: nowrap;
  265. line-height: 30px;
  266. box-sizing: border-box;
  267. &.active {
  268. color: #333;
  269. }
  270. }
  271. .uni-select-cy-icon {
  272. cursor: pointer;
  273. position: absolute;
  274. right: 0;
  275. top: 0;
  276. height: 100%;
  277. width: 30px;
  278. display: flex;
  279. align-items: center;
  280. justify-content: center;
  281. &::before {
  282. content: "";
  283. width: 1px;
  284. height: 100%;
  285. position: absolute;
  286. left: 0;
  287. top: 0;
  288. background-color: #e5e5e5;
  289. }
  290. text {
  291. display: block;
  292. width: 0;
  293. height: 0;
  294. border-width: 12rpx 12rpx 0;
  295. border-style: solid;
  296. border-color: #bbb transparent transparent;
  297. transition: .3s;
  298. }
  299. &.disabled {
  300. cursor: no-drop;
  301. text {
  302. width: 20rpx;
  303. height: 20rpx;
  304. border: 2px solid #ff0000;
  305. border-radius: 50%;
  306. transition: .3s;
  307. position: relative;
  308. z-index: 999;
  309. &::after {
  310. content: "";
  311. position: absolute;
  312. top: 50%;
  313. left: 0;
  314. width: 100%;
  315. height: 2px;
  316. margin-top: -1px;
  317. background-color: #ff0000;
  318. transform: rotate(45deg);
  319. }
  320. }
  321. }
  322. }
  323. &.active .uni-select-cy-icon {
  324. text {
  325. transform: rotate(180deg);
  326. }
  327. }
  328. }
  329. // options部分
  330. .uni-select-cy-options {
  331. user-select: none;
  332. position: absolute;
  333. top: calc(100% + 5px);
  334. left: 0;
  335. width: 100%;
  336. height: 500rpx;
  337. border-radius: 4px;
  338. border: 1px solid rgb(229, 229, 229);
  339. background: #fff;
  340. padding: 5px 0;
  341. box-sizing: border-box;
  342. z-index: 9;
  343. .uni-select-cy-item {
  344. padding: 0 10px;
  345. box-sizing: border-box;
  346. cursor: pointer;
  347. line-height: 2.5;
  348. transition: .3s;
  349. font-size: 14px;
  350. &.active {
  351. color: #409eff;
  352. background-color: #f5f7fa &:hover {
  353. color: #409eff;
  354. background-color: #f5f7fa
  355. }
  356. }
  357. &:hover {
  358. background-color: #f5f5f5;
  359. }
  360. }
  361. }
  362. }
  363. </style>