声明:文章为稀土技能社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!

哈喽咱们好!这篇文章来到了发布渠道全栈开发的前端部分,总算回到咱们最熟悉的前端了!本文将接着前面三篇文章,翻开介绍发布渠道的前端实战!依然是熟悉的手把手,看完不懂你直接打我!

系列文章:

  1. 总览前端自动化布置流程,如何完结前端发布渠道?文章链接
  2. 前端发布渠道node server实战!文章链接
  3. 前端发布渠道jenkins实战!如何完结前端自动化布置?文章链接
  4. 前端发布渠道全栈实战(前后端开发完整篇)!开发一个前端发布渠道
  5. websocket 全栈实战,完结仅有构建实例 + 日志同步。文章链接

回忆前面三篇文章,笔者分别介绍了:前端项目的发布全貌、node server实战开发、触发 jenkins 完结自动化布置。本文是第四篇「前端发布渠道全栈实战——前端篇」的实战记载共享,首要经过共享 Vue + Element-plus + Koa 完结一个发布渠道的前端。下面是本文需求完结的中心点:

  1. 前端后端数据分页展现完结
  2. 全栈增删改数据完结

就怕只写前端的实战对咱们来太没意思了,看都看不下去!那笔者就趁机在 demo项目 中运用最近比较火的 tailwindcss 来玩玩,因为真实不想再给需求设置款式的 dom 起类名了(就凭这一点仍是很香的)!这儿是 vue3 项目装置 tailwindcss 的 文档,假如你也想玩玩赶紧在项目里面装一个,合作插件运用更爽!下面进入文章主题。let’s go!!!

快速看源码

  • 前端项目源码

一、构建装备前端显示

回忆榜首篇文章,那时分现已新建好了一个前端项目了,咱们接着之前的开干。在正式进入实战开发之前,准备工作仍是不能少的,前端项目仍是要装一些包来协助咱们的,比方 axioselement-plusvue-router 这些,都是咱们十分熟悉的依靠包了,直接装置即可。笔者现已自己完结装置,直接从代码实战开端讲起。

1. 分页展现前端模板

之前在讲 实战Koa 的时分,咱们现已能够经过 postman 恳求后端接口完结装备数据的创立、保存。现在,咱们完结一下在前端将数据展现出来。因为装备数据可能有很多条,所以笔者计划经过 table + 分页 的方式展现数据。

首要先搞个简略的静态界面:

<!-- 写 tailwindcss 后再也不用想类名了! -->
<el-card class="w-screen">
  <template #header>
    <span class="font-bold">项目装备</span>
  </template>
  <!-- 筛选框部分 -->
  <el-form inline>
    <el-form-item label="项目名称"></el-form-item>
  </el-form>
  <!-- 表格部分 -->
  <el-table>
    <el-table-column label="项目名称" prop="projectName" />
    ...
  </el-table>
  <!-- 翻页 -->
  <el-pagination ... />
</el-card>

ToB 的同学在哪里,这玩意很熟悉有木有?现在静态的前端界面就出来了,接下来便是要经过 axios 去服务端恳求装备数据,完结前端界面动态接入数据啦~

全栈开发—Vue+Element+Koa 实战发布渠道CRUD!

2. 后端完结分页查询

回忆之前的文章,笔者在后端实战中完结了装备的 创立更新删去 的接口,可是并没有完结 分页查询 的接口,所以在完结前端开发之前,首要需求完结分页接口。所以,笔者在之前的 route 中新建一个路由:

全栈开发—Vue+Element+Koa 实战发布渠道CRUD!

首要咱们需求完结 getConfigList 的接口,中心代码如下:

export async function getConfigList (ctx, next) {
  try {
    // 获取分页参数(由前端带上来)
    const { pageNo: page, pageSize, projectName } = ctx.request.query
    // 调用 services 层的 findJobPage 完结分页数据查询
    const pageData = await services.findJobPage(page, pageSize, { projectName })
    // 查询成功的回来
    ctx.state.apiResponse = {
      code: RESPONSE_CODE.SUC,
      data: pageData
    }
  } catch (e) {
    ctx.state.apiResponse = {
      code: RESPONSE_CODE.ERR,
      msg: '装备分页查询失利'
    }
  }
  next()
}

