jwyu 2 years ago
parent
commit
84c0b133bf

+ 53 - 0
api/myChart.js

@@ -0,0 +1,53 @@
+//我的图库
+import { httpGet, httpPost } from "@/utils/request.js";
+
+/**
+ * 我的图库列表
+ * @param keyword
+ * @param classify_id 分类ID
+ */
+export const apiMyChartList=params=>{
+    return httpGet('/my_chart/list',params)
+}
+
+/**
+ * 我的图库分类列表
+ * @param classify_id
+ * @param keyword
+ */
+export const apiMyChartClassifyList=()=>{
+    return httpGet('/my_chart_classify/list',{})
+}
+
+/**
+ * 新增我的图库分类
+ * @param classify_name
+ */
+export const apiMyChartClassifyAdd=params=>{
+    return httpPost('/my_chart_classify/add',params)
+}
+
+/**
+ * 编辑我的图库分类
+ * @param classify_name
+ * @param classify_id
+ */
+export const apiMyChartClassifyEdit=params=>{
+    return httpPost('/my_chart_classify/edit',params)
+}
+
+/**
+ * 删除我的图库分类
+ * @param classify_id
+ */
+export const apiMyChartClassifyDel=params=>{
+    return httpPost('/my_chart_classify/del',params)
+}
+
+/**
+ * 排序我的图库分类
+ * @param list<item>:{ "classify_id": 1, //分类ID "sort": 3 //排序}
+ */
+export const apiMyChartClassifySort=params=>{
+    return httpPost('/my_chart_classify/sort',params)
+}

+ 235 - 0
pages-myChart/classify.vue

