当前位置: 首页 > article >正文

6. 【Vue实战--孢子记账--Web 版开发】-- 主币种设置

从这篇文章开始我们将一起实现孢子记账的功能,这篇文章实现主币种设置。这个功能比较简单,因此我们从这个功能开始做。

一、功能

根据项目前期的需求调研,用户需要在设置主币种的时候查看汇率信息(别问为什么有这么个需求,很多用户的需求很离谱),因此我们画出了如下的原型图。
在这里插入图片描述
在这个原型图中顶部是面包屑导航,接着是显示和设置主币种的功能,最后是汇率表。

二、实现

在这一小节,我们一步一步的实现前面所描述的三个部分。

2.1 面包屑导航

el-breadcrumb是 Element Plus 提供的面包屑导航组件,主要用于指示当前页面所在的位置,并能快速返回上一级或首页。在 Vue3 的项目中,它通常与 Vue Router 结合使用,以提供清晰的导航路径。el-breadcrumb组件的基本使用方式是通过el-breadcrumb-item子组件来定义每一层级的路径。例如,最简单的用法如下:

<el-breadcrumb separator="/">
  <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
  <el-breadcrumb-item :to="{ path: '/category' }">分类</el-breadcrumb-item>
  <el-breadcrumb-item>详情</el-breadcrumb-item>
</el-breadcrumb>

在代码中separator属性用于定义分隔符,可以自定义,如separator=">"或者separator-icon="ArrowRight",后者可以使用 Element Plus 提供的图标。每个el-breadcrumb-item代表面包屑中的一级导航,to属性可以绑定 Vue Router 的路径,使其变成可点击的链接,而最后一个面包屑项通常不设置to,表示当前页面。
在动态路由中,我们可以结合 Vue Router 的route.matched来动态生成面包屑。例如:

<el-breadcrumb separator="/">
  <el-breadcrumb-item v-for="(item, index) in $route.matched" :key="index" :to="item.path">
    {{ item.meta.title }}
  </el-breadcrumb-item>
</el-breadcrumb>

这里的route.matched数组存储了当前匹配到的所有路由信息,而meta.title则可以在路由配置中定义每个页面的标题,例如:

{
  path: '/category',
  component: Category,
  meta: { title: '分类' }
}

除了separatorel-breadcrumb还支持separator-icon,可以使用 Element Plus 的el-icon组件。例如:

<el-breadcrumb separator-icon="ArrowRight">
  <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
  <el-breadcrumb-item>详情</el-breadcrumb-item>
</el-breadcrumb>

这样,分隔符会变成ArrowRight图标,提高视觉效果。
根据上面的讲解,我们实现了自己的面包屑导航:

<el-breadcrumb separator="/">
    <el-breadcrumb-item :to="{path:'/'}">首页</el-breadcrumb-item>
    <el-breadcrumb-item :to="{path:'/config'}">系统配置</el-breadcrumb-item>
    <el-breadcrumb-item><span style="font-weight: bold">主币种设置</span></el-breadcrumb-item>
</el-breadcrumb>
2.2 主币种显示与设置

主币种显示预设值很简单,我们主要用到了el-textel-select来实现,辅助的组件有el-formel-buttonel-textel-button比较简单就不多讲了,这里主要先讲一下el-formel-select
el-form是 Element Plus 提供的表单组件,主要用于数据收集、校验和提交。它通常与el-form-itemel-inputel-select等控件配合使用,实现完整的表单功能。
el-form通过model绑定数据对象,每个el-form-item绑定prop以对应model的属性值。

<el-form :model="formData" label-width="80px">
  <el-form-item label="用户名" prop="username">
    <el-input v-model="formData.username"></el-input>
  </el-form-item>
  <el-form-item label="密码" prop="password">
    <el-input v-model="formData.password" type="password"></el-input>
  </el-form-item>
  <el-form-item>
    <el-button type="primary" @click="submitForm">提交</el-button>
  </el-form-item>
</el-form>
import { reactive } from 'vue';

const formData = reactive({
  username: '',
  password: ''
});

const submitForm = () => {
  console.log(formData);
};

我们也可以使用rules来定义校验规则,并在el-form-item设置prop关联。

<el-form :model="formData" :rules="rules" ref="formRef">
  <el-form-item label="邮箱" prop="email">
    <el-input v-model="formData.email"></el-input>
  </el-form-item>
