Przeglądaj źródła

常用自选表单和系统指引页面自选表单

cyy 2 tygodni temu
rodzic
commit
08e12aeec8

+ 10 - 0
src/assets/styles/pages/dashboard.scss

@@ -382,6 +382,16 @@ $transition: all 0.5s;
     }
   }
 
+  .cyzxbd-scroll {
+    scrollbar-width: none;
+    -ms-overflow-style: none;
+    &::-webkit-scrollbar {
+      display: none;
+      width: 0;
+      height: 0;
+    }
+  }
+
   .bg-red {
     background-color: #e7505a;
   }

+ 335 - 144
src/views/system/dashboard/components/util.js

@@ -29,9 +29,8 @@ import dayjs from 'dayjs'
 import { scheduleType } from '@/views/constants/schedule'
 import { attendanceDetailClockIn } from '@/api/business/attendance'
 import { lifeTimeData } from '@/views/business/deviceManagement/constants/simulated'
-import {
-  queryScheduleConfigItem
-} from '@/api/business/schedule'
+import { queryScheduleConfigItem } from '@/api/business/schedule'
+import { querySystemGuide } from '@/api/business/general'
 
 /**
  * 创建组件
@@ -46,7 +45,7 @@ export function buildComponent(name, column, preview, vm) {
       props: {
         params: {
           type: Object,
-          default: () => { }
+          default: () => {}
         },
         height: {
           type: Number,
@@ -114,6 +113,9 @@ export function buildComponent(name, column, preview, vm) {
           data: null,
           totalCount: 0,
           quickNavigationData: [],
+          cyzxbdData: [],
+          cyzxbdCommonData: [],
+          cyzxbdSelfData: [],
           navigationList: [],
           stautusOptions: [],
           bpmnFormrenderDialogVisible: false, // 表单
@@ -122,7 +124,10 @@ export function buildComponent(name, column, preview, vm) {
           show: false,
           showHeight: '',
           cardHeight: '100%',
-
+          pagination: {
+            limit: 10000,
+            page: 1
+          },
           activeName: 'innerMessage',
           unreadMessageOption: {},
           formName: 'quickNavform',
@@ -136,7 +141,10 @@ export function buildComponent(name, column, preview, vm) {
           },
           defaultForm: {},
 
-          pendingTabActiveName: 'user-type',
+          pendingTabActiveName:
+            column.templateHtml && column.templateHtml.includes('commonlyForm')
+              ? 'commonlyForm'
+              : 'user-type',
           bodyParams: ActionUtils.formatParams({}, {}, {}),
           pendingBusinessOption: {},
           bpmn: [],
@@ -190,7 +198,8 @@ export function buildComponent(name, column, preview, vm) {
           todaySchedule: [],
           tempSelectedValue: '',
           searchText: '',
-          keysList: []
+          keysList: [],
+          sorts: { SN_: 'ASC' }
         }
       },
       computed: {
@@ -206,18 +215,26 @@ export function buildComponent(name, column, preview, vm) {
           // this.scheduleData = await this.getScheduleData()
           this.todaySchedule = await this.getTodaySchedule()
         })
-
       },
       methods: {
         // 受控文件查阅模块搜索
-        searchFile () {
-          this.$router.push({ path: '/xxgl/nbwj', query: { searchText: this.searchText } })
+        searchFile() {
+          this.$router.push({
+            path: '/xxgl/nbwj',
+            query: { searchText: this.searchText }
+          })
         },
         goDetail(nodeInfo) {
-          if(!nodeInfo){
+          if (!nodeInfo) {
             return
           }
-          this.$router.push({ path: '/xxgl/nbwj', query: {info: JSON.parse(JSON.stringify(nodeInfo)), id:nodeInfo.id} })
+          this.$router.push({
+            path: '/xxgl/nbwj',
+            query: {
+              info: JSON.parse(JSON.stringify(nodeInfo)),
+              id: nodeInfo.id
+            }
+          })
         },
         fetchData(columns, params = {}) {
           this.loading = true
@@ -225,8 +242,8 @@ export function buildComponent(name, column, preview, vm) {
           this.showHeight = this.getHeight()
           const param =
             Utils.isNotEmpty(columns) &&
-              (column.alias === 'unreadMessage' ||
-                column.alias === 'pendingBusiness')
+            (column.alias === 'unreadMessage' ||
+              column.alias === 'pendingBusiness')
               ? { dataMode: column.dataMode, dataFrom: column.dataFrom }
               : column
           if (param.alias === 'myCalendar') {
@@ -267,11 +284,13 @@ export function buildComponent(name, column, preview, vm) {
               })
               this.quickNavigationData = data
             })
+          } else if (param.alias === 'cyzxbd') {
+            this.loadCyzxbdData()
           } else {
             const { first = '', second = '' } = this.$store.getters.level || {}
             // console.log('11111111', param, params, typeof params)
             let type = true
-            if(param.alias == 'newmk'){
+            if (param.alias == 'newmk') {
               type = false
               params['diDian'] = second || first
             }
@@ -289,7 +308,7 @@ export function buildComponent(name, column, preview, vm) {
                   Bus.$emit('getMessageCount', this.totalCount)
                 }
                 this.variables = res.variables
-                if(param.alias == 'newmk'){
+                if (param.alias == 'newmk') {
                   this.keysList = Object.keys(this.variables)
                 }
                 this.loading = false
@@ -299,10 +318,162 @@ export function buildComponent(name, column, preview, vm) {
               })
           }
         },
-        
-        
-        
-        
+        getSearchFormDatacyzxbd(page = { page: 1, limit: 100 }) {
+          const params = {}
+          // 默认过滤 SN 字段值不为空的数据
+          params[`Q^sn_^SNE`] = '1'
+          // 当前后端接口未实现字符串字段【SN】的正确排序,获取全部数据前端过滤
+          return {
+            parameters: this.formatParameters(params),
+            ...ActionUtils.formatParams(null, page, this.sorts)
+          }
+        },
+        parseCyzxbdRoleIds(value) {
+          if (Utils.isEmpty(value)) return []
+          if (Array.isArray(value)) {
+            return value
+              .map((v) => (typeof v === 'object' ? v.id : v))
+              .filter(Boolean)
+          }
+          const str = String(value)
+          if (Utils.isJSON(str)) {
+            try {
+              const data = Utils.parseData(str)
+              const arr = Array.isArray(data) ? data : [data]
+              return arr.map((d) => d.id || d).filter(Boolean)
+            } catch (e) {
+              return []
+            }
+          }
+          return str
+            .split(',')
+            .map((s) => s.trim())
+            .filter(Boolean)
+        },
+        async fetchAllCyzxbdGuideData() {
+          const pageSize = 100
+          let page = 1
+          let all = []
+          let total = Infinity
+          while (all.length < total) {
+            const res = await querySystemGuide(
+              this.getSearchFormDatacyzxbd({ page, limit: pageSize })
+            )
+            const { dataResult = [], pageResult = {} } = res.data || {}
+            all = all.concat(dataResult)
+            total =
+              pageResult.totalCount != null
+                ? Number(pageResult.totalCount)
+                : all.length
+            if (!dataResult.length || dataResult.length < pageSize) break
+            page += 1
+          }
+          return all
+        },
+        async loadCyzxbdData() {
+          try {
+            const userRoles = this.$store.getters.role || []
+            const allRoleId = userRoles.map((item) => item.id)
+            const roleFields = [
+              'bianZhiJiaoSe',
+              'jieDianSiJiaoSe',
+              'jieDianWuJiaoSe',
+              'shenHeJiaoSe',
+              'shenPiJiaoSe'
+            ]
+            const [dataResult, collectRes] = await Promise.all([
+              this.fetchAllCyzxbdGuideData(),
+              this.$common.request('query', {
+                key: 'zxbdryglgxcx',
+                params: [this.userId]
+              })
+            ])
+            const { isEmpty } = this.$utils
+            if (isEmpty(this.sorts)) {
+              dataResult.sort((a, b) => +a.sn - +b.sn)
+            }
+            const collectIds = new Set(
+              ((collectRes.variables && collectRes.variables.data) || [])
+                .map((item) => item.ji_lu_biao_dan_id)
+                .filter(Boolean)
+                .map((id) => String(id))
+            )
+            this.cyzxbdCommonData = dataResult.filter((item) => {
+              const itemRoleIds = roleFields.reduce(
+                (ids, field) =>
+                  ids.concat(this.parseCyzxbdRoleIds(item[field])),
+                []
+              )
+              return allRoleId.some((roleId) => itemRoleIds.includes(roleId))
+            })
+            this.cyzxbdSelfData = dataResult.filter((item) =>
+              collectIds.has(String(item.id))
+            )
+            this.applyCyzxbdTabData()
+          } catch (e) {
+            this.cyzxbdCommonData = []
+            this.cyzxbdSelfData = []
+            this.cyzxbdData = []
+          } finally {
+            this.loading = false
+          }
+        },
+        applyCyzxbdTabData() {
+          this.cyzxbdData =
+            this.pendingTabActiveName === 'selfForm'
+              ? this.cyzxbdSelfData
+              : this.cyzxbdCommonData
+        },
+        handleCyzxbdTabClick(tab) {
+          if (tab && tab.name) {
+            this.pendingTabActiveName = tab.name
+          }
+          this.applyCyzxbdTabData()
+        },
+        findPagePath(res) {
+          const resList = res.split('.')
+          const findAlias = (nodes, path) => {
+            const [currentId, ...rest] = path
+            const node = nodes.find((n) => n.id === currentId)
+            return node && rest.length
+              ? [node.alias, ...findAlias(node.children, rest)]
+              : node && [node.alias]
+          }
+          this.$store.dispatch('ibps/menu/activeHeaderSet', {
+            activeHeader: resList[0],
+            vm: this
+          })
+          return findAlias(this.menus, resList).join('/')
+        },
+        handleCyzxbdClick(data) {
+          const { ziYuanLuJing = '' } = data
+          if (!ziYuanLuJing) {
+            this.$message.warning('未配置资源菜单!')
+            return
+          }
+          const path = '/' + this.findPagePath(ziYuanLuJing)
+          this.$router.push(path)
+        },
+        formatParameters(data) {
+          if (this.$utils.isEmpty(data)) {
+            return []
+          }
+          const parameters = Object.entries(data).map(([key, value]) =>
+            Array.isArray(value)
+              ? {
+                  relation: 'OR',
+                  parameters: value.map((v) => ({
+                    key,
+                    value: v,
+                    param: this.$utils.guid()
+                  }))
+                }
+              : { key, value }
+          )
+          return parameters.length === 1
+            ? [parameters[0]]
+            : [{ relation: 'AND', parameters }]
+        },
         // 过滤日程提醒数据
         filterAlertData(data, dayNumber = 3) {
           if (dayNumber <= 0) return
@@ -532,7 +703,7 @@ export function buildComponent(name, column, preview, vm) {
             notice: 'tygl/tzgg',
             myFacility: 'sshjgl/sshjjk/sshjkzzl',
             quickNavigation: 'xtgl/xtsjpz/tyglpz/kjdhpz',
-            moreFile: 'xxgl/nbwj'  //受控文件查阅
+            moreFile: 'xxgl/nbwj' //受控文件查阅
           }
           if (menuMap[url]) {
             const alias = menuMap[url].split('/')[0]
@@ -551,6 +722,9 @@ export function buildComponent(name, column, preview, vm) {
           if (this.attrs.alias === 'quickNavigation') {
             return this.openPlate('quickNavigation')
           }
+          if (this.attrs.alias === 'cyzxbd') {
+            return this.openPlate('mySysGuide')
+          }
           if (!this.attrs.colUrl) {
             return this.$message.warning('未设置更多路径的url')
           }
@@ -586,7 +760,7 @@ export function buildComponent(name, column, preview, vm) {
         },
         formValidate(formName) {
           this.$nextTick(() => {
-            this.$refs[formName].validate(() => { })
+            this.$refs[formName].validate(() => {})
           })
         },
         getFormData() {
@@ -713,15 +887,19 @@ export function buildComponent(name, column, preview, vm) {
                   if (item.ban_ci_bie_ming_) {
                     let obj = {}
                     obj.label = item.ban_ci_ming_ + '/' + item.ban_ci_bie_ming_
-                    obj.type = 'info'  //班次默认显示灰色
-                    if (item.da_ka_shi_jian_1_ && item.da_ka_shi_jian_2_) { //上下班时间都打卡了,班次显示绿色
+                    obj.type = 'info' //班次默认显示灰色
+                    if (item.da_ka_shi_jian_1_ && item.da_ka_shi_jian_2_) {
+                      //上下班时间都打卡了,班次显示绿色
                       obj.type = 'success'
-                    } else if (item.da_ka_shi_jian_1_ || item.da_ka_shi_jian_2_) {//上下班时间打卡了其中一个,班次显示橙色
+                    } else if (
+                      item.da_ka_shi_jian_1_ ||
+                      item.da_ka_shi_jian_2_
+                    ) {
+                      //上下班时间打卡了其中一个,班次显示橙色
                       obj.type = 'warning'
                     }
                     todaySchedule.push(obj) // 加入今日班次
                   }
-
                 })
                 resolve(todaySchedule)
               })
@@ -782,7 +960,7 @@ export function buildComponent(name, column, preview, vm) {
                 data.forEach((item) => {
                   // 跳过“休息”班次,不显示在日历上
                   if (item.ban_ci_ming_ === '休息') return
-                  
+
                   // 构建全天事件,每个班次显示为一个方块
                   const event = {
                     id: item.id_,
@@ -871,14 +1049,18 @@ export function buildComponent(name, column, preview, vm) {
                               return d.type === 'allday'
                                 ? '全天'
                                 : `当天 ${d.startTime}` +
-                                ' 至 ' +
-                                `${d.isSecondDay === 'Y' ? '第二天' : '当天'} ${d.endTime}`
+                                    ' 至 ' +
+                                    `${
+                                      d.isSecondDay === 'Y' ? '第二天' : '当天'
+                                    } ${d.endTime}`
                             })
                             .join('\n'),
                           title: s,
                           start: date,
-                          end: t.dateRange[0].isSecondDay == 'Y' ? nextdate : date, //是否跨天班次,跨天班次要设置为结束日期的下一天,即开始日期的后天
-                          jieShuShiJian: t.dateRange[0].isSecondDay == 'Y' ? nextdate : date,
+                          end:
+                            t.dateRange[0].isSecondDay == 'Y' ? nextdate : date, //是否跨天班次,跨天班次要设置为结束日期的下一天,即开始日期的后天
+                          jieShuShiJian:
+                            t.dateRange[0].isSecondDay == 'Y' ? nextdate : date,
                           kaishishijian: date,
                           zhuangTai: '',
                           // id: i,
@@ -913,7 +1095,8 @@ export function buildComponent(name, column, preview, vm) {
             param.event._def.title
           )
         },
-        showDaKaBtn(targetDay1, targetDay2) { //班次开始或结束时间有一个是今天就显示打卡按钮
+        showDaKaBtn(targetDay1, targetDay2) {
+          //班次开始或结束时间有一个是今天就显示打卡按钮
 
           // 判断是否展示打卡按钮,当前日期则展示
           const today = this.$common.getDateNow()
@@ -948,28 +1131,31 @@ export function buildComponent(name, column, preview, vm) {
         // 港大新首页打卡处理逻辑
         handleClockFromTabNew() {
           const { userInfo } = this.$store.getters || {}
-          const buMen = userInfo.mainPosition?.id || userInfo.positions[0]?.id || ''
+          const buMen =
+            userInfo.mainPosition?.id || userInfo.positions[0]?.id || ''
           const params = {
-              "pageNo": 1,
-              "limit": 50,
-              "param": {
-                  "buMen": buMen,
-                  "shengXiaoBiaoZhi":"Y"
-              }
+            pageNo: 1,
+            limit: 50,
+            param: {
+              buMen: buMen,
+              shengXiaoBiaoZhi: 'Y'
+            }
           }
           //获取当前用户所在部门的班次信息
           queryScheduleConfigItem(params)
-          .then((res) => {
-            const data = res.data.dataResult || []
-            if (data.length > 0) { 
-              this.$emit('action-event', 'daka', data)
-            } else {
-              this.$message.warning('您所在部门目前没有配置生效的班次,无法打卡')
-            }
-          })
-          .catch(() => {
-            console.log('获取班次信息失败')
-          })
+            .then((res) => {
+              const data = res.data.dataResult || []
+              if (data.length > 0) {
+                this.$emit('action-event', 'daka', data)
+              } else {
+                this.$message.warning(
+                  '您所在部门目前没有配置生效的班次,无法打卡'
+                )
+              }
+            })
+            .catch(() => {
+              console.log('获取班次信息失败')
+            })
         },
 
         // 首页打卡处理逻辑
@@ -980,7 +1166,11 @@ export function buildComponent(name, column, preview, vm) {
             this.$emit('dakaSingle', todaySchedule[0].label.split('/')[1])
             return
           } else {
-            this.$emit('action-event', 'daka', todaySchedule.map(item => item.label.split('/')[1]))
+            this.$emit(
+              'action-event',
+              'daka',
+              todaySchedule.map((item) => item.label.split('/')[1])
+            )
           }
         },
         /*
@@ -1084,96 +1274,97 @@ export function buildComponent(name, column, preview, vm) {
           this.$emit('action-event', 'mySchedule', scheduleConfig)
         }*/
 