@@ -0,0 +1,235 @@
+<template>
+    <view class="classify-list-page">
+        
+        <drag
+          ref="dragIns"
+          generic:item="classify-item"
+          :columns="1"
+          :list-data="list"
+          :itemHeight="88"
+          @sortend="sortend"
+          @click="ItemClick"
+          @scroll="chartScroll"
+          :scroll-top="scrollTop"
+        ></drag>
+
+
+        <view class="add-classify-btn" @click="showAdd=true">添加分类</view>
+        <van-dialog
+            use-slot
+            :title="editId?'编辑分类名称':'添加分类名称'"
+            :show="showAdd"
+            confirmButtonText="确定"
+            show-cancel-button
+            @close="showAdd=false"
+            @confirm="handleConfirmAdd"
+        >
+            <input class="add-input" v-model="inputClassifyVal" maxlength="10" type="text" placeholder="请输入分类名称">
+            <view style="color:#999;padding-left:10%;margin-bottom:40rpx;font-size:12px">注:字数控制在10个字以内!</view>
+              
+        </van-dialog>
+
+        <van-dialog id="van-dialog" />
+    </view>
+      
+</template>
+
+<script>
+import classifyItem from './components/classifyItem.vue'
+import {
+    apiMyChartClassifyAdd,
+    apiMyChartClassifyEdit,
+    apiMyChartClassifyDel,
+    apiMyChartClassifySort,
+    apiMyChartClassifyList
+} from '@/api/myChart'
+export default {
+    components:{
+        'classify-item':classifyItem
+    },
+    watch:{
+        showAdd(n){
+            if(!n){
+                this.editId=0
+                this.inputClassifyVal=''
+            }
+        }
+    },
+    data() {
+        return {
+            dragIns:null,
+            list:[],
+
+            showAdd:false,
+            inputClassifyVal:'',
+            editId:0,
+        }
+    },
+    onLoad(){
+        this.getClassifyList()
+    },
+    methods: {
+        // 获取分类数据
+        async getClassifyList(){
+            const res=await apiMyChartClassifyList()
+            if(res.code===200){
+                const arr=res.data||[]
+                this.list=arr.map(item=>{
+                    return {
+                        ...item,
+                        dragId:item.my_chart_classify_id
+                    }
+                })
+                setTimeout(() => {
+                    this.dragIns=this.$refs.dragIns
+                    this.dragIns.init();// 初始化列表
+                }, 100);
+            }
+        },
+
+        ItemClick(e){
+            const item=e.detail.data
+            const type=e.detail.extra.__args__[0]?.optType||''
+            if(type==='del'){
+                this.handleDel(item)
+            }else if(type==='edit'){
+                this.handleEdit(item)
+            }else{
+                uni.navigateTo({
+                    url: `/pages-myChart/list?classifyId=${item.my_chart_classify_id}&classifyName=${item.my_chart_classify_name}`,
+                    success: (result) => {},
+                    fail: () => {},
+                    complete: () => {}
+                });
+            }
+            
+        },
+
+        // 删除
+        handleDel(item){
+            this.$dialog.confirm({
+                title: '',
+                message: `是否确认删除分类${item.my_chart_classify_name}?`,
+                showCancelButton:true,
+                confirmButtonText:'确定'
+            })
+            .then(() => {
+                // on confirm
+                apiMyChartClassifyDel({
+                    classify_id:item.my_chart_classify_id
+                }).then(res=>{
+                    if(res.code===200){
+                        uni.showToast({
+                            title:"删除成功",
+                            icon:"none"
+                        })
+                        this.getClassifyList()
+                    }else if(res.code===4001){
+                        this.$dialog.alert({
+                            title: '',
+                            message: '删除失败,该分类下有图表',
+                            showConfirmButton:false,
+                            showCancelButton:true,
+                            cancelButtonText:'知道了'
+                        }).then(() => {
+                        // on close
+                        });
+                    }
+                })
+            })
+            .catch(() => {
+                // on cancel
+            });
+        },
+
+        //编辑
+        handleEdit(item){
+            this.editId=item.my_chart_classify_id
+            this.inputClassifyVal=item.my_chart_classify_name
+            this.showAdd=true
+        },
+
+        //排序
+        async sortend(e){
+            // curIndex 为排序前元素所在位置  listData为排序后的数组
+            let {curIndex,listData}=e.detail
+            console.log(listData);
+            const arr=listData.map((item,index)=>{
+                return  {
+                    sort:index+1,
+                    classify_id:item.my_chart_classify_id
+                }
+            })
+            const res=await apiMyChartClassifySort([...arr])
+            if(res.code!==200){
+                uni.showToast({
+                    title: res.msg,
+                    icon: 'none'
+                })
+            }
+        },
+
+        async handleConfirmAdd(){
+            if(!this.inputClassifyVal){
+                uni.showToast({
+                    title: '请输入分类名称',
+                    icon: 'none',
+                });
+                return 
+            }
+            let res
+            if(this.editId){
+                res=await apiMyChartClassifyEdit({
+                    classify_name:this.inputClassifyVal,
+                    classify_id:this.editId
+                })
+            }else{
+                res=await apiMyChartClassifyAdd({
+                    classify_name:this.inputClassifyVal
+                })
+            }
+            if(res.code===200){
+                uni.showToast({
+                    title: `${this.editId?'编辑':'新增'}成功`,
+                    icon: 'none',
+                });
+                this.showAdd=false
+                this.getClassifyList()
+            }
+        }
+    },
+
+}
+</script>
+
+<style lang="scss" scoped>
+.classify-list-page{
+    padding: 34rpx 34rpx 120rpx 34rpx;
+}
+
+.add-classify-btn{
+    position: fixed;
+    left: 0;
+    bottom: 0;
+    right: 0;
+    font-size: 32rpx;
+    padding-top: 18rpx;
+    text-align: center;
+    color: #E3B377;
+    background: #333333;
+    box-shadow: 0px 4rpx 20rpx rgba(160, 126, 84, 0.25);
+    z-index: 99;
+    padding-bottom: calc(18rpx + constant(safe-area-inset-bottom));
+    padding-bottom: calc(18rpx + env(safe-area-inset-bottom));
+}
+
+.add-input{
+    display: block;
+    width: 80%;
+    background: #F7F8FA;
+    border-radius: 8px;
+    padding: 20rpx;
+    margin: 30rpx auto 10rpx auto;
+}
+
+</style>

+ 47 - 0
pages-myChart/components/classifyItem.vue

