chart.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. <template>
  2. <page-meta :page-style="showFilter? 'overflow: hidden;' : ''" :scroll-top="pageMetaScrollTop" />
  3. <view class="chart-page" v-if="hasAuth">
  4. <van-sticky style="background: #fff">
  5. <view class="flex search-wrap">
  6. <van-search
  7. shape="round"
  8. :value="searchVal"
  9. placeholder="图表名称搜索"
  10. @change="searchValChange"
  11. @search="onSearch"
  12. @clear="onClearSearch"
  13. clear-trigger="always"
  14. style="flex:1"
  15. />
  16. <image
  17. src="../../static/chart/menu.png"
  18. mode="widthFix"
  19. class="menu-icon"
  20. @click="showFilter=true"
  21. />
  22. </view>
  23. </van-sticky>
  24. <view class="empty-box" v-if="list.length==0&&finished">
  25. <image
  26. :src="globalImgUrls.chartEmpty"
  27. mode="widthFix"
  28. />
  29. <view v-if="searchVal">暂时找不到对应图,试试别的搜索词吧~</view>
  30. <view v-else>
  31. <text v-if="myClassifyList.length==0&&pubClassifyList.length==0">暂时没有图分类,请耐心等待</text>
  32. <text v-else>暂时找不到对应图,试试别的分类吧~</text>
  33. </view>
  34. </view>
  35. <view class="chart-list-wrap" v-else>
  36. <drag
  37. v-if="list.length>0"
  38. ref="chartDragIns"
  39. generic:item="chart-item"
  40. :columns="2"
  41. :list-data="list"
  42. :itemHeight="400"
  43. :searchVal="searchVal"
  44. @sortend="chartSortend"
  45. @click="chartClick"
  46. @scroll="chartScroll"
  47. :scroll-top="scrollTop"
  48. ></drag>
  49. </view>
  50. </view>
  51. <!-- 无权限 -->
  52. <noAuth :info="noAuthData" v-else></noAuth>
  53. <!-- 筛选弹窗 -->
  54. <van-popup
  55. :show="showFilter"
  56. @close="showFilter=false"
  57. position="bottom"
  58. closeable
  59. round
  60. z-index="99999"
  61. >
  62. <view class="filter-wrap">
  63. <view class="top">
  64. <text class="left" @click="goAllTypes">展开</text>
  65. <text class="center">全部筛选</text>
  66. </view>
  67. <view class="filter-list" style="padding-top:200rpx;text-align:center" v-if="myClassifyList.length==0&&pubClassifyList.length==0">
  68. 暂时没有图分类,请耐心等待
  69. </view>
  70. <view class="filter-list" v-else>
  71. <view class="title" v-if="userInfo.is_inner==1">公共图库</view>
  72. <view
  73. :class="['filter-item',selectClassifyId==item.myChartClassifyId?'active':'']"
  74. v-for="item in pubClassifyList"
  75. :key="item.myChartClassifyName"
  76. @click="handleSelectClassify(item,true)"
  77. >{{item.myChartClassifyName}}</view>
  78. <block v-if="myClassifyList.length>0">
  79. <view class="title" style="border:none">我的图库</view>
  80. <dragSorts
  81. :list="myClassifyList"
  82. :selectId="selectClassifyId"
  83. :rowHeight="rowHeight"
  84. :listHeight="classifyListHeight+20"
  85. @onclick="myClassifyClick"
  86. @confirm="myClassifyMoveEnd"
  87. ></dragSorts>
  88. </block>
  89. </view>
  90. </view>
  91. </van-popup>
  92. </template>
  93. <script>
  94. import chartItem from './component/chartItem.vue'
  95. import dragSorts from '../../components/chartClassifyItem/HM-dragSorts.vue'
  96. import noAuth from './component/noAuth.vue'
  97. import {apiChartList,apiChartClassifyList,apiChartMove,apiClassifyMove} from '@/api/chart'
  98. export default {
  99. components: {
  100. 'chart-item':chartItem,
  101. dragSorts,
  102. noAuth
  103. },
  104. data() {
  105. return {
  106. list:[],
  107. page:1,
  108. finished:false,
  109. chartDragIns:null,//图表拖拽实例
  110. pageMetaScrollTop:0,
  111. scrollTop:0,
  112. showFilter:false,//显示筛选弹窗
  113. pubClassifyList:[],//公共图库分类数据
  114. myClassifyList:[],//我的图库分类数据
  115. selectClassifyId:0,//选中的分类id
  116. isPublic:false,//是否当前显示的列表数据为公共图库数据
  117. classifyListHeight:0,//我的分类默认高度
  118. rowHeight:44,
  119. searchVal:'',//图库搜素关键词
  120. hasAuth:true,//是否有权限
  121. noAuthData:null,//没有权限时传给无权限组件的值
  122. }
  123. },
  124. onLoad() {
  125. this.getClassifyList('first')
  126. this.addEventListenerSelectClassify()
  127. },
  128. onShow() {
  129. this.getClassifyList()
  130. // if(!this.hasAuth){
  131. // this.getClassifyList()
  132. // }
  133. },
  134. onUnload(){
  135. uni.$off('classifyPageSelect')
  136. },
  137. onPullDownRefresh() {
  138. this.initPage()
  139. this.getClassifyList('first')
  140. setTimeout(() => {
  141. uni.stopPullDownRefresh()
  142. }, 1500)
  143. },
  144. onReachBottom() {
  145. if (this.finished) return
  146. this.page++
  147. this.getList()
  148. },
  149. onShareAppMessage(res) {
  150. return {
  151. title: 'ETA图库',
  152. path: ''
  153. }
  154. },
  155. onPageScroll({ scrollTop }) {
  156. this.scrollTop=scrollTop
  157. },
  158. methods: {
  159. // 获取列表
  160. async getList(){
  161. this.scrollTop=0
  162. this.pageMetaScrollTop=0
  163. const res=await apiChartList({
  164. Page:this.page,
  165. Limit:20,
  166. ClassifyId:this.selectClassifyId,
  167. Keywords:this.searchVal
  168. })
  169. if(res.code===200){
  170. this.hasAuth=true
  171. if(res.data){
  172. // 公共图库分类下数据不允许拖动
  173. let arr=res.data.map(item=>{
  174. return {...item,dragId:item.UniqueCode,fixed: this.isPublic?true:false}
  175. })
  176. this.list=[...this.list,...arr]
  177. setTimeout(() => {
  178. this.chartDragIns=this.$refs.chartDragIns
  179. this.chartDragIns.init();// 初始化列表
  180. }, 100);
  181. }else{
  182. this.finished=true
  183. }
  184. }else if(res.code===403){//无权限
  185. this.hasAuth=false
  186. this.noAuthData=res.data
  187. }
  188. },
  189. //图表移动排序结束
  190. async chartSortend(e){
  191. // curIndex 为排序前元素所在位置 listData为排序后的数组
  192. let {curIndex,listData}=e.detail
  193. const moveTarget=this.list[curIndex]
  194. console.log(moveTarget.ChartName);
  195. // 找到移动后所在位置
  196. const endIndex=listData.findIndex(item=>item.MyChartId===moveTarget.MyChartId)
  197. console.log('移动结束后序号:',endIndex);
  198. const NextMyChartId=listData[endIndex+1]&&listData[endIndex+1].MyChartId||0
  199. const PrevMyChartId=listData[endIndex-1]&&listData[endIndex-1].MyChartId||0
  200. const res=await apiChartMove({
  201. MyChartId:moveTarget.MyChartId,
  202. MyChartClassifyId:this.selectClassifyId,
  203. PrevMyChartId:PrevMyChartId,
  204. NextMyChartId:NextMyChartId,
  205. })
  206. if(res.code===200){
  207. this.list=listData
  208. setTimeout(() => {
  209. this.chartDragIns.init();
  210. }, 100);
  211. }else{
  212. uni.showToast({
  213. title: '移动失败',
  214. icon: 'none'
  215. })
  216. }
  217. },
  218. // 图表点击某项
  219. chartClick(e){
  220. console.log(e.detail.data);
  221. uni.navigateTo({
  222. url:`/pages-chart/chartDetail?chartInfoId=${e.detail.data.ChartInfoId}&searchVal=${this.searchVal}&MyChartId=${e.detail.data.MyChartId}&MyChartClassifyId=${this.selectClassifyId}`
  223. })
  224. },
  225. // 图表移动时滚动
  226. chartScroll(e){
  227. uni.stopPullDownRefresh()
  228. this.pageMetaScrollTop=e.detail.scrollTop
  229. },
  230. // 获取分类数据
  231. async getClassifyList(no){
  232. const res=await apiChartClassifyList()
  233. if(res.code===200){
  234. this.myClassifyList=res.data.private_classify||[]
  235. this.pubClassifyList=res.data.public_classify||[]
  236. this.classifyListHeight=this.rowHeight*this.myClassifyList.length
  237. if(no=='first'){
  238. if(res.data.private_classify){
  239. this.selectClassifyId=res.data.private_classify&&res.data.private_classify[0].myChartClassifyId||''
  240. this.isPublic=false
  241. }else{
  242. this.selectClassifyId=res.data.public_classify&&res.data.public_classify[0].myChartClassifyId||''
  243. this.isPublic=true
  244. }
  245. this.getList()
  246. }
  247. }else if(res.code===403){//无权限
  248. this.hasAuth=false
  249. this.noAuthData=res.data
  250. }
  251. },
  252. // 我的分类点击
  253. myClassifyClick(e){
  254. this.handleSelectClassify(e.value,false)
  255. },
  256. // 选中分类
  257. handleSelectClassify(item,isPublic){
  258. this.initPage()
  259. this.searchVal=''
  260. this.selectClassifyId=item.myChartClassifyId
  261. this.isPublic=isPublic
  262. this.getList()
  263. this.showFilter=false
  264. },
  265. // 跳转全部分类
  266. goAllTypes(){
  267. uni.navigateTo({
  268. url: '/pages-chart/allTypes?selectId='+this.selectClassifyId
  269. })
  270. this.showFilter=false
  271. },
  272. // 分类移动
  273. async myClassifyMoveEnd(e){
  274. const moveTarget=e.moveRow
  275. const index=e.moveTo// 拖动后的序号
  276. const list=e.list//拖动后的列表
  277. // console.log(moveTarget.myChartClassifyId);
  278. // console.log(index);
  279. // console.log(list);
  280. const PrevClassifyId=list[index-1]&&list[index-1].myChartClassifyId||0
  281. const NextClassifyId=list[index+1]&&list[index+1].myChartClassifyId||0
  282. const res=await apiClassifyMove({
  283. MyChartClassifyId:moveTarget.myChartClassifyId,
  284. PrevClassifyId:PrevClassifyId,
  285. NextClassifyId:NextClassifyId
  286. })
  287. if(res.code===200){
  288. this.myClassifyList=list
  289. }else{
  290. uni.showToast({
  291. title: '移动失败',
  292. icon: 'none'
  293. })
  294. }
  295. },
  296. // 搜索关键词变化
  297. searchValChange(e){
  298. this.searchVal=e.detail
  299. },
  300. // 确认搜索 搜索图表下的都不允许拖动排序
  301. onSearch(){
  302. if(!this.searchVal){
  303. uni.showToast({
  304. title:"请输入搜索关键词",
  305. icon:'none'
  306. })
  307. return
  308. }
  309. this.initPage()
  310. this.isPublic=true
  311. this.getList()
  312. },
  313. // 清除搜索内容
  314. onClearSearch(){
  315. this.initPage()
  316. this.searchVal=''
  317. this.isPublic=false
  318. this.getClassifyList('first')
  319. },
  320. // 初始化页面数据
  321. initPage(){
  322. this.page=1
  323. this.list=[]
  324. this.finished=false
  325. this.selectClassifyId=0
  326. this.pageMetaScrollTop=0
  327. this.scrollTop=0
  328. },
  329. // 监听分类页面选中分类事件
  330. addEventListenerSelectClassify(){
  331. uni.$on('classifyPageSelect',e=>{
  332. console.log(e);
  333. this.handleSelectClassify({myChartClassifyId:e.selectId},e.isPublic)
  334. })
  335. },
  336. }
  337. }
  338. </script>
  339. <style lang="scss" scoped>
  340. .chart-page {
  341. min-height: calc(100vh - calc(50px + constant(safe-area-inset-bottom)));
  342. min-height: calc(100vh - calc(50px + env(safe-area-inset-bottom)));
  343. background-color: #f9f9f9;
  344. position: relative;
  345. }
  346. .search-wrap {
  347. background-color: #fff;
  348. padding: 30rpx 34rpx;
  349. align-items: center;
  350. .menu-icon{
  351. width: 52rpx;
  352. height: 40rpx;
  353. display: block;
  354. flex-shrink: 0;
  355. margin-left: 30rpx;
  356. }
  357. .van-search{
  358. padding: 0;
  359. }
  360. }
  361. .chart-list-wrap{
  362. padding: 24rpx 15rpx;
  363. }
  364. .filter-wrap{
  365. .top{
  366. height: 105rpx;
  367. background: #FFFFFF;
  368. box-shadow: 0px 3rpx 6rpx rgba(206, 206, 206, 0.16);
  369. position: relative;
  370. .left{
  371. position: absolute;
  372. left: 34rpx;
  373. top: 50%;
  374. transform: translateY(-50%);
  375. font-size: 16px;
  376. color: #E3B377;
  377. }
  378. .center{
  379. position: absolute;
  380. left: 50%;
  381. top: 50%;
  382. transform: translate(-50%,-50%);
  383. font-size: 16px;
  384. color: #1F243A;
  385. }
  386. }
  387. .filter-list{
  388. height: 60vh;
  389. overflow-y: auto;
  390. .title{
  391. font-size: 16px;
  392. font-weight: bold;
  393. color: #1F243A;
  394. padding: 60rpx 0 30rpx 34rpx;
  395. border-bottom: 1px solid #E5E5E5;
  396. }
  397. .filter-item{
  398. padding: 20rpx 34rpx;
  399. border-bottom: 1px solid #E5E5E5;
  400. font-size: 14px;
  401. color: #1F243A;
  402. }
  403. .active{
  404. color: #E3B377;
  405. }
  406. }
  407. }
  408. .empty-box{
  409. text-align: center;
  410. font-size: 32rpx;
  411. color: #999;
  412. padding-top: 150rpx;
  413. image{
  414. width: 346rpx;
  415. margin-bottom: 57rpx;
  416. }
  417. }
  418. </style>