selectProject.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. <template>
  2. <el-select v-model="selectedValue" size="mini" filterable remote @change="updateValue"
  3. :remote-method="projectListRemotemethod" :loading="newProjectListLoading" @visible-change="visibleChangeProjrct" @focus="peojectFocus">
  4. <div ref="mySelectProject" class="select-project-class">
  5. <el-option v-for="item in newProjectList" :key="item.id" :label="item.projectName + '\u3000' + item.projectCode"
  6. :value="item.id">
  7. <span style="float: left; color: #8492a6; font-size: 13px;">{{ item.projectCode }}</span>
  8. <span style="float: right;margin-left: 20px">{{ item.projectName }}</span>
  9. </el-option>
  10. <div class="itemsLoading" v-if="loadingInProgress">
  11. 加载中...
  12. </div>
  13. </div>
  14. </el-select>
  15. </template>
  16. <script>
  17. export default {
  18. name: 'selectProject',
  19. props: {
  20. value: {
  21. type: [String, Number],
  22. required: true
  23. }
  24. },
  25. data() {
  26. return {
  27. newProjectListLoading: false,
  28. newProjectList: [],
  29. selectedValue: this.value,
  30. newProjectListPage: 1,
  31. newProjectListSize: 20,
  32. newProjectListTotal: 0,
  33. loadingInProgress: false,
  34. loadingInProgressHight: 0,
  35. refRollVal: null,
  36. scrollListener: null,
  37. infoString: ''
  38. }
  39. },
  40. watch: {
  41. value(newValue) {
  42. this.selectedValue = newValue;
  43. },
  44. selectedValue(newValue) {
  45. this.$emit('input', newValue);
  46. }
  47. },
  48. methods: {
  49. projectListRemotemethod: _.debounce(function (val) {
  50. this.newProjectListPage = 1
  51. this.getNewProjectList(val)
  52. }, 300),
  53. peojectFocus() {
  54. this.newProjectListPage = 1
  55. this.getNewProjectList()
  56. },
  57. getNewProjectList(infoString = '') {
  58. this.infoString = infoString
  59. this.newProjectListLoading = true
  60. this.postData(`/project/getProjectListByPage`, {
  61. pageIndex: this.newProjectListPage,
  62. pageSize: this.newProjectListSize,
  63. id: this.curProjectId,
  64. forReport: 0,
  65. infoString,
  66. }).then((res) => {
  67. this.newProjectList = res.data.data
  68. this.newProjectListTotal = res.data.total
  69. }).finally(() => {
  70. this.newProjectListLoading = false
  71. })
  72. },
  73. addNewProjectList() {
  74. this.loadingInProgress = true
  75. this.postData(`/project/getProjectListByPage`, {
  76. pageIndex: this.newProjectListPage,
  77. pageSize: this.newProjectListSize,
  78. id: this.curProjectId,
  79. forReport: 0,
  80. infoString: this.infoString,
  81. }).then((res) => {
  82. this.newProjectList = [...this.newProjectList, ...res.data.data]
  83. }).finally(() => {
  84. setTimeout(() => {
  85. this.loadingInProgress = false
  86. }, 500)
  87. })
  88. },
  89. handleScroll(event) {
  90. const container = event.target;
  91. const { scrollTop, scrollHeight, clientHeight } = container;
  92. const totalPage = Math.ceil(this.newProjectListTotal / this.newProjectListSize);
  93. if (scrollTop + clientHeight >= scrollHeight - 20 && this.newProjectListPage < totalPage && !this.loadingInProgress) {
  94. this.loadMoreData()
  95. }
  96. },
  97. loadMoreData() {
  98. this.newProjectListPage += 1;
  99. this.addNewProjectList();
  100. },
  101. visibleChangeProjrct(flag) {
  102. if (flag) {
  103. this.$nextTick(() => {
  104. this.addScrollListener();
  105. });
  106. } else {
  107. this.removeScrollListener();
  108. }
  109. },
  110. addScrollListener() {
  111. const container = this.$refs.mySelectProject;
  112. const scrollbar = container.closest('.el-scrollbar__wrap');
  113. if (scrollbar) {
  114. this.loadingInProgressHight = scrollbar.clientHeight - 40
  115. this.removeScrollListener();
  116. const debouncedHandleScroll = _.debounce(this.handleScroll, 200);
  117. scrollbar.addEventListener('scroll', debouncedHandleScroll);
  118. this.scrollListener = debouncedHandleScroll;
  119. }
  120. },
  121. removeScrollListener() {
  122. const container = this.$refs.mySelectProject;
  123. const scrollbar = container.closest('.el-scrollbar__wrap');
  124. if (scrollbar && this.scrollListener) {
  125. scrollbar.removeEventListener('scroll', this.scrollListener);
  126. this.scrollListener = null;
  127. }
  128. },
  129. async postData(urls, param) {
  130. return new Promise((resolve, reject) => {
  131. this.http.post(urls, { ...param },
  132. res => {
  133. if (res.code == 'ok') {
  134. resolve(res)
  135. } else {
  136. this.$message({
  137. message: res.msg,
  138. type: 'error'
  139. })
  140. reject(res)
  141. }
  142. resolve(res)
  143. },
  144. error => {
  145. this.$message({
  146. message: error,
  147. type: "error"
  148. });
  149. reject(error)
  150. }
  151. )
  152. });
  153. },
  154. updateValue(value) {
  155. this.$emit('input', value);
  156. this.$emit('change', value);
  157. }
  158. },
  159. created() {
  160. },
  161. mounted() {
  162. this.getNewProjectList()
  163. },
  164. beforeDestroy() {
  165. this.removeScrollListener();
  166. }
  167. }
  168. </script>
  169. <style lang="scss" scoped>
  170. .select-project-class {
  171. position: relative;
  172. .itemsLoading {
  173. position: absolute;
  174. left: 0;
  175. bottom: -2px;
  176. width: 100%;
  177. text-align: center;
  178. padding: 10px;
  179. background: #fff;
  180. box-shadow: 0px -4px 20px 0px #999;
  181. font-size: 12px;
  182. color: #999;
  183. z-index: 99;
  184. box-sizing: border-box;
  185. }
  186. }
  187. </style>