@@ -0,0 +1,47 @@
+<template>
+    <view class="flex classify-item" :data-id="itemData.dragId" @click.stop="itemClick">
+        <view class="name">{{itemData.my_chart_classify_name}}</view>
+        <image class="img" src="../static/edit-icon.png" mode="widthFix" @click.stop="handleClick('edit')"/>
+        <image class="img" src="../static/del-icon.png" mode="widthFix" @click.stop="handleClick('del')"/>
+        <image class="img" src="../static/drag-icon.png" mode="widthFix"/>
+    </view>
+      
+</template>
+
+<script>
+export default {
+    name:'classifyItem',
+    props: {
+        itemData:{
+            type: Object,
+		    value: {}
+        },
+    },
+    methods: {
+        itemClick(){
+            this.$emit('click')
+        },
+        handleClick(e){
+            this.$emit('click',{optType:e})
+        }
+
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.classify-item{
+    padding: 24rpx 0;
+    border-bottom: 1px solid #E5E5E5;
+    background-color: #fff;
+    .name{
+        flex: 1;
+        padding-left: 10rpx;
+    }
+    .img{
+        width: 40rpx;
+        height: 40rpx;
+        margin-left: 50rpx;
+    }
+}
+</style>

+ 36 - 0
pages-myChart/detail.vue

@@ -0,0 +1,36 @@
+<template>
+    <web-view :src="url"></web-view>
+</template>
+
+<script>
+import {h5BaseUrl} from '../utils/config'
+export default {
+    data () {
+        return {
+            url:''
+        }
+    },
+    onLoad(options){
+        const queryObj={
+            ChartInfoId:options.chartInfoId,
+            source:'ybxcx_my_chart',
+            token:this.$store.state.user.token||uni.getStorageSync("token"),
+            timestamp:new Date().getTime(),//防止缓存
+        }
+        let queryObjStr=''
+        for (const key in queryObj) {
+            if(!queryObjStr){
+                    queryObjStr=`${key}=${queryObj[key]}`
+            }else{
+                queryObjStr=`${queryObjStr}&${key}=${queryObj[key]}`
+            }
+        }
+        console.log('拼接字符串:',queryObjStr);
+        this.url=`${h5BaseUrl}/hzyb/chart/detail?${queryObjStr}#wechat_redirect`
+    }
+}
+</script>
+
+<style>
+
+</style>

+ 140 - 0
pages-myChart/list.vue

@@ -0,0 +1,140 @@
+<template>
+    <view class="mychart-page">
+        <view class="flex top-wrap">
+            <searchBox
+                placeholder="关键字搜索" 
+                :focus="focus"
+                @change="onChange"
+                @search="onSearch"
+                style="flex:1"
+            />
+        </view>
+        <view class="report-empty-box" v-if="list.length==0&&finished">
+            <image
+                :src="globalImgUrls.chartEmpty"
+                mode="widthFix"
+            />
+            <view>暂无图表收藏的信息</view>
+        </view>
+        <view class="flex list-wrap" v-else>
+            <view class="item" v-for="item in list" :key="item.chart_info_id">
+                <view class="van-multi-ellipsis--l2 title">{{item.chart_name}}</view>
+                <image class="img" :src="item.chart_image" mode="widthFix" lazy-load="true"/>
+            </view>
+            <view style="height:0;width: 47%;"></view>
+        </view>
+    </view>
+      
+</template>
+
+<script>
+import searchBox from '@/components/searchBox/searchBox.vue'
+import {apiMyChartList} from '@/api/myChart'
+export default {
+    components:{
+        searchBox
+    },
+    data() {
+        return {
+            focus:false,
+            list:[],
+            page:1,
+            pageSize:20,
+            finished:false,
+            keyword:'',
+            classify_id:''
+        }
+    },
+    onLoad(opt){
+        this.classify_id=opt.classifyId||''
+        const title=decodeURIComponent(opt.classifyName)||''
+        if(title=='搜索'){
+            this.focus=true
+        }else{
+            this.getList()
+        }
+        uni.setNavigationBarTitle({
+            title: title,
+            success: (result) => {},
+            fail: () => {},
+            complete: () => {}
+        });
+    },
+    onReachBottom() {
+        if(this.finished) return
+        this.page++
+        this.getList()
+    },
+    methods: {
+        onChange(e){
+            this.keyword=e
+        },
+
+        onSearch(){
+            this.page=1
+            this.list=[]
+            this.finished=false
+            this.getList()
+        },
+
+        async getList(){
+            const res=await apiMyChartList({
+                classify_id:this.classify_id,
+                keyword:this.keyword,
+                curr_page:this.page,
+                page_size:this.pageSize
+            })
+            if(res.code===200){
+                const arr=res.data.list||[]
+                this.list=[...this.list,...arr]
+                this.finished=res.data.paging.is_end
+            }
+        },
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.mychart-page{
+    padding-top: 132rpx;
+}
+.top-wrap{
+    position: fixed;
+    left: 0;
+    top: 0;
+    right: 0;
+    background-color: #fff;
+    z-index: 99;
+    padding: 30rpx 34rpx;
+    border-bottom: 1px solid rgba(0,0,0,0.1);
+    align-items: center;
+}
+.list-wrap{
+    justify-content: space-around;
+    flex-wrap: wrap;
+    padding: 20rpx 0;
+    .item{
+        padding: 20rpx;
+        margin-bottom: 20rpx;
+        background: #FFFFFF;
+        border: 1px solid #EBEBEB;
+        box-shadow: 0px 0px 12rpx rgba(204, 204, 204, 0.25);
+        border-radius: 8rpx;
+        width: 47%;
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        align-items: center;
+        .title{
+            margin-bottom: 20rpx;
+            width: 100%;
+        }
+        .img{
+            width: 300rpx;
+            height: 261rpx;
+            background-color: #f5f5f5;
+        }
+    }
+}
+
+</style>

BIN
pages-myChart/static/del-icon.png


BIN
pages-myChart/static/drag-icon.png


BIN
pages-myChart/static/edit-icon.png


+ 35 - 4
pages.json

@@ -86,6 +86,13 @@
 				"navigationBarTitleText": "线上路演",
 				"enablePullDownRefresh": true
 			}
+		},
+		{
+			"path":"pages/myChart/index",
+			"style": {
+				"navigationBarTitleText": "我的图库",
+				"enablePullDownRefresh": true
+			}
 		}
 	],
 	"subPackages":[
@@ -350,6 +357,30 @@
 					}
 				}
 			]
