tui-sel-load-list.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. <template>
  2. <view class="gui-sel-load-list">
  3. <view @tap.stop="show">
  4. <slot :selData="selData" :selId="selData.id">
  5. <text v-if="maxCounts==1">{{selData&&selData.label?selData.label:placeholder}}</text>
  6. <block v-else>
  7. <text v-for="(item, index) in selData" :key="index">{{index>0?', ':''}}{{item.label}}</text>
  8. <text v-if="!selData || selData.length<=0">{{placeholder}}</text>
  9. </block>
  10. </slot>
  11. </view>
  12. <tui-bottom-popup class="page-popup" :title="title" :dotColor="dotColor" :show="visible"
  13. backgroundColor="#ffffff" @close="pickerCancel">
  14. <view class="pf-picker-cnt" @touchmove.stop.prevent>
  15. <view class="padding-30 pt-20 pb-20" v-if="searchKey">
  16. <uni-search-bar class="uni-mt-10" radius="100" placeholder="搜索" cancelButton="none"
  17. @confirm="search" />
  18. </view>
  19. <scroll-view style="height: 50vh;" scroll-y @scrolltolower="loadApiData">
  20. <tui-load-list ref="list" @change="changeData" :limit="maxCounts==1?20:1000" :postData="parPostData"
  21. :apiUrl="apiUrl">
  22. <block v-if="maxCounts==1">
  23. <radio-group @change="radioChange">
  24. <label
  25. class="df ai-center pt-24 pb-24 ml-30 uni-border-bottom font-26 uni-color-darkgrey"
  26. v-for="(item, index) in listData" :key="index">
  27. <view>
  28. <radio style="transform:scale(0.8)" :value="item.id" :color="dotColor"
  29. :checked="String(myvalue) === String(item.id)" />
  30. </view>
  31. <view class="ml-10">{{item.label}}</view>
  32. </label>
  33. </radio-group>
  34. </block>
  35. <block v-else>
  36. <checkbox-group @change="checkboxChange">
  37. <label
  38. class="df ai-center pt-24 pb-24 ml-30 uni-border-bottom font-26 uni-color-darkgrey"
  39. v-for="(item, index) in listData" :key="index">
  40. <view>
  41. <checkbox style="transform:scale(0.8)" :value="item.id" :color="dotColor"
  42. :checked="checkboxHas(item.id)" />
  43. </view>
  44. <view class="ml-10">{{item.label}}</view>
  45. </label>
  46. </checkbox-group>
  47. </block>
  48. </tui-load-list>
  49. </scroll-view>
  50. <view class="submit-frame">
  51. <view class="btn-frame">
  52. <view style="background:#f4f4f4;" v-if="!notClear" class="flex uni-tab__cart-button-right"
  53. @click="clearData">
  54. <text style="color:#333333;" class="uni-tab__cart-button-right-text">清除</text>
  55. </view>
  56. <view style="background:#f4f4f4;" v-else class="flex uni-tab__cart-button-right"
  57. @click="pickerCancel">
  58. <text style="color:#333333;" class="uni-tab__cart-button-right-text">取消</text>
  59. </view>
  60. <view style="background:#007aff;flex:3;" class="flex uni-tab__cart-button-right"
  61. @click="returndata">
  62. <text style="color:#ffffff;" class="uni-tab__cart-button-right-text">确认</text>
  63. </view>
  64. <!-- <uni-goods-nav :fill="true" :options="options" :button-group="customButtonGroup" @click="clearData"
  65. @buttonClick="buttonClick" /> -->
  66. </view>
  67. </view>
  68. </view>
  69. </tui-bottom-popup>
  70. </view>
  71. </template>
  72. <script>
  73. let App = getApp()
  74. import mixinsPage from "@/common/mixins-model.js"
  75. export default {
  76. mixins: [mixinsPage],
  77. components: {},
  78. data() {
  79. return {
  80. datas: {
  81. years: [],
  82. months: [],
  83. hours: [],
  84. minutes: [],
  85. seconds: []
  86. },
  87. listData: [],
  88. _selData: {},
  89. selData: {},
  90. myvalue: '',
  91. parPostData: null,
  92. visible: false
  93. }
  94. },
  95. props: {
  96. title: {
  97. type: String,
  98. default: "选择行业"
  99. },
  100. dotColor: {
  101. type: String,
  102. default: '#2979ff'
  103. },
  104. notClear: {
  105. type: Boolean,
  106. default: false
  107. },
  108. disabled: {
  109. type: Boolean,
  110. default: false
  111. },
  112. // 占位符
  113. placeholder: {
  114. type: String,
  115. default: "无"
  116. },
  117. apiUrl: {
  118. type: String,
  119. default: ""
  120. },
  121. itemsKey: {
  122. type: String,
  123. default: "records"
  124. },
  125. postData: {
  126. type: Object,
  127. default: null
  128. },
  129. searchKey: {
  130. type: String,
  131. default: ""
  132. },
  133. keyLabel: {
  134. type: String,
  135. default: "name"
  136. },
  137. keyId: {
  138. type: String,
  139. default: "id"
  140. },
  141. initlist: {
  142. type: [Array],
  143. default: () => {
  144. return []
  145. }
  146. },
  147. list: {
  148. type: [Array],
  149. default: () => {
  150. return []
  151. }
  152. },
  153. maxCounts: {
  154. type: [Number, String],
  155. default: 1
  156. },
  157. value: {
  158. type: [Number, String, Array],
  159. default: ""
  160. }
  161. },
  162. watch: {
  163. value(val) {
  164. // console.log('=========>变化', val)
  165. this.myvalue = val;
  166. this.init()
  167. },
  168. postData: {
  169. handler: function() {
  170. if (this.apiUrl && JSON.stringify(this.parPostData) !== JSON.stringify(this.postData)) {
  171. this.parPostData = this.postData;
  172. }
  173. },
  174. deep: true
  175. },
  176. list(val) {
  177. this.initData()
  178. }
  179. },
  180. created() {
  181. this.appData = App.globalData ? App.globalData : getApp().globalData;
  182. this.parPostData = this.postData;
  183. this.initvalue();
  184. this.initData();
  185. },
  186. methods: {
  187. initvalue() {
  188. if (this.maxCounts == 1) {
  189. this.myvalue = this.value;
  190. } else {
  191. if (!this.value) {
  192. this.myvalue = []
  193. } else if (this.$api.isString(this.value)) {
  194. this.myvalue = String(this.value).split(',')
  195. } else {
  196. this.myvalue = this.value;
  197. }
  198. /* this.value.map(item => {
  199. this.$set(item, 'label', item[this.keyLabel])
  200. this.$set(item, 'id', item[this.keyId])
  201. return item
  202. }) */
  203. }
  204. },
  205. clearData() {
  206. if (this.maxCounts == 1) {
  207. this.selData = {
  208. id: '',
  209. label: ''
  210. }
  211. this.$emit("change", null);
  212. this.$emit("input", '');
  213. } else {
  214. this.selData = [];
  215. this.$emit("change", []);
  216. this.$emit("input", []);
  217. }
  218. this.pickerCancel();
  219. },
  220. buttonClick(index) {
  221. if (index == 1) {
  222. // console.log('确认', e)
  223. this.returndata()
  224. } else {
  225. // console.log('取消', e)
  226. this.pickerCancel()
  227. }
  228. },
  229. loadData() {
  230. // 默认的初始函数
  231. },
  232. initData() {
  233. if (this.apiUrl) {
  234. return false;
  235. } else if (this.list && this.list.length > 0) {
  236. this.listData = this.list.map(item => {
  237. this.$set(item, 'label', item[this.keyLabel])
  238. this.$set(item, 'id', item[this.keyId])
  239. return item
  240. })
  241. this.init()
  242. }
  243. },
  244. returndata() {
  245. if (!this.listData || this.listData.length <= 0) {
  246. this.$api.toast("没有可选择的数据项")
  247. return false
  248. }
  249. if (this.maxCounts == 1) {
  250. if (this._selData) {
  251. this.selData = Object.assign({}, this._selData)
  252. this.$emit("input", this.selData.id)
  253. this.$emit("change", this.selData)
  254. } else {
  255. this.$api.toast("请点击选择数据项")
  256. return false
  257. }
  258. } else {
  259. if (this.maxCounts > 1 && this._selData.length > this.maxCounts) {
  260. this.$api.toast("选项不能超过:" + this.maxCounts + "个!")
  261. return false
  262. }
  263. // console.log('当前选择数据:', this._selData)
  264. if (this._selData && this._selData.length > 0) {
  265. this.selData = [].concat(this._selData)
  266. this.$emit("input", this.selData.map(item => {
  267. return item.id
  268. }))
  269. this.$emit("change", this.selData)
  270. } else {
  271. this.selData = []
  272. this.$emit("input", [])
  273. this.$emit("change", [])
  274. }
  275. }
  276. this.visible = false;
  277. },
  278. checkboxChange(e) {
  279. const myvalue = e.detail.value;
  280. const id = [];
  281. const label = [];
  282. const data = this.listData.filter(item => {
  283. return myvalue.some(id => {
  284. return String(id) == String(item.id)
  285. })
  286. })
  287. this.myvalue = myvalue
  288. this._selData = [].concat(data)
  289. },
  290. radioChange(evt) {
  291. this.myvalue = evt.detail.value
  292. const data = this.listData.find(item => {
  293. return String(item.id) == String(this.myvalue)
  294. })
  295. this._selData = Object.assign({}, data)
  296. // console.log(this.selData)
  297. },
  298. loadApiData() {
  299. if (this.$refs.list) {
  300. this.$refs.list.loadData().then(res => {}).catch(res => {});
  301. }
  302. },
  303. search(res) {
  304. const keys = res.value
  305. this.$set(this.parPostData, this.searchKey, keys)
  306. },
  307. changeData(data) {
  308. var list = []
  309. if (data && data.list) {
  310. list = data.list
  311. }
  312. const listData = list.map((item, index) => {
  313. const items = Object.assign({}, item, {
  314. label: item[this.keyLabel],
  315. id: item[this.keyId]
  316. })
  317. return items
  318. });
  319. // console.log(listData)
  320. this.listData = this.initlist.concat(listData)
  321. this.init()
  322. },
  323. init() {
  324. if (!this.listData || this.listData.length <= 0) {
  325. // this.myvalue = '';
  326. this._selData = null;
  327. return false
  328. }
  329. if (this.maxCounts == 1) {
  330. this._selData = null;
  331. this.listData.forEach((item, index) => {
  332. if (String(this.myvalue) == String(item.id)) {
  333. this.myvalue = item.id
  334. this._selData = item
  335. // this.$emit("change", this.selData)
  336. }
  337. })
  338. this.selData = Object.assign({}, this._selData)
  339. } else {
  340. this._selData = this.listData.filter(item => {
  341. const hasvalue = this.myvalue ? this.myvalue.some(id => {
  342. return String(item.id) == String(id)
  343. }) : false
  344. if (hasvalue) {
  345. return true
  346. } else {
  347. return false
  348. }
  349. })
  350. // console.log(this.myvalue, '==========', this._selData)
  351. this.selData = [].concat(this._selData)
  352. }
  353. },
  354. checkboxHas(id) {
  355. if (!this.myvalue || this.myvalue.length <= 0) {
  356. return false
  357. }
  358. // console.log('======this.myvalue', this.myvalue)
  359. return this.myvalue ? this.myvalue.some(item => {
  360. return String(item) == String(id)
  361. }) : false
  362. },
  363. //显示
  364. show() {
  365. if (this.disabled) {
  366. return false
  367. }
  368. this.initvalue()
  369. this.visible = true;
  370. },
  371. //点击取消
  372. pickerCancel() {
  373. this.visible = false;
  374. }
  375. }
  376. }
  377. </script>
  378. <style lang="scss" scoped>
  379. .submit-frame {
  380. background-color: #ffffff;
  381. padding: 24rpx 30rpx;
  382. box-shadow: 0 0 12rpx 12rpx rgba(0, 0, 0, 0.04);
  383. .btn-frame {
  384. /* #ifndef APP-NVUE */
  385. display: flex;
  386. /* #endif */
  387. flex: 1;
  388. flex-direction: row;
  389. border-radius: 88rpx;
  390. overflow: hidden;
  391. }
  392. .flex {
  393. /* #ifndef APP-NVUE */
  394. display: flex;
  395. /* #endif */
  396. flex-direction: row;
  397. }
  398. .uni-tab__cart-button-right {
  399. height: 88rpx;
  400. /* #ifndef APP-NVUE */
  401. display: flex;
  402. flex-direction: column;
  403. /* #endif */
  404. flex: 2;
  405. justify-content: center;
  406. align-items: center;
  407. /* #ifdef H5 */
  408. cursor: pointer;
  409. /* #endif */
  410. }
  411. .uni-tab__cart-button-right-text {
  412. font-size: 14px;
  413. color: #fff;
  414. }
  415. .uni-tab__cart-button-right:active {
  416. opacity: 0.7;
  417. }
  418. }
  419. .gui-sel-load-list {
  420. overflow: hidden;
  421. .pf-picker-hd {
  422. display: flex;
  423. padding: 30rpx;
  424. background-color: #fff;
  425. position: relative;
  426. text-align: center;
  427. font-size: 34rpx;
  428. justify-content: space-between;
  429. &:after {
  430. content: ' ';
  431. position: absolute;
  432. left: 0;
  433. bottom: 0;
  434. right: 0;
  435. height: 1rpx;
  436. z-index: 1;
  437. // border-bottom: 1rpx solid #e5e5e5;
  438. background-color: #e5e5e5;
  439. transform-origin: 0 100%;
  440. transform: scaleY(0.5);
  441. }
  442. }
  443. .item {
  444. text-align: center;
  445. line-height: 80rpx;
  446. text-overflow: ellipsis;
  447. white-space: nowrap;
  448. font-size: 32rpx;
  449. }
  450. .pf-picker-view {
  451. width: 100%;
  452. height: 600rpx;
  453. overflow: hidden;
  454. background-color: rgba(255, 255, 255, 1);
  455. z-index: 666;
  456. }
  457. .pf-picker-btn {
  458. font-size: 32rpx;
  459. color: #888888;
  460. }
  461. .one-picker-view {
  462. height: 100%;
  463. }
  464. }
  465. .uni-border-bottom {
  466. position: relative;
  467. }
  468. .uni-border-bottom::after {
  469. content: ' ';
  470. position: absolute;
  471. left: 64rpx;
  472. bottom: 0;
  473. right: 0;
  474. height: 1rpx;
  475. z-index: 1;
  476. background-color: #e5e5e5;
  477. transform-origin: 0 100%;
  478. transform: scaleY(0.5);
  479. }
  480. </style>