Vue开发实战十八:官网搭建全过程

本文详述了使用Vue进行官网搭建的全过程,包括轮播图、首页、案例管理、服务流程等模块的实现。同时,介绍了后台管理系统的页面、接口设计以及权限控制。在部署阶段,讲解了Linux服务器上文件上传、配置启动和Nginx的设置,确保前端与后台的顺畅运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


本来打算写个七八篇做一个官网搭建的系列,之前写过一篇十七新闻资讯的实现,后来的模块和之前的基本类似就不在重复,这篇文章从前后端到服务器,详细介绍下官网搭建的全过程。

1.最终效果图

官网数据及权限全开展示

1.1轮播图

image

1.2首页

image

1.3案例管理模块

image

image

1.4服务流程

image

1.5新闻资讯

image

image

1.6合作伙伴

image

1.7关于我们

image

1.8联系我们

image

1.9后台管理管理员

image

2.0后台体验用户

image

2.1体验用户只能查看没有新增、修改、删除权限

image

2.2官网前端数据只开首页及案例如下

image

点击底部的后台管理进入后台管理系统登录界面,可在关于模块动态设置是否展示

image

隐藏后如下
image

2.官网前端页面的实现

   <BinnerItem :text="binnerText"></BinnerItem>

    <div v-for="(item,index) in menuArr"
         :key="index">
      <title-item :title="item.title"></title-item>
      <div v-if="item.path=='/' ">
        <SiteIndexItem></SiteIndexItem>
      </div>

      <div v-else-if="item.path=='/example' ">
        <SiteExampleItem></SiteExampleItem>
        <div class="moer-btn-box">
          <router-link to="/example"
                       class="moer-btn">更多案例展示</router-link>
        </div>
      </div>

      <div v-else-if="item.path=='/service' ">
        <SiteServiceItem></SiteServiceItem>
      </div>

      <div v-else-if="item.path=='/news' ">
        <SiteNewsItem></SiteNewsItem>
        <div class="moer-btn-box">
          <router-link to="/news"
                       class="moer-btn">更多资讯</router-link>
        </div>
      </div>

      <div v-else-if="item.path=='/partner' ">
        <SitePartnerItem></SitePartnerItem>
      </div>

      <div v-else-if="item.path=='/about' ">
        <SiteCompanyItem></SiteCompanyItem>
        <AboutItem></AboutItem>
      </div>

      <div v-else-if="item.path=='/contact' ">
        <SiteContactItem></SiteContactItem>
      </div>

      <div v-else>

      </div>

    </div>

菜单是否展示及数据如下

image

每个模块都是个组件方便在点击右上角顶部的按钮时切换到对应的组件中

官网前端运行命令yarn run serve
官网前端打包命令yarn run build
打包后生成dist文件夹等会上传到linux服务器上

3.后端管理系统页面

已案例模块为例

