2023年2月

在我们公司门户网站里面,如果有需要,我们可以提供一个页面给用户反馈信息,以便获得宝贵的用户信息反馈或者一些产品咨询的记录,一般这个结合邮件发送到负责人的邮箱即可。本篇随笔结合后端发送邮件的操作,把相关信息发送到门户网站的负责人邮箱里面。

1、客户反馈界面

我们这个主题主要介绍BootstrapVue的使用,虽然我们有时候使用了常规的HTML元素,不过也是使用了Bootstrap的样式来处理界面的。

本篇随笔继续介绍BootstrapVue中的表单组件 b-form 及表单元素的使用。在线反馈界面如下所示。

在这里主要通过一些常规的数据录入获得客户的反馈即可。

Vue模板的HTML界面代码如下所示

<b-form@submit="onSubmit"class="mt-4 mb-5">
  <b-form-groupid="input-group-1"label-for="input-1"class="mb-4">
    <b-form-inputid="input-1"v-model="form.name"required placeholder="请输入您的姓名"></b-form-input>
  </b-form-group>

  <b-form-groupid="input-group-2"label-for="input-2"class="mb-4">
    <b-form-inputid="input-2"v-model="form.phone"required placeholder="请输入您的手机/邮箱"></b-form-input>
  </b-form-group>

  <b-form-groupid="input-group-3"label-for="input-3"class="mb-4">
    <b-form-selectid="input-3"v-model="form.suggest"placeholder="反馈类型":options="suggest"required></b-form-select>
  </b-form-group>

  <b-form-groupid="input-group-4"label-for="input-3"class="mb-5">
    <b-form-textareaid="input-4"v-model="form.message"required rows="5"placeholder="请输入您想说的话"></b-form-textarea>
  </b-form-group>

  <b-buttontype="submit"block variant="info">提 交</b-button>
</b-form>

而其中data里面定义了表单对应的数据,如下所示

form: {
name:
'',
phone:
'',
suggest:
null,
message:
'',
},
suggest: [
{ value:
null, text: '反馈类型'},
{ value:
'需求上报', text: '需求上报'},
{ value:
'商务洽谈', text: '商务洽谈'},
{ value:
'意见建议', text: '意见建议'},
{ value:
'其它', text: '其它'}
],

在数据提交的时候,我们根据正则表达式来判断一下对应的数据,当然我们也可以使用BootstrapVue的表单验证控件来处理,具体可以参考BootstrapVue的表单验证组件。

