家政维修平台实战:08搭建服务分类
目录
- 1 创建应用
- 2 搭建页面
- 3 配置服务分类
- 4 配置图片上传
- 4.1 搭建云函数
- 4.2 前端调用
- 最终的效果
现在我们已经完成了用户的注册、修改、添加地址的功能,接着我们就可以开发业务板块了。在小程序端用户可以浏览服务、下单、支付、评价等操作,首先就是要提供后台功能可以添加服务分类和服务内容。
1 创建应用
后台功能我们也可以创建一个空白应用,类别我们选择管理应用
2 搭建页面
点击页面设计,创建我们的功能页面
在前述章节中我们已经创建了我们的表结构,管理后台就是要根据数据表来自动生成我们的页面,在低代码中叫模型驱动开发
我们已经创建了服务分类表
和服务项目表
点击创建页面的图标,选择表格与表单模板,根据表来生成页面
页面添加后需要搭建一下左侧导航菜单,切换到布局设计
点击根据页面自动配置菜单的功能
只保留服务分类列表
修改一下菜单的图标和名称
按照上述步骤设置一下服务项目的页面以及菜单
3 配置服务分类
页面设置好了之后,我们就需要对表格的功能进行相关配置。首先配置表格的查询条件,选中表格,设置筛选器
勾选分类名称和分类状态
4 配置图片上传
我们现在如果默认上传的话会上传到微搭自己的云存储里,如果要在多维表格里看的话是看不了的。为了跨平台可以访问,我们需要集成一下TOS,通过对象存储设置公开访问来解决这个问题。
先要修改一下默认的分类图标的上传功能,打开新建页面,添加图片上传组件
如果使用默认的方式,可以看到图片上传完毕是云存储自己的一个路径,这种路径在互联网是访问不到的。我们的思路是调用它自己的上传前处理函数,先上传到云存储,然后把返回的互联网地址传给自己建的云函数调用TOS的上传方法进行上传。
4.1 搭建云函数
创建一个云函数
输入函数的名称
建好之后从列表进入
配置需要的环境变量
这几个主要是TOS需要的,不同厂家的COS需要的参数是不一样的
我用的是火山引擎的,可以从API密钥这进行配置
官方建议你是通过子账号来配置
我设置了TOS相关的权限
并配置了密钥
这些配置好之后你就可以创建你的存储桶了
在存储桶概览里可以找到我们程序需要的各种信息
完成了环境变量的配置之后就可以切换到函数代码编写具体的代码了
完整的代码
'use strict';
const { ACLType,TosClient } = require('@volcengine/tos-sdk');
const axios = require('axios'); // 导入 axios
// 创建客户端
const tosClient = new TosClient({accessKeyId: process.env.TOS_ACCESS_KEY_ID, accessKeySecret: process.env.TOS_SECRET_ACCESS_KEY, region: "cn-beijing", // 填写 Bucket 所在地域。以华北2(北京)为例,"Provide your region" 填写为 cn-beijing。endpoint: "", // 填写域名地址
});
const VOLCENGINE_TOS_CDN_HOST = ""
exports.main = async (event, context) => {console.log('中转云函数被调用,Event:', JSON.stringify(event, null, 2));// 从 event 中获取前端传递的数据const { tcbCosUrl, originalFileName, originalFileType } = event;console.log("TOS Client:", tosClient); // 打印 tosClient 对象if (!tcbCosUrl || !originalFileName || !originalFileType) {return {code: -1,message: 'Missing tcbCosUrl, originalFileName, or originalFileType.',};}try {// 1. 从腾讯云 COS 的 URL 下载文件内容 (使用 axios)console.log(`正在从 ${tcbCosUrl} 下载文件...`);const response = await axios.get(tcbCosUrl, {responseType: 'arraybuffer', // 关键:指定响应类型为二进制数据});// axios 下载成功后,数据在 response.data 中,且已经是 Buffer 格式const fileBuffer = Buffer.from(response.data); console.log(`文件下载完成,大小: ${fileBuffer.length} bytes`);// 2. 构造上传到 TOS 的对象 Key (确保唯一性)// 修正语法错误,使用反引号 ` ` 进行模板字符串拼接const tosObjectKey = `images/${Date.now()}_${Math.random().toString(36).substring(2, 15)}_${originalFileName}`;// 3. 上传文件到火山引擎 TOSconsole.log(`正在上传 ${tosObjectKey} 到 TOS...`);const putObjectResult = await tosClient.putObject({bucket: " ",key: tosObjectKey,body: fileBuffer, // 使用下载到的 fileBufferheaders: {'Content-Type': originalFileType, // 使用原始文件类型},acl: ACLType.ACLPublicRead,});console.log(`文件成功上传到 TOS. ETag: ${putObjectResult.Etag}`);// 4. 构造最终的下载 URLconst tosDownloadUrl = VOLCENGINE_TOS_CDN_HOST ?`${VOLCENGINE_TOS_CDN_HOST}/${tosObjectKey}` :`https://${VOLCENGINE_TOS_BUCKET_NAME}.tos-${VOLCENGINE_TOS_REGION}.volces.com/${tosObjectKey}`;console.log(`最终TOS地址: ${tosDownloadUrl}`);// (可选) 成功上传到 TOS 后,可以在这里尝试删除 COS 中的原文件// ... (删除COS文件部分,如果您需要,请取消注释并确保配置相关权限和SDK) ...return {code: 0,message: 'File transferred to TOS successfully',tosDownloadUrl: tosDownloadUrl, // 确保返回 tosDownloadUrl};} catch (error) {console.error('处理文件或上传到TOS失败:', error);// 捕获 axios 错误,提供更详细信息if (axios.isAxiosError(error)) {console.error('Axios Error Details:', error.response ? error.response.data : error.message);}return {code: -1,message: `文件处理失败: ${error.message || '未知错误'}`,};}
};
4.2 前端调用
云函数编写完毕后就可以在前端调用,前端的代码
async (result) => {console.log('beforeUpload', result);const file = result.files[0]; if (!file) {console.log('请选择图片'); return false;}// 1. 生成唯一的云存储路径,建议加上日期或用户ID等,保持原始文件名// 避免所有文件都覆盖 ttt/abc.jpg,保持原始文件名并增加唯一性const cloudPath = `uploads/${Date.now()}_${Math.random().toString(36).substring(2, 15)}_${file.name}`;let tcbCosUrl = ''; // 存储从腾讯云COS得到的URLtry {const tcb = await $w.cloud.getCloudInstance();const uploadRes = await tcb.uploadFile({cloudPath: cloudPath, // 使用唯一的云存储路径filePath: file // result.files[0] 就是 File 或 Blob 对象});tcbCosUrl = uploadRes.download_url; // 腾讯云COS返回的带签名的URLconsole.log('文件已上传到腾讯云COS:', tcbCosUrl);} catch (error) {console.error('上传到腾讯云COS失败:', error);$w.showToast({ content: `文件上传失败到腾讯云COS: ${error.message || '未知错误'}` }); return false;}// 2. 调用内部云函数,将腾讯云COS的URL传递给它// !!! 替换为你的云函数名称,例如 "upload" !!!const cloudFunctionName = 'upload'; try {const callFunctionRes = await $w.cloud.callFunction({name: cloudFunctionName,data: {tcbCosUrl: tcbCosUrl, // 腾讯云COS的下载URLoriginalFileName: file.name, // 原始文件名originalFileType: file.type // 原始文件类型},});// 假设云函数返回的结果在 res.result 中const data = callFunctionRes.result; if (data && data.code === 0 && data.tosDownloadUrl) {console.log('文件成功中转到TOS,TOS 地址:', data.tosDownloadUrl);$w.uploadImage1.setValue({ value: [data.tosDownloadUrl] }); // 将得到的TOS地址设置到图片上传组件中return false; // 中止上传} else {console.error('中转云函数返回错误:', data);$w.showToast({ content: `文件处理失败: ${data ? (data.message || '未知错误') : '云函数无返回'}` });return false;}} catch (error) {console.error('调用中转云函数时发生错误:', error);$w.showToast({ content: `调用云函数失败: ${error.message || '未知错误'}` }); return false; }
};
我们这个方法先用微搭的云存储做了一次中转,然后进入到我们的TOS中
保存的时候报了一个错
这是因为图片上传组件的返回值是一个数组,我们修改一下我们的表结构,改成数组
最终的效果
当点击新建,上传图片的时候,可以看到图片正常显示了
而且我们的TOS的存储桶里也有了图片
在数据库中,我们也看到了正确的http的地址
有了这个公开访问的地址的时候,再和多维表格集成我们就不需要考虑太多图片传递的问题,使用起来就比较方便了