# 桌面端动态组件

# 一 注意事项

  • 1 请使用vue2来实现;
  • 2 请采用库文件的方式打包,构建目标 - 库 (opens new window)
  • 3 工程项目package.json文件,name属性值以"workbench-com"开头,否则组件会挂载失败。

# 二 平台能力

提供打开新窗口、hwork的token、用户信息、事件订阅发布等能力;
具体有doOpenTab、hworkInfo、userInfo、eventEmitter、refresh;

  • 1 doOpenTab(params),打开新的窗口方法;
export default {
    inject: ['_hwork'],
    .... // 省略与接入不相关的代码
    methods: {
        openNewTab () {
            this._hwork.doOpenTab({
                componentName: 'xxx',                     // 🌟 组件的名称
                componentUrl: 'https://xxx.xxx.xxx/xxx',  // 🌟 组件url地址
                uniqueVal: 'xxx',                         // 🌟 组件唯一标示   
                iconUrl: 'https://xxx.xxx.xxx/xxx',       // 🌟 组件icon地址
                type: 2,                                  // 🌟 2: 打开新窗口
                // isRefresh: false                       // 是否刷新
            })
        }
    }
}
  • 2 hworkInfo(Object),hwork的token;
hworkInfo = {
    token: "xxx"               // 🌟 Hwork web端token,非桌面端      
    refreshToken: "xxx"                 
    iamAccessToken: "xxx"      // iamToken             
}
  • 3 userInfo(Object),用户信息;
userInfo = {
    userName: "张某某"                 // 姓名      
    userId: "19123456"                // 工号        
    gwName: "产品管理(产品经理)"       // 职位             
    deptName: "用户运营节点小微"         // 部门            
    phone: "13387654321"              // 电话                
    email: "zhangmoumou@haier.com"   // email                           
    hworkAvatar: "https://haier-hwork-public.oss-cn-qingdao.aliyuncs.com/hwork-emp-prod/8e37da58b4cd411f8fac4d58ef97207a.jpg" // 头像           
    roleName: "管理员(业务)"           // 角色                    
    userSex: "1"                     // 1: 男 2: 女                  
}
  • 4 eventEmitter(Object),事件订阅发布;
// 订阅
on (event, callback) { }    // event: '事件名称' callback: '回调函数'
// 订阅一次
once (event, callback) { }  // event: '事件名称' callback: '回调函数'
// 取消订阅
off (event, callback) { }   // event: '事件名称' callback: '回调函数'
// 发布
emit () { }

// 示例
this._hwork.eventEmitter.on('jsh-switch-page', (params) => { // 🌟 jsh代表的是项目缩写,避免命名污染;
    ...... // 业务逻辑省略
})
this._hwork.eventEmitter.emit('jsh-switch-page', {
    pageNum: 1,
    pageNo: 10
    code: 's112'
})
  • 5 refresh(Boolean),有相互关联的不同窗口,需要刷新;

# 三 接入步骤

以 dynamic 项目为例:

# 1. 目录结构

dynamic # 项目目录
├── .env.development # 开发环境配置
├── .env.testing     # 测试环境配置
├── .env.production  # 生产环境配置
├── lib # 打包后存放目录
    ├── dynamic-dev.umd.js
    ├── dynamic-dev.umd.min.js
    ├── dynamic-dev.common.js
├── src # 项目主文件目录
    ├── dynamic.js    # 入口文件
    ├── Dynamic.vue   # 根组件(初始化)
    ├── components    # 组件目录
        ├── DynamicIndex.vue
        ......               
├── package.json
├── vue.config.js     # 打包配置文件

# 2. dynamic.js

import Dynamic from '@/Dynamic.vue'
export default Dynamic

# 3. Dynamic.vue

<template>
    <DynamicIndex />
</template>

<script>
import DynamicIndex from '@/components/DynamicIndex.vue'

export default {
    name: 'Dynamic',
    components: {
        DynamicIndex
    },
    props: {
        doOpenTab: { // 🌟 打开新窗口的方法
            type: Function,
            default: () => { }
        },
        hworkInfo: { // 🌟 token数据
            type: Object,
            default: () => ({})
        },
        userInfo: { // 🌟 用户信息
            type: Object,
            default: () => ({})
        },
        eventEmitter: { // 🌟 事件订阅发布
            type: Object,
            default: () => ({})
        },
        refresh: { // 🌟 是否刷新页面
            type: Boolean,
            default: false
        }
    },
    provide() {
        const _hwork = {}
        Object.defineProperty(_hwork, 'doOpenTab', {
            enumerable: true,
            get: () => this.doOpenTab
        })
        Object.defineProperty(_hwork, 'hworkInfo', {
            enumerable: true,
            get: () => this.hworkInfo
        })
        Object.defineProperty(_hwork, 'userInfo', {
            enumerable: true,
            get: () => this.userInfo
        })
        Object.defineProperty(_hwork, 'eventEmitter', {
            enumerable: true,
            get: () => this.eventEmitter
        })
        Object.defineProperty(_hwork, 'refresh', {
            enumerable: true,
            get: () => this.refresh
        })

        return {
            _hwork
        };
    },
    created() {
        sessionStorage.setItem('imAppRefreshToken', this.hworkInfo.refreshToken)
        sessionStorage.setItem('imAppToken', this.hworkInfo.token)
    }
}
</script>

# 3. vue.config.js

const { name } = require('./package');

module.exports = {
    publicPath: '/dynamic/',
    devServer: {
        headers: {
            'Access-Control-Allow-Origin': '*'
        }
    },
    productionSourceMap: false, // 禁用生产环境的 source map
    css: {
        extract: false // 🌟 css强制内联
    },
    chainWebpack: config => {
        config.module
            .rule('images')
            .use('url-loader')
            .loader('url-loader')
            .tap(options => Object.assign(options, { limit: 20000 })) // 20kb以下的图片转成base64
    },
    configureWebpack: {
        output: {
            library: `${name}-[name]`,
            libraryTarget: 'umd', // 🌟 把微应用打包成 umd 库格式
            jsonpFunction: `webpackJsonp_${name}`
        }
    }
};

# 4. package.json

{
  "name": "workbench-com-application", // 🌟 name名称以“workbench-com”开头
  .... // 省略与接入不相关的代码
  "scripts": {
    "dev": "vue-cli-service serve",
    "fix": "vue-cli-service lint --fix",
    // 开发环境打包
    "dynamic:dev": "vue-cli-service build --mode development --target lib --inline-vue --name dynamic-dev --dest lib ./src/dynamic.js",
    // 测试环境打包
    "dynamic:test": "vue-cli-service build --mode testing --target lib --inline-vue --name dynamic-test --dest lib ./src/dynamic.js",
    // 生产环境打包
    "dynamic:prod": "vue-cli-service build --mode production --target lib --inline-vue --name dynamic-prod --dest lib ./src/dynamic.js"
  }
  ... // 省略与接入不相关的代码
}