chart.vue 14 KB

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