【从前端到后端导入excel文件实现批量导入-笔记模仿芋道源码的《系统管理-用户管理-导入-批量导入》】
批量导入预约数据-笔记
- 前端
- 场馆列表
- 后端
前端
场馆列表
该列表进入出现的是这样的,这儿是列表操作
<el-table-column label="操作" align="center" width="220px"><template #default="scope"><el-buttonlinktype="primary"@click="openForm('update', scope.row.id, scope.row.name)"v-hasPermi="['sports:venue:update']">编辑</el-button><el-buttonlinktype="primary"@click="openImportForm('update', scope.row.id, scope.row.name, scope.row.capacity)"v-hasPermi="['sports:venue:update']">批量导入预约</el-button><el-buttonlinktype="danger"@click="handleDelete(scope.row.id)"v-hasPermi="['sports:venue:delete']">删除</el-button></template></el-table-column>
批量导入操作在这儿
<el-buttonlinktype="primary"@click="openImportForm('update', scope.row.id, scope.row.name, scope.row.capacity)"v-hasPermi="['sports:venue:update']">批量导入预约</el-button>
<!-- 批量导入 --><UserImportForm ref="importFormRef" @success="getList" />import UserImportForm from './UserImportForm.vue'// 批量导入const importFormRef = ref()const openImportForm = (type: string, id?: number, name?: string, capacity: number) => {if (!importFormRef.value) {console.error('importFormRef 未正确绑定')return}importFormRef.value.open(type, id, name)
}
这是导入的弹窗
<template><Dialog v-model="dialogVisible" title="批量导入场馆预约" width="480"><el-form-item class="form-item"><el-date-pickerv-model="bookingDates"type="date"value-format="YYYY-MM-DD"placeholder="请选择预约的日期":disabled-date="disabledDate":clearable="true"class="custom-date-picker"/></el-form-item><el-uploadref="uploadRef"v-model:file-list="fileList":action="importUrl":auto-upload="false":disabled="formLoading":headers="uploadHeaders":limit="1":on-error="submitFormError":on-exceed="handleExceed":on-success="submitFormSuccess"accept=".xlsx, .xls"dragclass="upload-area"><Icon icon="ep:upload" /><div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div><template #tip><div class="el-upload__tip text-center"><span>仅允许导入 xls、xlsx 格式文件。</span><el-link:underline="false"style="font-size: 12px; vertical-align: baseline"type="primary"@click="importTemplate">下载模板</el-link></div></template></el-upload><template #footer><el-button :disabled="formLoading" type="primary" @click="submitForm" class="submit-button">确 定</el-button><el-button @click="dialogVisible = false" class="cancel-button">取 消</el-button></template></Dialog>
</template><script lang="ts" setup>
import { ref, nextTick, defineExpose } from 'vue'
import axios from 'axios'
import { getAccessToken, getTenantId } from '@/utils/auth'
import * as VenueBookingApi from '@/api/sports/venuebooking'
import download from '@/utils/download'
import { getUserProfile } from '@/api/system/user/profile'
defineOptions({ name: 'VenueBookingImportForm' })const message = useMessage()const dialogVisible = ref(false)
const formLoading = ref(false)
const uploadRef = ref()
const importUrl =import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/sports/venue-booking/import'
const uploadHeaders = ref()
const fileList = ref([])
const updateSupport = ref(0)
const bookingDates = ref([]) // 日期范围
const venueId = ref(null) // 用于存储场馆ID
const venueName = ref('') // 用于存储场馆名称// 用于打开导入对话框并传入参数
const open = (type: string, id: number, name: string) => {dialogVisible.value = truevenueId.value = id // 设置 venueIdvenueName.value = name // 设置 venueNameupdateSupport.value = 0fileList.value = []bookingDates.value = [] // 重置日期范围resetForm()
}defineExpose({ open })// 限制选择日期的函数(例如,不能选择过去的日期)
const disabledDate = (date: Date) => {return date.getTime() < Date.now() // 禁止选择过去的日期
}// 提交表单
const submitForm = async () => {if (!validateForm()) returnuploadHeaders.value = {Authorization: 'Bearer ' + getAccessToken(),'tenant-id': getTenantId()}formLoading.value = true// 创建 FormData 对象,包含文件和其他参数const formData = new FormData()formData.append('file', fileList.value[0].raw)formData.append('venueId', venueId.value) // 场馆 IDformData.append('venueName', venueName.value) // 场馆名称formData.append('bookingTime', bookingDates.value) // 预约日期formData.append('updateSupport', updateSupport.value ? 'true' : 'false')// 获取用户资料并添加到 formData 中// 发起请求try {const res = await getUserProfile(); // 假设 getUserProfile 是异步函数formData.append('agent', res.nickname); // 将 nickname 作为 agent 添加到 FormData 中formData.append('agentId', res.id);const response = await axios.post(importUrl, formData, {headers: uploadHeaders.value})// 检查接口返回的 response 格式,如果是包含 code 的结构if (response.data && response.data.code === 0) {// 上传成功message.alertSuccess('批量导入成功!!')submitFormSuccess(response.data)} else {// 上传失败,显示错误信息submitFormError(response.data)}} catch (error) {submitFormError(error) // 请求失败}
}// 失败回调
const submitFormError = (error: any): void => {if (error && error.msg) {message.error(error.msg || '上传失败,请重新上传!')} else {message.error('上传失败,请重新上传!')}formLoading.value = false
}// 成功回调
const submitFormSuccess = (response: any) => {if (response.code !== 0) {message.error(response.msg || '上传失败')formLoading.value = falsereturn}// 完成后恢复状态formLoading.value = falsedialogVisible.value = false
}// 重置表单
const resetForm = async (): Promise<void> => {formLoading.value = falseawait nextTick()uploadRef.value?.clearFiles()
}// 处理文件超出限制
const handleExceed = (): void => {message.error('最多只能上传一个文件!')
}// 下载模板
const importTemplate = async () => {const res = await VenueBookingApi.importUserTemplate()download.excel(res, '用户导入模版.xls')
}// 验证表单输入
const validateForm = () => {if (!fileList.value.length) {message.error('请上传文件')return false}if (!bookingDates.value || bookingDates.value.length === 0) {message.error('请先选择预约日期')return false}return true
}
</script><style scoped>
.form-item {margin-left: 110px;
}
</style>
// 下载用户导入模板
export const importUserTemplate = () => {return request.download({ url: '/sports/venue-booking/get-import-template' })
}
下载用户模板插件
const download0 = (data: Blob, fileName: string, mineType: string) => {// 创建 blobconst blob = new Blob([data], { type: mineType })// 创建 href 超链接,点击进行下载window.URL = window.URL || window.webkitURLconst href = URL.createObjectURL(blob)const downA = document.createElement('a')downA.href = hrefdownA.download = fileNamedownA.click()// 销毁超连接window.URL.revokeObjectURL(href)
}const download = {// 下载 Excel 方法excel: (data: Blob, fileName: string) => {download0(data, fileName, 'application/vnd.ms-excel')},// 下载 Word 方法word: (data: Blob, fileName: string) => {download0(data, fileName, 'application/msword')},// 下载 Zip 方法zip: (data: Blob, fileName: string) => {download0(data, fileName, 'application/zip')},// 下载 Html 方法html: (data: Blob, fileName: string) => {download0(data, fileName, 'text/html')},// 下载 Markdown 方法markdown: (data: Blob, fileName: string) => {download0(data, fileName, 'text/markdown')},// 下载图片(允许跨域)image: ({url,canvasWidth,canvasHeight,drawWithImageSize = true}: {url: stringcanvasWidth?: number // 指定画布宽度canvasHeight?: number // 指定画布高度drawWithImageSize?: boolean // 将图片绘制在画布上时带上图片的宽高值, 默认是要带上的}) => {const image = new Image()// image.setAttribute('crossOrigin', 'anonymous')image.src = urlimage.onload = () => {const canvas = document.createElement('canvas')canvas.width = canvasWidth || image.widthcanvas.height = canvasHeight || image.heightconst ctx = canvas.getContext('2d') as CanvasRenderingContext2Dctx?.clearRect(0, 0, canvas.width, canvas.height)if (drawWithImageSize) {ctx.drawImage(image, 0, 0, image.width, image.height)} else {ctx.drawImage(image, 0, 0)}const url = canvas.toDataURL('image/png')const a = document.createElement('a')a.href = urla.download = 'image.png'a.click()}}
}export default download
后端
用户模板下载
@GetMapping("/get-import-template")@Operation(summary = "获得导入用户模板")public void importTemplate(HttpServletResponse response) throws IOException {// 手动创建导出 demoList<UserImportDemoExcelVO> list = Arrays.asList(UserImportDemoExcelVO.builder().registrant("张三").phone("15601691300").idCard("522324198805060010").build());// 输出ExcelUtils.write(response, "预约用户导入模板.xls", "预约用户列表", UserImportDemoExcelVO.class, list);}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = false) // 设置 chain = false,避免用户导入有问题
public class UserImportDemoExcelVO {// @ExcelProperty("场馆id")
// private Long venueId;
//
// @ExcelProperty("场馆名称")
// private String venueName;@ExcelProperty("预定人姓名")private String registrant;@ExcelProperty("预定人联系方式")private String phone;@ExcelProperty("预定人身份证号")private String idCard;// @ExcelProperty("预约时间")
// private LocalDateTime bookingTime;}
导入模板
@PostMapping("/import")@Operation(summary = "导入场馆预约数据")@Parameters({@Parameter(name = "file", description = "Excel 文件", required = true),@Parameter(name = "venueId", description = "场馆 ID", required = true),@Parameter(name = "venueName", description = "场馆名称", required = true),@Parameter(name = "bookingTime", description = "预约时间", required = true),@Parameter(name = "agent", description = "代理预约人", required = true),@Parameter(name = "agentId", description = "代理id", required = true),@Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "false")})@PreAuthorize("@ss.hasPermission('sports:venue:booking:import')")public CommonResult<VenueBookingRespVO> importExcel(@RequestParam("file") MultipartFile file,@RequestParam("venueId") Long venueId,@RequestParam("agentId") Long agentId,@RequestParam("venueName") String venueName,@RequestParam("bookingTime") String bookingTime,@RequestParam("agent") String agent,@RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception {// 解析 Excel 文件为对象列表List<UserImportExcelVO> list = ExcelUtils.read(file, UserImportExcelVO.class);// 调用 service 层进行导入,获取导入结果CommonResult<VenueBookingRespVO> result = venueBookingService.importVenueBookingList(list, venueId, venueName,agent,agentId, bookingTime, updateSupport);// 返回服务层的响应return result;}
@Schema(description = "管理后台 - 观赛预约记录 Response VO")
@Data
@ExcelIgnoreUnannotated
public class VenueBookingRespVO {@ExcelProperty("代理预定人id")private Long id;@Schema(description = "预定人")@ExcelProperty("预定人")private String registrant;@Schema(description = "预定人")@ExcelProperty("代理预定人")private String agent;@Schema(description = "代理预定人id", example = "19070")@ExcelProperty("代理预定人id")private Long agentId;@Schema(description = "预定人员电话号码")@ExcelProperty("预定人员电话号码")private String phone;@Schema(description = "预定人员身份证")@ExcelProperty("预定人员身份证")private String idCard;@Schema(description = "预约时间")@ExcelProperty("预约时间")private LocalDateTime bookingTime;@Schema(description = "场馆id", example = "19070")@ExcelProperty("场馆id")private Long venueId;@Schema(description = "场馆名称")@ExcelProperty("场馆名称")private String venueName;@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)@ExcelProperty("创建时间")private LocalDateTime createTime;private String message;// 带有多个字段的构造方法public VenueBookingRespVO(String message, String registrant, String phone, String idCard,LocalDateTime bookingTime, Long venueId, String venueName, LocalDateTime createTime) {this.message = message;this.registrant = registrant;this.phone = phone;this.idCard = idCard;this.bookingTime = bookingTime;this.venueId = venueId;this.venueName = venueName;this.createTime = createTime;}}
/*** 用户 Excel 导入 VO*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = false) // 设置 chain = false,避免用户导入有问题
public class UserImportExcelVO {@ExcelProperty("场馆id")private Long venueId;@ExcelProperty("场馆名称")private String venueName;@ExcelProperty("预定人姓名")private String registrant;@ExcelProperty("预定人联系方式")private String phone;@ExcelProperty("预定人身份证号")private String idCard;@ExcelProperty("预约时间")private LocalDateTime bookingTime;}
@Override@Transactional(rollbackFor = Exception.class)public CommonResult<VenueBookingRespVO> importVenueBookingList(List<UserImportExcelVO> list, Long venueId, String venueName, String agent, Long agentId, String bookingTime, Boolean updateSupport) {if (list == null || list.isEmpty()) {return CommonResult.error(400, "导入的数据不能为空!");}List<String> errorMessages = new ArrayList<>();LocalDateTime bookingDateTime = LocalDateTime.parse(bookingTime + "T00:00:00");// 身份证号和手机号验证正则表达式String idCardRegex = "^[1-9]\\d{5}(?:18|19|20)\\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\\d|30|31)\\d{3}[\\dXx]$";Pattern idCardPattern = Pattern.compile(idCardRegex);String phoneRegex = "^1[3-9]\\d{9}$";Pattern phonePattern = Pattern.compile(phoneRegex);List<VenueBookingDO> venueBookingList = new ArrayList<>();Set<String> idCardSet = new HashSet<>(); // 用于存储已存在的身份证号,查重for (int i = 0; i < list.size(); i++) {UserImportExcelVO excelVO = list.get(i);errorMessages.clear(); // 清空错误信息列表// 验证身份证号格式Matcher idCardMatcher = idCardPattern.matcher(excelVO.getIdCard());if (!idCardMatcher.matches()) {errorMessages.add("第" + (i + 1) + "条记录:身份证号格式不正确");}// 验证手机号格式Matcher phoneMatcher = phonePattern.matcher(excelVO.getPhone());if (!phoneMatcher.matches()) {errorMessages.add("第" + (i + 1) + "条记录:手机号格式不正确");}// 检查身份证号是否重复if (idCardSet.contains(excelVO.getIdCard())) {errorMessages.add("第" + (i + 1) + "条记录:身份数据重复");} else {idCardSet.add(excelVO.getIdCard()); // 加入已存在身份证号集合}// 如果有错误,返回错误信息并终止插入if (!errorMessages.isEmpty()) {return CommonResult.error(400, String.join(",", errorMessages)); // 使用 error 方法返回错误信息}// 对身份证号进行加密处理String encryptedIdCard = Sm2Util.signMd5(excelVO.getIdCard());excelVO.setVenueId(venueId);excelVO.setVenueName(venueName);excelVO.setBookingTime(bookingDateTime);excelVO.setIdCard(encryptedIdCard);VenueBookingDO venueBookingDO = new VenueBookingDO();venueBookingDO.setVenueId(excelVO.getVenueId());venueBookingDO.setVenueName(excelVO.getVenueName());venueBookingDO.setBookingTime(excelVO.getBookingTime());venueBookingDO.setIdCard(excelVO.getIdCard()); // 设置加密后的身份证号venueBookingDO.setPhone(excelVO.getPhone());venueBookingDO.setRegistrant(excelVO.getRegistrant());venueBookingDO.setAgent(agent);venueBookingDO.setAgentId(agentId);venueBookingDO.setBookingStatus(0);venueBookingList.add(venueBookingDO);}// 批量插入数据if (!venueBookingList.isEmpty()) {venueBookingMapper.insertBatch(venueBookingList);}// 返回成功的响应,填充所有字段return CommonResult.success(new VenueBookingRespVO("导入成功", "registrantData", "12345678901", "123456789012345678", bookingDateTime, venueId, venueName, LocalDateTime.now()));}
相关文章:
【从前端到后端导入excel文件实现批量导入-笔记模仿芋道源码的《系统管理-用户管理-导入-批量导入》】
批量导入预约数据-笔记 前端场馆列表后端 前端 场馆列表 该列表进入出现的是这样的,这儿是列表操作 <el-table-column label"操作" align"center" width"220px"><template #default"scope"><el-buttonlinktype"…...

LabVIEW音频测试分析
LabVIEW通过读取指定WAV 文件,实现对音频信号的播放、多维度测量分析功能,为音频设备研发、声学研究及质量检测提供专业工具支持。 主要功能 文件读取与播放:支持持续读取示例数据文件夹内的 WAV 文件,可实时播放音频以监听被测信…...
MySQL 8.0 绿色版安装和配置过程
MySQL作为云计算时代,被广泛使用的一款数据库,他的安装方式有很多种,有yum安装、rpm安装、二进制文件安装,当然也有本文提到的绿色版安装,因绿色版与系统无关,且可快速复制生成,具有较强的优势。…...

RoseMirrorHA 双机热备全解析
在数字化时代,企业核心业务系统一旦瘫痪,每分钟可能造成数万甚至数十万的损失。想象一下,如果银行的交易系统突然中断,或者医院的挂号系统无法访问,会引发怎样的连锁反应?为了守护这些关键业务,…...

day 18进行聚类,进而推断出每个簇的实际含义
浙大疏锦行 对聚类的结果根据具体的特征进行解释,进而推断出每个簇的实际含义 两种思路: 你最开始聚类的时候,就选择了你想最后用来确定簇含义的特征, 最开始用全部特征来聚类,把其余特征作为 x,聚类得到…...
pandas 字符串存储技术演进:从 object 到 PyArrow 的十年历程
文章目录 1. 引言2. 阶段1:原始时代(pandas 1.0前)3. 阶段2:Python-backed StringDtype(pandas 1.0 - 1.3)4. 阶段3:PyArrow初次尝试(pandas 1.3 - 2.1)5. 阶段4…...

LLMs 系列科普文(6)
截止到目前,我们从模型预训练阶段的数据准备讲起,谈到了 Tokenizer、模型的结构、模型的训练,基础模型、预训练阶段、后训练阶段等,这里存在大量的术语或名词,也有一些奇奇怪怪或者说是看起来乱七八糟的内容。这期间跳…...
exp1_code
#include <iostream> using namespace std; // 链栈节点结构 struct StackNode { int data; StackNode* next; StackNode(int val) : data(val), next(nullptr) {} }; // 顺序栈实现 class SeqStack { private: int* data; int top; int capac…...

serv00 ssh登录保活脚本-邮件通知版
适用于自己有服务器情况,ssh定时登录到serv00,并在登录成功后发送邮件通知 msmtp 和 mutt安装 需要安装msmtp 和 mutt这两个邮件客户端并配置,参考如下文章前几步是讲配置这俩客户端的,很简单,不再赘述 用Shell脚本实…...

意识上传伦理前夜:我们是否在创造数字奴隶?
当韩国财阀将“数字永生”标价1亿美元准入权时,联合国预警的“神经种姓制度”正从科幻步入现实。某脑机接口公司用户协议中“上传意识衍生算法归公司所有”的隐藏条款,恰似德里达预言的当代印证:“当意识沦为可交易数据流,主体性便…...

【AIGC】RAGAS评估原理及实践
【AIGC】RAGAS评估原理及实践 (1)准备评估数据集(2)开始评估2.1 加载数据集2.2 评估忠实性2.3 评估答案相关性2.4 上下文精度2.5 上下文召回率2.6 计算上下文实体召回率 RAGas(RAG Assessment)RAG 评估的缩写ÿ…...

ESP12E/F 参数对比
模式GPIO0GPIO2GPIO15描述正常启动高高低从闪存运行固件闪光模式低高低启用固件刷写 PinNameFunction1RSTReset (Active Low)2ADC (A0)Analog Input (0–1V)3EN (CH_PD)Chip Enable (Pull High for Normal Operation)4GPIO16Wake from Deep Sleep, General Purpose I/O5GPIO14S…...

第二十八章 字符串与数字
第二十八章 字符串与数字 计算机程序完全就是和数据打交道。很多编程问题需要使用字符串和数字这种更小的数据来解决。 参数扩展 第七章,已经接触过参数扩展,但未进行详细说明,大多数参数扩展并不用于命令行,而是出现在脚本文件中。 如果没有什么特殊原因,把参数扩展放…...

[RDK X5] MJPG编解码开发实战:从官方API到OpenWanderary库的C++/Python实现
业余时间一直在基于RDK X5搞一些小研究,需要基于高分辨率图像检测目标。实际落地时,在图像采集上遇到了个大坑。首先,考虑到可行性,我挑选了一个性价比最高的百元内摄像头,已确定可以在X5上使用,接下来就开…...
java复习 05
我的天啊一天又要过去了,没事的还有时间!!! 不要焦虑不要焦虑,事实证明只要我认真地投入进去一切都还是来得及的,代码多实操多复盘,别叽叽喳喳胡思乱想多多思考,有迷茫前害怕后的功…...

aardio 简单网页自动化
WebView自动化,以前每次重复做网页登录、搜索这些操作时都觉得好麻烦,现在终于能让程序替我干活了,赶紧记录下这个超实用的技能! 一、初次接触WebView WebView自动化就像给程序装了个"网页浏览器",第一步得…...

打卡第39天:Dataset 和 Dataloader类
知识点回顾: 1.Dataset类的__getitem__和__len__方法(本质是python的特殊方法) 2.Dataloader类 3.minist手写数据集的了解 作业:了解下cifar数据集,尝试获取其中一张图片 import torch import torch.nn as nn import…...
【评测】Qwen3-Embedding模型初体验
每一篇文章前后都增加返回目录 回到目录 【评测】Qwen3-Embedding模型初体验 模型的介绍页面 本机配置:八代i5-8265U,16G内存,无GPU核显运行,win10操作系统 ollama可以通过下面命令拉取模型: ollama pull modelscope…...
BeanFactory 和 FactoryBean 有何区别与联系?
导语: Spring 是后端面试中的“常青树”,而 BeanFactory 与 FactoryBean 的关系更是高频卡人点。很多候选人混淆两者概念,答非所问,轻则失分,重则直接被“pass”。本文将从面试官视角,深入剖析这一经典问题…...

如何做好一份优秀的技术文档:专业指南与最佳实践
如何做好一份优秀的技术文档:专业指南与最佳实践 技术文档是产品开发、用户支持和团队协作的核心工具。高质量的技术文档能够提升开发效率、降低维护成本并改善用户体验。本文将从实践出发,详细讲解如何编写专业、清晰且实用的技术文档。 🌟…...
C语言内存管理和编译优化实战
参考: C语言内存管理“玄学”:从崩溃到精通的避坑指南C语言编译优化实战:从入门到进阶的高效代码优化技巧...

TCP相关问题 第一篇
TCP相关问题1 1.TCP主动断开连接方为什么需要等待2MSL 如上图所示:在被动链接方调用close,发送FIN时进入LAST_ACK状态,但未收到主动连接方的ack确认,需要被动连接方重新发送一个FIN,而为什么是2MSL,一般认为丢失ack在…...

6.Pandas 数据可视化图-1
第三章 数据可视化 文章目录 目录 第三章 数据可视化 文章目录 前言 一、数据可视化 二、使用步骤 1.pyplot 1.1引入库 1.2 设置汉字字体 1.3 数据准备 1.4 设置索引列 编辑 1.5 调用绘图函数 2.使用seaborn绘图 2.1 安装导入seaborn 2.2 设置背景风格 2.3 调用绘图方法 2.…...

软件功能测试报告都包含哪些内容?
软件功能测试报告是软件开发生命周期中的重要文档,主要涵盖以下关键内容: 1.测试概况:概述测试目标、范围和方法,确保读者对测试背景有清晰了解。 2.测试环境:详细描述测试所用的硬件、软件环境,确保…...

在Vue或React项目中使用Tailwind CSS实现暗黑模式切换:从系统适配到手动控制
在现代Web开发中,暗黑模式(Dark Mode)已成为提升用户体验的重要功能。本文将带你使用Tailwind CSS在React项目(Vue项目类似)中实现两种暗黑模式控制方式: 系统自动适配 - 根据用户设备偏好自动切换手动切换 - 通过按钮让用户自由选择 一、项目准备 使…...

Linux--命令行参数和环境变量
1.命令行参数 Linux 命令行参数基础 1.1参数格式 位置参数:无符号,按顺序传递(如 ls /home/user 中 /home/user 是位置参数) 选项参数: 短选项:以 - 开头,单个字母(如 -l 表示长格…...
Android 集成 Firebase 指南
Firebase 是 Google 提供的一套移动开发平台,包含分析、认证、数据库、消息推送等多种服务。以下是在 Android 应用中集成 Firebase 的详细步骤: 1. 准备工作 安装 Android Studio - 确保使用最新版本 创建或打开 Android 项目 - 项目需要配置正确的包…...

springboot线上教学平台
摘要:在社会快速发展的影响下,使线上教学平台的管理和运营比过去十年更加理性化。依照这一现实为基础,设计一个快捷而又方便的网上线上教学平台系统是一项十分重要并且有价值的事情。对于传统的线上教学平台控制模型来说,网上线上…...
阿里云 Linux 搭建邮件系统全流程及常见问题解决
阿里云 Linux 搭建 [conkl.com]邮件系统全流程及常见问题解决 目录 阿里云 Linux 搭建 [conkl.com]邮件系统全流程及常见问题解决一、前期准备(关键配置需重点检查)1.1 服务器与域名准备1.2 系统初始化(必做操作) 二、核心组件安装…...
【Elasticsearch】映射:fielddata 详解
映射:fielddata 详解 1.fielddata 是什么2.fielddata 的工作原理3.主要用法3.1 启用 fielddata(通常在 text 字段上)3.2 监控 fielddata 使用情况3.3 清除 fielddata 缓存 4.使用场景示例示例 1:对 text 字段进行聚合示例 2&#…...