Skip to content

布局与主题



基座的一个重要职能就是统一整个 PC 端管理后台的视觉呈现。

在旧的系统中,主题、布局组件重复和分散在各个子应用中,这导致更新维护起来比较麻烦,常常会出现视觉不统一的情况。

举个例子,在项目交付时,需要针对客户的需求和企业特色定义视觉,旧的系统中,我们需要对每个子应用都进行更新,然后再打包部署。这种工作繁琐且无聊。


🆕 现在由我们的基座来做这件事情,我们甚至可以做到不停机一键切换。



为了实现主题的灵活配置,基座做了以下调整:



统一定义的 CSS 变量

我们根据 惟客 PC 端的视觉规范 定义了一套 CSS 变量集



css-variables



我们规定: 无论什么时候,你都应该优先使用这套CSS 变量集, 而不是:

  • 引用 SCSS/Less 的静态变量
  • 引用 ElementUI 这些组件库暴露出来的变量
  • 硬编码主题色

DANGER

为什么不推荐引用 SCSS/Less 的变量?
因为这些变量是静态的,调整这些变量需要重新编译。

而 CSS 变量集由主题包提供,并挂载在基座中,这些变量支持运行时修改和切换, 子应用不需要变更任何代码。


DANGER

为什么不推荐引用 ElementUI/ElementPlus 的变量?

我们的提供的变量更加中立,不耦合任何框架。维护起来更轻松。



组件库样式包外置

为了实现主题动态切换,子应用、基座都不需要再导入 element-ui、element-plus 等相关组件库的 CSS 样式表。而是外置到主题包中维护

因此,子应用集成到基座时应该把相对应的组件库样式导入移除:

INFO

element-ui


-import 'element-ui/lib/theme-chalk/index.css';

同时 wkb-common-ui 也废弃了:

-import 'wkb-common-ui/style';
-import 'wkb-common-ui/packages/theme-chalk/src/index.less'; // 引入wkb-common-ui中的自定义样式

INFO

element-plus

完整导入,移除:

-import 'element-plus/dist/index.css'

如果是 element-plus,且使用到了按需组件导入的功能,需要关闭样式导入:

// webpack.config.js
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')

module.exports = {
  // ...
  plugins: [
    AutoImport({
-      resolvers: [ElementPlusResolver()],
+      resolvers: [ElementPlusResolver({importStyle: false})],
    }),
    Components({
-      resolvers: [ElementPlusResolver()],
+      resolvers: [ElementPlusResolver({importStyle: false})],
    }),
  ],
}

如果是手动导入,则不需要再安装 unplugin-element-plus 插件了。



WARNING

还有一个重要的事情。我们推荐新的项目使用 vue3 + element-plus, 但是,element-ui、element-plus 的样式并不兼容。 在较长的一段时间内,我们的系统可能会并存 element-ui、element-plus。

为了避免样式冲突,我们规定,element-plus 统一使用 ep 命名空间, 因此你的子应用需要做以下配置:

import { RouterView } from 'vue-router';
+import { ElConfigProvider } from 'element-plus';

export default () => (
+  <ElConfigProvider namespace="ep">
    <RouterView />
+  </ElConfigProvider>
);





统一提供布局组件

惟客管理后台在布局上有规范的定义。现在基座实现了这些定义,并通过 Web Component 的形式暴露到子应用使用


INFO

布局组件的详细 API 说明,见 基座 API


扩展插槽



基座提供了一些组件,供子应用扩展主界面的一些内容:


组件名称描述
wkc-header-slot头部扩展插槽
wkc-header-dropdown-menu头像下拉列表扩展
wkc-sidebar-top-slot侧边栏上方扩展插槽
wkc-sidebar-bottom-slot侧边栏下方扩展插槽

使用示例:

<template>
  <div>
    <wkc-sidebar-bottom-slot>
      <div slot="collapse">折叠显示</div>
      <div slot="expand">展开显示</div>
    </wkc-sidebar-bottom-slot>
  </div>
</template>

WARNING

注意:wkc-* 是 Web Component 组件,slot 的使用方式和 vue 有些差别,必须使用 slot 属性,且不能用于 template

WARNING

让 Vue 识别 Web Component 组件需要一些额外的配置, 详见 子应用集成




几种典型的布局

我们看几种典型的布局,在新的微前端体系之下怎么编写。



1. 内容筛选 + 四级菜单页面

fourth-layout

这是一个典型的表格页面,包含内容筛选区、内容区等。另外这是一个四级页面,因此头部以 Tab 的形式渲染。 基座提供了 <wkc-header><wkc-content> 组件来满足这种需求:

<template>
  <div class="my-page">
    <wkc-header>
      <!-- 扩展操作区域 -->
      <el-button slot="extra"><wkc-icon icon="Add"></wkc-icon> 新建图文</el-button>

      <el-form>
        <!-- 这里是内容筛选表单 -->
      </el-form>
    </wkc-header>

    <wkc-content>
      <fat-table><!-- 表格区域 --></fat-table>
    </wkc-content>
  </div>