+		},
+		// 我的图库模块
+		{
+			"root":"pages-myChart",
+			"pages":[
+				{
+					"path":"classify",
+					"style": {
+						"navigationBarTitleText": "分类"
+					}
+				},
+				{
+					"path":"list",
+					"style": {
+						"navigationBarTitleText": "列表"
+					}
+				},
+				{
+					"path":"detail",
+					"style": {
+						"navigationBarTitleText": "详情"
+					}
+				}
+			]
 		}
 	],
 		
@@ -371,10 +402,10 @@
 				"selectedIconPath": "./static/tabbar/roadShow-s.png"
 			},
 			{
-				"pagePath": "pages/video/videoList",
-				"text": "视频社区",
-				"iconPath": "./static/tabbar/video.png",
-				"selectedIconPath": "./static/tabbar/video-s.png"
+				"pagePath": "pages/myChart/index",
+				"text": "我的图库",
+				"iconPath": "./static/tabbar/mychart.png",
+				"selectedIconPath": "./static/tabbar/mychart-s.png"
 			},
 			{
 				"pagePath": "pages/question/question",

+ 243 - 0
pages/myChart/index.vue

@@ -0,0 +1,243 @@
+<template>
+    <view class="mychart-page">
+        <view class="flex top-wrap">
+            <view style="flex:1" @click="handleGoSearch">
+                <searchBox
+                    placeholder="关键字搜索" 
+                    :hasRightBtn="false" 
+                    :disabled="true"
+                />
+            </view>
+              
+            
+            <view class="icon-box filter-box" @click="showFilter=true">
+                <image src="@/static/question/select.png" mode="widthFix" lazy-load="false" binderror="" bindload="" />
+                <text>筛选</text>
+            </view>
+            <view class="icon-box filter-box" @click="goClassifyPage">
+                <image src="@/static/classify-icon.png" mode="widthFix" lazy-load="false" binderror="" bindload="" />
+                <text>分类</text>
+            </view>
+        </view>
+        <view class="report-empty-box" v-if="list.length==0&&finished">
+            <image
+                :src="globalImgUrls.chartEmpty"
+                mode="widthFix"
+            />
+            <view>暂无图表收藏的信息</view>
+        </view>
+        <view class="flex list-wrap" v-else>
+            <view class="item" v-for="item in list" :key="item.chart_info_id" @click="goDetail(item)">
+                <view class="van-multi-ellipsis--l2 title">{{item.chart_name}}</view>
+                <image class="img" :src="item.chart_image" mode="widthFix" lazy-load="true"/>
+            </view>
+        </view>
+        
+        <!-- 筛选弹窗 -->
+        <van-popup 
+            :show="showFilter" 
+            @close="showFilter=false"
+            position="bottom"
+            closeable
+            z-index="99999"
+        >
+            <view class="filter-wrap">
+                <view class="title">筛选分类</view>
+                <view class="filter-list">
+                    <view 
+                        v-for="item in filterOpts" 
+                        :key="item.my_chart_classify_id" 
+                        :class="['item',item.my_chart_classify_id==classify_id?'active':'']"
+                        @click="handleFilter(item)"
+                    >{{item.my_chart_classify_name}}</view>
+
+                    <view v-if="filterOpts.length==0">
+                        <view style="text-align:center;padding-top:200rpx">暂无分类,请先添加图表</view>
+                    </view>
+                      
+                </view>
+            </view>
+        </van-popup>
+    </view>
+      
+</template>
+
+<script>
+import searchBox from '@/components/searchBox/searchBox.vue'
+import {apiMyChartList,apiMyChartClassifyList} from '@/api/myChart'
+export default {
+    components:{
+        searchBox
+    },
+    data() {
+        return {
+            showFilter:false,
+            filterOpts:[],
+            classify_id:'',
+
+            list:[],
+            page:1,
+            pageSize:20,
+            finished:false,
+        }
+    },
+    onLoad(){
+        this.getList()
+    },
+    onShow(){
+        this.getClassifyList()
+    },
+    onPullDownRefresh() {
+        this.page=1
+        this.finished=false
+        this.classify_id=''
+        this.list=[]
+        this.getList()
+        this.getClassifyList()
+        setTimeout(() => {
+            uni.stopPullDownRefresh()
+        }, 1500);
+    },
+    onReachBottom() {
+        if(this.finished) return
+        this.page++
+        this.getList()
+    },
+    methods: {
+        async getList(){
+            const res=await apiMyChartList({
+                classify_id:this.classify_id,
+                curr_page:this.page,
+                page_size:this.pageSize
+            })
+            if(res.code===200){
+                const arr=res.data.list||[]
+                this.list=[...this.list,...arr]
+                this.finished=res.data.paging.is_end
+            }
+        },
+
+        // 获取分类数据
+        async getClassifyList(){
+            const res=await apiMyChartClassifyList()
+            if(res.code===200){
+                this.filterOpts=res.data||[]
+            }
+        },
+
+        //点击筛选
+        handleFilter(item){
+            if(item.my_chart_classify_id==this.classify_id){
+                this.classify_id=''
+            }else{
+                this.classify_id=item.my_chart_classify_id
+            }
+            this.page=1
+            this.list=[]
+            this.finished=false
+            this.getList()
+            this.showFilter=false
+        },
+
+        goClassifyPage(){
+            uni.navigateTo({
+                url: '/pages-myChart/classify',
+                success: (result) => {},
+                fail: () => {},
+                complete: () => {}
+            });
+        },
+
+        handleGoSearch(){
+            uni.navigateTo({
+                url: `/pages-myChart/list?classifyName=搜索`, 
+            });
+        },
+
+        goDetail(item){
+            uni.navigateTo({
+                url: `/pages-myChart/detail?chartInfoId=${item.chart_info_id}`, 
+            });
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.mychart-page{
+    padding-top: 132rpx;
+}
+.top-wrap{
+    position: fixed;
+    left: 0;
+    top: 0;
+    right: 0;
+    background-color: #fff;
+    z-index: 99;
+    padding: 30rpx 34rpx;
+    border-bottom: 1px solid rgba(0,0,0,0.1);
+    align-items: center;
+    .icon-box{
+        margin-left: 42rpx;
+        image{
+            width: 40rpx;
+            vertical-align: middle;
+            margin-right: 5rpx;
+        }
+        text{
+            color: #E3B377;
+            vertical-align: middle;
+            font-size: 28rpx;
+        }
+    }
+}
+.list-wrap{
+    justify-content: space-around;
+    flex-wrap: wrap;
+    padding: 20rpx 0;
+    .item{
+        padding: 20rpx;
+        margin-bottom: 20rpx;
+        background: #FFFFFF;
+        border: 1px solid #EBEBEB;
+        box-shadow: 0px 0px 12rpx rgba(204, 204, 204, 0.25);
+        border-radius: 8rpx;
+        width: 47%;
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        align-items: center;
+        .title{
+            margin-bottom: 20rpx;
+            width: 100%;
+        }
+        .img{
+            width: 300rpx;
+            height: 261rpx;
+            background-color: #f5f5f5;
+        }
+    }
+}
+
+.filter-wrap{
+    padding-top: 27rpx;
+    .title{
+        text-align: center;
+        font-size: 32rpx;
+        font-weight: 500;
+        padding-bottom: 40rpx;
+    }
+    .filter-list{
+        height: 40vh;
+        overflow-y: auto;
+        padding: 0 34rpx;
+        .item{
+            padding: 24rpx;
+            border-bottom: 1px solid #ededed;
+        }
+        .active{
+            color: #E3B377;
+        }
+    }
+}
+</style>

+ 2 - 1
pages/report/report.vue

@@ -122,7 +122,8 @@ export default {
         ['chart','/pages/chart/chart'],
         ['sandbox','/pages-sandTable/sandTable'],
         ['activity','/pages/activity/activity'],
-        ['pricedriven','/pages/pricedriven/pricedriven']
+        ['pricedriven','/pages/pricedriven/pricedriven'],
+        ['video','/pages/video/videoList']
       ]),
       tabCards: []
     }

BIN
static/classify-icon.png


BIN
static/tabbar/mychart-s.png


BIN
static/tabbar/mychart.png


+ 8 - 8
utils/config.js

@@ -7,12 +7,12 @@ let h5BaseUrl=''// h5页面根路径
 let pcBaseUrl=''//pc页面根路径
 if(env.envVersion==='develop'){//开发
     baseApiUrl='http://8.136.199.33:8612/api'
-    h5BaseUrl='http://xcxh5test.hzinsights.com/xcx_h5'
-	 // h5BaseUrl='http://192.168.77.17:3000/xcx_h5'
+    h5BaseUrl='https://xcxh5test.hzinsights.com/xcx_h5'
+	// h5BaseUrl='http://192.168.77.5:3000/xcx_h5'
     pcBaseUrl='https://ybpctest.hzinsights.com'
 }else if(env.envVersion==='trial'){//体验版
     baseApiUrl='https://ybpctest.hzinsights.com/api'
-    h5BaseUrl='http://xcxh5test.hzinsights.com/xcx_h5'
+    h5BaseUrl='https://xcxh5test.hzinsights.com/xcx_h5'
     pcBaseUrl='https://ybpctest.hzinsights.com'
 }else if(env.envVersion==='release'){//正式版
     baseApiUrl='https://yanbao.hzinsights.com/api'
@@ -54,11 +54,11 @@ const defaultTabBarListConfig=[
 		selectedIconPath: "../static/tabbar/roadShow-s.png"
 	},
     {
-        key: "video",
-        pagePath: "pages/video/videoList",
-        text: "视频社区",
-        iconPath: "../static/tabbar/video.png",
-        selectedIconPath: "../static/tabbar/video-s.png",
+        key: "my_chart",
+        pagePath: "pages/myChart/index",
+        text: "我的图库",
+        iconPath: "../static/tabbar/mychart.png",
+        selectedIconPath: "../static/tabbar/mychart-s.png",
     },
     {
         key: "question",

+ 1 - 1
utils/request.js

@@ -96,7 +96,7 @@ const http=(url,params,method)=>{
 			method:method,
 			header:{
 				Authorization:store.state.user.token,
-				version:'yb11.1'
+				version:'yb11.6'
 			},
 			success(e) {
 				// 接口404