</el-form>
const rules = {
  email: [{ required: true, message: '请输入邮箱', trigger: 'blur' }]
};

调用validate方法进行校验:

const formRef = ref(null);

const submitForm = () => {
  formRef.value.validate(valid => {
    if (valid) {
      console.log('提交成功');
    } else {
      console.log('校验失败');
    }
  });
};

el-select是 Element Plus 提供的下拉选择框组件,常用于需要用户从多个选项中选择一个或多个值的场景。它支持单选、多选、远程搜索、分组等功能,并能与el-option配合使用。
最简单的el-select通过v-model绑定选中的值,el-option通过value设置选项的实际值,label作为显示文本。

<el-select v-model="selectedValue" placeholder="请选择">
  <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
import { ref } from 'vue';

const selectedValue = ref('');
const options = ref([
  { value: 'apple', label: '苹果' },
  { value: 'banana', label: '香蕉' },
  { value: 'cherry', label: '樱桃' }
]);

设置multiple属性即可支持多选,并可通过collapse-tags控制已选项的展示方式。

<el-select v-model="selectedValues" multiple collapse-tags placeholder="请选择">
  <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
const selectedValues = ref([]);

可以使用filterableremote属性实现远程搜索,并结合remote-method进行动态数据加载。

<el-select v-model="selectedValue" filterable remote :remote-method="fetchOptions" placeholder="搜索水果">
  <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
const fetchOptions = (query) => {
  if (query) {
    options.value = [{ value: query, label:`搜索结果:${query}`}];
  } else {
    options.value = [];
  }
};

我们可以通过disabled属性禁用整个el-select,或在el-option里单独禁用某些选项。

<el-select v-model="selectedValue" disabled>
  <el-option value="apple" label="苹果"></el-option>
</el-select>

下面,我们就用这四个组件来实现主币种显示与修改功能。

<div v-if="!isEdit">
    <!-- 一个文本区域 -->
    <el-text>当前主币种:{{ primaryCurrency.name }}</el-text>
    <el-button type="primary" link style="padding-left: 10px" @click="edit">修改</el-button>
</div>
<el-form v-if="isEdit">
    <el-form-item label="主币种:">
    <el-select v-model="primaryCurrency.value" placeholder="请选择主币种" style="width: 10%;min-width: 168px">
        <el-option
            v-for="item in primaryCurrencyOptions"
            :key="item.id"
            :label="item.name"
            :value="item.id">
        </el-option>
    </el-select>
    <el-button id="save" type="primary" @click="save">保存</el-button>
    </el-form-item>
</el-form>

这段代码实现了主币种的展示和编辑功能。默认情况下isEditfalse时,界面显示el-text组件,直接展示当前主币种的名称,同时提供一个“修改”按钮,点击后会调用edit方法,使isEdit变为true,从而进入编辑模式。在编辑模式下,页面显示el-form表单,其中el-select组件用于选择新的主币种,其选项来源于primaryCurrencyOptions,并绑定到primaryCurrency.value。用户选择后,可以点击“保存”按钮,触发save方法,将修改后的币种值提交或处理。整个交互通过v-if切换视图,使用户在查看和编辑之间自由切换,提供了一种直观的编辑体验。

import type {Config as PrimaryCurrency} from "../../Interface/config.ts";
import type {Currency} from "../../Interface/currency.ts";
const isEdit = ref(false)
//定义接受返回值的PrimaryCurrency
const primaryCurrency = reactive<PrimaryCurrency>({
  id: '',
  value: '',
  name: ''
})
//定义接收全部币种返回值的Currency
const primaryCurrencyOptions = ref<Currency[]>([]);
onMounted(() => {
  queryPrimaryCurrency();
  queryExchangeRate();
})

// 页面加载出来后,获取主币种
const queryPrimaryCurrency = () => {
  axios.get(import.meta.env.VITE_API_BASE_URL + '/api/Config/QueryByConfigType/0', {
    headers: {
      Authorization: localStorage.getItem('token')
    }
  })
      .then((res: any) => {
        const response = res.data;
        if (response.statusCode === 200) {
          // 接收返回值
          primaryCurrency.id = response.data.id;
          primaryCurrency.value = response.data.value;
          primaryCurrency.name = response.data.name;
        } else {
          ElMessage.error(response.errorMessage)
        }
      }).catch((err: any) => {
    ElMessage.error(err.message);
  });
}