</template>


这就行了。 如果是四级页面 <wkc-header> 会自动渲染 Tab 菜单。尽管如此,你依旧可以使用 title 来设置自定义标题。




2. 内容筛选 + 三级菜单页面


这种情况和上述例子一样。<wkc-header/> 会自动处理。




3. 简单内容



简单的内容页面,没有筛选区。底部有一个悬浮操作栏。实现例子:

<template>
  <div class="my-page">
    <wkc-header>
      <!-- 可选,如果要复杂的标题渲染可以使用 title slot。默认情况基座会拿菜单配置的标题 -->
      <span slot="title">小程序设置</span>
      <el-button slot="extra">恢复导航</el-button>
    </wkc-header>
    <wkc-content><!-- 内容区 --></wkc-content>

    <!-- 浮动底部栏 -->
    <wkc-float-footer><el-button>保存</el-button></wkc-float-footer>
  </div>
</template>




4. 全屏页面

fullscreen-layout

全屏的页面,比如应用装修。可以使用 <wkc-fullscreen></wkc-fullscreen> 包裹





5. 表单/预览页面

form-layout

典型的表单、预览页面,实现例子:

<template>
  <wkc-header title="商品入库">
    <wkc-breadcrumb />
    <!-- 表单内容 -->
  </wkc-header>
</template>




6. 错误页面

基座也内置了错误页面,供子应用使用:

<template>
  <!-- 默认 404 -->
  <wkc-error-page-not-found />
</template>

<template>
  <!-- 默认 403 -->
  <wkc-error-page-forbidden />
</template>

<template>
  <!-- 默认 403 -->
  <wkc-error-page :image="可选,支持自定义图片" description="发现外星人">详细描述坐标</wkc-error-page>
</template>




7. 自定义

custom-layout


自定义布局? 完全可以,基座并没有限制子应用应该渲染什么内容。





主题包

我们定义了一套主题包机制,配合微前端运行容器实现主题动态切换。


通过主题包可以定制以下内容:

  • 主题变量
  • 组件库样式、页面样式
  • 图片(比如 Logo)、文案
  • 语言包
  • 扩展 Javascript 代码
  • 其他配置参数

WARNING

注意: 无法通过主题包覆盖某些 Vue 页面,我们认为这些需求属于定制化需求。主题包仅限于样式、文案等层面的干预



如何定制文案、图片等静态资源?

在基座中,我们使用 @wakeadmin/assets 库来实现。 比如基座中的 Logo 是这样定义的:









 






















// ....
import DEFAULT_LOGO from './logo-default.png';

export const Header = defineComponent({
  name: 'BayHeader',
  async setup() {
    // ...

    const defaultLogo = useAsset('IMG_BAY_LOGO', DEFAULT_LOGO);

    return () => {
      // ....

      return (
        <header class="bay-header">
          <div class="bay-header__before">
            <div class="bay-header__logo">
              <img
                class="bay-header__logo-img"
                src={bay.sessionInfo?.appInfo.appImage ?? defaultLogo.value}
                alt="logo"
              />
              <span class="bay-header__logo-name">{name}</span>
            </div>
          </div>
        </header>
      );
    };
  },
});


assets 有点像依赖注入。 可以用于定义任何文本类型的 主题扩展点, 比如图片、文案、路由。以下是基座目前定义的扩展点,后面随着需求的迭代,会有更多扩展点暴露出来:

  • IMG_BAY_FAVICON: favicon
  • IMG_BAY_LOGO: logo
  • IMG_BAY_AVATAR: 头像
  • IMG_BAY_ERROR: 默认错误图片
  • IMG_BAY_APP_LOADING: 应用加载中图片
  • IMG_BAY_ERROR_404: 默认 404 错误图片
  • IMG_BAY_ERROR_403: 默认 403 错误图片
  • URL_LOGIN: 登录页面路由

TIP

命名规范


<TYPE>_<MODULE>_<NAME>

  • TYPE: 类型,如 IMG、ICO、TXT、URL 等等。
    
  • MODULE: 模块名称,如 BAY
    
  • NAME: 资源命名
    


那怎么配置这些 assets 呢? 这个依赖于我们的微前端运行容器(这个会在 部署 中介绍)。可以通过运行容器的配置文件来进行配置:



配置示例:

# config.yml
assets:
  IMG_BAY_LOGO: '<BASE_URL>/__theme__/logo.png'
  TXT_BAY_FOOTER: '版权归惟客所有'

我们也推荐在子应用中也应用这套方案。




语言包

如果对应的文案启用了多语言,那么可以在主题包中定义语言包来进行覆盖。 详见 主题包定制

基座预定义的语言包可以查看这里




关于自定义主题包的话题,移步到 主题包定制

客户经营,找惟客