很简略是吧,都是之前咱们搞过的。接下来具体看看 services.findJobPage 的代码完结:

export async function findJobPage (page, pageSize, params) {
  // 过滤掉前端传操控的查找条件
  Object.keys(params).forEach(key => {
    if (!params[key]) Reflect.deleteProperty(params, key)
  })
  /**
   * find() 查询数据
   * skip() 故名思义越过:指定越过的文档条数
   * limit() 最大条数
  **/
  const DocumentUserList = await JobModel.find(params)
    .skip((page - 1) * pageSize)
    .limit(pageSize)
  // toObject() 将查询出来的 Document 目标转换成 js 目标
  return DocumentUserList.map(_ => _.toObject())
}

其中的数据库交互都是直接调用 mongoose 供给的 api ,在运用层面对笔者这种后端菜鸟来说仍是相对简略的。想要了解更多 api 的能够戳 mongoose文档,需求什么接口尽管往里面找,完结 CRUD ,甚至更复杂的事务都彻底不在话下啦。

好了,这儿咱们现已完结完装备的分页查询接口了,咱们再接再励地到前端页面的开发中!首要咱们需求在前端中建议恳求,来验证一下咱们完结的接口能不能运转!接着往下看

3. 前端接入分页接口

前后端正式联调之前,咱们需求先把前端项目的 proxy 设置一下,在 vite.config 中:

proxy: {
  '/api': {
    target: 'http://localhost:3200/', // 代理到后端地址
    changeOrigin: true,
    rewrite: path => {
      return path.replace(/^/api/, '')
    }
  }
}

接下来咱们经过 axios 完结对后端接口的恳求,代码如下:

export async function getConfig (params) {
  return axios.get('/job', { params })
}

紧接着,笔者在 onMounted 阶段进行数据恳求,履行恳求函数,结果如图所示。可知,咱们现已能够从方才完结的接口中获取到对应的数据了。接下来只需求把数据信息跟前端的 table 组件接上去就能够完结数据展现了!

全栈开发—Vue+Element+Koa 实战发布渠道CRUD!

当然,到这一步的时分,笔者才发现忘记对 axios 的回来做阻拦了,导致在事务层中获取数据的时分需求经过 data.data 才能获取到,看起来真实是有点不雅,所以笔者决定补回 axios 的回来阻拦!依据 axios 的阻拦写法完结阻拦,代码如下:

axios.interceptors.response.use(function (response) {
  const data = response.data
  if (data.code === 0) {
    return data.data // 这样在事务层就不需求两层 data 获取数据了
  }
  data.message = data.message || data.msg
  return Promise.reject(data)
})

回到获取接口数据的代码中,事务层的完结其实十分简略,笔者经过一个名为 tableDataref 响应式数据获取数据,然后传入到 el-tabledata 属性中。具体的就不翻开了,仍是比较简略的,笔者这儿就贴个伪代码和终究的实际图吧:

  // 获取数据
  tableData.value = await getConfig(searchParams)
  <el-table :data="tableData">
    ...
  </el-table>

全栈开发—Vue+Element+Koa 实战发布渠道CRUD!

从上图中能够看出,整个 table 的数据接入现已完结,看起来现已有点容貌了。可是,功用并没有彻底完结,回想一下方才咱们完结分页查询的接口中有没有遗漏了哪一个过程!没错,便是漏了完结 total 这个字段,咱们方才只是完结了分页数据的查询,可是并没有管 total 字段~接下来咱们继续完善咱们的分页接口。

其实 total 更简略!咱们把相同的分页查询条件经过 mongoosecount() 函数履行一下就完结了~便是这么简略,直接看代码吧:

export function countJob (params) {
  // 处理为空的查询条件
  Object.keys(params).forEach(key => {
    if (!params[key]) Reflect.deleteProperty(params, key)
  })
  // 经过 count 得到 total
  return JobModel.count(params)
}