<template>
  <div class="app-container">
    <el-form :model="queryParams"
             ref="queryForm"
             :inline="true"
             v-show="showSearch"
             label-width="68px">
      <el-form-item label="标题"
                    prop="title">
        <el-input v-model="queryParams.title"
                  placeholder="请输入标题"
                  clearable
                  size="small"
                  @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary"
                   icon="el-icon-search"
                   size="mini"
                   @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh"
                   size="mini"
                   @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10"
            class="mb8">
      <el-col :span="1.5">
        <el-button type="primary"
                   plain
                   icon="el-icon-plus"
                   size="mini"
                   @click="handleAdd"
                  >新增</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="success"
                   plain
                   icon="el-icon-edit"
                   size="mini"
                   :disabled="single"
                   @click="handleUpdate"
                   v-hasPermi="['site:example:edit']">修改</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="danger"
                   plain
                   icon="el-icon-delete"
                   size="mini"
                   :disabled="multiple"
                   @click="handleDelete"
                   v-hasPermi="['site:example:remove']">删除</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="warning"
                   plain
                   icon="el-icon-download"
                   size="mini"
                   @click="handleExport"
                   v-hasPermi="['site:example:export']">导出</el-button>
      </el-col>
      <right-toolbar :showSearch.sync="showSearch"
                     @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table v-loading="loading"
              :data="exampleList"
              @selection-change="handleSelectionChange">
      <el-table-column type="selection"
                       width="55"
                       align="center" />
      <el-table-column label="标题"
                       align="center"
                       prop="title" />
      <el-table-column label="分类"
                       align="center"
                       prop="type" />
      <el-table-column label="内容"
                       align="center"
                       prop="content" show-overflow-tooltip  />
      <el-table-column label="跳转地址"
                       align="center"
                       prop="urlAddress" show-overflow-tooltip />
      <el-table-column label="图片"
                       align="center"
                       prop="iconBase64" show-overflow-tooltip  />
      <el-table-column label="创建人"
                       align="center"
                       prop="createUser" />
      <el-table-column label="是否开启0关闭;1开启"
                       align="center"
                       prop="isUse" />
      <el-table-column label="是否删除0正常;1删除"
                       align="center"
                       prop="isDel" />
      <el-table-column label="操作"
                       align="center"
                       class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button size="mini"
                     type="text"
                     icon="el-icon-edit"
                     @click="handleUpdate(scope.row)">修改</el-button>
          <el-button size="mini"
                     type="text"
                     icon="el-icon-delete"
                      v-hasPermi="['site:example:remove']"
                     @click="handleDelete(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <pagination v-show="total>0"
                :total="total"
                :page.sync="queryParams.pageNum"
                :limit.sync="queryParams.pageSize"
                @pagination="getList" />

    <!-- 添加或修改案例对话框 -->
    <el-dialog :title="title"
               :visible.sync="open"
               width="800px"
               append-to-body>
      <el-form ref="form"
               :model="form"
               :rules="rules"
               label-width="150px">
        <el-form-item label="标题"
                      prop="title">
          <el-input v-model="form.title"
                    placeholder="请输入标题" />
        </el-form-item>
        <el-form-item label="内容">
          <!-- <editor v-model="form.content"
                  :min-height="192" /> -->

          <el-input type="textarea"
                    :autosize="{ minRows: 2, maxRows: 8}"
                    placeholder="请输入内容"
                    v-model="form.content">
          </el-input>
        </el-form-item>
        <el-form-item label="跳转地址"
                      prop="urlAddress">
          <el-input v-model="form.urlAddress"
                    placeholder="请输入跳转地址" />
        </el-form-item>
        <el-form-item label="图片">
          <imageUpload v-model="form.iconBase64" />
        </el-form-item>
        <el-form-item label="创建人"
                      prop="createUser">
          <el-input v-model="form.createUser"
                    placeholder="请输入创建人" />
        </el-form-item>

        <el-form-item label="是否开启0关闭;1开启"
                      prop="isUse">
          <el-input v-model="form.isUse"
                    placeholder="请输入是否开启0关闭;1开启" />
        </el-form-item>
        <el-form-item label="是否删除0正常;1删除"
                      prop="isDel">
          <el-input v-model="form.isDel"
                    placeholder="请输入是否删除0正常;1删除" />
        </el-form-item>
      </el-form>
      <div slot="footer"
           class="dialog-footer">
        <el-button type="primary"
                   @click="submitForm">确 定</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import {
  listExample,
  getExample,
  delExample,
  addExample,
  updateExample,
} from '@/api/site/example'

export default {
  name: 'Example',
  data() {
    return {
      // 遮罩层
      loading: true,
      // 选中数组
      ids: [],
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // 案例表格数据
      exampleList: [],
      // 弹出层标题
      title: '',
      // 是否显示弹出层
      open: false,
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        title: null,
      },
      // 表单参数
      form: {},
      // 表单校验
      rules: {},
    }
  },
  created() {
    this.getList()
  },
  methods: {
    /** 查询案例列表 */
    getList() {
      this.loading = true
      listExample(this.queryParams).then((response) => {
        this.exampleList = response.rows
        this.total = response.total
        this.loading = false
      })
    },
    // 取消按钮
    cancel() {
      this.open = false
      this.reset()
    },
    // 表单重置
    reset() {
      this.form = {
        id: null,
        title: null,
        type: null,
        content: null,
        urlAddress: null,
        iconBase64: null,
        isUse: '0',
      }
      this.resetForm('form')
    },
    /** 搜索按钮操作 */
    handleQuery() {
      this.queryParams.pageNum = 1
      this.getList()
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.resetForm('queryForm')
      this.handleQuery()
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      this.ids = selection.map((item) => item.id)
      this.single = selection.length !== 1
      this.multiple = !selection.length
    },
    /** 新增按钮操作 */
    handleAdd() {
      this.reset()
      this.open = true
      this.title = '添加案例'
    },
    /** 修改按钮操作 */
    handleUpdate(row) {
      this.reset()
      const id = row.id || this.ids
      getExample(id).then((response) => {
        this.form = response.data
        this.open = true
        this.title = '修改案例'
      })
    },
    /** 提交按钮 */
    submitForm() {
      this.$refs['form'].validate((valid) => {
        if (valid) {
          if (this.form.id != null) {
            updateExample(this.form).then((response) => {
              this.$modal.msgSuccess('修改成功')
              this.open = false
              this.getList()
            })
          } else {
            addExample(this.form).then((response) => {
              this.$modal.msgSuccess('新增成功')
              this.open = false
              this.getList()
            })
          }
        }
      })
    },
    /** 删除按钮操作 */
    handleDelete(row) {
      const ids = row.id || this.ids
      this.$modal
        .confirm('是否确认删除案例编号为"' + ids + '"的数据项?')
        .then(function () {
          return delExample(ids)
        })
        .then(() => {
          this.getList()
          this.$modal.msgSuccess('删除成功')
        })
        .catch(() => {})
    },
  },
}
</script>