const edit = () => {
  isEdit.value = true;
  //获取全部币种
  axios.get(import.meta.env.VITE_API_BASE_URL + '/api/Currency/QueryAll', {
    headers: {
      Authorization: localStorage.getItem('token')
    }
  })
      .then((res: any) => {
        const response = res.data;
        if (response.statusCode === 200) {
          // 接收返回值
          primaryCurrencyOptions.value = response.data;
        } else {
          ElMessage.error(response.errorMessage)
        }
      }).catch((err: any) => {
    ElMessage.error(err.message);
  });
}

const save = () => {
  axios.put(import.meta.env.VITE_API_BASE_URL + '/api/Config/Update', {
    id: primaryCurrency.id,
    value: primaryCurrency.value,
    configTypeEnum: 0
  }, {
    headers: {
      Authorization: localStorage.getItem('token')
    }
  })
      .then((res: any) => {
        const response = res.data;
        if (response.statusCode === 200) {
          queryPrimaryCurrency();
          isEdit.value = false;
          ElMessage.success("主币种设置完成")
        } else {
          ElMessage.error(response.errorMessage)
        }
      }).catch((err: any) => {
    ElMessage.error(err.message);
  });
}

这段代码首先通过import type {Config as PrimaryCurrency}导入了主币种配置的类型定义,确保primaryCurrency对象具有明确的属性类型。接着,通过ref定义了一个响应式布尔值isEdit用于标识当前是否处于编辑状态,而reactive定义了一个响应式对象primaryCurrency,包含 id、value 和 name 三个属性,用于存储从后端接口获取到的主币种信息。
在组件挂载完成后(onMounted),调用queryPrimaryCurrency方法,通过 axios 的 GET 请求向后端接口获取当前主币种数据,请求中携带了保存在本地存储中的 token 作为授权信息。请求返回后,如果响应状态码为 200,则将返回数据赋值给primaryCurrency对象,否则通过 Element Plus 的ElMessage.error提示错误信息。
当用户点击“修改”按钮时,会调用edit方法,该方法将isEdit设为true,表示进入编辑模式。此时,同样通过 axios 的 GET 请求从后端接口获取所有币种列表(用于供用户选择),返回成功后,将币种选项赋值给primaryCurrencyOptions(此处变量应在其他位置定义为响应式变量),否则显示错误提示。
在编辑完成后,用户点击“保存”按钮会调用save方法,该方法通过 axios 的 PUT 请求将当前选中的主币种数据更新到后端,传递的参数包括主币种的 id、value 以及一个枚举值 configTypeEnum(值为 0 表示主币种)。若更新成功,则调用queryPrimaryCurrency刷新主币种数据,并将isEdit设置为false返回非编辑状态,同时提示用户“主币种设置完成”;若更新失败,则通过错误提示告知用户相关信息。

2.3 汇率表

最后,我们实现汇率表功能,汇率表使用el-tableel-pagination组件来实现。
Element Plus 的el-table是一个基于 Vue 3 的高性能表格组件,提供了丰富的功能和灵活的配置选项,方便开发者快速构建数据展示与交互界面。其核心特点在于易用性与高度可定制化,既支持基本的数据渲染,也能满足复杂业务需求。
首先,el-table支持通过data属性传入数组数据,并根据el-table-column子组件自动生成表格列。每个el-table-column可以单独设置proplabelwidth等属性,从而实现自定义列宽、列标题以及数据绑定。开发者可以根据实际需求,通过插槽(slot)来自定义单元格内容,实现更加灵活的展示效果,例如在单元格中嵌入按钮、图标或其他组件。
其次,排序与筛选是 el-table 的重要功能。通过设置sortable属性,可以让某一列支持排序操作,用户点击列头即可切换排序状态。同时,还可以借助内置的筛选功能,通过filters属性预定义筛选项,并结合filter-method自定义筛选逻辑,使表格能够根据特定条件动态过滤数据,提升用户体验。
此外,el-table 还提供了诸如多选、单选、行扩展、固定列等实用功能。通过配置type="selection"可以轻松实现多选框,便于用户批量操作数据。固定列功能则适用于数据量大、列数较多的场景,固定左侧或右侧的列可以在滚动时保持可见,保证关键信息不丢失。行扩展功能允许开发者在表格中嵌入更多细节信息,用户点击后即可展开显示隐藏的内容,进一步提升数据展示的层次感。
在使用上,el-table 还支持响应式布局与动态数据更新,当数据源发生变化时,表格能够自动响应,保证界面实时刷新。同时,Element Plus 通过提供丰富的事件回调(如row-clicksort-change等),使开发者可以在用户交互时执行自定义逻辑,增强了表格组件与业务逻辑的融合度。
Element Plus 的el-pagination组件是一个强大的分页工具,主要用于处理大数据列表的分页展示。它通过total属性指定数据总数,page-size控制每页显示的条数,而current-page负责追踪当前页码。默认情况下,它会显示上一页、下一页按钮,以及页码选择,用户可以点击页码切换不同页面,从而触发current-change事件,更新列表数据。
在实际使用中,el-pagination允许开发者灵活配置其布局,通过layout属性调整显示内容,例如"total, sizes, prev, pager, next, jumper"组合可以在分页器中展示总条数、每页条数选择、跳页输入框等。用户可以使用page-sizes设定不同的分页条数选项,并监听size-change事件,在切换时动态加载数据。此外,它还支持小型模式,通过small属性调整样式,使其更适用于移动端或紧凑布局。
下面我们一起实现汇率表。