既然现在需求把 total 字段回来前端,那咱们的回来数据的格局就不能简略的回来一个 分页list 数据,所以笔者这儿经过目标把它们包起来,把数据一同回来去前端~稍微改造一下回来的代码,具体回来如下:

ctx.state.apiResponse = {
  code: RESPONSE_CODE.SUC,
  data: {
    list: pageData,
    page,
    pageSize,
    total
  }
}

现在,再在前端经过接口查询,看看回来的数据!如下图所示:

全栈开发—Vue+Element+Koa 实战发布渠道CRUD!

嗯,有内味了。平时跟后端联调是不是经常能看到这一串!现在咱们自己也完结了,哈哈哈,全栈还挺好玩~那现在前端接入数据这部分现已完结了,接下来咱们快速把 装备新建装备修正装备删去的也一同完结了!

二、全栈开发完结 CRUD

1. 新建装备

新建的接口在之前的 Koa 实战中现已完结了,所以这儿咱们只需求完结前端界面并联调好后端的接口就好了,十分 easy ~既然是需求新增,笔者这儿决定选用弹窗的交互方式去完结。当用户点击一个“新增装备”的按钮时,弹起弹窗,弹窗的具体内容便是一个表单。事不宜迟,直接上代码:

  1. 首要要添加一个新建的按钮:

    <el-button type="" @click="">新增装备</el-button>
    

    作用如图所示:

    全栈开发—Vue+Element+Koa 实战发布渠道CRUD!

  2. 新建一个新增、修正的弹窗(修正时默认回填数据):

    <el-dialog v-model="dialogVisible" :title="dialogTitle">
      <el-form :model="formData">
        <el-form-item label="项目名称" prop="projectName">
          <el-input v-model="formData.projectName" placeholder="输入项目名称" />
        </el-form-item>
        ......
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="onSubmit">承认</el-button>
        </span>
      </template>
    </el-dialog>
    

    弹窗作用如图所示:

    全栈开发—Vue+Element+Koa 实战发布渠道CRUD!

  3. 完结新增装备信息函数 onSubmit (用户点击弹窗的“承认”时触发):

    // 响应式数据 formData ,现已绑定在装备弹窗对应表单控件的 v-model 中
    const formData = reactive({
      projectName: '',
      gitUrl: '',
      gitBranch: '',
      buildCommand: '',
      uploadPath: ''
    })
    const onSubmit = async () => {
      try {
        // 调用保存函数,传入参数 formData
        await postSave(formData)
        // 保存成功提示
        ElMessage.success('装备保存成功')
        // 保存成功后更新当时页面数据
        await initData()
        // 关闭装备弹窗
        dialogVisible.value = false
      } catch (e) {
        ElMessage.error('装备保存失利')
      }
    }
    

以上便是整个新增装备的前端代码完结了,接下来咱们就一同来看看作用。笔者点击 新建装备 按钮,并在弹窗中输入如下装备信息:

全栈开发—Vue+Element+Koa 实战发布渠道CRUD!

紧接着笔者翻开 操控台 ,点击承认按钮后查看 netWork 信息如下:

全栈开发—Vue+Element+Koa 实战发布渠道CRUD!
如图能够看到,这儿成功调用了 save 接口完结了数据的保存。并且在前端页面中,也现已呈现了咱们新增的内容。新增装备功用大功告成!咱们趁热打铁,接着完结修正功用!

2. 修正装备

完结修正装备的功用,咱们需求让后端知道咱们要修正的是哪一条数据,所以咱们最好是经过 id(仅有) 去恳求后端,然后再带上咱们修正后的数据。所以按照这样的需求场景,最普遍的做法便是在表格中新增一列操作列,并把当时的修正的数据信息传入处理修正的函数中。接下来咱们经过代码把功用完结一下!

首要咱们在 el-table 中添加一列操作列,模板代码如下:

<el-table-column label="操作">
  <template #default="scope">
    <!-- 传入 scopr.row -->
    <el-button type="primary" link @click="onEdit(scope.row)">修正</el-button>
  </template>
</el-table-column>

当用户点击修正时,咱们需求做两件事:

  1. 翻开弹窗
  2. 回填数据

