chart.vue 12 KB

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