-          async showMySchedule() {
-            // 直接获取考勤事件数组,不再获取排班数据
-            const events = await this.getAttendanceDataNew()
-            
-            const scheduleConfig = {
-              height: '100%',
-              locale: 'zh-cn',
-              selectable: true,
-              buttonText: {
-                today: '今天',
-                dayGridMonth: '月',
-                listMonth: '',
-                month: '月',
-                week: '周视图',
-                day: '日视图',
-                list: '表'
-              },
-              headerToolbar: {
-                right: 'prev,next today',
-                left: '',
-                center: 'title'
-              },
-              events: events,
-              eventColor: '#ffffff',
-              // 自定义事件渲染
-              eventContent: (arg) => {
-                const event = arg.event
-                const ext = event.extendedProps
-                const titleStr = `${ext.banCiMing}`
-              
-                const rawStart = ext.daKaShiJian1
-                const rawEnd = ext.daKaShiJian2
-              
-                const startTimeText = rawStart ? rawStart.substring(11, 19) : '未打卡'
-                const endTimeText = rawEnd ? rawEnd.substring(11, 19) : '未打卡'
-              
-                const hasStart = !!rawStart
-                const hasEnd = !!rawEnd
+        async showMySchedule() {
+          // 直接获取考勤事件数组,不再获取排班数据
+          const events = await this.getAttendanceDataNew()
 
-                
-                // 迟到判断(仅当有上班打卡时)
-                let isLate = false
-                if (hasStart && (ext.zhuangTai1 !== '正常')) {
-                  const startDateTime = new Date(rawStart)
-                  const banStart = new Date(ext.banCiKaiShi)
-                  isLate = startDateTime > banStart
-                }
-              
-                // 早退判断(仅当有下班打卡时)
-                let isEarlyLeave = false
-                if (hasEnd && (ext.zhuangTai2 !== '正常')) {
-                  const endDateTime = new Date(rawEnd)
-                  const banEnd = new Date(ext.banCiJieShu)
-                  isEarlyLeave = endDateTime < banEnd
-                }
-              
-                // 最终是否完全正常:有两次打卡 && 不迟到 && 不早退 && 两次打卡状态都为正常
-                const isAllNormal = hasStart && hasEnd && !isLate && !isEarlyLeave && ext.zhuangTai1 == '正常' && ext.zhuangTai2 == '正常'
-              
-                // 小方块颜色与状态图标
-                const dotColor = isAllNormal ? '#67C23A' : '#F56C6C'
-                const statusIconHtml = isAllNormal
-                  ? '<i class="el-icon-check" style="color:#67C23A; font-size:14px;"></i>'
-                  : '<i class="el-icon-warning-outline" style="color:#F56C6C; font-size:14px;"></i>'
-              
-                // 上班打卡显示
-                let startDisplay = startTimeText
-                let startColorStyle = ''
-                if (!hasStart) {
-                  startColorStyle = 'style="color:#F56C6C; font-weight:500;"'
-                } else if (isLate) {
-                  startDisplay = startTimeText + ' (迟到)'
-                  startColorStyle = 'style="color:#F56C6C; font-weight:500;"'
-                }
-                const startTimeHtml = `<span ${startColorStyle}>${startDisplay}</span>`
-              
-                // 下班打卡显示
-                let endDisplay = endTimeText
-                let endColorStyle = ''
-                if (!hasEnd) {
-                  endColorStyle = 'style="color:#F56C6C; font-weight:500;"'
-                } else if (isEarlyLeave) {
-                  endDisplay = endTimeText + ' (早退)'
-                  endColorStyle = 'style="color:#F56C6C; font-weight:500;"'
-                }
-                const endTimeHtml = `<span ${endColorStyle}>${endDisplay}</span>`
-              
-                const fragment = document.createDocumentFragment()
-                const content = document.createElement('div')
-                content.innerHTML = `
+          const scheduleConfig = {
+            height: '100%',
+            locale: 'zh-cn',
+            selectable: true,
+            buttonText: {
+              today: '今天',
+              dayGridMonth: '月',
+              listMonth: '',
+              month: '月',
+              week: '周视图',
+              day: '日视图',
+              list: '表'
+            },
+            headerToolbar: {
+              right: 'prev,next today',
+              left: '',
+              center: 'title'
+            },
+            events: events,
+            eventColor: '#ffffff',
+            // 自定义事件渲染
+            eventContent: (arg) => {
+              const event = arg.event
+              const ext = event.extendedProps
+              const titleStr = `${ext.banCiMing}`
+
+              const rawStart = ext.daKaShiJian1
+              const rawEnd = ext.daKaShiJian2
+
+              const startTimeText = rawStart
+                ? rawStart.substring(11, 19)
+                : '未打卡'
+              const endTimeText = rawEnd ? rawEnd.substring(11, 19) : '未打卡'
+
+              const hasStart = !!rawStart
+              const hasEnd = !!rawEnd
+
+              // 迟到判断(仅当有上班打卡时)
+              let isLate = false
+              if (hasStart) {
+                const startDateTime = new Date(rawStart)
+                const banStart = new Date(ext.banCiKaiShi)
+                isLate = startDateTime > banStart
+              }
+
+              // 早退判断(仅当有下班打卡时)
+              let isEarlyLeave = false
+              if (hasEnd) {
+                const endDateTime = new Date(rawEnd)
+                const banEnd = new Date(ext.banCiJieShu)
+                isEarlyLeave = endDateTime < banEnd
+              }
+
+              // 最终是否完全正常:有两次打卡 && 不迟到 && 不早退
+              const isAllNormal = hasStart && hasEnd && !isLate && !isEarlyLeave
+
+              // 小方块颜色与状态图标
+              const dotColor = isAllNormal ? '#67C23A' : '#F56C6C'
+              const statusIconHtml = isAllNormal
+                ? '<i class="el-icon-check" style="color:#67C23A; font-size:14px;"></i>'
+                : '<i class="el-icon-warning-outline" style="color:#F56C6C; font-size:14px;"></i>'
+
+              // 上班打卡显示
+              let startDisplay = startTimeText
+              let startColorStyle = ''
+              if (!hasStart) {
+                startColorStyle = 'style="color:#F56C6C; font-weight:500;"'
+              } else if (isLate) {
+                startDisplay = startTimeText + ' (迟到)'
+                startColorStyle = 'style="color:#F56C6C; font-weight:500;"'
+              }
+              const startTimeHtml = `<span ${startColorStyle}>${startDisplay}</span>`
+
+              // 下班打卡显示
+              let endDisplay = endTimeText
+              let endColorStyle = ''
+              if (!hasEnd) {
+                endColorStyle = 'style="color:#F56C6C; font-weight:500;"'
+              } else if (isEarlyLeave) {
+                endDisplay = endTimeText + ' (早退)'
+                endColorStyle = 'style="color:#F56C6C; font-weight:500;"'
+              }
+              const endTimeHtml = `<span ${endColorStyle}>${endDisplay}</span>`
+
+              const fragment = document.createDocumentFragment()
+              const content = document.createElement('div')
+              content.innerHTML = `
                   <div class="event-header" style="display:flex; justify-content:space-between; align-items:center;">
                     <div>
                       <div style="background:${dotColor}; height:10px; width:10px; display:inline-block; border-radius:2px;"></div>
@@ -1186,12 +1377,12 @@ export function buildComponent(name, column, preview, vm) {
                     <div>下班打卡时间:${endTimeHtml}</div>
                   </div>
                 `
-                fragment.appendChild(content)
-                return { domNodes: [fragment] }
-              }
+              fragment.appendChild(content)
+              return { domNodes: [fragment] }
             }
-            this.$emit('action-event', 'mySchedule', scheduleConfig)
           }
+          this.$emit('action-event', 'mySchedule', scheduleConfig)
+        }
       },
       template:
         column.templateHtml !== '' ? `${column.templateHtml}` : `<div></div>`

+ 95 - 0
src/views/system/dashboard/templates/cyzxbd.vue

@@ -0,0 +1,95 @@
+<template>
+  <el-card
+    v-loading.fullscreen.lock="loading"
+    class="home-card pending-business cyzxbd-panel"
+    :element-loading-text="$t('common.loading')"
+    element-loading-background="transparent"
+    :style="{
+      height: '100%',
+      overflow: 'hidden'
+    }"
+    :body-style="{
+      height: '100%',
+      boxSizing: 'border-box',
+      overflow: 'hidden',
+      padding: '10px 20px 15px'
+    }"
+  >
+    <div
+      class="tabs-toolbar"
+      style="position: absolute; right: 20px; top: 12px; z-index: 3"
+    >
+      <ibps-desktop-toolbar
+        ref="toolbar"
+        :actions="[{ key: 'more' }]"
+        @action-event="handleActionEvent"
+      />
+    </div>
+    <el-tabs
+      v-model="pendingTabActiveName"
+      class="pending-Tabs"
+      @tab-click="handleCyzxbdTabClick"
+    >
+      <el-tab-pane
+        v-for="item in [
+          {
+            label: '常用表单',
+            name: 'commonlyForm'
+          },
+          {
+            label: '自选表单',
+            name: 'selfForm'
+          }
+        ]"
+        :key="item.name"
+        :label="item.label"
+        :name="item.name"
+      >
+        <div
+          ref="body"
+          class="cyzxbd-scroll"
+          :style="{
+            height: 'calc(56vh - 80px)',
+            width: '100%',
+            overflowX: 'hidden',
+            overflowY: 'auto',
+            scrollbarWidth: 'none',
+            msOverflowStyle: 'none'
+          }"
+        >
+          <ibps-list
+            v-if="cyzxbdData && cyzxbdData.length > 0"
+            class="ibps-pr-10"
+          >
+            <ibps-list-item
+              v-for="(d, index) in cyzxbdData"
+              :key="d.id || index"
+              style="padding: 0"
+              @click.native="handleCyzxbdClick(d)"
+            >
+              <ibps-list-item-meta>
+                <el-link slot="title" type="primary" :underline="false">
+                  <i
+                    class="el-icon-document"
+                    style="
+                      font-size: 1em;
+                      margin-right: 4px;
+                      vertical-align: middle;
+                    "
+                  ></i>
+                  {{ d.biaoDanMingChe }}
+                </el-link>
+              </ibps-list-item-meta>
+            </ibps-list-item>
+          </ibps-list>
+          <el-alert
+            v-else
+            :title="$t('common.noData')"
+            :closable="false"
+            type="warning"
+          />
+        </div>
+      </el-tab-pane>
+    </el-tabs>
+  </el-card>
+</template>

+ 134 - 4
src/views/system/dashboard/templates/systemGuide.vue

@@ -19,6 +19,13 @@
           @sort-change="handleSortChange"
           @pagination-change="handlePaginationChange"
         >
+          <template slot="collect" slot-scope="{ row }">
+            <i
+              class="collect-star"
+              :class="row.collect ? 'ibps-icon-star' : 'ibps-icon-star-o'"
+              @click.stop="handleCollectClick(row)"
+            />
+          </template>
           <template slot="role" slot-scope="{ row, column }">
             <ibps-user-selector
               v-model="row[column.prop]"
@@ -64,7 +71,8 @@ export default {
       deptList = [],
       role = [],
       menus = [],
-      isSuper
+      isSuper,
+      userId
     } = this.$store.getters || {}
     const allRolesMap = new Map()
     userList.forEach((user) => {
@@ -100,6 +108,7 @@ export default {
       }
     ]
     return {
+      userId,
       title: '系统指引',
       level,
       userList,
@@ -117,15 +126,53 @@ export default {
         limit: 100,
         page: 1
       },
+      isSetting: false,
+      collectFormIds: [],
+      collectChanges: {},
       listConfig: {
         searchForm,
         toolbars: [
           {
             key: 'search'
+          },
+          {
+            key: 'settingUp',
+            label: '自选表单设置',
+            icon: 'ibps-icon-cog',
+            type: 'warning',
+            hidden: (data) => {
+              return this.isSetting
+            }
+          },
+          {
+            key: 'saveChoose',
+            label: '保存自选',
+            icon: 'ibps-icon-edit',
+            type: 'success',
+            hidden: (data) => {
+              return !this.isSetting
+            }
+          },
+          {
+            key: 'cancelChoose',
+            label: '取消',
+            icon: 'ibps-icon-cancel',
+            type: 'info',
+            hidden: (data) => {
+              return !this.isSetting
+            }
           }
         ],
         // 表格字段配置
         columns: [
+          {
+            prop: 'collect',
+            label: '自选',
+            width: 60,
+            align: 'center',
+            fieldType: 'slot',
+            slotName: 'collect'
+          },
           // { prop: 'sn', label: '序号', width: 60, sort: true },
           { prop: 'suoShuXiTong', label: '所属子系统', width: 100 },
           {
@@ -203,9 +250,32 @@ export default {
     },
     loadData() {
       this.loading = true
-      querySystemGuide(this.getSearchFormData())
-        .then((res) => {
+
+      Promise.all([
+        querySystemGuide(this.getSearchFormData()),
+        this.$common.request('query', {
+          key: 'zxbdryglgxcx',
+          params: [this.userId]
+        })
+      ])
+        .then(([res, res1]) => {
+          console.log(res, res1)
           const { dataResult } = res.data
+          const { data = [] } = res1.variables || {}
+          this.collectFormIds = data
+            .map((item) => item.ji_lu_biao_dan_id)
+            .filter(Boolean)
+          const collectIdSet = new Set(
+            this.collectFormIds.map((id) => String(id))
+          )
+          dataResult.forEach((item) => {
+            item.collect = Object.prototype.hasOwnProperty.call(
+              this.collectChanges,
+              item.id
+            )
+              ? this.collectChanges[item.id]
+              : collectIdSet.has(String(item.id))
+          })
           const { isEmpty } = this.$utils
           // 无排序字段时,默认按序号排序
           if (isEmpty(this.sorts)) {
@@ -305,7 +375,8 @@ export default {
       this.loadData()
     },
     // 处理表格点击事件
-    handleRowClick(data) {
+    handleRowClick(data, column) {
+      if (column && column.property === 'collect') return
       const { ziYuanLuJing = '' } = data
       if (!ziYuanLuJing) {
         this.$message.warning('未配置资源菜单!')
@@ -314,12 +385,67 @@ export default {
       const path = '/' + this.findPagePath(ziYuanLuJing)
       this.$router.push(path)
     },
+    handleCollectClick(row) {
+      if (!this.isSetting) return
+      row.collect = !row.collect
+      this.$set(this.collectChanges, row.id, row.collect)
+    },
+    async saveChoose() {
+      this.loading = true
+      try {
+        // 以原收藏为基础,叠加本次勾选变更,避免分页/筛选导致漏写
+        const formIdSet = new Set(
+          this.collectFormIds.map((id) => String(id))
+        )
+        Object.entries(this.collectChanges).forEach(([id, collected]) => {
+          if (collected) {
+            formIdSet.add(String(id))
+          } else {
+            formIdSet.delete(String(id))
+          }
+        })
+        await this.$common.request('delete', {
+          tableName: 't_zxbdryglgxb',
+          paramWhere: {
+            bian_zhi_ren_: this.userId
+          }
+        })
+        const collectIds = Array.from(formIdSet).filter(Boolean)
+        if (collectIds.length) {
+          await this.$common.request('add', {
+            tableName: 't_zxbdryglgxb',
+            paramWhere: collectIds.map((id) => ({
+              ji_lu_biao_dan_id: id,
+              bian_zhi_ren_: this.userId
+            }))
+          })
+        }
+        this.collectChanges = {}
+        this.isSetting = false
+        this.$message.success('保存成功')
+        this.loadData()
+      } catch (e) {
+        this.loading = false
+        this.$message.warning('保存失败')
+      }
+    },
     handleAction(command, position, selection, data) {
       switch (command) {
         case 'search': // 查询
           ActionUtils.setFirstPagination(this.pagination || {})
           this.search()
           break
+        case 'settingUp':
+          this.isSetting = true
+          break
+        case 'saveChoose':
+          this.saveChoose()
+          break
+        case 'cancelChoose':
+          this.collectChanges = {}
+          this.isSetting = false
+          this.loadData()
+          break
         default:
           break
       }
@@ -343,6 +469,10 @@ export default {
 }
 </script>
 <style lang="scss" scoped>
+.collect-star {
+  color: #e6a23c;
+  cursor: pointer;
+}
 ::v-deep .el-table__row {
   cursor: pointer;
 }