<el-table :data="exchangeRate.data" style="width: 100%">
    <el-table-column type="index" width="100" label="编号"></el-table-column>
    <el-table-column prop="currency1" label="币种1"></el-table-column>
    <el-table-column prop="currency2" label="币种2"></el-table-column>
    <el-table-column prop="rate" label="汇率"></el-table-column>
    <el-table-column prop="updateTime" label="日期" :formatter="formatDate"></el-table-column>
</el-table>
<el-pagination
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
    :current-page="currentPage"
    :page-sizes="[10, 20, 30, 40]"
    :page-size="pageSize"
    layout="total, sizes, prev, pager, next, jumper"
    :total="exchangeRate.rowCount" style="margin-top: 20px">
</el-pagination>

在代码中el-table部分,data属性绑定了表格的数据源exchangeRate.data,即展示的汇率数据。el-table-column用来定义每列的内容,展示不同的字段:type="index"用于显示行号,width="100"设置列宽度为100px。接下来的几列分别显示币种1(currency1)、币种2(currency2)、汇率(rate),以及日期(updateTime)。对于日期列,通过:formatter="formatDate"属性,调用formatDate方法格式化日期显示。下方的el-pagination组件用于分页功能,支持切换每页显示的数据条数(@size-change)和当前页(@current-change)。它的current-pagepage-size分别绑定当前页数和每页显示条数,total属性显示总数据条数(exchangeRate.rowCount)。分页控制的布局(layout)包括了总数、页码大小选择、前后页按钮、页码跳转等,样式上通过style="margin-top: 20px"设置了与表格的间距。

import type {ExchangeRate} from "../../Interface/exchangeRate.ts";
import type {PageResponse} from '../../Interface/response';
import {dayjs} from "element-plus";
//接收汇率返回值ExchangeRate
const exchangeRate :PageResponse<ExchangeRate> = reactive({
  data: [],
  rowCount: 0,
  pageCount: 0
})

const pageSize = ref(10);
const currentPage = ref(1);


onMounted(() => {
  queryPrimaryCurrency();
  queryExchangeRate();
})
// 获取汇率
const queryExchangeRate = () => {
  axios.get(import.meta.env.VITE_API_BASE_URL + '/api/ExchangeRate/Query/' + currentPage.value + '/' + pageSize.value, {
    headers: {
      Authorization: localStorage.getItem('token')
    }
  })
      .then((res: any) => {
        const response = res.data;
        if (response.statusCode === 200) {
          // 接收返回值
          exchangeRate.rowCount = response.data.rowCount;
          exchangeRate.data = response.data.data;
          exchangeRate.pageCount=response.data.pageCount;
        } else {
          ElMessage.error(response.errorMessage)
        }
      }).catch((err: any) => {
    ElMessage.error(err.message);
  });
}
const handleSizeChange = (value: number) => {
  pageSize.value = value;
  queryExchangeRate();
}
const handleCurrentChange = (value: number) => {
  currentPage.value = value;
  queryExchangeRate();
}

const formatDate = (row: any, column: any, cellValue: any, index: number) => {
  return dayjs(cellValue).format('YYYY-MM-DD');
};

