浏览代码

checkout branch

Karsa 7 月之前
父节点
当前提交
373f38a3b2

+ 123 - 0
src/api/report.js

@@ -121,6 +121,7 @@ export default {
     reportAuthorList:params=>{
         return get('/report/author',params)
     },
+    
     /**
      * 通过报告分类id获取报告内容(继承上一篇报告)
      * @param ClassifyIdFirst
@@ -240,4 +241,126 @@ export default {
     report2PdfImg(params){
         return post("/smart_report/get_pdf_url",params)
     },
+
+        
+    /* v2=============================== */
+    /**
+     * 获取分类关联品种
+     * @param {*} params 
+     * @returns 
+     */
+    classifyPermissionList: params => {
+        return get('/classify/permission_list',params)
+    },
+
+    /**
+     * 获取系统用户
+     * @param {*} params 
+     * @returns 
+     */
+    getSystemUser: params => {
+        return get("/system/department/user_tree",params)
+    },
+
+    /**
+     * 获取有权限的列表 
+     * @param {
+     *  CurrentIndex PageSize KeyWord ClassifyIdFirst ClassifyIdSecond ClassifyIdThird
+    * } params 
+    * @returns 
+    */
+    getAuthReportList: params => {
+        return get('/report/list/authorized',params)
+    },
+ 
+    /**
+    * 报告基础信息
+    * @param {*ReportId} params 
+    * @returns 
+    */
+    getRportBase: params => {
+        return get('/report/detail/base',params)
+    },
+ 
+    /**
+    * 修改章节基础信息
+    * @param {*} params 
+    * @returns 
+    */
+    editChapterBase: params => {
+        return post('/report/chapter/base_info/edit',params)
+    },
+ 
+    /**
+    * 章节拖动排序
+    * @param {*ReportChapterId PrevReportChapterId NextReportChapterId} params 
+    * @returns 
+    */
+    moveChapter: params => {
+        return post('/report/chapter/move',params)
+    },
+ 
+    /**
+     * 删除章节
+     * @param {*ReportChapterId} params 
+     * @returns 
+     */
+    removeChapter: params => {
+        return post('/report/chapter/del',params)
+    },
+ 
+    /**
+     * 添加章节
+     * 
+     * @param {* Title  ReportId PermissionIdList AdminIdList} params 
+     * @returns 
+     */
+    addChapter: params => {
+        return post('/report/chapter/add',params)
+    },
+ 
+    /**
+     * 上传章节音频
+     * @param {*ReportChapterId File} params 
+     * @returns 
+     */
+    uploadChpterAudio: params => {
+        return post('/report/chapter/voice/upload',params)
+    },
+ 
+    /**
+     * 校验所有章节是否发布
+     * @param {*ReportId} params 
+     * @returns 
+     */
+    checkChaterPublishState: params => {
+        return get('/report/chapter/un_publish/list',params)
+    },
+ 
+    /**
+     * 设置版图
+     * @param {*ReportId HeadImg HeadResourceId EndImg EndResourceId CanvasColor} params 
+     * @returns 
+     */
+    setReportLayoutImg: params => {
+        return post('/report/layout_img/edit',params)
+    },
+ 
+    /**
+     * 获取分类关联的品种列表
+     * @param {*ClassifyId} params 
+     * @returns 
+     */
+    getClassifyPermissionList: params => {
+        return	get('/classify/permission/list',params)
+    },
+
+    /**
+     * 保存章节标题 
+     * @param {*ReportChapterId Title} params 
+     * @returns 
+     */
+    saveChapterTitle: params => {
+        return post('/report/chapter/title/edit',params)
+    }
 }

+ 9 - 1
src/router/report.js

@@ -80,5 +80,13 @@ export const reportRoutes=[
             keepAlive:true,
             hasBackTop:true
         },
-    }
+    },
+    {
+        path:"/smart_report/edit",
+        name:"SmartReportEdit",
+        component: () => import("@/views/report/smartReport/EditReport.vue"),
+        meta: { 
+            title: "编辑研报",
+        },
+    },
 ]

+ 52 - 53
src/views/report/List.vue

@@ -9,7 +9,7 @@ import { showToast,showDialog,Dialog } from 'vant';
 import { useRouter } from 'vue-router';
 import { useWindowSize } from '@vueuse/core'
 import {useCachedViewsStore} from '@/store/modules/cachedViews'
-import {reportFrequencyOpts} from './utils/config'
+// import {reportFrequencyOpts} from './utils/config'
 import {useDownLoadFile} from '@/hooks/useDownLoadFile'
 import {reportManageBtn,useAuthBtn} from '@/hooks/useAuthBtn'
 import {useReportApprove} from '@/hooks/useReportApprove'
@@ -28,19 +28,9 @@ const {checkAuthBtn} = useAuthBtn()
 
 //添加按钮和添加选项
 const isAddReportBtnShow = computed(()=>{
-    return checkAuthBtn(reportManageBtn.reportManage_reportAdd)||checkAuthBtn(reportManageBtn.reportManage_dayWeekReportAdd)
+    return checkAuthBtn(reportManageBtn.reportManage_reportAdd)
 })
 
-const addReportActions = computed(()=>{
-    let arr = []
-    if(checkAuthBtn(reportManageBtn.reportManage_reportAdd)){
-        arr.push({name:'研报'})
-    }
-    if(checkAuthBtn(reportManageBtn.reportManage_dayWeekReportAdd)){
-        arr.push({name:'晨报/周报'})
-    }
-    return arr.reverse()
-})
 
 const { width, height } = useWindowSize()
 
