123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721 |
- <template>
- <WorkspaceCard class="work-common" title="常用功能">
- <span slot="header-right" class="header-right-set" @click="setCommonFun"><i class="icon-set-img"></i> 设置</span>
- <div class="common-lists">
- <div class="list-item" v-for="item in commonList" :key="item.id" @click="openLink(item)">
- <div class="icon-box-container" v-if="item.icon && item.icon.indexOf('icon-') === 0">
- <JyIcon :name="item.icon" classPrefix=""></JyIcon>
- </div>
- <div v-else class="icon-box-container">
- <el-image :src="item.icon" alt="常用功能">
- <img slot="error" src="https://www.jianyu360.cn/common-module/public/image/auto.png" />
- </el-image>
- </div>
- <span v-html="item.name.replace('/', '/<br>')" class="item-name"></span>
- </div>
- <div v-if="commonList && commonList.length < maxCount" class="list-add" @click="setCommonFun">
- <span class="icon-add-img"></span>
- <span class="add-text">添加常用功能</span>
- </div>
- </div>
- <!-- 设置常用功能dialog -->
- <el-dialog
- custom-class="fn-dialog"
- :visible.sync="dialogShow"
- :close-on-click-modal="false"
- :show-close="false"
- v-if="dialogShow"
- center
- width="696px">
- <SelectorCard @onCancel="changeDialogState(false)" @onConfirm="confirmSaveFn" confirmText="确定">
- <div slot="header">常用功能设置</div>
- <div class="transfer-content">
- <Transfer :maxCount="maxCount" submitKey="id" :left="allFunctions" :right="transferCommonList" @onSave="onTransferSave"></Transfer>
- </div>
- </SelectorCard>
- </el-dialog>
- <!-- 改为抽屉式 -->
- <DrawerCard customClass="drawer-class" title="常用功能设置" percent="600px" :with-header="false" v-model="drawerShow" @close="onCloseDrawer" @saveData="onSaveDrawer">
- <div class="function-drawer-content" ref="drawerScroll" @scroll="handleScroll($event)">
- <div class="added-function">
- <h3 class="added-title">已添加({{addedList.length}})</h3>
- <transition-group class="added-container" name="drag" tag="ul" v-if="addedList && addedList.length > 0">
- <li class="added-item" draggable v-for="(item, i) in addedList" :key="item.id" @dragover.prevent @dragstart="onDragstart($event, i)" @dragenter="onDragenter($event, i)" @dragend="onDragend($event, i)">
- <div class="icon-box-container">
- <el-image :src="item.icon" :alt="item.name">
- <img slot="error" src="https://www.jianyu360.cn/common-module/public/image/auto.png" />
- </el-image>
- </div>
- <span v-html="item.name.replace('/', '/<br>')" class="item-name"></span>
- <span class="remove-tag" @click.stop="onAddedRemove(item)">-</span>
- </li>
- </transition-group>
- <div v-else class="no-added">暂未设置常用功能</div>
- </div>
- <div class="classify-function" ref="refContent">
- <div class="classify-tab" :class="{'tab-fixed': tabFixed}" ref="tabBox">
- <span class="tab-item" :class="{'active': tabActive === index}" v-for="(item, index) in tabNames" :key="item.id" @click="goAnchor(item, index)">{{item.name}}</span>
- </div>
- <div class="classify-content">
- <ul class="outer-container">
- <li class="outer-item" :id="level.name" v-for="level in mainFunList" :key="level.id">
- <h3 class="outer-item-name">{{ level.name }}</h3>
- <ul class="insert-container">
- <li class="insert-item" v-for="next in level.children" :key="next.id">
- <div class="insert-item-left">
- <el-image :src="next.icon" :alt="next.name">
- <img slot="error" src="https://www.jianyu360.cn/common-module/public/image/auto.png" />
- </el-image>
- <span v-html="next.name.replace('<br>', '')"></span>
- </div>
- <transition name="el-zoom-in-center">
- <span v-if="next.status" class="handle-btn remove-btn" @click.stop="onRemoveFun(next)">移除</span>
- <span v-else class="handle-btn add-btn" @click.stop="onAddFun(next)">添加</span>
- </transition>
- </li>
- </ul>
- </li>
- </ul>
- </div>
- </div>
- </div>
- </DrawerCard>
- </WorkspaceCard>
- </template>
- <script>
- import { JyIcon } from '@jianyu/icon'
- import { mapState, mapMutations, mapActions } from 'vuex'
- import { Dialog, Image } from 'element-ui'
- import WorkspaceCard from '../ui/WorkspaceCard'
- import SelectorCard from '@/components/selector/SelectorCard'
- import Transfer from '@/components/work-desktop/Transfer'
- import { mixinNoPowerMessageTip } from '@/utils/mixins/no-power-message-box'
- import { tryCallHooks } from '@jianyu/easy-inject-qiankun'
- import { debounce } from '@/utils/globalFunctions'
- import DrawerCard from '@/components/drawer/Drawer.vue'
- export default {
- name: 'CommonUse',
- mixins: [mixinNoPowerMessageTip],
- components: {
- [Dialog.name]: Dialog,
- [Image.name]: Image,
- WorkspaceCard,
- SelectorCard,
- JyIcon,
- Transfer,
- DrawerCard
- },
- data () {
- return {
- addedList: [],
- mainFunList: [],
- dragIndex: '',
- enterIndex: '',
- tabActive: 0,
- tabFixed: false,
- isScrollAnchor: true
- }
- },
- computed: {
- ...mapState({
- maxCount: state => state.workspace.commonUse.maxCount,
- dialogShow: state => state.workspace.commonUse.dialogShow,
- allFunctions: state => state.workspace.commonUse.allFunctions, // 所有功能
- transferCommonList: state => state.workspace.commonUse.transferCommonList,
- commonList: state => state.workspace.commonUse.commonList, // 常用功能
- mainFunctions: state => state.workspace.commonUse.mainFunctions,
- drawerShow: state => state.workspace.commonUse.drawerShow
- }),
- tabNames () {
- return this.mainFunctions.filter(item => item.level === 1)
- }
- },
- watch: {
- commonList (val) {
- if (val) {
- this.addedList = JSON.parse(JSON.stringify(val))
- this.formatMainFunList(this.addedList)
- }
- },
- mainFunctions (val) {
- if (val) {
- this.mainFunList = JSON.parse(JSON.stringify(val))
- this.formatMainFunList(this.addedList)
- }
- },
- drawerShow (val) {
- if (!val) {
- this.tabFixed = false
- this.tabActive = 0
- }
- }
- },
- async created () {
- await this.getCanUseFunctions()
- await this.getAllFunctions({ vm: this })
- },
- beforeDestroy () {
- window.removeEventListener('scroll', this.handleScroll)
- },
- methods: {
- ...mapMutations('workspace/commonUse', [
- 'changeDialogState',
- 'transferSave',
- 'changeDrawerState'
- ]),
- ...mapActions('workspace/commonUse', [
- 'getAllFunctions',
- 'getCanUseFunctions',
- 'confirmSave'
- ]),
- // 穿梭框子组件传来的组件
- onTransferSave (data) {
- this.transferSave(data)
- },
- openLink (item) {
- const { url } = item
- if (item.usable) {
- tryCallHooks({
- fn: () => {
- this.$BRACE.methods.open({
- route: {
- ...item,
- link: url
- }
- })
- },
- spareFn: () => {
- window.open(url)
- }
- })
- } else {
- // 判断是否需要自定义弹窗文案
- const hasTipInfo = Object.keys(item?.tipInfo || {}).length > 0
- if (hasTipInfo) {
- // 自定义弹窗文案
- const menu = item
- // 格式化弹窗配置信息
- const dialogParams = {
- type: 'tip',
- title: menu.tipInfo?.title,
- message: menu.tipInfo?.content,
- options: Object.assign({
- dangerouslyUseHTMLString: true,
- customClass: 'custom-message-box',
- confirmButtonText: '我知道了',
- confirmButtonClass: 'custom-confirm-btn',
- showClose: false,
- showCancelButton: false,
- closeOnClickModal: false,
- center: true
- }, {
- showCancelButton: !!menu.tipInfo?.isShowCancel,
- confirmButtonText: menu.tipInfo?.confirmText
- }, menu.tipInfo?.options || {})
- }
- this.$confirm(dialogParams.message, dialogParams.title, dialogParams.options).then(() => {
- // 确认按钮自定义跳转
- if (menu.tipInfo?.confirmUrl) {
- // 调用工作桌面函数跳转
- tryCallHooks({
- fn: () => {
- this.$BRACE.methods.open({
- route: {
- link: menu.tipInfo?.confirmUrl,
- appType: menu.tipInfo?.appType,
- openType: menu.tipInfo?.openType
- }
- })
- },
- spareFn: () => {
- window.open(menu.tipInfo?.confirmUrl)
- }
- })
- }
- }).catch(e => e)
- } else {
- // 默认文案
- this.showNoPowerMessageTip()
- }
- }
- },
- confirmSaveFn () {
- try {
- this.confirmSave()
- } catch (error) {
- this.$toast(error)
- }
- },
- onDragstart (e, index) {
- this.dragIndex = index
- const element = e.target
- element.classList.add('drag-move-item')
- },
- onDragenter: debounce(function (e, index) {
- e.preventDefault()
- if (this.dragIndex !== index) {
- const source = this.addedList[this.dragIndex]
- this.addedList.splice(this.dragIndex, 1)
- this.addedList.splice(index, 0, source)
- this.dragIndex = index
- const ids = this.addedList.map(v => {
- return v.id
- })
- this.transferSave(ids)
- }
- }, 200),
- onDragend (e, index) {
- e.preventDefault()
- const element = e.srcElement
- element.classList.remove('drag-move-item')
- this.$forceUpdate()
- },
- formatMainFunList (addedList = []) {
- this.mainFunList.forEach(v => {
- v.children.forEach(t => {
- t.status = false
- addedList.forEach(s => {
- if (s.id === t.id || s.name === t.name) {
- t.status = true
- }
- })
- })
- })
- },
- onCloseDrawer () {
- // this.tabFixed = false
- // this.tabActive = 0
- this.formatMainFunList(this.commonList)
- this.changeDrawerState(false)
- },
- onSaveDrawer () {
- this.confirmSaveFn()
- },
- setCommonFun () {
- this.changeDrawerState(true)
- this.addedList = JSON.parse(JSON.stringify(this.commonList))
- this.formatMainFunList(this.addedList)
- },
- onRemoveFun (item) {
- item.status = false
- this.addedList.splice(this.addedList.findIndex(add => add.id === item.id || add.name === item.name), 1)
- this.updateMainFunStatus(item)
- },
- onAddFun (item) {
- item.status = true
- this.addedList.unshift(item)
- this.updateMainFunStatus(item)
- },
- onAddedRemove (item) {
- this.addedList.splice(this.addedList.findIndex(add => add.id === item.id), 1)
- this.mainFunList.forEach(v => {
- if (v.children) {
- v.children.forEach(s => {
- if (item.id === s.id || item.name === s.name) {
- s.status = false
- this.$forceUpdate()
- }
- })
- }
- })
- const ids = this.addedList.map(v => {
- return v.id
- })
- this.transferSave(ids)
- },
- goAnchor (item, index) {
- this.isScrollAnchor = false
- const dom = this.$root.$el.querySelector('#' + item.name)
- const offsetTop = this.getOffsetTop(dom)
- // qiankun 子应用选择器获取不到document 改为this.$root.$el
- const scrollDom = this.$root.$el.querySelector('.function-drawer-content')
- // const addTop = this.$root.$el.querySelector('.added-function').offsetHeight
- const scrollTop = offsetTop - 70 - 48
- scrollDom.scrollTo({
- /**
- * 抽屉header高度70px, tabs导航栏高度48px, 滚动子元素h3标题高度60px
- */
- top: scrollTop,
- behavior: 'smooth'
- })
- this.tabActive = index
- setTimeout(() => {
- this.isScrollAnchor = true
- }, 800)
- },
- handleScroll (e) {
- const tabOffsetTop = this.$refs.refContent.getBoundingClientRect().top
- this.tabFixed = tabOffsetTop <= 70
- if (!this.isScrollAnchor) return
- const scrollItems = this.$root.$el.querySelectorAll('.outer-item')
- for (let i = scrollItems.length - 1; i >= 0; i--) {
- // console.log(e.target.scrollTop, this.getOffsetTop(scrollItems[i]), this.getOffsetTop(scrollItems[0]), 'judge')
- const scrollItemTop = this.getOffsetTop(scrollItems[i])
- // 判断滚动条滚动距离是否大于当前滚动项可滚动距离
- const judge =
- e.target.scrollTop >= scrollItemTop - 70 - 48 - 60
- if (judge) {
- this.tabActive = i
- break
- }
- }
- },
- // 获取当前元素的offsetTop
- getOffsetTop (obj) {
- let offsetTop = 0
- while (obj !== window.document.body && obj != null) {
- offsetTop += obj.offsetTop
- obj = obj.offsetParent
- }
- return offsetTop
- },
- updateMainFunStatus (item) {
- this.mainFunList.forEach(v => {
- if (v.children) {
- v.children.forEach(s => {
- if (item.id === s.id || item.name === s.name) {
- s.status = item.status
- this.$forceUpdate()
- }
- })
- }
- })
- this.formatMainFunList(this.addedList)
- const ids = this.addedList.map(v => {
- return v.id
- })
- this.transferSave(ids)
- this.$forceUpdate()
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- $main: #2cb7ca;
- .drag-move {
- transition: transform .3s;
- }
- ::v-deep{
- .fn-dialog{
- .el-dialog__header,.el-dialog__body{
- padding: 0;
- }
- }
- .transfer-content{
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .selector-card-header{
- margin: 0 0 28px!important;
- }
- .selector-card.s-card{
- width: 100%;
- }
- .selector-card-content{
- display: block!important;
- padding: 0 30px;
- }
- .more-tips{
- margin-top: 20px;
- font-size: 14px;
- line-height: 22px;
- text-align: center;
- color: #686868;
- }
- .drawer-class{
- background: #F2F2F4;
- .el-header{
- padding: 26px 30px;
- font-size: 18px;
- background: #fff;
- box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.05) inset;
- }
- .el-main{
- overflow-y: hidden!important;
- }
- .function-drawer-content{
- height: 100%;
- overflow-y: scroll;
- }
- .added-function{
- padding: 16px 30px 24px;
- background: #fff;
- .added-title{
- line-height: 24px;
- font-size: 16px;
- }
- .no-added{
- padding: 40px;
- text-align: center;
- font-size: 16px;
- color: #686868;
- }
- .added-container{
- display: flex;
- flex-wrap: wrap;
- }
- .added-item{
- position: relative;
- display: flex;
- flex-direction: column;
- align-items: center;
- width: 104px;
- height: fit-content;
- margin: 16px 0 0 0;
- padding: 8px 0;
- text-align: center;
- flex-shrink: 0;
- border-radius: 8px;
- cursor: grabbing;
- .item-name{
- margin-top: 8px;
- line-height: 22px;
- font-size: 14px;
- color: #1D1D1D;
- pointer-events: none;
- }
- .remove-tag{
- position: absolute;
- top: 0;
- right: 8px;
- display: inline-block;
- width: 14px;
- height: 14px;
- line-height: 12px;
- border-radius: 50%;
- background: #FF3A20;
- color: #fff;
- font-weight: bold;
- cursor: pointer;
- font-size: 16px;
- }
- }
- .drag-move-item{
- // padding: 8px 0;
- border: 1px solid rgba(0, 0, 0, 0.05);
- box-shadow: 0px 2px 16px rgba(0, 0, 0, 0.08);
- // border-radius: 8px;
- .remove-tag{
- display: none;
- }
- }
- .drag-init-hide{
- transition: 0.01s;
- transform: translateX(-9999px);
- }
- }
- .classify-function{
- margin-top: 12px;
- .classify-tab{
- width: 100%;
- padding: 0 12px;
- background: #fff;
- white-space: nowrap;
- overflow-x: auto;
- border-bottom: 1px solid rgba(0, 0, 0, 0.05);
- &::-webkit-scrollbar{
- height: 4px;
- }
- &::-webkit-scrollbar-track {
- background-color: #f5f5f5;
- }
- &::-webkit-scrollbar-thumb {
- border-radius: 2px;
- background-color: #ECECEC;
- opacity: 0.15;
- }
- }
- .tab-fixed{
- position: fixed;
- top: 70px;
- width: 100%;
- background: #fff;
- z-index: 10;
- white-space: nowrap;
- overflow-x: auto;
- }
- .tab-item{
- display: inline-block;
- // height: 100%;
- height: 48px;
- line-height: 48px;
- padding: 0 20px;
- cursor: pointer;
- font-size: 16px;
- }
- .active{
- position: relative;
- color: $main;
- &::after{
- position: absolute;
- content: '';
- width: 32px;
- height: 2px;
- bottom: 0;
- left: 50%;
- margin-left: -16px;
- background: $main;
- }
- }
- .classify-content{
- .outer-container,
- .insert-container{
- display: flex;
- flex-direction: column;
- }
- .outer-item{
- padding-left: 30px;
- margin-bottom: 8px;
- background: #fff;
- &:last-child{
- min-height: 100%;
- }
- }
- .outer-item-name{
- padding: 24px 0 8px;
- font-size: 18px;
- line-height: 28px;
- font-weight: 700;
- color: #1D1D1D;
- }
- .insert-item{
- position: relative;
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 18px 30px 18px 0;
- &::after{
- position: absolute;
- content: '';
- right: 0;
- left: 60px;
- bottom: 0;
- border-bottom: 1px solid rgba(0, 0, 0, 0.05);
- }
- .el-image{
- width: 44px;
- height: 44px;
- flex-shrink: 0;
- }
- }
- .insert-item-left{
- display: flex;
- align-items: center;
- span{
- margin-left: 16px;
- font-size: 16px;
- line-height: 24px;
- }
- }
- .handle-btn{
- width: 72px;
- height: 30px;
- line-height: 28px;
- text-align: center;
- background: transparent;
- cursor: pointer;
- }
- .add-btn{
- border: 1px solid #E0E0E0;
- color: #1D1D1D;
- border-radius: 4px;
- }
- .remove-btn{
- border: 0;
- font-size: 14px;
- color: #FF3A20;
- }
- }
- }
- }
- }
- .icon-box-container {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 44px;
- height: 44px;
- pointer-events: none;
- ::before{
- content: ''
- }
- ::v-deep {
- .el-image {
- width: 100%;
- height: 100%;
- img {
- width: 100%;
- height: 100%;
- }
- }
- }
- }
- .icon-set-img{
- display: inline-block;
- width: 18px;
- height: 18px;
- margin-right: 6px;
- background: url('~@/assets/images/icon/icon-set.png') no-repeat center center;
- background-size: contain;
- }
- .icon-add-img{
- display: inline-block;
- width: 44px;
- height: 44px;
- background: url('~@/assets/images/icon/icon-add.png') no-repeat center center;
- background-size: contain;
- }
- .header-right-set {
- display: flex;
- align-items: center;
- color: $main;
- font-size: 14px;
- cursor: pointer;
- }
- .common-lists{
- padding: 0 20px;
- display: flex;
- flex-wrap: wrap;
- .list-item,
- .list-add{
- width: 120px;
- padding: 18px 0 24px;
- display: flex;
- flex-direction: column;
- align-items: center;
- text-align: center;
- cursor: pointer;
- }
- .list-item{
- // flex: 1;
- &:hover{
- span{
- color: $main;
- }
- }
- }
- .item-name,.add-text{
- margin-top: 10px;
- font-size: 14px;
- line-height: 20px;
- color: #1D1D1D;
- @media only screen and (max-width: 1280px) {
- font-size: 12px;
- }
- }
- .item-img{
- width: 44px;
- height: 44px;
- }
- .add-text{
- white-space: nowrap;
- color: #686868;
- }
- }
- </style>
|