这段代码主要用于处理汇率数据的获取、分页和格式化显示。首先,导入了ExchangeRatePageResponse类型,确保了汇率数据的类型安全。exchangeRate是一个响应式对象,类型为PageResponse<ExchangeRate>,它包含了数据(data)、行数(rowCount)和页数(pageCount)这三部分数据,初始化时data是一个空数组,rowCountpageCount是 0。
接着,定义了pageSizecurrentPage这两个响应式变量,分别表示每页显示的条数和当前页码,初始值分别为 10 和 1。
onMounted生命周期钩子中,组件加载完成后,调用queryPrimaryCurrencyqueryExchangeRate方法。queryExchangeRate方法用于通过 axios 发起 GET 请求,向服务器请求当前页的汇率数据。请求路径是根据当前页和每页条数动态拼接的,Authorization是从localStorage中获取的 token,作为请求头中的认证信息。
当请求成功返回时,如果状态码为 200,数据将被赋值给exchangeRate对象中的相应字段:rowCountdatapageCount,从而更新表格显示的数据。若请求失败,则通过ElMessage.error提示错误信息。
handleSizeChangehandleCurrentChange是两个分页控制的方法。当用户更改每页条数或当前页时,这两个方法分别更新pageSizecurrentPage的值,并重新调用queryExchangeRate方法以获取新的数据。
最后,formatDate方法用于格式化日期,接收四个参数:rowcolumncellValueindex,其中cellValue是需要格式化的日期,使用dayjs(cellValue).format('YYYY-MM-DD')将日期格式化为 “YYYY-MM-DD” 形式,并返回。

三、总结

这篇文章介绍了如何在孢子记账项目中实现主币种设置功能。首先,文章通过展示一个原型图,明确了功能需求,包括显示和设置主币种以及查看汇率信息。接着,文章详细介绍了三大组件的实现:面包屑导航、主币种显示与设置、以及汇率表。在实现主币种设置时,利用了 Element Plus 的el-breadcrumb组件实现了面包屑导航,帮助用户定位当前页面;el-formel-select用于展示和编辑主币种,通过简单的表单和下拉框让用户进行币种选择和修改;而汇率表则通过el-tableel-pagination结合使用,展示汇率数据并支持分页显示。
本文详细讲解了每个组件的使用方法,并通过代码示例展示了如何将这些功能整合到一个实际的应用中。通过这些步骤,开发者可以轻松实现类似的设置功能,并满足用户对汇率显示和币种管理的需求。


http://www.kler.cn/a/530715.html

相关文章:

  • FLTK - FLTK1.4.1 - demo - bitmap
  • 传输层协议 UDP 与 TCP
  • Spring Boot - 数据库集成06 - 集成ElasticSearch
  • AI大模型开发原理篇-5:循环神经网络RNN
  • 【Block总结】完全注意力Fully Attentional,同时捕捉空间和通道的注意力|即插即用
  • Visual Studio Code应用本地部署的deepseek
  • 强化学习、深度学习、深度强化学习的区别是什么?
  • PySPARK带多组参数和标签的SparkSQL批量数据导出到S3的程序
  • Unity Shader Graph 2D - 跳动的火焰
  • 大语言模型深度研究功能:人类认知与创新的新范式
  • Pyside6异步通信测试
  • Java设计模式:行为型模式→状态模式
  • 【R语言】R语言安装包的相关操作
  • Linux第105步_基于SiI9022A芯片的RGB转HDMI实验
  • 体系自适应的物联网漏洞挖掘系统研究背景及意义:物联网漏洞挖掘概述之物联网漏洞现状及问题
  • Python网络自动化运维---批量登录设备
  • 自然语言生成(NLG)算法模型评估方案的硬件配置、系统架构设计、软件技术栈、实现流程和关键代码
  • 【router路由的配置】
  • FPGA学习篇——开篇之作
  • Linux系统之whereis命令的基本使用
  • IM 即时通讯系统-47-beardlessCat IM 使用netty开发分布式Im,提供分布netty集群解决方案
  • 【Excel笔记_5】 LET 函数中数据范围不连续的处理方法
  • [漏洞篇]SQL注入漏洞详解
  • 开屏广告-跳过神器
  • Linux中基于RPM安装YUM的另一种方式
  • 自定义数据集 使用scikit-learn中svm的包实现svm分类