InvoiceProjectChoose.vue 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. <template>
  2. <view style="width: 100%;">
  3. <u-action-sheet :show="show" @close="onClose">
  4. <view class="cu-bar bg-white">
  5. <view class="action text-blue" @tap="onClose">取消</view>
  6. <view v-if="isShow">
  7. <u-radio-group v-model="checkType" >
  8. <u-radio
  9. :customStyle="{marginRight: '16px'}"
  10. v-for="(item, index) in checkTypeList"
  11. :key="index"
  12. :label="item.name"
  13. :name="item.value"
  14. @change="checkTypeChange"
  15. ></u-radio>
  16. </u-radio-group>
  17. </view>
  18. <view class="action text-green" @tap="selectUsers">确定</view>
  19. </view>
  20. <view style="max-height: 300px; overflow-y: auto;">
  21. <view v-for="item in data" :key="item.id" style="padding: 10px;">
  22. <view @tap="onItemClick(item)" style="display: flex; align-items: center;">
  23. <view style="flex: 1;text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">{{ item.projectName }}</view>
  24. <!-- <view v-if="checkType === '2'" style="flex: 1;text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">{{ item.reportNo }}</view>-->
  25. <view v-if="item.checked" style="color: #409eff;">已选择</view>
  26. </view>
  27. </view>
  28. </view>
  29. <view v-if="!allDataLoaded && !loading" style="text-align: center; padding: 10px;">
  30. <button class="load-more-button" @tap="loadMore">加载更多</button>
  31. </view>
  32. <view v-if="loading" style="text-align: center; padding: 10px;">
  33. Loading...
  34. </view>
  35. </u-action-sheet>
  36. </view>
  37. </template>
  38. <script>
  39. import projectRecordsService from '@/api/cw/projectRecords/ProjectRecordsService'
  40. export default {
  41. data() {
  42. return {
  43. checkType: '1',
  44. checkTypeList: [{
  45. name: '项目',
  46. value: '1',
  47. disabled: false
  48. },{
  49. name: '报告',
  50. value: '2',
  51. disabled: false
  52. }],
  53. show: false,
  54. isShow: false,
  55. labels:'',
  56. index:'',
  57. type:'',
  58. data: [],
  59. localMode: '', // 声明一个本地数据属性
  60. allDataLoaded: false, // 跟踪是否所有数据都已加载
  61. loading: false, // 跟踪加载状态
  62. pageSize: 10, // 每页获取的项目数
  63. currentPage: 1 // 当前页数
  64. };
  65. },
  66. props: {
  67. value: String,
  68. placeholder: {
  69. type: String,
  70. default: '请选择项目'
  71. },
  72. readonly: {
  73. type: Boolean,
  74. default: false
  75. },
  76. disabled: {
  77. type: Boolean,
  78. default: false
  79. },
  80. },
  81. mounted() {
  82. // this.loadData();
  83. },
  84. methods: {
  85. init(index, type) {
  86. this.pageSize = 10
  87. this.currentPage = 1
  88. this.show = true;
  89. this.index = index;
  90. //选项的选择模式,单选或多选,默认为多选
  91. // if (type === 'report') {
  92. // this.localMode = 'single'
  93. // } else {
  94. // this.localMode = 'multiple'
  95. // }
  96. this.localMode = 'multiple'
  97. if (this.isNotEmpty(type)) {
  98. this.checkType = type
  99. this.isShow = false
  100. } else {
  101. this.isShow = true
  102. }
  103. if (index === 1 || index === '1') {
  104. if (type === '1') {
  105. uni.showToast({
  106. title: '第一条为项目后面新增只能选择项目',
  107. icon: 'none',
  108. duration: 2000
  109. });
  110. } else if (type === '2') {
  111. uni.showToast({
  112. title: '第一条为报告后面新增只能选择报告',
  113. icon: 'none',
  114. duration: 2000
  115. });
  116. }
  117. }
  118. this.loadData();
  119. },
  120. onItemClick(item) {
  121. if (this.localMode === 'single') {
  122. this.data.forEach(node => {
  123. node.checked = node === item;
  124. });
  125. } else {
  126. item.checked = !item.checked;
  127. }
  128. },
  129. selectUsers() {
  130. if (this.data.some(item => item.checked)) {
  131. let checkedItems = this.data.filter(item => item.checked).map(item => {
  132. return {
  133. id: item.id,
  134. projectName: item.projectName,
  135. contractName: item.contractName,
  136. projectNumber: item.projectNumber,
  137. contractId: item.contractId,
  138. reportNo: item.reportNo,
  139. isPreInvoice: item.isPreInvoice,
  140. };
  141. });
  142. this.$emit('input', checkedItems, this.index);
  143. this.onClose()
  144. } else {
  145. uni.showToast({
  146. title: '请至少选择一条数据',
  147. icon: 'none',
  148. duration: 2000
  149. });
  150. }
  151. },
  152. loadData() {
  153. this.loading = true; // 开始加载数据,显示loading状态
  154. if (this.checkType === '1') {
  155. projectRecordsService.noReportList({ status: 5, current: this.currentPage, pageSize: this.pageSize })
  156. .then(data => {
  157. this.loading = false; // 数据加载完成,隐藏loading状态
  158. // 检查新返回的数据是否已经存在,如果存在,则不添加到原始数据数组中
  159. let newData = data.records.filter(record => !this.data.some(item => item.id === record.id));
  160. if (this.currentPage === 1) {
  161. // 如果是加载第一页,则直接赋值给 data
  162. this.data = newData.map(item => ({ ...item, checked: false }));
  163. } else {
  164. // 如果不是第一页,则追加到原始数据数组后面
  165. this.data = [...this.data, ...newData.map(item => ({ ...item, checked: false }))];
  166. }
  167. if (data.records.length < this.pageSize) {
  168. this.allDataLoaded = true; // 如果返回的数据少于每页数量,则表示所有数据都已加载
  169. }
  170. if (this.value) {
  171. let keys = this.value.split(',');
  172. this.data.forEach(node => {
  173. if (keys.includes(node.id)) {
  174. node.checked = true;
  175. }
  176. });
  177. this.labels = this.data.filter(node => node.checked).map(node => node.label).join(',');
  178. }
  179. })
  180. .catch(e => {
  181. this.loading = false; // 数据加载失败,隐藏loading状态
  182. throw e;
  183. });
  184. } else if (this.checkType === '2') {
  185. projectRecordsService.list1({ status: 5, current: this.currentPage, pageSize: this.pageSize })
  186. .then(data => {
  187. this.loading = false; // 数据加载完成,隐藏loading状态
  188. // 检查新返回的数据是否已经存在,如果存在,则不添加到原始数据数组中
  189. let newData = data.records.filter(record => !this.data.some(item => item.id === record.id));
  190. if (this.currentPage === 1) {
  191. // 如果是加载第一页,则直接赋值给 data
  192. this.data = newData.map(item => ({ ...item, checked: false }));
  193. } else {
  194. // 如果不是第一页,则追加到原始数据数组后面
  195. this.data = [...this.data, ...newData.map(item => ({ ...item, checked: false }))];
  196. }
  197. if (data.records.length < this.pageSize) {
  198. this.allDataLoaded = true; // 如果返回的数据少于每页数量,则表示所有数据都已加载
  199. }
  200. if (this.value) {
  201. let keys = this.value.split(',');
  202. this.data.forEach(node => {
  203. if (keys.includes(node.id)) {
  204. node.checked = true;
  205. }
  206. });
  207. this.labels = this.data.filter(node => node.checked).map(node => node.label).join(',');
  208. }
  209. })
  210. .catch(e => {
  211. this.loading = false; // 数据加载失败,隐藏loading状态
  212. throw e;
  213. });
  214. }
  215. },
  216. loadMore() {
  217. this.currentPage++; // 增加当前页数
  218. this.loadData(); // 加载更多数据
  219. },
  220. onClose() {
  221. // 在关闭操作中清除已选择标记
  222. this.data.forEach(item => {
  223. item.checked = false;
  224. });
  225. this.labels = ''; // 清空标签
  226. this.show = false;
  227. this.checkType = '1';
  228. this.data = []; // 清空原始数据
  229. },
  230. checkTypeChange(value){
  231. this.checkType = value
  232. this.pageSize = 10
  233. this.currentPage = 1
  234. this.data = []; // 清空原始数据
  235. this.loadData(); // 加载更多数据
  236. },
  237. isEmpty(value) {
  238. let result = false;
  239. if (value == null || value == undefined) {
  240. result = true;
  241. }
  242. if (typeof value == 'string' && (value.replace(/\s+/g, "") == "" || value == "")) {
  243. result = true;
  244. }
  245. if (typeof value == "object" && value instanceof Array && value.length === 0) {
  246. result = true;
  247. }
  248. return result;
  249. },
  250. isNotEmpty (value) {
  251. return !this.isEmpty(value)
  252. },
  253. }
  254. };
  255. </script>
  256. <style scoped>
  257. .load-more-button {
  258. background-color: #409eff;
  259. color: #fff;
  260. border: none;
  261. padding: 10px 20px;
  262. border-radius: 4px;
  263. cursor: pointer;
  264. }
  265. </style>