chart.vue 11 KB

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