说明:为了方便体验用户体验,因此将新增按钮及修改按钮的权限控制去除,但是后台权限还是有的,因此在页面能看到按钮,实际在调用接口方法的时候仍旧是无权限的。

后台管理页面运行命令 npm run dev
后台管理页面打包命令 npm run build:prod
最终也是生成dist文件,一会我们也会放到服务器上

4.后台接口的实现

以案例模块为例

package xxx.controller;
......

/**
 * 案例Controller
 * 
 * @author yingch
 * @date 2022-03-10
 */
@RestController
@RequestMapping("/site/example")
public class SiteExampleController extends BaseController
{
    @Autowired
    private ISiteExampleService siteExampleService;

    /**
     * 查询案例列表
     */
    @GetMapping("/list")
    public TableDataInfo list(SiteExample siteExample)
    {
        startPage();
        List<SiteExample> list = siteExampleService.selectSiteExampleList(siteExample);
        return getDataTable(list);
    }

    /**
     * 导出案例列表
     */
    @PreAuthorize("@ss.hasPermi('site:example:export')")
    @Log(title = "案例", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SiteExample siteExample)
    {
        List<SiteExample> list = siteExampleService.selectSiteExampleList(siteExample);
        ExcelUtil<SiteExample> util = new ExcelUtil<SiteExample>(SiteExample.class);
        util.exportExcel(response, list, "案例数据");
    }

    /**
     * 获取案例详细信息
     */
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return AjaxResult.success(siteExampleService.selectSiteExampleById(id));
    }

    /**
     * 新增案例
     */
    @PreAuthorize("@ss.hasPermi('site:example:add')")
    @Log(title = "案例", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody SiteExample siteExample)
    {
        return toAjax(siteExampleService.insertSiteExample(siteExample));
    }

    /**
     * 修改案例
     */
    @PreAuthorize("@ss.hasPermi('site:example:edit')")
    @Log(title = "案例", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody SiteExample siteExample)
    {
        return toAjax(siteExampleService.updateSiteExample(siteExample));
    }

    /**
     * 删除案例
     */
    @PreAuthorize("@ss.hasPermi('site:example:remove')")
    @Log(title = "案例", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(siteExampleService.deleteSiteExampleByIds(ids));
    }
}

