momo-multipleSelect.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. <template>
  2. <view class="select-container" v-show="show" @touchmove.stop.prevent>
  3. <view class="mask" :class="activeClass ? 'mask-show' : ''" @tap="onCancel(true)"></view>
  4. <view class="select-box" :class="activeClass ? 'select-box-show' : ''">
  5. <div style="height: 900rpx">
  6. <div style="display: flex">
  7. <uni-easyinput type="text" class="searchinput" v-model="formData.qymc" placeholder="输入关联企业名称(模糊查询)"
  8. style="height: 70rpx" />
  9. <van-button class="searchbutton" style="height: 70rpx" type="primary"
  10. @click="getCompaynList()">搜索</van-button>
  11. </div>
  12. <div class="chooseCompanyTags">
  13. <scroll-view class="body" scroll-y="true" style="position: absolute; z-index: 1000">
  14. <div v-for="(item, index) in companyList" :key="index" class="selectlist">
  15. <div class="title_2">
  16. {{ item.label }}
  17. </div>
  18. <div v-if="!item.isSelected" class="title_1" @click="chosseTags(item, index)">
  19. <uni-icons type="plusempty" size="30rpx"></uni-icons>
  20. </div>
  21. </div>
  22. </scroll-view>
  23. </div>
  24. </div>
  25. <view class="btn-view">
  26. <button class="btn" @click="openTagsDialog()" style="
  27. border-top-left-radius: 5rem;
  28. border-bottom-left-radius: 5rem;
  29. background: white;
  30. color: #1d18bc;
  31. border: 1px solid;
  32. ">
  33. 已选择({{ isSelectedList.length }})<van-icon name="arrow-down" />
  34. </button>
  35. <button style="
  36. border-radius: 0;
  37. border: 1px solid #1d18bc;
  38. border-top-right-radius: 5rem;
  39. border-bottom-right-radius: 5rem;
  40. " class="btn" @click="updown()">
  41. 确认提交
  42. </button>
  43. </view>
  44. </view>
  45. <is-selected-tags ref="isSelectedTags" :isSelectedList="isSelectedList" @clearAll="clearAll" @updown="updown"
  46. @spiliceIsSelectedList="spiliceIsSelectedList" />
  47. </view>
  48. </template>
  49. <!-- 多选组件 -->
  50. <script>
  51. import isSelectedTags from "./isSelectedTags.vue";
  52. export default {
  53. data() {
  54. return {
  55. isSelectedList: [],
  56. companyList: [],
  57. isSelectList: [],
  58. formData: {},
  59. show: false, //是否显示
  60. activeClass: false, //激活样式状态
  61. selectedArr: [], //选择对照列表
  62. selectedArrOld: [], //选择对照列表上一次的数据
  63. };
  64. },
  65. components: {
  66. isSelectedTags,
  67. },
  68. onShow() {
  69. this.show = this.value;
  70. },
  71. methods: {
  72. async updown() {
  73. console.log(this.isSelectedList);
  74. this.$emit("confirm", this.isSelectedList);
  75. this.show = false;
  76. },
  77. clearAll() {
  78. this.isSelectedList = [];
  79. this.companyList.forEach((e) => {
  80. e.isSelected = false;
  81. this.$forceUpdate();
  82. });
  83. },
  84. spiliceIsSelectedList(item, index) {
  85. this.isSelectedList.splice(index, 1);
  86. let changeIndex = this.companyList.findIndex(
  87. (e) => e.tagCategoryId == item.tagCategoryId
  88. );
  89. this.companyList[changeIndex].isSelected = false;
  90. this.$forceUpdate();
  91. },
  92. chosseTags(item, index) {
  93. let filterIndex = this.isSelectedList.findIndex(
  94. (e) => e.value == item.value
  95. );
  96. if (filterIndex != -1) {
  97. this.$showToast("该标签与已选择标签重复");
  98. return;
  99. }
  100. if (item.isEffective == 1) {
  101. this.openChooseTimeDialog(item, index);
  102. } else {
  103. this.isSelectedList.push(this.companyList[index]);
  104. this.companyList[index].isSelected = true;
  105. this.companyList = [...this.companyList];
  106. }
  107. },
  108. openTagsDialog() {
  109. this.$refs.isSelectedTags.onOpen([]);
  110. },
  111. getAllList(data) {
  112. this.companyList = [];
  113. this.companyList = data;
  114. },
  115. getCompaynList() {
  116. console.log(this.companyList);
  117. console.log(this.selectedArr);
  118. this.$emit("getCompanyAll", this.formData.qymc);
  119. },
  120. // 设置默认选中通用办法
  121. setItemActiveState() {
  122. if (this.companyList.length && this.defaultSelected.length) {
  123. this.companyList.forEach((item, i) => {
  124. for (let n = 0; n < this.defaultSelected.length; n++) {
  125. if (
  126. !item.disabled &&
  127. item[this.valueName] === this.defaultSelected[n]
  128. ) {
  129. this.selectedArr.splice(i, 1, true);
  130. break;
  131. }
  132. }
  133. });
  134. }
  135. },
  136. /**
  137. * 选择事件
  138. * @index {Number} 点击下标
  139. */
  140. onSelected(index) {
  141. if (this.companyList[index].disabled) return;
  142. console.log(this.companyList[index]);
  143. if (!this.companyList[index].isSelect) {
  144. this.isSelectList.push(this.companyList[index].value);
  145. this.companyList[index].isSelect = true;
  146. } else {
  147. let deleteIndex = this.isSelectList.findIndex(
  148. (e) => e.value == this.companyList[index].value
  149. );
  150. this.isSelectList.splice(deleteIndex, 1);
  151. this.companyList[index].isSelect = false;
  152. }
  153. this.$forceUpdate();
  154. this.companyList = [...this.companyList];
  155. // let index2Active = this.selectedArr[index];
  156. // this.selectedArr.splice(index, 1, !index2Active);
  157. },
  158. // 取消事件
  159. onCancel(isMask) {
  160. if (!isMask || this.maskCloseAble) {
  161. this.show = false;
  162. this.selectedArr = JSON.parse(JSON.stringify(this.selectedArrOld));
  163. } else {
  164. return;
  165. }
  166. this.$emit("cancel");
  167. },
  168. // 返回去除了disabled状态后的对照列表
  169. returnWipeDisabledList() {
  170. let arr = [];
  171. this.selectedArr.forEach((el, index) => {
  172. if (!this.companyList[index].disabled) arr.push(el);
  173. });
  174. return arr;
  175. },
  176. // 全选/非全选事件
  177. onAllToggle() {
  178. let wipeDisabledList = this.returnWipeDisabledList();
  179. // 如果去除了disabled的对照列表有false的数据,代表未全选
  180. if (wipeDisabledList.includes(false)) {
  181. this.selectedArr.forEach((el, index) => {
  182. if (!this.companyList[index].disabled)
  183. this.selectedArr.splice(index, 1, true);
  184. });
  185. } else {
  186. this.selectedArr.forEach((el, index) => {
  187. if (!this.companyList[index].disabled)
  188. el = this.selectedArr.splice(index, 1, false);
  189. });
  190. }
  191. },
  192. // 确定事件
  193. onConfirm() {
  194. this.show = false;
  195. let selectedData = [];
  196. this.companyList.forEach((e, index) => {
  197. if (e.isSelect) {
  198. selectedData.push(this.companyList[index]);
  199. }
  200. });
  201. if (this.mode === "multiple") {
  202. this.$emit("confirm", selectedData);
  203. } else {
  204. let backData = selectedData[0] || {};
  205. this.$emit("confirm", backData);
  206. }
  207. },
  208. },
  209. computed: {
  210. // 返回是否全选
  211. isAll() {
  212. let wipeDisabledList = this.returnWipeDisabledList();
  213. if (!wipeDisabledList.length) return false;
  214. return !wipeDisabledList.includes(false);
  215. },
  216. },
  217. props: {
  218. // 双向绑定
  219. value: {
  220. type: Boolean,
  221. default: false,
  222. },
  223. // 取消按钮文字
  224. cancelText: {
  225. type: String,
  226. default: "取消",
  227. },
  228. // 确认按钮文字
  229. confirmText: {
  230. type: String,
  231. default: "确认",
  232. },
  233. // label对应的key名称
  234. labelName: {
  235. type: String,
  236. default: "label",
  237. },
  238. // value对应的key名称
  239. valueName: {
  240. type: String,
  241. default: "value",
  242. },
  243. // 是否允许点击遮罩层关闭
  244. maskCloseAble: {
  245. type: Boolean,
  246. default: true,
  247. },
  248. // 是否显示全选
  249. allShow: {
  250. type: Boolean,
  251. default: true,
  252. },
  253. // 模式
  254. mode: {
  255. type: String,
  256. default: "multiple",
  257. },
  258. // 默认选中值
  259. defaultSelected: {
  260. type: Array,
  261. default: function () {
  262. return [];
  263. },
  264. },
  265. // 数据源
  266. // data: {
  267. // type: Array,
  268. // required: true,
  269. // default: () => {
  270. // return [];
  271. // },
  272. // },
  273. },
  274. watch: {
  275. async value(newVal) {
  276. this.show = newVal;
  277. await this.$nextTick();
  278. this.activeClass = newVal;
  279. if (newVal) {
  280. this.selectedArrOld = JSON.parse(JSON.stringify(this.selectedArr));
  281. }
  282. },
  283. show(newVal) {
  284. this.$emit("input", newVal);
  285. this.$emit("change", newVal);
  286. },
  287. defaultSelected: {
  288. handler() {
  289. this.setItemActiveState();
  290. },
  291. deep: true,
  292. immediate: true,
  293. },
  294. },
  295. };
  296. </script>
  297. <style lang="scss">
  298. .searchbutton {
  299. button {
  300. height: 69rpx;
  301. line-height: 69rpx;
  302. }
  303. }
  304. .searchinput {
  305. .uni-easyinput__content-input {
  306. height: 70rpx;
  307. }
  308. }
  309. .btn-view {
  310. width: 100%;
  311. height: 100rpx;
  312. padding: 20rpx 10%;
  313. background-color: #ffffff;
  314. position: fixed;
  315. bottom: 0;
  316. left: 0;
  317. z-index: 1000;
  318. button {
  319. &::after {
  320. border: none;
  321. }
  322. }
  323. }
  324. </style>
  325. <style lang="scss" scoped>
  326. .selectlist {
  327. border-bottom: 2rpx solid #cccccc;
  328. display: flex;
  329. align-items: center;
  330. justify-content: space-between;
  331. }
  332. .chooseCompanyTags {
  333. .title_1 {
  334. font-size: 28rpx;
  335. font-weight: 500;
  336. color: #333333;
  337. text-align: right;
  338. height: 64rpx;
  339. line-height: 64rpx;
  340. }
  341. .title_2 {
  342. font-size: 26rpx;
  343. font-weight: 500;
  344. color: #777777;
  345. height: 64rpx;
  346. line-height: 64rpx;
  347. text-align: left;
  348. }
  349. .title_3 {
  350. margin-bottom: 12rpx;
  351. font-size: 26rpx;
  352. font-weight: 500;
  353. color: #777777;
  354. }
  355. .cell_1 {
  356. float: left;
  357. width: 10%;
  358. }
  359. .checkbox {
  360. border: 1px solid #cccccc;
  361. border-radius: 4rpx 4rpx 4rpx 4rpx;
  362. height: 30rpx;
  363. width: 30rpx;
  364. }
  365. .cell_2 {
  366. float: left;
  367. width: 90%;
  368. img {
  369. height: 60rpx;
  370. width: 60rpx;
  371. float: right;
  372. margin: 96rpx 0rpx 94rpx 0;
  373. }
  374. }
  375. .btn {
  376. width: 40%;
  377. height: 90rpx;
  378. background: #1d18bc;
  379. line-height: 90rpx;
  380. color: white;
  381. float: left;
  382. }
  383. .jichuback {
  384. width: calc(100% - 64rpx);
  385. margin: 32rpx;
  386. background: white;
  387. border-bottom: 2rpx solid #cccccc;
  388. }
  389. .tags_type {
  390. width: calc(100% - 64rpx);
  391. margin: 16rpx;
  392. }
  393. }
  394. .btn-view {
  395. width: 100%;
  396. height: 100rpx;
  397. padding: 20rpx 10%;
  398. background-color: #ffffff;
  399. position: fixed;
  400. bottom: 0;
  401. left: 0;
  402. z-index: 1000;
  403. }
  404. .btn {
  405. width: 40%;
  406. height: 90rpx;
  407. background: #1d18bc;
  408. line-height: 90rpx;
  409. color: white;
  410. float: left;
  411. }
  412. .select-container {
  413. width: 100vw;
  414. height: 100vh;
  415. position: fixed;
  416. left: 0;
  417. top: 0;
  418. z-index: 999;
  419. $paddingLR: 18rpx;
  420. .mask {
  421. width: 100%;
  422. height: 100%;
  423. background-color: $uni-bg-color-mask;
  424. opacity: 0;
  425. transition: opacity 0.3s;
  426. &.mask-show {
  427. opacity: 1;
  428. }
  429. }
  430. // 选择器内容区域
  431. .select-box {
  432. width: 100%;
  433. position: absolute;
  434. bottom: 0;
  435. left: 0;
  436. transform: translate3d(0px, 100%, 0px);
  437. background-color: $uni-bg-color;
  438. transition: all 0.3s;
  439. &.select-box-show {
  440. transform: translateZ(0);
  441. }
  442. .header {
  443. display: flex;
  444. box-sizing: border-box;
  445. width: 100%;
  446. justify-content: space-between;
  447. border-bottom: 1px solid $uni-border-color;
  448. line-height: 76rpx;
  449. font-size: 30rpx;
  450. padding: 0 $paddingLR;
  451. .cancel {
  452. color: $uni-text-color-grey;
  453. }
  454. .all {
  455. .all-active {
  456. &::after {
  457. display: inline-block;
  458. content: "✔";
  459. padding-left: 8rpx;
  460. }
  461. }
  462. }
  463. .confirm {
  464. color: $uni-color-primary;
  465. }
  466. }
  467. .body-warp {
  468. width: 100%;
  469. height: 30vh;
  470. box-sizing: border-box;
  471. padding: 20rpx $paddingLR;
  472. }
  473. .body {
  474. width: 96%;
  475. height: 70%;
  476. overflow-y: auto;
  477. padding: 2%;
  478. .empty-tips {
  479. margin-top: 25%;
  480. text-align: center;
  481. font-size: 26rpx;
  482. color: $uni-color-error;
  483. }
  484. }
  485. }
  486. }
  487. </style>