async onSubmit (evt) {
evt.preventDefault()
const phoneReg
= /^1[3456789]\d{9}$/const emailReg= /^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/ if (!phoneReg.test(this.form.phone) && !emailReg.test(this.form.phone)) {this.$bvToast.toast(`提交失败,请输入正确的手机号或邮箱号`, {
title:
'提交结果',
variant:
'danger',
autoHideDelay:
5000})return}

而其中  this.$bvToast.toast 使用了BootstrapVue 冒泡提示组件。

通过
this.$bvToast.toast()
Vue组件实例注入从应用程序中的任何位置生成动态toast,而无需在应用程序中放置
<b-toast>
组件。

使用
this.$bvToast.toast()
方法生成toasts。该方法接受两个参数:

  • message
    : toast主体的内容(字符串或
    VNodes
    数组)。必填的。将不会显示带有空消息的Toasts。有关将
    VNodes
    数组作为消息传递的示例,请参阅
    Advanced usage
    部分。
  • options
    : 用于提供标题和/或附加配置选项的可选选项对象。
    title
    选项可以是字符串或
    VNodes
    数组

options参数接受
<b-toast>
组件以camelCase name格式而不是kebab case格式接受的大多数道具(
static

visible
的除外)。

接着我们收集客户的信息,组合后调用后端发送邮件接口,发送邮件即可,最后提示用户发送是否成功。

      var type = '反馈'
      var html =`<p><strong>发信人姓名:</strong></p>
          <p>${this.form.name}</p>
          <p><strong>发信人联系方式:</strong></p>
          <p>${this.form.phone}</p>
          <p><strong>发信人反馈类型:</strong></p>
          <p>${this.form.suggest}</p>
          <p><strong>发信人留言:</strong></p>
          <p>${this.form.message}</p>
`
const flag
=SendMail(html, type)if(flag) {this.form ={
name:
'',
phone:
'',
message:
''}this.$bvToast.toast(`提交成功,我们将尽快与您取得联系!`, {
title:
'提交结果',
variant:
'success',
autoHideDelay:
5000})
}
else{this.$bvToast.toast(`提交失败,请稍后重试!`, {
title:
'提交结果',
variant:
'danger',
autoHideDelay:
5000})
}

2、邮件的发送处理

关于邮件的发送,之前有参考过 nodemailer,这个使用node环境发送邮件的组件,不过我们现在的BootstrapVue项目的前端不符合这个条件,除非引入 nuxt ,让页面先在后端运行再推送给前端展示。

关于nodemailer的学习,可以参考下:
https://github.com/nodemailer/nodemailer
,或者官网:
https://nodemailer.com/about/

它的使用代码如下所示:


"use strict";
const nodemailer
= require("nodemailer");//async..await is not allowed in global scope, must use a wrapper
async functionmain() {//Generate test SMTP service account from ethereal.email
//Only needed if you don't have a real mail account for testing
let testAccount =await nodemailer.createTestAccount();//create reusable transporter object using the default SMTP transport
let transporter =nodemailer.createTransport({
host:
"smtp.ethereal.email",
port:
587,
secure:
false, //true for 465, false for other ports
auth: {
user: testAccount.user,
//generated ethereal user
pass: testAccount.pass, //generated ethereal password
},
});
//send mail with defined transport object
let info =await transporter.sendMail({
from:
'"Fred Foo

在BootstrapVue组件库里面,提供了很多对Bootstrap同等类似的组件封装,其中图片轮播可以采用b-carousel-slide组件实现,而有一些小的图片,如客户/合作伙伴Logo或者友情连接什么的,则可以使用一个滑动图片展示的vue-awesome-swiper组件。本篇随笔综合介绍使用b-carousel-slide组件实现图片轮播以及vue-awesome-swiper实现图片滑动展示。

1、使用b-carousel-slide组件实现图片轮播

轮播不会自动标准化幻灯片尺寸。 因此,您可能需要使用其他实用程序或自定义样式来适当调整内容的大小。 在每张幻灯片中使用图像时,请确保它们均具有相同的尺寸(或长宽比)。

轮播默认间隔为
5000
毫秒(5秒)。您可以通过将
interval
属性设置为所需的毫秒数来更改幻灯片之间的间隔。 支持的最小滑动间隔为1000毫秒(1秒)。

设置属性
controls
以启用前一个和后一个控件按钮。设置属性
indicators
以显示滑动指示器按钮。指示器和控件都可以同时设置或独立设置。

属性

  • caption
    : 用作幻灯片上主要标题的文本(放置在具有
    carousel-caption
    类的内部元素内)
  • text
    : 标题下的文本(放置在具有
    carousel-caption
    类的内部元素内)
  • img-src
    : 要放在幻灯片背景中的图像的URL
  • caption-html

    caption
    属性的 Alternate 属性,它支持HTML字符串
  • html

    text
    属性的 Alternate 属性,它支持HTML字符串

命名插槽

  • default
    将放置在具有
    carousel-caption
    类的内部元素内部的内容。 出现在
    caption

    text
    属性的任何内容之后。
  • img
    放置在幻灯片背景中的内容。 尽管有插槽的名称,但您几乎可以将任何内容放置在该插槽中,而不必使用
    default
    (默认)的插槽
    caption

    text
    属性。

下面是b-carousel-slide轮播组件的一个使用代码:

<div>
  <b-carouselid="carousel-fade"style="text-shadow: 0px 0px 2px #000"fade
indicators
img-width
="1024"img-height="480" > <b-carousel-slidecaption="First slide"img-src="https://picsum.photos/1024/480/?image=10" ></b-carousel-slide> <b-carousel-slidecaption="Second Slide"img-src="https://picsum.photos/1024/480/?image=12" ></b-carousel-slide> <b-carousel-slidecaption="Third Slide"img-src="https://picsum.photos/1024/480/?image=22" ></b-carousel-slide> </b-carousel> </div>

或者用命名插槽的方式,演示代码如下所示

 <b-carouselv-model="slide":interval="5000"controls fade indicators background="#ababab"style="text-shadow: 1px 1px 2px #333; background: #ccc"
@sliding-start
="onSlideStart"@sliding-end="onSlideEnd"> <b-carousel-slide> <templatev-slot:img> <b-imgfluid
:src
="size=='big' ? require('@/../static/site2/img/banner/banner01_big.jpg') : require('@/../static/site2/img/banner/banner01_small.jpg')"alt="banner" /> </template> </b-carousel-slide> </b-carousel> </template>

由于我们使用Vue,一般来说,轮播的图片是动态增加的,而不是固定的连接,因此用变量代替,遍历展示即可,模板代码如下代码。

  <b-carouselv-model="slide":interval="5000"controls fade indicators background="#ababab"
style
="text-shadow: 1px 1px 2px #333; background: #ccc"@sliding-start="onSlideStart"@sliding-end="onSlideEnd"> <b-carousel-slidev-for="(item, index) of carousel_list":key="index"> <templatev-slot:img> <divstyle="position: relative"> <b-imgfluid :src="size=='big' ? item.bigImage : item.smallImage"alt="banner" /> <divclass="mask":class="{mask2: (index+1)%2==0}"> <divclass="content":class="{content2: (index+1)%2==0}"> <h3class="title mb-3 wow fadeInLeft"data-wow-delay="0.2s">{{ item.title }}</h3> <divclass="desc wow mb-3 fadeInRight"data-wow-delay="0.2s"v-html="item.desc" /> <divclass="line wow fadeInUp"data-wow-delay="0.6s"v-html="item.subdesc" /> </div> </div> </div> </template> </b-carousel-slide> </b-carousel>

其中wow fadeInLeft 这些用了WOW的动态效果,而 {mask2: (index+1)%2==0} 的判断,用于左右显示文本的不同。

其中Vue部分的JS代码如下所示,定义了变量和所需的数据列表。

而轮播所需的carousel_list的集合数据,我们动态从接口获取即可。

而轮播列表的内容,我们可以模拟数据,或者从后端获取真实的数据,数据结构大概如下所示。

这样我们运行的时候 ,效果如下所示。

不同的轮播,我们指定不同的背景图片,以及文字,就很好的达到展示产品信息的目的。

一般轮播图片,我们是放在布局Layout页面里面的,因此需要在Layout页面定义的时候,引入对应的自定义封装的轮播组件即可。

<template>
  <div>
    <my-header/>
    <carouselclass="d-none d-md-block d-lg-block d-xl-block"style="height: 0; padding-bottom: 31.2%"size="big" />
    <carouselclass="d-block d-md-none d-lg-none d-xl-none"style="height: 0; padding-bottom: 120%"size="small" />
    <router-view:key="key" />
    <my-footer/>

    <divv-show="show_backtop"class="backtop"@click="backTop"><iclass="el-icon-arrow-up" /></div>
  </div>
</template>

<script>import MyHeader from'./components/Header'import MyFooter from'./components/Footer'import Carousel from'./components/Carousel'exportdefault{
components: {
MyHeader,
MyFooter,
Carousel
},

其中这里使用了两个轮播元素定义,是基于响应式框架布局考虑,d-none d-md-block d-lg-block d-xl-block 是在md/lg/xl的时候显示的,d-block d-md-none d-lg-none d-xl-none 则是在sm的情况下显示的,也就是md/lg/xl的时候不显示的意思。

如需详细了解,可以参考
https://code.z01.com/v4/utilities/display.html
Display显示属性的说明。

2、使用vue-awesome-swiper实现图片滑动展示

前面开头的地方说了,有一些小的图片,如客户/合作伙伴Logo或者友情连接什么的,我们可能希望以图片的方式展示一个图片墙即可,如果内容比较多,那么占用版面比较大,而采用 vue-awesome-swiper 则可以避免这个问题,它是在展示图片的基础上,定时动态移动图片浏览,可以在更小的空间上放置更多的图片。

vue-awesome-swiper 的使用有很多,不过不太建议用比较新的版本,有时候可能出现一些使用异常,比较难以处理,因此我采用比较稳定的低版本来展示图片。

我们来看看具体的展示效果,其中单击图片,可以打开合作伙伴的网站地址。

这个面板在可视范围内,展示固定的几张图片,然后动态滑动,可以放置很多,又能拖动查看,效果还是非常不错的。

这个合作伙伴的数据结构如下所示。

那么vue-awesome-swiper它的使用是如何的呢。

先通过npm进行安装组件指定版本

npm install vue-awesome-swiper@3 --save-dev

在Vue的项目中的main.js中全局增加对控件的加载。

import Vue from 'vue'import'swiper/dist/css/swiper.css'import  VueAwesomeSwiper from  'vue-awesome-swiper/dist/ssr'Vue.use(VueAwesomeSwiper)

定义一个滑动图片的组件,用于接收相关数据显示即可。

<!--可以拖动的Slide组件,需要安装vue-awesome-swiper组件-->
<template>
  <divclass="wrap">
    <divclass="mt-4 d-none d-lg-block d-xl-block">
      <divv-swiper:mySwiper1="swiperOptions">
        <divclass="swiper-wrapper">
          <divv-for="(item, index) of list":key="index"class="swiper-slide">
            <divclass="img-wrap mx-3 p-4">
              <b-img:src="item.icon"fluid :alt="item.title"@click="open(item.url)" />
            </div>
          </div>
        </div>
      </div>
    </div>

    <divclass="mt-4 d-block d-lg-none d-xl-none">
      <divv-swiper:mySwiper2="swiperOptions2">
        <divclass="swiper-wrapper">
          <divv-for="(item, index) of list":key="index"class="swiper-slide">
            <divclass="img-wrap mx-3 p-4">
              <b-img:src="item.icon"fluid :alt="item.title"@click="open(item.url)" />
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

这里用了两个声明,也是基于布局不同的显示的,和前面轮播的处理类似。

而 v-swiper 这是加载vue-awesome-swiper后注入的装饰器v-swiper.

其中这个组件的配置信息如下定义。

除了这两种,有时候我们的产品可能需要展示更多的图片,就是图片画廊的意思,那么我们就可以综合展示图片了,如下效果所示。

以上就是常规图片的几种处理方式,有时候根据不同的需求,可以定义不同的界面效果来进行展示。

系列文章如下所示:

循序渐进BootstrapVue,开发公司门户网站(1)---基于Bootstrap网站模板构建组件界面

循序渐进BootstrapVue,开发公司门户网站(2)--- 使用wow.js动画组件以及自定义的CSS样式处理动态效果

循序渐进BootstrapVue,开发公司门户网站(3)--- 结合邮件发送,收集用户反馈信息

循序渐进BootstrapVue,开发公司门户网站(4)--- 使用b-carousel-slide组件实现图片轮播以及vue-awesome-swiper实现图片滑动展示

循序渐进BootstrapVue,开发公司门户网站(5)--- 使用实际数据接口代替本地Mock数据

循序渐进BootstrapVue,开发公司门户网站(6)--- 门户网站后端内容管理

在我们开发一些门户网站功能的时候,有时候我们需要快速的创建数据模型来进行数据展示,因为数据结构可能处于不断的修正变化之中,因此服务端的接口我们可以暂时不开发,当我们基本完成数据结构和界面展示的时候,就可以正式开发并接入后端接口了,本篇随笔介绍在使用BootstrapVue开发公司门户网站的时候,使用实际数据接口代替本地Mock数据的解决思路。

1、使用Mock数据接口

在我之前一些《
Vue&Element
》的随笔介绍过Vue 中API模块、Mock模块、Store模块、Proxy代理之间的关系如下

这个对于我们目前的 BootstrapVue 项目来说,也是通用的关系,我们在早期数据变化的时候,为了快速开发界面效果,可以通过Mock模拟一些数据接口,并通过API模块和代理接口的方式构建访问接口,然后在完成的时候,简单的替换就可以切换到实际的后端接口中了。

引入了前后端分离的Vue 项目作为前端技术路线,那么前后端的边界则非常清晰,前端可以在通过网络获取对应的JSON就可以构建前端的应用了。

我们以BootstrapVue导航栏组件的使用为例介绍,阐明使用Mock数据的处理方式和实际调用后端Api的两种方式

导航栏(Navbar)

组件
<b-navbar>
是一个包装器, 它将品牌、导航和其他元素定位到一个简洁的标题中。它很容易扩展,而且由于
<b-collapse>
组件,它可以很容易地集成响应行为。

颜色配置

<b-navbar>
支持标准引导v4可用的背景色变量。 将
variant
属性设置为以下值之一以更改背景颜色:
primary
,
success
,
info
,
warning
,
danger
,
dark
,或
light

控制文本颜色,方法是将
type
属性设置为
light
以用于浅色背景颜色变体, 或将
dark
设置为深色背景颜色变体。

布局

通过设置两个属性之一来控制导航栏的位置:

属性 类型 默认值 描述
fixed String null 设置为
top
表示固定到视口的顶部,或设置为
bottom
表示固定到视口的
底部
sticky Boolean false 设置为
true
可使导航栏在滚动时粘在视口(或具有
position: relative
的父容器)的顶部。

注意事项:

  • 固定位置使用CSS
    position: fixed
    。您可能需要调整文档的顶部/底部填充或边距。
  • CSS位置:不是每个浏览器都完全支持sticky(用于
    sticky
    )。 对于不支持
    position: sticky
    的浏览器, 它将以本机方式回退到
    position: relative

支持的内容

导航条带有对少数子组件的内置支持。根据需要从以下选项中选择:

  • <b-navbar-brand>
    表示您的公司、产品或项目名称。
  • <b-navbar-toggle>
    用于
    <b-collapse is-nav>
    组件.
  • <b-collapse is-nav>
    用于按父断点分组和隐藏导航栏内容。
  • <b-navbar-nav>
    用于全高和轻量级导航(包括支持下拉菜单)。 支持
    <b-navbar-nav>
    中的以下子组件::
    • <b-nav-item>
      对于链接(和路由器链接)操作项
    • <b-nav-item-dropdown>
      导航下拉菜单
    • <b-nav-text>
      用于添加垂直居中的文本字符串。
    • <b-nav-form>
      用于任何窗体控件和操作。

使用代码如实例代码所示

<div>
  <!--Image and text-->
  <b-navbarvariant="faded"type="light">
    <b-navbar-brandhref="#">
      <imgsrc="https://placekitten.com/g/30/30"class="d-inline-block align-top"alt="Kitten">BootstrapVue</b-navbar-brand>
  </b-navbar>
</div>

详细的细节我们不一一介绍,需要了解这个组件及其他相关组件的使用,可以参考链接:
https://code.z01.com/bootstrap-vue/docs/components/navbar.html

例如我们在项目中准备导航栏的数据如下所示。

//导航菜单
export const navbarlist =[{
name:
'网站首页',
link:
'/',
children: []
},
{
name:
'产品解决方案',
link:
'/product',
children: [ ]
},
{
name:
'行业解决方案',
link:
'/business',
children: []
},
{
name:
'技术与支持',
link:
'/technology',
children: [{
name:
'业务培训范围',
link:
'/technology',
children: []
},
{
name:
'服务体系',
link:
'/technology',
children: []
},
{
name:
'在线反馈',
link:
'/technology',
children: []
}
]
},
{
name:
'公司新闻',
link:
'/news',
children: []
},
{
name:
'关于我们',
link:
'/about',
children: [ ]
}
]

并公布一个Mock的地址拦截

然后在Api模块类中定义一个指向Mock数据集合的Api接口行,如下所示。

listNavibar(params) {returnrequest({
url:
'/api/portal/listnavibar',
method:
'get',
params
})
}

当然api的转义处理,这里需要使用的是Mock的代理接口,才能访问到Mock的数据类。

因此在vue.config.js里面定义好api的代理跳转,如下所示。

数据准备好了,就再次回到组件
<b-navbar>中的界面使用上来,我们定义展示的Layout的头部导航栏,如下代码所示

    <b-navbartoggleable="lg"type="dark"variant="dark"class="active2":class="{active: showNavbarBg}">
      <divclass="container">
        <!--logo-->
        <b-navbar-brandto="/">
          <img:src="site.icon"class="mr-2"alt="logo"style="height:40px;width:auto">{{ site.title }}</b-navbar-brand>

        <!--切换按钮-->
        <b-navbar-toggletarget="nav-collapse":class="{active: showCollaps}" />

        <!--实际导航连接-->
        <b-collapseid="nav-collapse"v-model="showCollaps"is-nav>
          <b-navbar-navclass="ml-auto">
            <divv-for="(item, index) of navBarList":Key="index">
              <b-nav-itemv-if="item.children.length <= 0":to="item.link":active="$route.path === item.link">{{ item.name }}</b-nav-item>
              <templatev-else>
                <b-nav-item-dropdownright @show="handleShowDrop">
                  <templatev-slot:button-content>
                    <span:class="{active: $route.path.includes(item.link)}"@click="handleNavbarClick(item, '', $event)">{{ item.name }}</span>
                  </template>
                  <!--子菜单-->
                  <b-dropdown-itemv-for="(ite, ind) of item.children":key="ind"@click="handleNavbarClick(ite, ind, $event)">{{ ite.name }}</b-dropdown-item>
                </b-nav-item-dropdown>
              </template>
            </div>
          </b-navbar-nav>
        </b-collapse>
      </div>
    </b-navbar>

如果我们需要在JS模块中访问Mock数据,那么导入对应的MockApi类处理即可,如下所示。

import portal from '@/api/test/portal'

然后在函数中调用获取数据放到data变量navBarList 中即可。

      var param ={}//菜单信息
      portal.listNavibar(param).then(data =>{//console.log(data)
        this.navBarList =data.result
})

导航就可以根据Mock数据信息,正常显示出来导航连接效果了。

2、开发门户网站后端接口

对于门户网站,根据需要我们设计了后端存储的数据表,如下所示

按照后端ABP框架或者Web API所需的框架类,使用代码生成工具生成代码后,集成在项目中,常规的增删改查、分页管理等基础接口就可以直接使用了。

后端API接口通过Swagger查看对应公开接口,如下所示。

由于门户网站不需要用户登录,或者授权信息,那么可以公开部分接口作为匿名访问,如访问菜单集合的信息作为匿名接口访问,如下所示。

再次定义一个API类,这个是直接访问后端接口获取数据的,如下所示

这样我们如果需要使用实际接口获取数据的话,导入对应的API类即可,如下所示。

import portal2 from '@/api/system/portal'

然后调用API类获取数据如下所示,整个过程和Mock调用方法类似,不同的是一些小细节。

  portal2.listNavibar(param).then(data =>{
console.log(data)
this.navBarList =data.result
})

这样直接就切换到后端数据接口了,这样对于我们前期开发的Mock方式,修改只需要改动一下导入的Api类地址即可,平缓过度到实际接口,非常方便。

其他动态数据展示效果如下所示。

系列文章如下所示:

循序渐进BootstrapVue,开发公司门户网站(1)---基于Bootstrap网站模板构建组件界面

循序渐进BootstrapVue,开发公司门户网站(2)--- 使用wow.js动画组件以及自定义的CSS样式处理动态效果

循序渐进BootstrapVue,开发公司门户网站(3)--- 结合邮件发送,收集用户反馈信息

循序渐进BootstrapVue,开发公司门户网站(4)--- 使用b-carousel-slide组件实现图片轮播以及vue-awesome-swiper实现图片滑动展示

循序渐进BootstrapVue,开发公司门户网站(5)--- 使用实际数据接口代替本地Mock数据

循序渐进BootstrapVue,开发公司门户网站(6)--- 门户网站后端内容管理

我们在做门户网站的时候,如果网站的内容可以动态从后端进行管理,那么调整网站内容就非常方便,有时候如一些公司新闻、产品信息、轮播广告信息等都需要动态调整的,有一个方便的后端内容管理是非常方便的。本篇随笔介绍门户网站的后端管理界面,介绍网站后端的内容管理实现。

1、网站内容模块的设计

从前面的系列文章,我们大概可以了解到门户网站的一些常用模块,如网站菜单、网站轮播广告、网站内容介绍(如公司信息、产品信息、合作伙伴、公司客户等)、网站图片展览、公司新闻等等模块,以及网站的一些常规设置信息,如Logo、网站名称、网站底部信息(包括公司地址、备案信息等等)。

这些模块有些可以综合一起管理,因为内容大多数格式差不多,如网站内容介绍(如公司信息、产品信息、合作伙伴、公司客户等),有些这需要独立设计管理,如网站菜单、网站轮播广告
等,
另外一些内容管理如新闻和模块内容类似,我们为了方便也将它独立进行维护即可。

综合以上一些内容,我们可以设计一些表来承载这些信息,然后在后端提供对应对口,供前端使用即可。

对于门户网站,根据需要我们设计了后端存储的数据表,如下所示

我们来看看几个模块中的一些最终效果,然后再开始设计编码吧。

1)网站菜单和广告轮播

2)网站模块内容

其中包括产品、框架等产品的介绍,维护内容差不多,只是展示方式有所差异。

框架产品的介绍,和软件产品的类似,不过这里采用了大图展示的方式,栅格的大小也有所变化。

以上这些网站门户的内容,由于采用了BootstrapVue,因此也是自适应的窗口布局的,我们可以切换到手机屏幕模式,那么可以看到正常、合理的展示,而不会仅仅是给电脑桌面端的展示。

我们可以在实现代码的时候,合理设置栅格的大小,从而让内容按照自己的需要展示。

3)图片展示

如对于图片的展示,我们可以在小屏幕中展示两列,也可以展示一列,具体根据自己的需要处理即可。

而图片展示在电脑屏幕端,则设置为正常的几屏展示。

而有时候一些模块需要展示一些图片内容,如公司客户、合作伙伴等信息,主要是以企业LOGO和URL为展示的内容,那么我们可以结合内容管理,以及图片管理,综合展示这些内容即可,如下所示。

其中合作伙伴可以采用 vue-awesome-swiper 来动态滑动展示更多的图片信息。

4)新闻展示

公司一般都有一些新闻展示,用于为外界提供信息的参考,同时也是宣传公司产品信息或者发布动态信息的地方。

新闻内容一般比较多,可以结合分页的处理进行展示更多的新闻消息

打开新闻链接其实就是展示新闻详细信息即可,用一个页面来展示完整的信息和导航就可以了。

新闻一般为了吸引人,往往会增加很多图片,我们在后台的内容管理中适当增加图片即可达到图文并茂的效果。

2、网站的后端管理界面

门户网站前端负责合理展示内容,后端就需要整合数据模型,尽可能的把内容管理得更加方便一些,我们把几个模块的内容一起综合管理,根据不同的类别进行区分即可,因为大多数情况内容模型的格式是相似的。

我们创建了几个管理菜单入口,用于维护管理门户网站的内容信息,如下导航所示。

网站信息,主要就是维护LOGO、网站名称、网站底部信息的一些内容的。

模块的内容管理,是其中最为重要的部分,我们需要综合各个模块的模型,把它们统一按照分类管理起来,如下界面所示。

网站菜单管理,综合管理门户网站中的菜单连接信息。

图片管理,综合管理网站所需要管理的图片内容。

网站新闻,是维护新闻内容列表的。

内容编辑是采用富文本的处理方式,可以添加更加丰富的内容,包括格式、图片等等。

以上就是门户网站的前端展示和后端管理集合的大多数效果,前端负责更好的展示数据,后端为数据展示提供动态数据,以便更好的管理维护。

并且通过结合BootstrapVue,我们的网站具有很强大的多种设备兼容性,在各种展示的设备上,都是展示的非常好的效果。

系列文章如下所示:

循序渐进BootstrapVue,开发公司门户网站(1)---基于Bootstrap网站模板构建组件界面

循序渐进BootstrapVue,开发公司门户网站(2)--- 使用wow.js动画组件以及自定义的CSS样式处理动态效果

循序渐进BootstrapVue,开发公司门户网站(3)--- 结合邮件发送,收集用户反馈信息

循序渐进BootstrapVue,开发公司门户网站(4)--- 使用b-carousel-slide组件实现图片轮播以及vue-awesome-swiper实现图片滑动展示

循序渐进BootstrapVue,开发公司门户网站(5)--- 使用实际数据接口代替本地Mock数据

循序渐进BootstrapVue,开发公司门户网站(6)--- 门户网站后端内容管理

在Winform开发中,有时候为了方便,需要把窗体的一些常规性的数据和操作函数进行封装,通过自定义基类窗体的方式,可以实现这些封装管理,让我们的框架统一化、简单化的处理一些常规性的操作,如这里介绍的用户身份信息的缓存和提取。通过基类的封装,可以大大减少常规性的代码,这个也是基类封装的目的所在。

1、用户登录获得身份信息并缓存

用户登录界面,通过获得用户的账号密码进行登录验证,如下界面所示。

登录过程如下所示,成功后获得用户的身份信息并缓存起来待用,毕竟系统界面,大多数都需要获得用户的信息的。

获得用户的身份信息后,调用SetLoginInfo设置缓存数据,以备后用。

通过上面的处理,用户身份信息,权限信息,角色信息,都可以一次性获得,供各个界面上使用了。

2、基类窗体的用户身份提取

这里的LoginUserInfo是窗体基类的一个属性,这个属性通过两种方式获得,一个是通过用户在调用窗体显示前进行指定,一种是通过基类自动把缓存里面的用户对象赋值。

如下面的代码就是界面基类BaseForm的部分代码。

namespaceWHC.Framework.BaseUI
{
/// <summary> ///常规界面基类/// </summary> public partial classBaseForm : DevExpress.XtraEditors.XtraForm, IFunction
{
public event EventHandler OnDataSaved;//子窗体数据保存的触发 publicBaseForm()
{
InitializeComponent();
//为了保证一些界面控件的权限控制和身份确认,以及简化操作,在界面初始化的时候,从缓存里面内容(如果存在的话)//继承的子模块,也可以通过InitFunction()进行指定用户相关信息 this.LoginUserInfo = Cache.Instance["LoginUserInfo"] as LoginUserInfo;
this.FunctionDict = Cache.Instance["FunctionDict"] as Dictionary<string, string>
;
}

这样界面基类实例化的时候,就会自动获取用户信息了,这个操作类似于Web领域里面的Session操作,只要存储/获取的键值保存一致即可。

用户组件,也可以通过这样类似的方式定义一个基类,以后所有自定义用户组件,就很方便获得用户的身份信息了,如下代码所示。

在窗体界面上,可以放置很多模块,模块通过窗体获得用户身份信息、角色信息等进行初始化的判断

最终在主体界面中整合的是一个个模块,每个模块里面又有不同的窗体界面可供使用,但是都能通过缓存获得用户身份信息,数据处理起来就非常方便了。

对于业务报销信息,我们可以根据用户身份信息,迅速获得对应的记录列表,以及在修改的时候,记录用户的身份信息。

如新增一条主表记录的时候,那么可以弹出一个新的界面进行数据的维护处理,界面如下所示。

或者类似下面的界面处理。