xml中sql语句如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xxx.mapper.SiteExampleMapper">
    
    <resultMap type="SiteExample" id="SiteExampleResult">
        <result property="id"    column="id"    />
        <result property="title"    column="title"    />
        <result property="type"    column="type"    />
        <result property="content"    column="content"    />
        <result property="urlAddress"    column="url_address"    />
        <result property="iconBase64"    column="icon_base64"    />
        <result property="iconPath"    column="icon_path"    />
        <result property="createUser"    column="create_user"    />
        <result property="createTime"    column="create_time"    />
        <result property="isUse"    column="is_use"    />
        <result property="isDel"    column="is_del"    />
        <result property="remark1"    column="remark1"    />
        <result property="remark2"    column="remark2"    />
        <result property="remark3"    column="remark3"    />
        <result property="remark4"    column="remark4"    />
        <result property="remark5"    column="remark5"    />
    </resultMap>

    <sql id="selectSiteExampleVo">
        select id, title, type, content, url_address, icon_base64, icon_path, create_user, create_time, is_use, is_del, remark1, remark2, remark3, remark4, remark5 from site_example
    </sql>

    <select id="selectSiteExampleList" parameterType="SiteExample" resultMap="SiteExampleResult">
        <include refid="selectSiteExampleVo"/>
        <where>  
            <if test="title != null  and title != ''"> and title like concat('%', #{title}, '%')</if>
            <if test="type != null  and type != ''"> and type = #{type}</if>
            <if test="content != null  and content != ''"> and content = #{content}</if>
            <if test="urlAddress != null  and urlAddress != ''"> and url_address = #{urlAddress}</if>
            <if test="createUser != null  and createUser != ''"> and create_user = #{createUser}</if>
            <if test="isUse != null  and isUse != ''"> and is_use = #{isUse}</if>
            <if test="isDel != null  and isDel != ''"> and is_del = #{isDel}</if>
            <if test="remark1 != null  and remark1 != ''"> and remark1 = #{remark1}</if>
            <if test="remark2 != null  and remark2 != ''"> and remark2 = #{remark2}</if>
            <if test="remark3 != null  and remark3 != ''"> and remark3 = #{remark3}</if>
            <if test="remark4 != null  and remark4 != ''"> and remark4 = #{remark4}</if>
            <if test="remark5 != null  and remark5 != ''"> and remark5 = #{remark5}</if>
        </where>
    </select>
    
    <select id="selectSiteExampleById" parameterType="Long" resultMap="SiteExampleResult">
        <include refid="selectSiteExampleVo"/>
        where id = #{id}
    </select>
        
    <insert id="insertSiteExample" parameterType="SiteExample" useGeneratedKeys="true" keyProperty="id">
        insert into site_example
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="title != null">title,</if>
            <if test="type != null">type,</if>
            <if test="content != null">content,</if>
            <if test="urlAddress != null">url_address,</if>
            <if test="iconBase64 != null">icon_base64,</if>
            <if test="iconPath != null">icon_path,</if>
            <if test="createUser != null">create_user,</if>
            <if test="createTime != null">create_time,</if>
            <if test="isUse != null">is_use,</if>
            <if test="isDel != null">is_del,</if>
            <if test="remark1 != null">remark1,</if>
            <if test="remark2 != null">remark2,</if>
            <if test="remark3 != null">remark3,</if>
            <if test="remark4 != null">remark4,</if>
            <if test="remark5 != null">remark5,</if>
         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="title != null">#{title},</if>
            <if test="type != null">#{type},</if>
            <if test="content != null">#{content},</if>
            <if test="urlAddress != null">#{urlAddress},</if>
            <if test="iconBase64 != null">#{iconBase64},</if>
            <if test="iconPath != null">#{iconPath},</if>
            <if test="createUser != null">#{createUser},</if>
            <if test="createTime != null">#{createTime},</if>
            <if test="isUse != null">#{isUse},</if>
            <if test="isDel != null">#{isDel},</if>
            <if test="remark1 != null">#{remark1},</if>
            <if test="remark2 != null">#{remark2},</if>
            <if test="remark3 != null">#{remark3},</if>
            <if test="remark4 != null">#{remark4},</if>
            <if test="remark5 != null">#{remark5},</if>
         </trim>
    </insert>

    <update id="updateSiteExample" parameterType="SiteExample">
        update site_example
        <trim prefix="SET" suffixOverrides=",">
            <if test="title != null">title = #{title},</if>
            <if test="type != null">type = #{type},</if>
            <if test="content != null">content = #{content},</if>
            <if test="urlAddress != null">url_address = #{urlAddress},</if>
            <if test="iconBase64 != null">icon_base64 = #{iconBase64},</if>
            <if test="iconPath != null">icon_path = #{iconPath},</if>
            <if test="createUser != null">create_user = #{createUser},</if>
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="isUse != null">is_use = #{isUse},</if>
            <if test="isDel != null">is_del = #{isDel},</if>
            <if test="remark1 != null">remark1 = #{remark1},</if>
            <if test="remark2 != null">remark2 = #{remark2},</if>
            <if test="remark3 != null">remark3 = #{remark3},</if>
            <if test="remark4 != null">remark4 = #{remark4},</if>
            <if test="remark5 != null">remark5 = #{remark5},</if>
        </trim>
        where id = #{id}
    </update>

    <delete id="deleteSiteExampleById" parameterType="Long">
        delete from site_example where id = #{id}
    </delete>

    <delete id="deleteSiteExampleByIds" parameterType="String">
        delete from site_example where id in 
        <foreach item="id" collection="array" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete>
</mapper>

案例的数据库如下

image

接口写完后我们之间用idea打包即可如下

image

打包成功后标识如下

image

然后我们去target目录下找到生成的jar文件重命名下等待一会上传服务器

image

5.Linux服务器上传文件及配置启动

默认linux已经搭建好java环境并配置好项目环境了,如果没配置可以参考下我的这篇文章《Linux搭建后台管理系统》,将之前打包好的两个dist文件分别放到下面的目录中,将jar包放到jar目录下

image

image

注意dist文件的替换不需要重启nginx也不需要其他多余的操作,直接替换就行,jar的替换需要杀死进程并重启,命令如下

#jar进程查看 8080为项目端口号:
netstat -nlp|grep 8080 
#或者用:
ps -ef|grep java

#进程关闭 23568为进程查看得到的进程号
kill 23568

#jar包启动
nohup java -jar xx.jar &

6.Nginx的配置

官网前端Nginx配置如下

image

官网后台管理页面配置如下

image

注意:监听的端口,我默认的80端口作为官网的访问,那我的服务器绑定域名后,用户可以直接通过域名不加端口访问,后端管理页面则必通过域名+8001端口访问才行,由于我的官网是从之前php搭建的转到vue来的,因此在官网的配置中还能看index.php的文件,实际上就是访问dist文件下的index.html

注:可以有偿提供类似官网及后台管理系统搭建及部署,需要的私信即可

评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

博主逸尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值