selectObjectNoDedup.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <template>
  2. <view class="page_body">
  3. <!-- 头部 -->
  4. <nav-bar :class="{'item_width':pageType=='edit'}" height="320" title="选择采集对象" :defaultTabBtnValue="targetType" :tabBtns="state.tabBtns" :onlyTitle="false" :showHeadSearchInput="false" :showFilterPicker="false" :showTabs="false" :showTabBtns="true" rightWidth="0rpx" @CommonFilterData="CommonFilterData" @GoBack="GoBack">
  5. <template #tabs_bottom_content>
  6. <!-- 搜索框单独一行 -->
  7. <view class="nav_head row_search_box">
  8. <uni-easyinput class="search_box" v-model="state.searchWord" trim="all" :styles="state.searchInputStyles"
  9. :placeholderStyle="state.searchInputPlaceholderStyle" placeholder="请输入关键字搜索">
  10. <template #left>
  11. <image src="@/static/image/overview/search.png" class="search_icon"></image>
  12. </template>
  13. </uni-easyinput>
  14. </view>
  15. </template>
  16. </nav-bar>
  17. <!-- https://ofreshman.github.io/uni-tree-view/guide/quick-start -->
  18. <!-- expand-on-click-node: 点击整行是否展开/收起-->
  19. <view class="tree_node">
  20. <uni-tree-view
  21. selectable
  22. multiple
  23. ref="treeRef"
  24. theme-color="#2E64FA"
  25. v-model="state.defaultCheckedKeys"
  26. :default-expand-all="false"
  27. :expand-on-click-node="true"
  28. :checked-disabled="true"
  29. :filter-value="state.searchWord"
  30. highlight-filter
  31. :data="state.treeData"
  32. @check-change="HandleCheckChange"
  33. >
  34. <template #append="{ data,node }">
  35. <!-- data 是你传入的原始数据项,可读任意业务字段 -->
  36. <uni-icons v-if="data?.children?.length" :type="node.expanded?'down':'right'" style="font-size: 28rpx;color: #999999;"></uni-icons>
  37. </template>
  38. </uni-tree-view>
  39. </view>
  40. <view class="foot_btn">
  41. <view class="btn_submit" @click="SaveCheckedTreeData">确定{{state.checkedValue.length?`(已选${state.checkedValue.length}人)`:''}}</view>
  42. </view>
  43. </view>
  44. </template>
  45. <script setup>
  46. import navBar from '@/components/navBar.vue';
  47. import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue';
  48. import uniEasyinput from '@/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue';
  49. import uniTreeView from '@/uni_modules/KieranYin9527-tree/components/uni-tree-view/uni-tree-view.vue';
  50. import {findDepartContainUser,findCollectPersonalInfo} from '@/reqApi/notification.js';
  51. import {getDeptTreeData,subjectTreeData,gradTreeData,permTreeData} from '@/common/common.js';
  52. import {onLoad} from '@dcloudio/uni-app';
  53. import {reactive,ref,onUnmounted,nextTick} from 'vue';
  54. const state = reactive({
  55. tabBtns:[{
  56. label:'按部门',
  57. value:1,
  58. },{
  59. label:'按学科',
  60. value:2,
  61. },{
  62. label:'按年级',
  63. value:3,
  64. },{
  65. label:'按权限',
  66. value:4,
  67. }],
  68. defaultCheckedKeys:[],//初始选中key
  69. checkedDisabled:[],
  70. checkedValue:[],//勾选的项
  71. treeData:[],
  72. deptTreeData:[],//部门tree
  73. gradeTreeList:[],//年级tree
  74. permissionTreeList:[],//权限tree
  75. subjectTreeList:[]//学科tree
  76. });
  77. const schoolYearId = ref('');//学年学期id
  78. const targetType = ref('');//采集对象 1-按部门,2-按学科,3-按年级,4-按权限,5-按学生
  79. const pageType = ref('');//添加或修改
  80. const treeRef = ref('');
  81. onLoad((option) => {
  82. schoolYearId.value = option.schoolYearId;
  83. targetType.value = Number(option.targetType);
  84. pageType.value = option.type;
  85. const taskTargetsTreeData = uni.getStorageSync('taskTargetsTreeData');
  86. const taskTargets = taskTargetsTreeData?.taskTargets || [];
  87. state.checkedValue = taskTargets;
  88. state.defaultCheckedKeys = taskTargets?.map(item=>item.id) || [];
  89. state.checkedDisabled = taskTargets.filter(item=>item.disabled && item.checked=='checked');
  90. if(pageType.value == 'add'){
  91. GetDepartContainUser();
  92. GetCollectPersonalInfo();
  93. }else{//编辑
  94. state.tabBtns = state.tabBtns.filter(item=>item.value == targetType.value);
  95. state.treeData = taskTargetsTreeData?.taskTargetsTree || [];
  96. }
  97. })
  98. //查询本学校下的当前学年的所有部门及部门下的人
  99. const GetDepartContainUser = () => {
  100. findDepartContainUser(schoolYearId.value).then(res=>{
  101. if(res.code == 200){
  102. const resData = res.data || [];
  103. state.deptTreeData = getDeptTreeData(resData);
  104. CurrentTreeData();
  105. }
  106. })
  107. }
  108. //查询本学校下的当前学年的所有学科、年级、权限数据及下的人
  109. const GetCollectPersonalInfo = async () => {
  110. const res = await findCollectPersonalInfo(schoolYearId.value);
  111. const { collectGradePersonVos, collectPermissionPersonVos, subjectPersonVoList } = res.data;
  112. state.gradeTreeList = gradTreeData(collectGradePersonVos);
  113. state.permissionTreeList = permTreeData(collectPermissionPersonVos);
  114. state.subjectTreeList = subjectTreeData(subjectPersonVoList);
  115. CurrentTreeData();
  116. }
  117. const CommonFilterData = (filterOptions,type) => {
  118. if(type=='tabBtns' && pageType.value == 'add'){
  119. targetType.value = filterOptions.tabBtnSelected;
  120. CurrentTreeData();
  121. }
  122. }
  123. const CurrentTreeData = () => {
  124. // 1-按部门,2-按学科,3-按年级,4-按权限,5-按学生
  125. if(targetType.value == 1){
  126. state.treeData = [...state.deptTreeData];
  127. }else if(targetType.value == 2){
  128. state.treeData = [...state.subjectTreeList];
  129. }else if(targetType.value == 3){
  130. state.treeData = state.gradeTreeList;
  131. }else if(targetType.value == 4){
  132. state.treeData = state.permissionTreeList;
  133. }else{
  134. state.treeData = [];
  135. }
  136. }
  137. //选择的值
  138. const HandleCheckChange = ({keys,node,nodes,value}) => {
  139. // 不可取消的节点 key 列表
  140. const lockedKeys = state.checkedDisabled.map(el=>el.id)
  141. const merged = [...new Set([...keys, ...lockedKeys])];//去重
  142. state.defaultCheckedKeys = merged;
  143. const nodesList = nodes.filter(item => item.isLeaf).map(el => ({ ...el.source }));
  144. //去重
  145. state.checkedValue = [...new Map([...nodesList, ...state.checkedDisabled].map(item => [item.id, item])).values()];
  146. }
  147. //保存选择值
  148. const SaveCheckedTreeData = () => {
  149. if(state.checkedValue.length == 0){
  150. uni.showToast({
  151. title: '请选择采集对象!',
  152. icon: 'none'
  153. })
  154. return false
  155. }
  156. uni.setStorageSync('taskTargetsTreeData',{
  157. targetType:targetType.value,
  158. taskTargets:state.checkedValue//采集对象
  159. });//返回上一页并传值
  160. GoBack()
  161. }
  162. //返回
  163. const GoBack = () => {
  164. uni.navigateBack({
  165. delta: 1
  166. });
  167. }
  168. </script>
  169. <style scoped lang="scss">
  170. :deep(.item_width){
  171. .scroll_tab_btn{
  172. .tab_item{
  173. width: 122rpx;
  174. flex: 0;
  175. }
  176. }
  177. }
  178. :deep(.scroll_tab_btn){
  179. margin-top: 24rpx;
  180. .tab_item{
  181. &.selected{
  182. background-color: #2E64FA;
  183. color: #FFFFFF;
  184. }
  185. }
  186. }
  187. .page_body{
  188. display: flex;
  189. flex-direction: column;
  190. height: 100%;
  191. min-width: auto;
  192. .row_search_box{
  193. height: 96rpx;
  194. align-items: flex-start;
  195. }
  196. .tree_node{
  197. display: flex;
  198. width: 100%;
  199. padding: 0 24rpx;
  200. box-sizing: border-box;
  201. flex:1;
  202. overflow: auto;
  203. :deep(.utv-tree-item__arrow-icon){
  204. display: none;
  205. }
  206. }
  207. .foot_btn{
  208. width: 100%;
  209. padding: 40rpx 24rpx;
  210. flex-shrink: 0;
  211. box-sizing: border-box;
  212. .btn_submit{
  213. background-color: #2E64FA;
  214. border-radius: 8rpx;
  215. width: 100%;
  216. height: 90rpx;
  217. font-weight: 500;
  218. font-size: 28rpx;
  219. color: #FFFFFF;
  220. display: flex;
  221. align-items: center;
  222. justify-content: center;
  223. }
  224. }
  225. }
  226. </style>