完结 onEdit 函数代码如下:

const onEdit = rowData => {
  // 表示当时时修正状况
  isEdit.value = true
  // 翻开弹窗
  dialogVisible.value = true
  Object.keys(formData).forEach(key => {
    // 依据 rowData 回填 formData 数据
    formData[key] = rowData[key]
  })
  // 取得当时数据的 id
  formData.id = rowData._id
}

因为咱们整个提交逻辑跟新增的时分是相同的,所以咱们只需求经过 isEdit 来判别一下现在是新增仍是修正,从而去调用不同的接口即可。所以这儿咱们对上文提到的 onSubmit 函数进行小修正,代码如下:

const onSubmit = async () => {
  try {
    // 经过 isEdit 判别调用新增仍是修正接口
    isEdit.value
      ? await postUpdate(formData)
      : await postSave(formData)
    // 案牍依据 isEdit 进行调整
    ElMessage.success(isEdit.value ? '装备修正成功' : '装备保存成功')
    await initData()
    dialogVisible.value = false
  } catch (e) {
    // 案牍依据 isEdit 进行调整
    ElMessage.error(isEdit.value ? '装备修正失利' : '装备保存失利')
  }
}

验证一下作用,找到一条数据,并在所有数据项后面添加 updata 字符串。然后点击承认按钮。

全栈开发—Vue+Element+Koa 实战发布渠道CRUD!

如图所示,调用了 update 接口且正确上传参数(多了个id的参数),并且成功修正数据库数据显示在当时界面中:

全栈开发—Vue+Element+Koa 实战发布渠道CRUD!

又搞定了一个功用,现在咱们把最终一个功用「删去」也一同完结了,咱们接着往下看!

3. 删去装备

删去装备跟修正相同,也是需求 id(仅有标识) 传给后端,删去对应的装备数据。所以,咱们需求在 table 的操作列中新增一个删去的按钮。一般删去这种操作,都是需求二次承认的,所以笔者在这儿也应用上 Element-pluscomfirm 组件。

老样子,首要是 前端界面的代码完结:

<!-- 操作列中新增 删去 按钮 -->
<el-popconfirm title="承认删去该装备?" @confirm="onDel(scope.row)">
  <template #reference>
    <el-button type="danger" link>删去</el-button>
  </template>
</el-popconfirm>

作用如图所示:

全栈开发—Vue+Element+Koa 实战发布渠道CRUD!

接着咱们完结删去函数 onDel

const onDel = async rowData => {
  try {
    // 调用删去恳求,传入参数 id
    await postDelete({ id: rowData._id })
    ElMessage.success('装备删去成功')
    // 删去成功后更新当时界面数据
    await initData()
  } catch (e) {
    ElMessage.error('装备删去失利')
  }
}

删去函数的完结也是十分的简略!接下来,笔者就在界面中操作一下,看看删去是否成功完结!笔者在这儿就删去一条名为 test add 1 的装备数据,如图所示:

全栈开发—Vue+Element+Koa 实战发布渠道CRUD!

点击承认后,成功建议 del 接口的恳求,成功删去数据后刷新界面显示,作用如图所示:

全栈开发—Vue+Element+Koa 实战发布渠道CRUD!

好啦,到这儿整个 crud 的功用就搞定了,也算是体会一把全栈开发的感觉了有木有~在这儿,笔者带咱们进行简略的回忆本文的内容:

  • 首要是完结分页数据显示,从前端界面到后端接口的完结
  • 然后便是完结了装备信息的 crud 功用!

写在最终

经过本文后,整个专栏的文章编写现已挨近尾声了,回忆一下本专栏的内容,咱们从 前端后端jenkins 中现已逐步完结了发布渠道的功用了,现在仅剩最终一步:从前端建议构建、获取 jenkins 日志。没错,这一步笔者会在下一篇文章中进行解说,这儿列一下首要共享的内容:

  • 运用 websocket 完结 jenkins 日志传输
  • 后端完结当时构建项目仅有构建实例(多个用户翻开同个项目仅有一个构建状况)

咱们敬请期待!