@@ -60,16 +50,17 @@ const isClickClose=ref(false)//是否点击过关闭一键清空模块
 function handleCleanFilter(){
     listState.ClassifyNameFirst=''
     listState.ClassifyNameSecond=''
+    listState.ClassifyNameThird=''
+    listState.classifyIds=[]
+
     listState.MsgIsSend=''
-    listState.Frequency=''
     listState.StartDate=''
     listState.EndDate=''
+    listState.timeType='publish_time'
     listState.publishStatus=''
     refreshList()
 }
 
-// 分类弹窗
-const showClassify=ref(false)
 
 const reportTypes = [
     { label: '我的研报',key:'3' },
@@ -86,6 +77,7 @@ const statusMap = new Map([
     [6,{ bg:'#E3F9E9', color:'#006C45', msg:'已通过'}]
 ])
 
+
 // 水印
 const waterMarkStr=ref('')
 const listState = reactive({
@@ -96,6 +88,7 @@ const listState = reactive({
     classifyIds: [],
     ClassifyNameFirst:'',
     ClassifyNameSecond:'',
+    ClassifyNameThird:'',
     StartDate:'',
     EndDate:'',
     list:[],
@@ -105,7 +98,6 @@ const listState = reactive({
     loading:false
 })
 async function getList(){
-    const timeType = ['','publish_time','modify_time','approve_time']
     const res=await apiReport.getList({
         CurrentIndex:listState.page,
         PageSize:listState.pageSize,
@@ -123,12 +115,11 @@ async function getList(){
             : "",
         ClassifyIdThird:
           listState.classifyIds &&
-          listState.classifyIds.length > 1
+          listState.classifyIds.length > 2
             ? listState.classifyIds[2]
             : "",
-        Frequency:listState.Frequency,
         MsgIsSend:listState.MsgIsSend,
-        TimeType:timeType[dateType.value]||'publish_time',
+        TimeType:listState.timeType,
         State:listState.publishStatus,
         FilterReportType: listState.listType
     })
@@ -141,22 +132,23 @@ async function getList(){
         
         listState.finished=res.Data.Paging.IsEnd
         const arr=res.Data.List||[]
-        listState.list=[...listState.list,...arr]
+        listState.list= listState.page < 2 ? arr : [...listState.list,...arr]
     }
 }
 function onLoad(){
     listState.page++
     getList()
 }
-
 function refreshList(){
+    document.documentElement.scrollTop=0
     listState.page=1
-    listState.list=[]
+    // listState.list=[]
     listState.finished=false
     getList()
 }
 
 
+
 // 删除报告
 function handleReportDel(item){
     showDialog({
@@ -175,6 +167,7 @@ function handleReportDel(item){
     }).catch(()=>{})
 }
 
+
 // 发布报告
 let activeReportData=ref('')
 let showPublishPop=ref(false)
@@ -245,6 +238,7 @@ function handleReportSubmit(item){
         })
     }).catch(()=>{})
 }
+
 //撤销报告
 function handleReportCancel(item){
     showDialog({
@@ -261,6 +255,7 @@ function handleReportCancel(item){
         })
     }).catch(()=>{})
 }
+
 // type 1-pdf 2-长图
 function downloadPdfImg(item,type){
     showReportItemOpt.value=false
@@ -309,34 +304,35 @@ function handldReportMsgSend(item){
     })
 }
 
-// 日期筛选
-const calendarMinDate=new Date(2010,0,1)
-const showCalendar=ref(false)
-const calendarIns=ref(null)
-const dateType=ref(1)//1发布时间 2更新时间 3审批时间
-function handleCalendarChange(e){
-    listState.StartDate=moment(e[0]).format('YYYY-MM-DD')
-    listState.EndDate=moment(e[1]).format('YYYY-MM-DD')
-    
-    refreshList()
-    showCalendar.value=false
+/* 上传音频 */
+function handleUploadAudio() {
+
 }
-function handleResetCalendar(){
-    listState.StartDate=''
-    listState.EndDate=''
-    calendarIns.value.reset()
-    refreshList()
-    showCalendar.value=false
+
+/* 音频下载 */
+function handleDownloadAudio() {
+
 }
 
+
+
+const selectClassifyName = computed(() => {
+    return `${listState.ClassifyNameFirst}${listState.ClassifyNameSecond?('/'+listState.ClassifyNameSecond):''}${listState.ClassifyNameThird?('/'+listState.ClassifyNameThird):''}`
+})
+// 分类弹窗
+const showClassify=ref(false)
 // 分类筛选
-function handleConfirmClassify({firstClassify,secondClassify}){
-    listState.ClassifyNameFirst=firstClassify.text
-    listState.ClassifyNameSecond=secondClassify.text
+function handleConfirmClassify(arr){
+    console.log(arr)
+    listState.ClassifyNameFirst=arr[0]?.text;
+    listState.ClassifyNameSecond=arr[1]?.text;
+    listState.ClassifyNameThird=arr[2]?.text;
+    listState.classifyIds = arr.map(_=>_.id);
     refreshList()
     showClassify.value=false
 }
 
+
 // 跳转详情
 function goDetail(item){
     console.log(item);
@@ -392,7 +388,7 @@ function handleChangeFilter({ publishStatus,msgIsSend,timeType,startDate,endDate
     listState.timeType = timeType
     listState.StartDate = startDate
     listState.EndDate = endDate
-    showMoreFilter.value=false
+    isShowFilterPopup.value=false
     refreshList()
 }
 
@@ -409,13 +405,6 @@ const isShowReportInfoPopup = ref(false)
 //添加报告
 function handeAddReport(e){
     isShowReportInfoPopup.value = true
-    // if(e.name==='研报'){
-    //     router.push('/report/add')
-    // }else{
-    //     router.push('/report/dayweek/add')
-    // }
-
-    // router.push('/report/addReportInfo')
     
 }
 
@@ -506,7 +495,7 @@ onMounted(async ()=>{
             <div class="top-box">
                 <van-search
                     style="flex:1"
-                    shape="round" 
+                    shape="round"
                     readonly 
                     placeholder="请输入报告标题或创建人"
                     @click-input="goSearch"
@@ -520,7 +509,12 @@ onMounted(async ()=>{
                     </svg>
                 </div>
 
-                <div :class="['menu-icon',listState.MsgIsSend||listState.publishStatus?'active':'']" @click="handleShowFilter">
+                <div 
+                    :class="['menu-icon',{
+                        'active': listState.MsgIsSend||listState.publishStatus
+                    }]" 
+                    @click="handleShowFilter"
+                >
                     <svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
                         <path d="M30.283 23.977L40.824 9.5685C41.3719 8.81954 41.6002 7.88381 41.459 6.96667C41.3177 6.04952 40.8184 5.22589 40.0705 4.6765C39.4715 4.23699 38.7479 4 38.005 4H9.995C8.065 4 6.5 5.567 6.5 7.5C6.5 8.244 6.7365 8.9685 7.1755 9.5685L17.717 23.977V42.5C17.717 43.3285 18.3875 44 19.215 44C19.6125 43.9996 19.9935 43.8414 20.2743 43.5601C20.5552 43.2788 20.7128 42.8975 20.7125 42.5V23.486C20.7125 23.1675 20.611 22.857 20.423 22.5995L9.592 7.7955C9.53761 7.72096 9.50489 7.63283 9.49745 7.54085C9.49001 7.44887 9.50814 7.35663 9.54984 7.27431C9.59155 7.192 9.65519 7.12281 9.73375 7.0744C9.81231 7.02599 9.90272 7.00024 9.995 7H38.005C38.0973 7.00015 38.1878 7.02586 38.2664 7.07427C38.345 7.12268 38.4086 7.1919 38.4503 7.27426C38.492 7.35663 38.51 7.44892 38.5025 7.54092C38.4949 7.63292 38.4621 7.72104 38.4075 7.7955L27.5765 22.5995C27.3884 22.8568 27.287 23.1673 27.287 23.486V38.271C27.287 39.0995 27.9575 39.771 28.785 39.771C28.9819 39.7709 29.1768 39.732 29.3586 39.6565C29.5404 39.5811 29.7056 39.4705 29.8447 39.3312C29.9838 39.192 30.0941 39.0266 30.1693 38.8447C30.2445 38.6628 30.2831 38.4678 30.283 38.271V23.977Z" fill="currentColor"/>
                     </svg>
@@ -544,11 +538,12 @@ onMounted(async ()=>{
                 </van-tabs>
             </div>
 
-            <div class="classify-name">分类1/分类2/分类3</div>
+            <div class="classify-name" v-if="listState.classifyIds&&listState.classifyIds.length">{{ selectClassifyName }}</div>
         </div>
         <van-list
             v-model:loading="listState.loading"
             :finished="listState.finished"
+            :offset="100"
             :finished-text="listState.list.length>0?'没有更多了':'暂无相关报告'"
             @load="onLoad"
         >   
@@ -1095,5 +1090,9 @@ onMounted(async ()=>{
             font-size: 16px;
         }
     }
+
+    .classify-name {
+        padding: 15px;
+    }
 }
 </style>

+ 26 - 1
src/views/report/Search.vue

@@ -9,8 +9,15 @@ console.log('搜索页setup');
 
 const router=useRouter()
 
+const reportTypes = [
+    { label: '我的研报',key:'3' },
+    { label: '共享研报',key:'2' },
+    { label: '公共研报',key:'1' },
+]
+
 const keyword=ref('')
 const listState = reactive({
+    listType: '3',
     list:[],
     page:1,
     pageSize:20,
@@ -21,7 +28,8 @@ async function getList(){
     const res=await apiReport.getList({
         CurrentIndex:listState.page,
         PageSize:listState.pageSize,
-        KeyWord:keyword.value
+        KeyWord:keyword.value,
+        FilterReportType: listState.listType
     })
     if(res.Ret===200){
         listState.loading=false
@@ -71,7 +79,24 @@ function goDetail(item){
                 v-model="keyword"
                 @search="handleSearch"
             />
+
+            <div class="report-type">
+                <van-tabs 
+                    v-model:active="listState.listType" 
+                    title-active-color="#0052D9" 
+                    title-inactive-color="#333"
+                >
+                    <van-tab 
+                        :title="tab.label" 
+                        v-for="tab in reportTypes" 
+                        :key="tab.key" 
+                        :name="tab.key"
+                    ></van-tab>
+                </van-tabs>
+            </div>
         </div>
+        
+
         <img v-if="listState.list.length==0&&listState.finished&&keyword" class="list-empty-img" src="https://hzstatic.hzinsights.com/static/ETA_mobile/empty_img.png" alt="">
         <template v-if="keyword">
         <van-list

+ 222 - 121
src/views/report/components/AddReportBaseInfoV2.vue

@@ -1,9 +1,11 @@
 <script setup name="AddReportInfo">
 import moment from 'moment'
-import {ref,reactive} from 'vue'
+import {ref,reactive, computed} from 'vue'
 import { useRouter } from 'vue-router'
 import apiReport from '@/api/report'
 import { showToast } from 'vant'
+import ListClassify from './ListClassify.vue'
+import CooperUserSelect from './CooperUserSelect.vue'
 
 
 const router=useRouter()
@@ -17,13 +19,24 @@ const props = defineProps({
     type: Object
   }
 })
-const emit = defineEmits(['close'])
+const emit = defineEmits(['close','change'])
 
+const relationVarietyLabel = computed(() => {
+  if(!reportBaseInfo.relationVariety) return  ''
+
+  return reportBaseInfo.relationVariety.map(_ => _.PermissionName).join(',')
+})
+
+const cooperationUsersLabel = computed(() => {
+  if(!reportBaseInfo.cooperationUsers) return  ''
+
+  return reportBaseInfo.cooperationUsers.map(_ => _.NodeName).join(',')
+})
 
 const reportBaseInfo=reactive({
     type: 1,
     inheritId: 0,//继承report id
-    classify: [],
+    classifyIds: [],
     classifyName:'',
     relationVariety: [],
     title: "",
@@ -36,93 +49,74 @@ const reportBaseInfo=reactive({
     isPublcPublish: 1
 })
 
-function getClassifyList() {
 
+const reportAuthor = ref([])
+// 获取作者
+function getReportauthor() {
+  apiReport.reportAuthorList().then((res) => {
+    if (res.Ret == 200) {
+      reportAuthor.value = res.Data.List || [];
+    }
+  });
 }
+getReportauthor()
 
 
 
-// 报告标题
-const showReportTitlePop=ref(false)
-const temReportTitleVal=ref('')
-function handleShowReportTitle(){
-    temReportTitleVal.value=reportBaseInfo.title
-    showReportTitlePop.value=true
-}
-function handleConfirmReportTitle(){
-    reportBaseInfo.title=temReportTitleVal.value
-    showReportTitlePop.value=false
-}
-
 
-//作者
-const showAuthorPop=ref(false)
-const temAuthorVal=ref('')
-function handleShowAuthor(){
-    temAuthorVal.value=reportBaseInfo.author
-    showAuthorPop.value=true
-}
-function handleConfirmAuthor(){
-    reportBaseInfo.author=temAuthorVal.value
-    showAuthorPop.value=false
+// 分类弹窗
+const showClassify=ref(false)
+// 分类筛选
+function handleShowClassify() {
+  // temReportTitleVal.value=reportBaseInfo.title
+  showClassify.value=true
 }
+function handleConfirmClassify(arr){
+    reportBaseInfo.classifyName = arr.map(_=>_.text).join('/')
+    reportBaseInfo.classifyIds = arr.map(_=>_.id);
+    showClassify.value=false
 
-
-// 创建日期
-const minDate=new Date(2015, 0, 1)
-const defaultDate=ref(new Date())
-const showCreateTimePop=ref(false)
-function handleShowCreatetime(){
-    defaultDate.value=new Date(reportBaseInfo.time.replace(/-/g,'/'))
-    showCreateTimePop.value=true
-}
-function handleConfirmCreatime(e){
-    reportBaseInfo.time=moment(e).format('YYYY-MM-DD')
-    showCreateTimePop.value=false
+    getRelationPermission()
+    handleUpdateBaseInfo()
 }
+/* 获取关联品种 */
+async function getRelationPermission() {
+  if(!reportBaseInfo.classifyIds.length) return
 
+  const res = await apiReport.classifyPermissionList({ClassifyId:reportBaseInfo.classifyIds[reportBaseInfo.classifyIds.length-1]})
 
- //分类变化 获取关联品种 
-function handleChangeClassify(val) {
-  this.getRelationPermission()
-  this.handleUpdateBaseInfo()
+    if(res.Ret!==200) return
+    reportBaseInfo.relationVariety = res.Data || []
 }
 
 function handleUpdateBaseInfo() {
-  this.formData.inheritId = 0;
+  reportBaseInfo.inheritId = 0;
 
-  if (this.formData.type === 1) {
-    if (this.formData.classify.length === 2) {
-      this.formData.title = this.getSelectClassifyName()[1];
-    }
-  }
-  if(!this.formData.classify.length) return
+  if(!reportBaseInfo.classifyIds.length) return
 
   
   //获取上次报告
-  reportV2Interface
-    .getAuthReportList({
-      ClassifyIdFirst: this.formData.classify[0],
-      ClassifyIdSecond: this.formData.classify[1],
-      ClassifyIdThird: this.formData.classify[3],
+  apiReport.getAuthReportList({
+      ClassifyIdFirst: reportBaseInfo.classifyIds[0],
+      ClassifyIdSecond: reportBaseInfo.classifyIds[1],
+      ClassifyIdThird: reportBaseInfo.classifyIds[3],
       CurrentIndex: 1,
       PageSize:1,
       Keyword:''
     }).then((res) => {
       if (res.Ret !== 200) return;
       if (!res.Data.List) {
-        this.$message.warning(
-          this.$t("ReportManage.ReportList.no_reports_msg")
-        );
+        showToast('该分类暂无报告')
+        
         return false;
       }
 
-      if(this.formData.type===1) { //默认只带出作者
-        this.formData.author = res.Data.List
-          ? res.Data.List[0].Author.split(",")
-          : [''];
+      if(reportBaseInfo.type===1) { //默认只带出作者
+        reportBaseInfo.author = res.Data.List
+          ? res.Data.List[0].Author
+          : '';
       }else {
-        this.chooseInheritReport(res.Data.List[0])
+        chooseInheritReport(res.Data.List[0])
       }
     });
 }
@@ -131,16 +125,14 @@ function handleUpdateBaseInfo() {
 async function chooseInheritReport(item) {
   const { Id,Title,Abstract,Author,CollaborateType,ReportLayout,IsPublicPublish,ClassifyIdFirst,ClassifyIdSecond,ClassifyIdThird } = item;
 
-  this.formData.title = Title;
-  this.formData.abstract = Abstract;
-  this.formData.author = Author
-    ? Author.split(",")
-    : "";
-  this.formData.cooperationType = CollaborateType;
-  this.formData.inheritId = Id;
-  this.formData.reportLayout = ReportLayout;
-  this.formData.isPublcPublish = IsPublicPublish;
-  this.formData.classify = ClassifyIdThird
+  reportBaseInfo.title = Title;
+  reportBaseInfo.abstract = Abstract;
+  reportBaseInfo.author = Author;
+  reportBaseInfo.cooperationType = CollaborateType;
+  reportBaseInfo.inheritId = Id;
+  reportBaseInfo.reportLayout = ReportLayout;
+  reportBaseInfo.isPublcPublish = IsPublicPublish;
+  reportBaseInfo.classifyIds = ClassifyIdThird
     ? [ClassifyIdFirst,ClassifyIdSecond,ClassifyIdThird]
     : ClassifyIdSecond 
     ? [ClassifyIdFirst,ClassifyIdSecond]
@@ -148,14 +140,14 @@ async function chooseInheritReport(item) {
   
   //继承的章节报告默认带出协作人
   if(CollaborateType===1) {
-    this.formData.cooperationUsers = [];
+    reportBaseInfo.cooperationUsers = [];
   }else {
-    const res = await reportV2Interface.getRportBase({
+    const res = await apiReport.getRportBase({
       ReportId: Id
     })
     if(res.Ret!==200) return
     
-    this.formData.cooperationUsers = res.Data.GrandAdminList
+    reportBaseInfo.cooperationUsers = res.Data.GrandAdminList
       ? res.Data.GrandAdminList.map(_ => ({
           NodeId: _.AdminId,
           NodeName: _.AdminName
@@ -164,17 +156,102 @@ async function chooseInheritReport(item) {
   }
 }
 
+
+
+//作者弹窗
+const showAuthorPop=ref(false)
+const temAuthorVal=ref('')
+function handleShowAuthor(){
+    temAuthorVal.value=reportBaseInfo.author
+    showAuthorPop.value=true
+}
+function handleConfirmAuthor(){
+    reportBaseInfo.author=temAuthorVal.value
+    showAuthorPop.value=false
+}
+
+
+// 创建日期
+const minDate=new Date(2015, 0, 1)
+const defaultDate=ref(new Date())
+const showCreateTimePop=ref(false)
+function handleShowCreatetime(){
+    defaultDate.value=new Date(reportBaseInfo.time.replace(/-/g,'/'))
+    showCreateTimePop.value=true
+}
+function handleConfirmCreatime(e){
+    reportBaseInfo.time=moment(e).format('YYYY-MM-DD')
+    showCreateTimePop.value=false
+}
+
+
+/* 协作人弹窗 */
+const isChooseCooperaUserPop = ref(false)
 //选择协作人
-function handleChooseCooper() {
-  this.isChooseCooperaUser = true
+function handleShowCooperUser() {
+  isChooseCooperaUserPop.value = true
 }
+function handleConfirmCooperaUser() {
+  isChooseCooperaUserPop.value = false
+}
+
+
 
 
 function close() {
   emit('close')
 }
-function handleSave() {
-
+async function handleSave() {
+
+  let classifyNameArr = reportBaseInfo.classifyName.split(',')
+  const params = {
+    AddType: reportBaseInfo.type,
+    ClassifyIdFirst: reportBaseInfo.classifyIds[0]
+      ? reportBaseInfo.classifyIds[0]
+      : 0,
+    ClassifyNameFirst: classifyNameArr[0]||'',
+    ClassifyIdSecond: reportBaseInfo.classifyIds[1]
+      ? reportBaseInfo.classifyIds[1]
+      : 0,
+    ClassifyNameSecond: classifyNameArr[1]||'',
+    ClassifyIdThird: reportBaseInfo.classifyIds[2]
+      ? reportBaseInfo.classifyIds[2]
+      : 0,
+    ClassifyNameThird: classifyNameArr[2]||'',
+    Title: reportBaseInfo.title,
+    Abstract: reportBaseInfo.abstract,
+    Author: reportBaseInfo.author,
+    CreateTime: reportBaseInfo.time,
+    ReportLayout: reportBaseInfo.reportLayout,
+    CollaborateType: reportBaseInfo.cooperationType,
+    IsPublicPublish: reportBaseInfo.isPublcPublish,
+    InheritReportId: reportBaseInfo.inheritId,
+    GrantAdminIdList: reportBaseInfo.cooperationUsers.map(_ => _.NodeId)
+  };
+
+
+  // 编辑
+  if (props.id) {
+    emit("change", params);
+    return;
+  }
+  apiReport.reportAdd(params).then((res) => {
+    if (res.Ret === 200) {
+
+      let { href } = router.resolve({
+        path: reportBaseInfo.reportLayout===1 
+          ? '/report/edit'
+          : "/smpartReportEditV2",
+        query: { 
+          id: res.Data.ReportId,
+          coopType: params.CollaborateType
+        },
+      });
+      window.open(href, "_blank");
+
+      close();
+    }
+  });
 }
 
 </script>
@@ -183,7 +260,12 @@ function handleSave() {
     <van-cell-group>
       <van-field name="radio" label="报告类型">
         <template #input>
-          <van-radio-group v-model="reportBaseInfo.type" direction="horizontal">
+          <van-radio-group 
+            v-model="reportBaseInfo.type" 
+            direction="horizontal" 
+            @change="handleUpdateBaseInfo"
+            :disabled="id"
+          >
             <van-radio :name="1">新增</van-radio>
             <van-radio :name="2">继承</van-radio>
           </van-radio-group>
@@ -196,34 +278,43 @@ function handleSave() {
         title="报告分类"
         :label="reportBaseInfo.classifyName"
         is-link
+        @click="handleShowClassify"
       />
     </van-cell-group>
-    <van-cell-group>
+    <van-cell-group v-if="reportBaseInfo.relationVariety.length">
       <van-cell
-        required
-        title="报告标题"
-        :label="reportBaseInfo.title"
-        is-link
-        @click="handleShowReportTitle"
+        title="关联品种"
+        :label="relationVarietyLabel"
       />
     </van-cell-group>
     <van-cell-group>
-      <van-cell
-        required
-        title="报告摘要"
-        :label="reportBaseInfo.abstract"
-        is-link
-        @click="handleShowReportTitle"
+      <van-field 
+        v-model="reportBaseInfo.title"
+        label="报告标题"
+        placeholder="请输入报告标题"
+        input-align="right"
+      />
+    </van-cell-group>
+    <van-cell-group>
+      <van-field
+        v-model="reportBaseInfo.abstract"
+        rows="2"
+        autosize
+        label="报告摘要"
+        type="textarea"
+        placeholder="请输入摘要"
+        input-align="right"
       />
     </van-cell-group>
     <van-cell-group>
       <van-cell
         required
         title="报告作者"
-        :label="reportBaseInfo.author"
+        :value="reportBaseInfo.author"
         is-link
         @click="handleShowAuthor"
       />
+     
     </van-cell-group>
     <van-cell-group>
       <van-cell
@@ -237,17 +328,33 @@ function handleSave() {
     <van-cell-group>
       <van-field name="radio" label="协作方式">
         <template #input>
-          <van-radio-group v-model="reportBaseInfo.cooperationType" direction="horizontal">
+          <van-radio-group 
+            v-model="reportBaseInfo.cooperationType" 
+            direction="horizontal"
+            :disabled="id||reportBaseInfo.type===2"
+          >
             <van-radio :name="1">个人</van-radio>
             <van-radio :name="2">多人协作</van-radio>
           </van-radio-group>
         </template>
       </van-field>
     </van-cell-group>
+    <van-cell-group>
+      <van-cell
+        title="协作人"
+        :value="cooperationUsersLabel"
+        is-link
+        @click="handleShowCooperUser"
+      />
+    </van-cell-group>
     <van-cell-group>
       <van-field name="radio" label="报告布局">
         <template #input>
-          <van-radio-group v-model="reportBaseInfo.reportLayout" direction="horizontal">
+          <van-radio-group 
+            v-model="reportBaseInfo.reportLayout" 
+            direction="horizontal"
+            :disabled="id||reportBaseInfo.type===2"
+            >
             <van-radio :name="1">常规布局</van-radio>
             <van-radio :name="2">智能布局</van-radio>
           </van-radio-group>
@@ -276,32 +383,6 @@ function handleSave() {
   </div>
 
 
-  <!-- 标题 -->
-  <van-popup
-    v-model:show="showReportTitlePop"
-    position="bottom"
-    :style="{ height: '100%' }"
-  >
-    <div class="input-report-title-pop">
-      <van-field v-model="temReportTitleVal" placeholder="请输入报告标题" />
-      <div class="bot-btns">
-        <van-button
-          class="bot-btn"
-          type="default"
-          @click="showReportTitlePop = false"
-          >取消</van-button
-        >
-        <van-button
-          class="bot-btn"
-          type="primary"
-          :disabled="!temReportTitleVal"
-          @click="handleConfirmReportTitle"
-          >确定</van-button
-        >
-      </div>
-    </div>
-  </van-popup>
-
   <!-- 创建日期 -->
   <van-popup
     v-model:show="showCreateTimePop"
@@ -345,6 +426,26 @@ function handleSave() {
       </div>
     </div>
   </van-popup>
+
+
+  <!-- 分类弹窗 -->
+  <van-popup 
+      v-model:show="showClassify"
+      :position="width>650?'center':'bottom'"
+      :style="width>650?{ width: '400px'}:''"
+      round
+  >
+      <ListClassify @close="showClassify=false" @confirm="handleConfirmClassify"/>
+  </van-popup>
+
+  <!-- 协作人弹窗 -->
+  <van-popup 
+      v-model:show="isChooseCooperaUserPop"
+      :position="width>650?'center':'bottom'"
+      :style="width>650?{ width: '400px'}:''"
+  >
+      <CooperUserSelect @close="isChooseCooperaUserPop=false" @confirm="handleConfirmCooperaUser"/>
+  </van-popup>
 </template>
 <style scoped lang="scss">
 .reportInfo-page{

+ 86 - 0
src/views/report/components/CooperUserSelect.vue

@@ -0,0 +1,86 @@
+<script setup>
+import { ref } from 'vue'
+import apiReport from '@/api/report'
+
+const props = defineProps({
+  defaultVal: null
+})
+const emit = defineEmits(['close',' confirm'])
+
+const activeId = ref(0)
+const list = ref([])
+async function getUser() {
+  const res = await apiReport.getSystemUser({
+    KeyWord: ''
+  })
+  
+  if(res.Ret !== 200) return 
+  list.value = res.Data || [];
+
+}
+getUser()
+
+function onFinish() {
+
+}
+
+function handleCancle() {
+  emit('close')
+}
+function handleConfirm() {
+
+}
+</script>
+<template>
+  <div class="choose-user-wrap">
+      <div class="top-box">
+          <span style="color:#666666" @click="handleCancle">取消</span>
+          <span style="font-size:18px;font-weight:bold">选择协作人</span>
+          <span style="color:#0052D9" @click="handleConfirm">确定</span>
+      </div>
+
+      <van-search 
+          shape="round"
+          placeholder="请输入用户"
+          v-model="keyword"
+          @search="handleSearch"
+      />
+
+      <van-cascader
+          v-model="activeId"
+          :show-header="false"
+          :closeable="false"
+          :options="list"
+          :field-names="{
+              text: 'NodeName',
+              value: 'NodeId',
+              children: 'Children'
+          }"
+          @finish="onFinish"
+      />
+      
+  </div>
+</template>
+<style scoped lang="scss">
+.choose-user-wrap{
+    .top-box{
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        height: 116px;
+        border-bottom: 1px solid $border-color;
+        padding: 0 34px;
+    }
+}
+.van-cascader {
+    width: 100%;
+}
+@media screen and (min-width:$media-width){
+    .choose-user-wrap{
+        .top-box{
+            height: 50px;
+            padding: 0 16px;
+        }
+    }
+}
+</style>

+ 30 - 91
src/views/report/components/ListClassify.vue

@@ -13,7 +13,6 @@ const props=defineProps({
 const emits=defineEmits(['close','confirm'])
 
 const list=ref([])
-const firstList = ref([])
 const childList = ref([])
 function getClassifyList(){
     apiReport.getClassifyList({
@@ -25,98 +24,42 @@ function getClassifyList(){
         if(res.Ret===200){
             const arr=res.Data.List||[]
             
-            firstList.value = arr.map(item => ({
-                text:item.ClassifyName,
-                id:item.Id,
-                disabled:props.firstClassifyDisabled&&child.length===0?true:false,
-                HasTeleconference:item.HasTeleconference
+            list.value = arr;
 
-            }))
-
-
-            list.value=arr.map(item=>{
-                const child=item.Child?item.Child.map(e=>{
-                    return {
-                        text:e.ClassifyName,
-                        id:e.Id,
-                        HasTeleconference:e.HasTeleconference
-                    }
-                }):[]
-                return {
-                    text:item.ClassifyName,
-                    id:item.Id,
-                    children:child,
-                    disabled:props.firstClassifyDisabled&&child.length===0?true:false,
-                    HasTeleconference:item.HasTeleconference
-                }
-            })
             if(props.defaultVal&&props.defaultVal[1]){
                 activeId.value=props.defaultVal[1].id
-                list.value.forEach((item,index)=>{
-                    if(item.id===props.defaultVal[0].id){
-                        activeIndex.value=index
-                    }
-                })
+                selectClassify.value = props.defaultVal
             }
         }
     })
 }
 getClassifyList()
 
-const activeFirstClassifyId = ref(0)
 const activeId = ref(null);
-const activeIndex = ref(0);
-
-function handleChangeFirstClassify(val) {
-    console.log(val)
-    console.log(list.value)
-    let arr = list.value[val].child
-    childList.value = arr.map(item=>{
-        const child=item.Child?item.Child.map(e=>{
-            return {
-                text:e.ClassifyName,
-                id:e.Id,
-                HasTeleconference:e.HasTeleconference
-            }
-        }):[]
-        return {
-            text:item.ClassifyName,
-            id:item.Id,
-            children:child,
-            disabled:props.firstClassifyDisabled&&child.length===0?true:false,
-            HasTeleconference:item.HasTeleconference
-        }
-    })
-}
+const selectClassify = ref([])
 
 function handleCancle(){
     emits('close')
 }
 
 function handleReset(){
-    activeIndex.value=0
     activeId.value=null
-    emits('confirm',{firstClassify:'',secondClassify:''})
+    emits('confirm',[])
+}
+
+function onFinish(e) {
+    console.log(e)
+    selectClassify.value = e.selectedOptions
 }
 
 function handleConfirm(){
-    const firstClassify={
-        text:list.value[activeIndex.value].text,
-        id:list.value[activeIndex.value].id,
-        HasTeleconference:list.value[activeIndex.value].HasTeleconference,
-    }
-    let secondClassify={text:'',id:'',HasTeleconference:''}
-    if(activeId.value){
-        list.value[activeIndex.value].children.forEach(e => {
-            if(e.id===activeId.value){
-                secondClassify.text=e.text
-                secondClassify.id=e.id
-                secondClassify.HasTeleconference=e.HasTeleconference
-            }
-        });
-    }
 
-    emits('confirm',{firstClassify,secondClassify})
+    let arr = selectClassify.value.map(_ => ({
+        text:_.ClassifyName,
+        id:_.Id,
+    }))
+
+    emits('confirm',arr)
 }
 </script>
 
@@ -129,23 +72,19 @@ function handleConfirm(){
             <span style="color:#0052D9" @click="handleConfirm">确定</span>
         </div>
 
-        <div class="select-wrapper">
-            <van-sidebar
-                v-model="activeFirstClassifyId"
-                @change="handleChangeFirstClassify" 
-                style="height:300px"
-            >
-                <van-sidebar-item :title="tab.text" v-for="tab in firstList" :key="tab.id"/>
-            </van-sidebar>
-            <van-tree-select
-                style="flex:1"
-                v-model:active-id="activeId"
-                v-model:main-active-index="activeIndex"
-                :items="list"
-                @click-nav="activeId=null"
-            />
-            
-        </div>
+        <van-cascader
+            v-model="activeId"
+            :show-header="false"
+            :closeable="false"
+            :options="list"
+            :field-names="{
+                text: 'ClassifyName',
+                value: 'Id',
+                children: 'Child'
+            }"
+            @finish="onFinish"
+        />
+        
     </div>
 </template>
 
@@ -160,8 +99,8 @@ function handleConfirm(){
         padding: 0 34px;
     }
 }
-.select-wrapper {
-    display: flex;
+.van-cascader {
+    width: 100%;
 }
 @media screen and (min-width:$media-width){
     .report-list-classify-wrap{

+ 82 - 62
src/views/report/components/ReportFilter.vue

@@ -1,6 +1,7 @@
 <script setup>
 import { reactive, ref } from 'vue'
 import { useWindowSize } from '@vueuse/core'
+import moment from 'moment'
 
 const { width, height } = useWindowSize()
 
@@ -89,6 +90,11 @@ function getName(key) {
   let title = nameMap[key]?.text
   return title
 }
+function getDate() {
+    if(!filterState.startDate||!filterState.endDate) return ''
+
+    return `${filterState.startDate}~${filterState.endDate}`
+}
 
 
 const showPicker = ref(false)
@@ -96,7 +102,6 @@ const selectKey = ref('')
 const selectTimeType = ref([])
 const selectStatus = ref([])
 const selectMsgSend = ref([])
-const selectDate = ref([])
 function handleOpenPicker(key) {
     selectKey.value = key;
     selectTimeType.value = [filterState[key]]
@@ -121,9 +126,28 @@ function handleConfirmMsgSend() {
 }
 
 
+
+/* 日期弹窗 */
+const selectDate = ref([])
 const showCalendar = ref(false)
+const calendarMinDate=new Date(2010,0,1)
+const calendarIns=ref(null)
 function handleOpenDatePicker() {
-  
+    selectDate.value = [filterState.startDate?new Date(filterState.startDate):'',filterState.endDate?new Date(filterState.endDate):'']
+    showCalendar.value = true;
+}
+function handleCalendarChange(e){
+    filterState.startDate=moment(e[0]).format('YYYY-MM-DD')
+    filterState.endDate=moment(e[1]).format('YYYY-MM-DD')
+    
+    showCalendar.value=false
+}
+function handleResetCalendar(){
+    filterState.startDate=''
+    filterState.endDate=''
+    calendarIns.value.reset()
+
+    showCalendar.value=false
 }
 </script>
 <template>
@@ -163,7 +187,7 @@ function handleOpenDatePicker() {
               value-class="cell-con"
               required
               title="更新时间"
-              :value="filterState.startDate"
+              :value="getDate()"
               is-link
               @click="handleOpenDatePicker"
           />
@@ -180,67 +204,63 @@ function handleOpenDatePicker() {
       </div>
   </div>
 
-  <!-- 日期筛选 -->
-  <van-popup 
-      v-model:show="showCalendar"
-      :position="width>650?'center':'bottom'"
-      :style="width>650?{ width: '400px'}:''"
-      round
-  >
-      <van-calendar 
-          ref="calendarIns"
-          :poppable="false"
-          type="range"
-          allow-same-day
-          :min-date="calendarMinDate"
-          @confirm="handleCalendarChange" 
-          :style="{ height: '500px' }"
-          class="calendar-box"
-      >
-          <template #title>
-              <div style="position: relative;">
-                  <span style="color:#666;position: absolute;left:16px" @click="handleResetCalendar">重置</span>
-                  <span>日期选择</span>
-              </div>
-              <div class="time-type-box">
-                  <span @click="dateType=1" :class="['item',dateType===1?'active':'']">发布时间</span>
-                  <span @click="dateType=2" :class="['item',dateType===2?'active':'']">更新时间</span>
-                  <span @click="dateType=3" :class="['item',dateType===3?'active':'']">审批时间</span>
-              </div>
-          </template>
-      </van-calendar>
-  </van-popup>
+    <!-- 日期筛选 -->
+    <van-popup 
+        v-model:show="showCalendar"
+        :position="width>650?'center':'bottom'"
+        :style="width>650?{ width: '400px'}:''"
+        round
+    >
+        <van-calendar
+            :default-date="selectDate"
+            ref="calendarIns"
+            :poppable="false"
+            type="range"
+            allow-same-day
+            :min-date="calendarMinDate"
+            @confirm="handleCalendarChange" 
+            :style="{ height: '500px' }"
+            class="calendar-box"
+        >
+            <template #title>
+                <div style="position: relative;">
+                    <span style="color:#666;position: absolute;left:16px" @click="handleResetCalendar">重置</span>
+                    <span>日期选择</span>
+                </div>
+            </template>
+        </van-calendar>
+    </van-popup>
 
 
-  <!-- 下拉选择 -->
-  <van-popup 
-    v-model:show="showPicker"
-    :position="width>650?'center':'bottom'"
-    :style="width>650?{ width: '400px'}:''"
-    round
-  >
-    <van-picker
-      v-if="selectKey==='timeType'"
-      v-model="selectTimeType"
-      :columns="timeTypeOpt"
-      @cancel="showPicker = false"
-      @confirm="handleConfirmTimeType"
-    />
-    <van-picker
-      v-else-if="selectKey==='publishStatus'"
-      v-model="selectStatus"
-      :columns="publishStatusOpt"
-      @cancel="showPicker = false"
-      @confirm="handleConfirmStatus"
-    />
-    <van-picker
-      v-else-if="selectKey==='msgIsSend'"
-      v-model="selectMsgSend"
-      :columns="reportStatusOpt"
-      @cancel="showPicker = false"
-      @confirm="handleConfirmMsgSend"
-    />
-  </van-popup>  
+    <!-- 下拉选择 -->
+    <van-popup 
+        v-model:show="showPicker"
+        :position="width>650?'center':'bottom'"
+        :style="width>650?{ width: '400px'}:''"
+        round
+    >
+        <van-picker
+        v-if="selectKey==='timeType'"
+        v-model="selectTimeType"
+        :columns="timeTypeOpt"
+        @cancel="showPicker = false"
+        @confirm="handleConfirmTimeType"
+        />
+        <van-picker
+        v-else-if="selectKey==='publishStatus'"
+        v-model="selectStatus"
+        :columns="publishStatusOpt"
+        @cancel="showPicker = false"
+        @confirm="handleConfirmStatus"
+        />
+        <van-picker
+        v-else-if="selectKey==='msgIsSend'"
+        v-model="selectMsgSend"
+        :columns="reportStatusOpt"
+        @cancel="showPicker = false"
+        @confirm="handleConfirmMsgSend"
+        />
+    </van-popup>  
 
 
 </template>

+ 10 - 0
src/views/report/smartReport/EditReport.vue

@@ -0,0 +1,10 @@
+<script setup>
+import { ref } from 'vue'
+
+</script>
+<template>
+  <div></div>
+</template>
+<style scoped lang="scss">
+
+</style>