• [案例共创] 【案例共创】基于MaaS结合开发者空间Astro低代码平台完成基线核查结果分析系统
    一、概述1. 案例介绍本案例面向网安行业运维人员等,用于分析基线报告的风险等级,筛选需要紧急修复的配置项,降低认为分析的操作误差。通过实际操作,了解如何利用Astro低代码平台开发应用。在这个过程中,学习从模型集成、界面操作、页面布置到逻辑实现以及应用打包一系列关键步骤,从而掌握Astro低代码平台的基本使用方法及于大模型的结合,体验其在应用开发中的优势。开发者空间Astro低代码开发平台通过平台提供的界面、逻辑、对象等可视化编排工具,以“拖、拉、拽”的方式来快速构建应用,从而实现所见即所得的应用开发构建体验。华为开发者空间,是为全球开发者打造的专属开发者空间,致力于为每位开发者提供一台云主机、一套开发工具和云上存储空间,汇聚昇腾、鸿蒙、鲲鹏、GaussDB、欧拉等华为各项根技术的开发工具资源,并提供配套案例指导开发者 从开发编码到应用调测,基于华为根技术生态高效便捷的知识学习、技术体验、应用创新。ModelArts Studio(MaaS)平台:是华为云推出的一款大模型即服务平台,可以一站式的对业界主流开源大模型进行部署托管,同时开放大模型API服务,可以结合业界主流Agent开发框架,轻松构建AI Agent应用。2. 适用对象企业个人开发者高校学生3. 案例时间本案例总时长预计90分钟。4. 案例流程说明:领取华为开发者空间,登录华为开发者空间-低代码应用开发平台;新建低代码应用,进入Astro轻应用服务控制台主页,开发应用;5. 资源总览本案例预计花费0元。资源名称规格单价(元)时长(分钟)MaaS 平台商用模型DeepSeek-R1 轻量体验包(¥7.00)/ DeepSeek-V3 轻量体验包(¥3.50)领券免费90华为开发者空间 - 低代码应用开发平台系统标配免费90二、案例准备1、开通ModelArts Studio(MaaS)商用百万Token活动连接:每周畅领100万商用级Tokens!基于CloudMatrix384超节点,Token时延低、TPM/RPM速率高,助您开发商用级AI应用!商用百万Token代金券免费领取链接(可每周领取):DeepSeek-R1/V3-64K百万tokens代金券:cid:link_22.1、大模型领取:切换到开发者空间首页,或者点击上面连接,参与活动“百万商用服务tokens免费领!”活动,按照使用说明进行服务开通:活动页面:2.2、开通完成后,进行大模型的接入:ModelArts控制台:ModelArts - Console在线推理里面搜刚刚买的R1还是V3,然后点击搜索结果后面的调用说明,看一下model参数,后面会用上,一般都是DeepSeek-R1或DeepSeek-V3:2.3、创建apikey点击前往API Key管理创建apikey,点击新建创建apikey注意!!创建好API Key之后,点击后面的复制按钮,妥善保存,若未复制保存,后续只能新建。三、华为开发者空间-低代码应用开发平台开发应用登录华为开发者空间,在左侧菜单列表选择华为开发者空间 -> 开发平台 -> Astro 低代码开发,进入华为开发者空间-低代码应用开发平台。 创建应用新建Astro低代码应用,标准应用创建 填写应用必备的属性 创建连接器跳转后选择集成,创建一个大模型连接器: 正确填写模型名称和KEY,我这里购买了R1的资源包,所以填写的R1的模型名称: 保存后点击测试看是否成功调用:  创建OBS连接器:这里前提需要创建一个OBS对象桶并购买对应的资源包,已经生成ak/sk获取ak/sk的方法放上官方链接:cid:link_6创建桶和资源包这个不必说,大家都懂得!下面继续添加桶信息: 创建数据对象新建一个数据对象: 确认后编辑该对象: 新建字段:这里选择文本区,能容纳更多的字段: 继续添加其他字段,我这里只需要用到三个:  创建结构体新建结构体用于数据调用:创建后修改结构体:   创建UI页面随后点击页面->新建页面,输入一些必备信息: 页面这里拖入一个表单进去: 然后点击箭头所向的数据绑定,新建一个模型: 新建一个对象: 下一步配置对象,选择字段:  下一步,自动新增方法:  然后选择模型,确认保存: 这里我选择只绑定模型:   这里拖动一个多行文本框,并输入一些基本属性: 点击数据绑定设置,将当前元素与模型中自建的文本报告字段绑定: 拖动一个上传控件,相同的一些操作,再加个必填的属性:修改属性:    拖动一个提交按钮,不绑定数据:     为了输出直观一点,这里拖动一个md控件,并绑定属性为result报告输出字段:    创建服务编排创建服务编排: 添加赋值与maas连接器  全局上下文添加变量:  配置出入参:  模块赋值:  配置大模型连接器:   配置大模型参数:   然后按顺序点击按钮保存一下:  第三步会打开一个测试页面,可简单测试一下:    编写脚本Obs文件读取脚本至此,开始编写脚本, 首先前面的obs对象已绑定。点击逻辑->脚本,新建一个名称: 这里是为了读取obs的excel文件,然后解析内容。完整代码如下:import * as excel from 'excel';import * as objectstorage from 'objectstorage';@action.object({ type: "param" })export class Input { @action.param({ type: "String", required: true, description: "fileUrl" }) fileUrl: string;}@action.object({ type: "param" })export class Output { @action.param({ type: "Any", description: "result message" }) fileContent: Object;}@action.object({ type: "method" })export class PostProcess { @action.method({ input: "Input", output: "Output" }) public postProcess(input: Input): Output { let ObsCli = objectstorage.newClient(objectstorage.StoreType.OBS, "SecLineCheck__uploadobs", "up-files"); // 连接器名称+桶名 let data = ObsCli.getObject(input.fileUrl);//文件名 let x = excel.decodeAll(data); let out = new Output(); out.fileContent = x; return out; }}然后回到页面,点击按钮,数据绑定: 这一步是为了新建一个模型,用于存数据,但是无需绑定:点击新建模型,选择自定义,继续下一步即可:  然后选择事件,新增脚本:  选择执行脚本,添加输入的文件地址,以及内容输出到指定的数据模型:(这里传入的url地址是表单提交后的CheckData数据模型里面的SecLineCheck__filesUrl字段的originalUrl值,由于环境需要,所以采用的JSON解析传递,想要具体探究的可以选择自定义动作,然后将整个数据模型的表单用控制台打印一下就行。)  流程调用脚本保存完继续新建,自定义脚本,这里就是汇聚文本框和文件内容, 然后调用编排动作去执行分析并返回对应的数据: 完整代码:var model = context.$model.ref("CheckData").getData(); var modelCopy = JSON.parse(JSON.stringify(model)); var model2 = context.$model.ref("excel_result").getData(); var modelCopy2 = JSON.parse(JSON.stringify(model2)); var keys = Object.keys(modelCopy2); console.log(keys); var allSheetValues = []; keys.forEach(key => { if (Array.isArray(modelCopy2[key])) { const sheetArray = modelCopy2[key]; sheetArray.forEach(row => { if (Array.isArray(row)) { allSheetValues.push(...row); } }); } }); var newSheetValues = allSheetValues.join(",") console.log(allSheetValues); // 处理非字符串字段 Object.keys(modelCopy).forEach(item => { if (modelCopy[item] && typeof modelCopy[item] !== "string") { modelCopy[item] = JSON.stringify(modelCopy[item]); } }); // 提取问题字段值 var message = modelCopy["SecLineCheck__text__CST"] // 构建提示文本 var suggestionText = `你是一个精通网络安全的专家,现在已经为甲方单位的服务器做完基线核查,这里是具体的报告,请你根据报告内容分析危险等级,先输出需要紧急修复的配置,再输出风险等级分析,使用MAKEDOWN的格式。这里是我补充的其他文本信息,如果它存在的话:${message}。\n这里是需要处理的报告信息,如果它存在的话:${newSheetValues}`.replace(/"/g, "'"); // 初始化Flow var _flow = context.flow("SecLineCheck__process"); // 调用AI服务获取建议 try { // 提示信息 context.$message.info("正在分析,请稍后..."); const resp = await _flow.run({ input: suggestionText }); const reader = resp.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; let msg = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value); const lines = buffer.split('\n'); // 保留最后一行(可能不完整) buffer = lines.pop() || ''; for (const line of lines) { if (!line.trim()) continue; try { const jsonStr = line.startsWith('data: ') ? line.substring(6) : line; if (jsonStr.trim() === '[DONE]') continue; const obj = JSON.parse(jsonStr); const newMsg = obj?.choices[0]?.delta?.content || ''; if (newMsg) msg += newMsg; } catch (err) { console.warn('解析JSON失败,保留到下一轮处理:', err.message); buffer = line + '\n' + buffer; } } } // 最终保存结果 modelCopy.SecLineCheck__result__CST = msg; context.$model.ref("CheckData").setData(modelCopy); // 提交数据 const saveResult = await context.$model.ref("CheckData").save(); if (saveResult.resCode == 0) { const recordId = saveResult.result[0]?.id; if (recordId) { // context.$page.loadStdPage('xiaocao__t_mass', "recordId=" + recordId); // // 成功消息 // context.$message.success('生成成功'); } } } catch (error) { console.error("AI服务调用失败:", error); // 可以添加错误处理逻辑,如显示错误信息 }至此这个版本的编辑结束,选择保存,预览:   结束预览输出结果:  四、案例分享至此案例结束,案例整体步骤看起来比较多,但实际基本上都是命令的参数相互调用,建议不要使用大小写来重复命令,容易混淆,我已经上过当了。另外通过案例发现该低代码应用场景的处理节点还是比较缺乏的。譬如我这个案例最不好处理的就是附件上传,一开始是直接创建数据对象来存储,但是无法上传,后续就采用OBS存储,但是只返回违反没链接,而大模型不处理链接,所以需要写脚本来解析上传附件到OBS返回的文件链接,然后再与其他的内容进行合并,输送到流程里面进行下一步。这里如果上传支持一些节点调用或者直接返回数据而无需上传的功能就更好使了。另外还有一个问题就是我的案例是基线结果分析,那么提供的检查报告里面肯定会存在一些代码,而这些内容在流程这一块是走不通的,会提示疑似攻击行为,但是直接调用大模型却可以。希望后续能够优化一下。感谢华为云提供的学习平台,让自己能够接触到更多的新鲜东西,仅仅需要付出一些时间成本,而收获良多。希望后续针对该平台优化得更好! 附件分享文章不支持zip上传,放一个百度网盘的地址:链接: https://pan.baidu.com/s/1zUtbbqMp43-2Ljj1PNex6g?pwd=ukfw 提取码: ukfw 复制这段内容后打开百度网盘手机App,操作更方便哦我正在参加【案例共创】第7期 基于MaaS商用服务 + 华为开发者空间 - Astro 低代码开发平台构建低代码应用 cid:link_3
  • [案例共创] 【案例共创】基于华为开发者空间-云开发环境(容器)+MaaS实现 <来刷题吧> - AI试卷生成和测试平台
    案例介绍本项目是基于华为开发者空间云上开发环境部署的<AI试卷生成与在线测试平台>技术实践案例。该应用深度集成华为云MaaS(ModelArts as a Service)平台提供的DeepSeek-V3大语言模型,充分利用平台提供的百万级商用token处理能力,构建了一个能够一键生成任意学科、任意难度的试卷,提供模拟考试环境、自动评分以及智能解析功能的智能试卷生成与在线测试平台。案例内容一、概述1. 案例介绍华为开发者空间,是为全球开发者打造的专属开发者空间,致力于为每位开发者提供一台云主机、一套开发工具和云上存储空间,汇聚昇腾、鸿蒙、鲲鹏、GaussDB、欧拉等华为各项根技术的开发工具资源,并提供配套案例指导开发者从开发编码到应用调测,基于华为根技术生态高效便捷的知识学习、技术体验、应用创新。本项目是华为开发者空间开发平台 - 云开发环境(容器)部署的<AI试卷生成与在线测试平台>技术实践案例。该应用深度集成华为云MaaS(ModelArts as a Service)平台提供的DeepSeek-V3大语言模型,充分利用平台提供的百万级商用token处理能力,构建了一个能够一键生成任意学科、任意难度的试卷,提供模拟考试环境、自动评分以及智能解析功能的智能试卷生成与在线测试平台。<AI试卷生成与在线测试平台>技术架构上,项目采用react+typescript技术栈,基于华为MaaS平台的强大算力支持,实现了智能解析功能的智能试卷生成与在线测试平台。华为MaaS平台不仅提供高质量的DeepSeek-V3模型,更具备百万token的超长上下文处理能力,使得本应用能够生成准确的试题。前端采用React框架构建响应式界面,后端通过封装MaaS平台API,为用户提供刷题、模拟考试、自动评分、智能解析等功能。2. 功能特性AI 智能出题: 输入任意主题(如“Python基础”、“中国近代史”、“驾考科目一”),即刻生成包含单选、多选、判断题的完整试卷。模拟考试: 沉浸式答题界面,配备倒计时功能。自动评分: 考试结束后立即出分,通过可视化图表展示得分详情。错题回顾: 提供复习模式,高亮显示错题,并附带 AI 生成的详细解析。题集功能: 建立错题难题题集,不断复习巩固知识。题集试卷: 根据题集生成试卷,检验你的学习成果。历史记录: 自动保存考试记录与成绩,随时回溯过往练习。云端同步: 支持配置 Huawei Cloud OBS 将考试记录同步至云端。3. 适用对象企业个人开发者高校学生4. 案例时间本案例总时长预计60分钟。5. 案例流程说明:登录华为开发者空间,VS Code安装Huawei Developer Space插件,远程连接操作云开发环境;远程创建、开机、连接云开发环境(虚拟机);领取百万token代金券福利,开通商用模型服务,获取模型API 地址、API Key等参数;GitCode拉取代码 https://gitcode.com/zhepama/ai-exam-platform.git,安装依赖,修改参数;启动程序,在浏览器端测试验证<AI试卷生成与在线测试平台>。5. 资源总览本案例预计花费0元。资源名称规格单价(元)时长(分钟)华为开发者空间开发平台 - 云开发环境(容器)鲲鹏通用计算增强型 kc1 | 2vCPUs | 4G | HCE免费60二、基础环境与资源准备1. VS Code远程连接云开发环境(容器)参考案例《华为开发者空间 - 云开发环境(容器)IDE插件远程连接操作指导》中的“二、云开发环境IDE插件远程连接操作指导”的内容,完成“1. 安装插件” ~ “4. 连接”章节步骤。完成连接之后的状态:2. 领取百万免费token福利参考案例《Versatile Agent中自定义接入大模型配置华为云Maas指导》中的“一、 领取”章节内容,领取华为开发者空间百万token代金券福利,购买ModelArts Studio DeepSeek-V3 轻量体验包(¥3.50)。开通商用模型服务,最后获取API地址、API Key的参数值。三、来刷题吧 - AI试卷生成与在线测试平台1.来刷题吧 - AI试卷生成与在线测试平台功能介绍AI试卷生成与在线测试平台是一个基于DeepSeek大模型的智能聊天应用,提供美观的Web界面和流畅的对话体验。项目采用React + Typescript,结合华为云MaaS平台百万免费商用token,配置DeepSeek-V3大模型。🛠️ 技术栈核心框架: React 19构建工具: ViteUI 样式: Tailwind CSS图标库: Lucide React环境管理: dotenv📂 目录结构server/index.js - 后端服务主入口与路由逻辑src/App.tsx - 前端应用主入口与路由逻辑src/services/geminiService.ts - AI 接口调用与试卷生成逻辑src/services/storageService.ts - 本地存储与云同步逻辑src/components/ - UI 组件库types.ts - TypeScript 类型定义2. 获取来刷题吧 - AI试卷生成与在线测试平台代码新建项目文件在/workspace/node目录下创建ai-exam-platform文件夹。cd /workspace/node mkdir ai-exam-platform cd ai-exam-platform下载代码点击Source Control图标,然后点Initialize Repository。点CHANGES右侧的 ··· 图标,在下拉菜单中选择Clone。输入代码仓地址,Clone from URL: https://gitcode.com/zhepama/ai-exam-platform.git选择代码仓目录:/workspace/ai-exam-platform/,点Select as Repository Destination。然后点Open,将此目录设置为本地代码仓。加载结束后的状态如下:3. 安装项目依赖安装项目依赖npm install2. 修改配置文件,配置API Key在项目根目录下创建一个 .env 文件,参考 .env.example 进行配置:cp .env.example .env打开配置文件.env,修改配置参数。将配置文件中的your_API_Key替换为“二、基础环境与资源准备”章中的“4. 领取百万免费福利”节最后获取到的API Key。配置项说明:变量名必填描述示例API_KEY✅AI 模型的 API 密钥 (Gemini 或 OpenAI)AIzaSy...AI_PROVIDER❌指定 AI 提供商 (gemini 或 openai)openaiAI_MODEL❌指定模型版本deepseek-v3.1AI_BASE_URL❌OpenAI 接口地址 (用于代理)https://api.modelarts-maas.com/v2OBS_SERVER❌连接OBS的服务地址``OBS_ACCESS_KEY_ID❌OBS访问密钥中的AK。``OBS_SECRET_ACCESS_KEY❌OBS访问密钥中的SK。``OBS_BUCKET❌OBS的bucker``JUDGE_COUNT❌判断题数量。5SINGLE_CHOICE_COUNT❌单选题数量。5MULTI_CHOICE_COUNT❌多选题数量5# API配置 # AI Provider Configuration # Options: 'gemini' | 'openai' # Default: 'gemini' AI_PROVIDER=openai # API Key for the selected provider # For Gemini: Get from Google AI Studio # For OpenAI: Get from OpenAI Platform API_KEY=your_API_Key # 替换为你的实际API密钥 # AI Model to use # Default for Gemini: 'gemini-2.5-flash' # Default for OpenAI: 'gpt-3.5-turbo' # You can override this with other models like 'gpt-4', 'gemini-1.5-pro', etc. AI_MODEL=deepseek-v3.1 # AI Base URL # Only used if AI_PROVIDER is 'openai' (or compatible services like DeepSeek, Moonshot, etc.) # Default: 'https://api.openai.com/v1' AI_BASE_URL=https://api.modelarts-maas.com/v2 5. 测试体验来刷题吧 - AI试卷生成与在线测试平台在VS Code终端窗口中运行如下命令,启动来刷题吧 - AI试卷生成与在线测试平台。npm run dev:server在VS Code弹出的对话框中点Open in Browser,或者直接在浏览器中打开:http://localhost:3000/输入测试问题:“驾考科目一”,来刷题吧 - AI试卷生成与在线测试平台正确回答。开始答题提交试卷查看错题每一题都会有答案解析数据同步题集功能 (新增)查看题集题集中会随机出题,供你测试点击题目卡片,卡片反转可以查看答案题集试卷根据题目生成试卷生成新的试卷进行测试吧至此,基于华为开发者空间-云开发环境(容器)+MaaS实现来刷题吧 - AI试卷生成与在线测试平台案例结束,各位开发者快来华为开发者空间体验吧。我正在参加【案例共创】【第8期】基于华为开发者空间云开发环境(容器),集成华为云AI服务(Agent或MaaS API),完成AI应用构建开发最佳实践cid:link_6
  • [问题求助] 【求助】Astro适合做一个简易的个人博客吗?
    想问问,想做一个个人博客,所以想问Astro适合吗?
  • [问题求助] VPN启动失败
    strongswan up gw-gw 命令retransmit 5 of request with message ID 0sending packet: from 192.168.0.222[500] to 121.37.54.108[500] (464 bytes)giving up after 5 retransmitsestablishing IKE_SA failed, peer not respondingestablishing connection 'gw-gw' failed
  • [案例共创] 【案例共创】基于MaaS结合Astro平台快速创建景点推荐智能化系统
    案例介绍本案例应用基于MaaS结合Astro平台快速创建景点推荐智能化系统,针对用户选择的城市基于人工智能大模型DeepSeek智能输出景区推荐。 一、概述1. 案例介绍开发者空间Astro低代码开发平台通过平台提供的界面、逻辑、对象等可视化编排工具,以“拖、拉、拽”的方式来快速构建应用,从而实现所见即所得的应用开发构建体验。本案例应用基于MaaS结合Astro平台快速创建景点推荐智能化系统,针对用户选择的城市基于人工智能大模型DeepSeek智能输出景区推荐。通过项目实际流程操作,让大家更加清晰的了解如何利用Astro低代码平台来进行应用的开发。在这个操作流程中,大家将会学习到Astro集成模型、界面拖拽操作、页面布置到逻辑实现以及应用打包一系列关键步骤,从而掌握Astro低代码平台的基本使用方法及于大模型的结合,体验其在应用开发中的优势。华为开发者空间,是为全球开发者打造的专属开发者空间,致力于为每位开发者提供一台云主机、一套开发工具和云上存储空间,汇聚昇腾、鸿蒙、鲲鹏、GaussDB、欧拉等华为各项根技术的开发工具资源,并提供配套案例指导开发者 从开发编码到应用调测,基于华为根技术生态高效便捷的知识学习、技术体验、应用创新。2. 适用对象企业个人开发者高校学生3. 案例时间本案例总时长预计90分钟。4. 案例流程说明:领取华为开发者空间,登录华为开发者空间-低代码应用开发平台;新建低代码应用,进入Astro轻应用服务控制台主页,开发应用;5. 资源总览本案例预计花费0元。资源名称规格单价(元)时长(分钟)MaaS 平台商用模型DeepSeek-R1 轻量体验包(¥7.00)/ DeepSeek-V3 轻量体验包(¥3.50)领券免费90华为开发者空间 - 低代码应用开发平台系统标配免费90 二、华为开发者空间-低代码应用开发平台1. 登录华为开发者空间-低代码应用开发平台华为开发者空间-低代码应用开发平台( Astro 低代码开发平台)是华为云推出的一款可视化应用开发平台,旨在通过提供的界面、逻辑、对象等可视化编排工具,以“拖、拉、拽”的方式来快速构建应用,从而实现所见即所得的应用开发构建体验,以此来降低开发门槛,提升企业数字化应用构建效率。平台主要特点包括:可视化开发:通过图形化界面和预置组件,无需编写复杂代码即可快速搭建应用;全场景支持:覆盖Web、移动端、大屏等多终端应用开发;高效集成:内置连接器可快速对接华为云及其他主流企业系统;智能辅助:提供AI辅助开发能力,如智能表单生成、流程自动化等;企业级能力:具备权限管理、数据安全、高可用等企业所需特性。登录华为开发者空间,在左侧菜单列表选择华为开发者空间 -> 开发平台 -> Astro 低代码开发,进入华为开发者空间-低代码应用开发平台。2. 创建低代码应用华为开发者空间-低代码应用开发平台页面点击新建低代码应用,在弹出的新建低代码应用对话框中,选择标准应用/基于模板创建,点击确定按钮。点击确定后,弹出创建空白应用页面,上传图片、填写名称、标签后,点击确定,则可创建成功。创建成功后,浏览器会自动打开一个新的页面:Astro轻应用服务控制台。三、项目设计开发1、页面简单了解点击菜单界面-页面 后面的加好可以创建一个新页面,当然也可以点击后面的目录,创建一个新目录,对页面进行汇总,这里我们就不演示了,直接创建一个页面点击创建后,弹出《添加标准页面》,填写标签和名称,这里可以根据自己的需求进行 填写,填写完成后点击添加。这样就创建出了一个空白 的html页面,大家可以看到基本组件块,有很多基础组件,包括了表单 、表格、容器、分栏等等,一应俱全。将表单拖拽到中间页面上,右侧会自动弹出元数据表单配置向导,其中可以选择数据源,选择后可以下一步进行配置功能点。注意:这里的数据源可以先选择一个默认的测试一下。后面我们会详细配置数据源。数据源表单我们选择名称、文件名称后,点击下一步,选择按钮为保存 。 可以看到页面上创建了一个表单,有名称和文件名称2个字段,且事件按钮为保存。接下来我们需要注意的是,关于这个表单所有的操作,如属性、事件、库等,都可以在右侧进行配置。 2、Mass领取开发者空间首页-激励管理-非计划权益中选择DeepSeek-R1领取百万tokens,点击立即申请可申请代金券。购买DeepSeek Tokens套餐包,DeepSeek-R1 轻量体验包(¥7.00)或DeepSeek-V3 轻量体验包(¥3.50)。点击去支付后 ,在支付 页面选择代金券后,0元购买。 购买完成后, 进入ModelArts Studio服务页面—在线推理—商用服务—DeepSeek-V3/R1-64K—开通服务—API Key配置。这里我们选择DeepSeek-R1 模型。API Key的配置一定要注意,在调用模型时必须要用API Key进行验证,所以需要生成一个秘钥,秘钥生成时可以复制,后面是不能查看的,忘记了就只能删除重新生成。3、配置连接器生成完成API Key后,我们回到Astro页面,点击右侧菜单集成 - 连接器实例-大模型-MaaS云平台,来 新增一个与大模型进行连接的连接器。创建连接器时,标签可以自行填写。名称需要注意,后面在调用模型时,是以这个名称来进行调用的,我这个名称相当于是:xiaocao__mass 。模型名称填写真实的就行,这样可以更好的区分。API Key则是上面刚创建的秘钥。保存后,一个连接器就创建好了,接下来就是测试和配置连接器了。我们先测试下,点击Maas云平台详情,也就是上面这张图,有一个测试按钮,可以输入参数测试一下,如果正常返回数据了,说明大模型已经联通了。接下来,我们创建一个逻辑编排,使用一个逻辑,把输入与大模型进行连接起 来(也就是实现上面测试模块的功能点)点击逻辑-编排。添加一个编排。添加编排时,最需要注意的也是这个名称。我们在后面在页面上调用编排时,使用的就是编排名称值。添加完成后,页面上就有 一个启动按钮,点击启动按钮,可以弹出基本信息浮层,点击全局上下文,我们来创建一些变量。创建2个变量input和output ,其中input是文本输入,output是任意类型代表输出。注意修改类型可以点击右侧三个小点-设置里面进行设置。接下来我们要创建一个对象变量来接收大模型返回的数据,在此之前我们创建一个全局的数据结构体来接收这个对象。点击数据-结构体-新建结构体。开始创建全局结构体填写完成结构体基本 信息后,可以看到关于结构体的详细信息。点击结构按钮,进行结构体内容 模块,点击结构体后面的编辑按钮,增加相应的结构类型。role是角色的意思,content是内容,也就是我们要通过角色和内容去调用 maas.结构体创建完成后,我们需要回到编排页面中去,继续创建对象变量,这样 我们在创建时就可以选择全局结构体,直接选择我们刚才创建的结构体。 变量都创建完成后, 我们就可以在画布上进行变量的操作了。点击参数按钮,将入参和出参拖动到对应的位置 选择赋值图标,将赋值图标拖进画布,并连接起来选择赋值图标后,可以将变量赋值,新增一行message变量中的role,直接拖入就可以,值设置为"user"(要用英文双引号),再新增 一行message变量中的content,变量值直接将变量中的input拖入回到一级菜单,选择连接器,选择Mass云平台,拖进画布。将赋值与Mass云平台进行连接。将Mass连接器关联上我们创建的大模型对连接器进行参数设置,目标message将配置的message拖入到源。新增输出参数:选择result ,将 output拖入。在这里强调一下,其实我们很明确了,这里就是在配置给大模型的入参和出参。现在就已经配置完成整个连接器了, 接下来我们保存、启用、运行就可以进行测试了。点击启用后会打开一个新页面显示,输入参数:{"input":""},运行。 可以看到运行的结果,这是大模型的结果,这样就已经通了。 4、页面构造我们是基于一个城市的旅游推荐,所以我页面上只需要选择一个city,通过提示词由智能体推荐出来旅游推荐就可。所以我们先创建一个城市数据选择项,点击数据-选项列表-新建,开始创建选项列表和一个存用户输入信息的表就行。填写完成标签、名称后、增加标签名称。比如北京:标签和名称都填写北京就可以,后续如果有其他的城市我们也可以在这里添加。点击数据-对象,添加一 个对像,添加完成对象后,会默认有一些表字段,根据需求我们在创建一些自己的表字段就可以了。数据创建后,我们就可以开始构建页面了。在界面菜单,点击新增创建一个旅游推荐页面,将页面修改为手机端。在页面右侧选择公共区域,这是整个页面的公共区域,可以先上传一张背景图。选择容器,对容器进行布局的基础配置,选择标题。选择标题,对标题进行一些简单的布局和字体处理。这里需要有一个小细节可以加速我们的学习:组件导航这里可以更方便的选择一个模块。添加表单到页面配置好下拉列表,将其他3个标签删除选中表单,简单调整一下边距和透明度,效果就实现了。我们丢选择下拉选框,开始给下拉选框绑定数据输入名称,选择按对象创建选择对象,选择字段,点击下一步选中名称,点击确定,就绑定好数据了。选中开始推荐按钮,绑定事件,开始对接大模型点击创建后,编写js代码, 注意需要将我提供的内容关于xiaocao的命名空间进行修改。这js的用法与vue是一样的。// 表单校验var _form = context.$component.form;var validFlag = _form.formValidateUnPromise();if (!validFlag) return false;// 序列化表单数据var model = context.$model.ref("message").getData();var modelCopy = JSON.parse(JSON.stringify(model));// 处理非字符串字段Object.keys(modelCopy).forEach(item => { if (modelCopy[item] && typeof modelCopy[item] !== "string") { modelCopy[item] = JSON.stringify(modelCopy[item]); }});// 提取问题字段值var city = modelCopy["name"]var message = modelCopy["xiaocao__message__CST"]// 构建提示文本var suggestionText = `你是一个全能百科,用户想要在${city}旅游,给用户推荐一下当地的特色点及旅游景点`.replace(/"/g, "'");var model_value0 = {"from":"user","content":suggestionText}var model_value1 = {"from":"model","content":"正在生成中","thinkProcessContent":"您好","thinkProcessStatus":"thinking"}var model_value_list = [model_value0,model_value1];// modelCopy.xiaocao__message__CST = suggestionText;// 初始化Flowvar _flow = context.flow("xiaocao__ds");// 调用AI服务获取建议try { // 提示信息 // context.$message.info("信息分析中,正在生成建议。。。。。。"); // context.$model.ref("content").setData("获取推荐中..."); context.$model.ref("model_value").setData(model_value_list) const resp = await _flow.run({ input: suggestionText }); const reader = resp.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; let msg = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value); const lines = buffer.split('\n'); // 保留最后一行(可能不完整) buffer = lines.pop() || ''; for (const line of lines) { if (!line.trim()) continue; try { const jsonStr = line.startsWith('data: ') ? line.substring(6) : line; if (jsonStr.trim() === '[DONE]') continue; const obj = JSON.parse(jsonStr); const newMsg = obj?.choices[0]?.delta?.content || ''; if (newMsg) msg += newMsg; // context.$model.ref("content").setData(msg); model_value1.content = msg; // model_value1.thinkProcessStatus = "complete"; context.$model.ref("model_value").setData([model_value0,model_value1]) } catch (err) { console.warn('解析JSON失败,保留到下一轮处理:', err.message); buffer = line + '\n' + buffer; } } } // 最终保存结果 modelCopy.xiaocao__content__CST = msg; context.$model.ref("message").setData(modelCopy); model_value1.thinkProcessStatus = "complete"; context.$model.ref("model_value").setData([model_value0,model_value1]) // 提交数据 const saveResult = await context.$model.ref("message").save(); if (saveResult.resCode == 0) { const recordId = saveResult.result[0]?.id; if (recordId) { // context.$page.loadStdPage('xiaocao__t_mass', "recordId=" + recordId); // // 成功消息 // context.$message.success('生成成功'); } }} catch (error) { console.error("AI服务调用失败:", error); // 可以添加错误处理逻辑,如显示错误信息}将对话列表拖入页面中,然后进行数据绑定。这里的绑定我写的model_value,这是一个自定义的数据类型,下面我截图了为什么定义这个类型和这个类型的结构,核心还是这个对话列表需要这样的数据结构所以才创建。 至些,我们整体 的就开发完了。看一下效果。dian我正在参加【案例共创】第7期 基于MaaS商用服务 + 华为开发者空间 - Astro 低代码开发平台构建低代码应用 cid:link_5  
  • [案例共创] 通过华为云Astro轻应用开发答题程序
    通过华为云Astro轻应用开发答题程序这是一个网络安全宣传的答题程序,可以更换试题,开发自己的固定试卷的答题程序,具有答题和排行榜的功能。下面将详细阐述如何从零开始,利用华为云Astro轻应用低代码平台开发一款功能完备的网络安全知识竞赛小程序。该程序旨在通过互动答题的形式,向用户普及网络安全知识。其核心功能包括:固定的题库答题、用户身份记录、成绩自动计算、以及动态实时更新的排行榜。通过本指南,开发者可以快速掌握关键页面的创建、数据结构的规划、前后端逻辑的连接,并最终打造出属于自己的定制化答题应用。排行榜参考了:https://support.huaweicloud.com/bestpractice-astrozero/astrozero_07_1009.html1、创建首页1.1同理创建相应的其他页面:1.2创建相应的数据结构:1.3在上面进行编辑,导入相应的模板内容:题目的数据库导入下载模板之后,将问题的字段写好后进行导入:点击确定进行相应的上传:2、首页设置:2.1 布局设置好了之后,将控件重命名。接着将按钮的点击事件先进行绑定,相应的输入框绑定输入的值。输入框绑定用户名:2.2生成模板对象username——通过数据库结构生成:2.2.1第一步:2.2.2第二步:2.2.3 第三步确认:生成后点击数据模型进行确定:2.3 开始答题按钮增加页面跳转:2.4同样在排行榜的按钮创建排行榜,注意相应的动作名称可以更改哦。注意点左上角保存哦,这个平台很差劲,很多时候不能修改;修改的暂存按左上角的保存有的时候会被其他锁住,导致状态不一致修改丢失,经常会出现丢失。3、答题页面答题页面的组件布局也是一样的,只能够单选题或者多选题,随机出题这种几乎实现不了,(考虑过根据题型进行单选多选判断,但是失败了,小程序的企业微信客服也不理人的,官方文档用处也没有,Gemini YYDS)3.1题目加载:因为题目固定,所以没有加载,就是相应的静态3.2提交按钮事件(标记未完成)提交按钮一样进行添加事件:这个需要添加相应的提交接口,先暂停,后面再绑定。3.3 设置相应的数据的绑定examData3.4 相应的题目和相应的数据结构绑定50个就不一一展示了4、提交页面这个抄一下官方的示例的,复制官方模板进行生成:4.1再次答题按钮设置跳转:4.2查看排行榜按钮:还可以设置每次答题的分数和用时,但是这个平台调试和bug太多了,舍弃~~、5、排行榜页面补充:这个参考如下:因为之前使用其他的列表不太好用都没有实现,最后的方案是自己相应的嵌套出来的,参考如下:组件导航->页面->容器->列表视图容器->表格容器->表格5.1首先设置相应的数据的绑定和跳转页面的内容:选中表格后进行相应的数据绑定:5.1.1模型设置为rankdata去绑定相应的排行信息。5.1.2第二步:设置相应的数据5.1.3第三步:下一步,然后确定就可以了。5.1.4距离美化还差一个排名,需要增加,后面给后端去计算:点击确定就成了这样了:这个rank有点突兀,改一下中文。就可以了。5.2返回首页增加点击事件:进入增加相应的跳转:现在基本的跳转已经实现了,现在开始相应的接口开发和业务的处理:6、进行接口的开发前置——脚本:6.1新建脚本submiexam:添加内容后保存后启用:TypeScript import * as context from 'context';import * as db from 'db';// [修正] 不再需要 'decimal' 模块,已将其移除// 声明此脚本将操作的对象@useObject(['secweek__questions__CST'])/** * 定义从前端页面接收的输入参数结构 (保持不变) */@action.object({ type: 'param' })export class Input {    @action.param({ type: 'String', required: true, label: 'question_1' }) question_1: string;    @action.param({ type: 'String', required: true, label: 'question_2' }) question_2: string;    @action.param({ type: 'String', required: true, label: 'question_3' }) question_3: string;    @action.param({ type: 'String', required: true, label: 'question_4' }) question_4: string;    @action.param({ type: 'String', required: true, label: 'question_5' }) question_5: string;    @action.param({ type: 'String', required: true, label: 'question_6' }) question_6: string;    @action.param({ type: 'String', required: true, label: 'question_7' }) question_7: string;    @action.param({ type: 'String', required: true, label: 'question_8' }) question_8: string;    @action.param({ type: 'String', required: true, label: 'question_9' }) question_9: string;    @action.param({ type: 'String', required: true, label: 'question_10' }) question_10: string;    @action.param({ type: 'String', required: true, label: 'question_11' }) question_11: string;    @action.param({ type: 'String', required: true, label: 'question_12' }) question_12: string;    @action.param({ type: 'String', required: true, label: 'question_13' }) question_13: string;    @action.param({ type: 'String', required: true, label: 'question_14' }) question_14: string;    @action.param({ type: 'String', required: true, label: 'question_15' }) question_15: string;    @action.param({ type: 'String', required: true, label: 'question_16' }) question_16: string;    @action.param({ type: 'String', required: true, label: 'question_17' }) question_17: string;    @action.param({ type: 'String', required: true, label: 'question_18' }) question_18: string;    @action.param({ type: 'String', required: true, label: 'question_19' }) question_19: string;    @action.param({ type: 'String', required: true, label: 'question_20' }) question_20: string;    @action.param({ type: 'String', required: true, label: 'question_21' }) question_21: string;    @action.param({ type: 'String', required: true, label: 'question_22' }) question_22: string;    @action.param({ type: 'String', required: true, label: 'question_23' }) question_23: string;    @action.param({ type: 'String', required: true, label: 'question_24' }) question_24: string;    @action.param({ type: 'String', required: true, label: 'question_25' }) question_25: string;    @action.param({ type: 'String', required: true, label: 'question_26' }) question_26: string;    @action.param({ type: 'String', required: true, label: 'question_27' }) question_27: string;    @action.param({ type: 'String', required: true, label: 'question_28' }) question_28: string;    @action.param({ type: 'String', required: true, label: 'question_29' }) question_29: string;    @action.param({ type: 'String', required: true, label: 'question_30' }) question_30: string;    @action.param({ type: 'String', required: true, label: 'question_31' }) question_31: string;    @action.param({ type: 'String', required: true, label: 'question_32' }) question_32: string;    @action.param({ type: 'String', required: true, label: 'question_33' }) question_33: string;    @action.param({ type: 'String', required: true, label: 'question_34' }) question_34: string;    @action.param({ type: 'String', required: true, label: 'question_35' }) question_35: string;    @action.param({ type: 'String', required: true, label: 'question_36' }) question_36: string;    @action.param({ type: 'String', required: true, label: 'question_37' }) question_37: string;    @action.param({ type: 'String', required: true, label: 'question_38' }) question_38: string;    @action.param({ type: 'String', required: true, label: 'question_39' }) question_39: string;    @action.param({ type: 'String', required: true, label: 'question_40' }) question_40: string;    @action.param({ type: 'String', required: true, label: 'question_41' }) question_41: string;    @action.param({ type: 'String', required: true, label: 'question_42' }) question_42: string;    @action.param({ type: 'String', required: true, label: 'question_43' }) question_43: string;    @action.param({ type: 'String', required: true, label: 'question_44' }) question_44: string;    @action.param({ type: 'String', required: true, label: 'question_45' }) question_45: string;    @action.param({ type: 'String', required: true, label: 'question_46' }) question_46: string;    @action.param({ type: 'String', required: true, label: 'question_47' }) question_47: string;    @action.param({ type: 'String', required: true, label: 'question_48' }) question_48: string;    @action.param({ type: 'String', required: true, label: 'question_49' }) question_49: string;    @action.param({ type: 'String', required: true, label: 'question_50' }) question_50: string;}/** * 定义成功时返回给前端的输出参数结构 */@action.object({ type: 'param' })export class Output {    @action.param({ type: 'String', required: true, label: 'id' })    id: string; // 成功创建的记录ID    @action.param({ type: 'String', required: true, label: 'message' })    message: string; // 成功的提示信息}/** * 主逻辑类 */@action.object({ type: 'method' })export class Main {    @action.method({ input: 'Input', output: 'Output', description: 'Submit Cyber Security Quiz Answers with Proactive Error Throwing' })    public run(input: Input): Output {        // --- 1. 前置校验 ---        console.log('开始执行提交答卷脚本...');        if (!input) {            throw new Error('[E1001] 请求参数无效:输入数据为空。');        }        const userId = context.getUserId();        const userName = context.getUserName();        if (!userId || !userName) {            throw new Error('[E1002] 用户身份验证失败:无法获取当前用户信息,请尝试重新登录。');        }        console.log(`校验通过,用户ID: ${userId}, 用户名: ${userName}`);        // --- 2. 业务逻辑:计算得分 ---        const correctAnswers = {            question_1: 'A', question_2: 'B', question_3: 'B', question_4: 'C', question_5: 'B',            question_6: 'B', question_7: 'C', question_8: 'B', question_9: 'B', question_10: 'C',            question_11: 'B', question_12: 'B', question_13: 'C', question_14: 'C', question_15: 'B',            question_16: 'B', question_17: 'C', question_18: 'C', question_19: 'C', question_20: 'C',            question_21: 'C', question_22: 'D', question_23: 'B', question_24: 'B', question_25: 'B',            question_26: 'D', question_27: 'B', question_28: 'B', question_29: 'C', question_30: 'C',            question_31: 'C', question_32: 'B', question_33: 'A', question_34: 'B', question_35: 'B',            question_36: 'B', question_37: 'C', question_38: 'B', question_39: 'B', question_40: 'C',            question_41: 'A', question_42: 'C', question_43: 'B', question_44: 'B', question_45: 'A',            question_46: 'B', question_47: 'B', question_48: 'C', question_49: 'B', question_50: 'B'        };        let score = 0;        for (let i = 1; i <= 50; i++) {            const questionKey = `question_${i}` as keyof Input;            const correctAnswerKey = `question_${i}` as keyof typeof correctAnswers;            if (input[questionKey] === correctAnswers[correctAnswerKey]) {                score += 2;            }        }        console.log(`分数计算完成,总得分: ${score}`);        // --- 3. 数据库交互 ---        const _object = db.object('secweek__questions__CST');        // // 3.1 清理历史记录        // try {        //     const _condition = { conjunction: 'AND', conditions: [{ field: 'secweek__userid__CST', operator: 'eq', value: userId }] };        //     const existingRecords = _object.queryByCondition(_condition);        //     if (existingRecords && existingRecords.length > 0) {        //         console.log(`找到 ${existingRecords.length} 条该用户的历史记录,准备删除...`);        //         existingRecords.forEach(record => {        //             _object.deleteById(record.id);        //         });        //         console.log('历史记录删除完毕。');        //     }        // } catch (e) {        //     console.error('数据库错误:查询或删除历史记录时失败。', e);        //     throw new Error(`[E2001] 系统繁忙:清理历史答卷时发生错误,请稍后重试。`);        // }        // 3.2 准备新记录        const quizRecord: { [key: string]: any } = {            name: userName,            secweek__userid__CST: userId,            // [修正] 直接传递 Number 类型的 score 变量            secweek__score__CST: score        };        for (let i = 1; i <= 50; i++) {            quizRecord[`secweek__question_${i}__CST`] = input[`question_${i}` as keyof Input];        }        // 3.3 插入新记录        let newRecordId: string;        try {            console.log('准备向数据库插入新记录...');            newRecordId = _object.insert(quizRecord);            console.log(`新记录插入成功,记录ID: ${newRecordId}`);        } catch (e) {            console.error('数据库错误:插入新记录时失败。', e);            throw new Error(`[E2002] 提交失败:保存您的答卷时系统发生错误,请稍后重试。`);        }        if (!newRecordId) {            console.error('逻辑错误:数据库insert操作未返回新记录ID。');            throw new Error('[E2003] 严重错误:数据保存后未能获取确认ID,请联系管理员核实。');        }        // --- 4. 成功返回 ---        console.log('脚本所有步骤执行成功,准备返回响应。');        const out = new Output();        out.id = newRecordId;        out.message = '答卷提交成功!';        return out;    }} 6.2脚本继续增加获取排行榜信息:一样增加代码保存后运行:TypeScriptimport * as context from 'context';import * as db from 'db';// 声明此脚本将操作的对象@useObject(['secweek__questions__CST'])// --- 平台可见的输入/输出定义 ---@action.object({ type: 'param' })export class Input {    @action.param({ type: 'Number', required: false, label: 'Top N' })    topN: number;}@action.object({ type: 'param' })export class Output {    @action.param({ type: 'String', required: true, label: '结果JSON字符串' })    result: string;}// --- 内部使用的数据结构 ---class RankEntry {    rank: number;    name: string;    score: number;    submissionTime: string;}class LeaderboardResult {    topRanks: RankEntry[];    currentUser?: RankEntry;}// --- 主逻辑类 ---@action.object({ type: 'method' })export class Main {    /**     * 安全地格式化日期字符串,处理无效或空值。     * (您的日期格式化函数保持不变)     */    private formatDate(dateInput: any): string {        if (!dateInput) {            return 'N/A';        }        try {            const originalDate = new Date(dateInput);            if (isNaN(originalDate.getTime())) {                return 'Invalid Date';            }            const CST_OFFSET = 8 * 60 * 60 * 1000;            const cstDate = new Date(originalDate.getTime() + CST_OFFSET);            const year = cstDate.getUTCFullYear();            const month = String(cstDate.getUTCMonth() + 1).padStart(2, '0');            const day = String(cstDate.getUTCDate()).padStart(2, '0');            const hours = String(cstDate.getUTCHours()).padStart(2, '0');            const minutes = String(cstDate.getUTCMinutes()).padStart(2, '0');            const seconds = String(cstDate.getUTCSeconds()).padStart(2, '0');            return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;        } catch (e) {            return 'Date Format Error';        }    }    @action.method({ input: 'Input', output: 'Output', description: '获取排行榜,每个用户只显示最高分,并包含当前用户的排名信息' })    public run(input: Input): Output {        const out = new Output();        const finalResult: LeaderboardResult = { topRanks: [], currentUser: undefined };        try {            const topN = input.topN || 20;            const currentUserId = context.getUserId();            const _object = db.object('secweek__questions__CST');            // --- 步骤 1: 一次性获取所有有效记录,并按排名规则排序 ---            // 这是整个优化的基础:先将所有记录按最终排名规则排序。            const allRecords = _object.queryByCondition({                conjunction: 'AND',                conditions: [                    { field: 'secweek__score__CST', operator: 'isnotnull' }                ],                sort: [                    { field: 'secweek__score__CST', order: 'desc' }, // 分数从高到低                    { field: 'createdDate', order: 'asc' }       // 分数相同,时间从早到晚                ]            });            // --- 步骤 2: 遍历排序后的记录,筛选出每个用户的最高分记录 ---            // `uniqueUserRecords` 将是最终的、无重复用户的排名列表。            const uniqueUserRecords: any[] = [];            const processedUserIds = new Set<string>(); // 用于跟踪已处理过的用户            if (allRecords && allRecords.length > 0) {                for (const record of allRecords) {                    const userId = record.secweek__userid__CST;                    // 如果用户ID有效,并且我们还没有处理过这个用户                    if (userId && !processedUserIds.has(userId)) {                        // 因为 `allRecords` 已经排序,所以我们遇到的第一个该用户的记录就是他的最佳记录。                        uniqueUserRecords.push(record);                        processedUserIds.add(userId); // 标记该用户已处理                    }                }            }            // --- 步骤 3: 从 `uniqueUserRecords` 构建 Top N 排行榜 ---            // `uniqueUserRecords` 本身就是完整的排行榜,我们只需截取前 N 名。            finalResult.topRanks = uniqueUserRecords                .slice(0, topN) // 获取前 N 条记录                .map((record, index) => ({                    rank: index + 1, // 排名就是索引 + 1                    name: record.name || '匿名用户',                    score: record.secweek__score__CST,                    submissionTime: this.formatDate(record.createdDate)                }));            // --- 步骤 4: 从 `uniqueUserRecords` 中查找当前用户并确定其排名 ---            if (currentUserId) {                // 使用 findIndex 在已去重的排名列表中查找当前用户的位置。                // 这个索引 + 1 就是他的真实排名。                const currentUserRankIndex = uniqueUserRecords.findIndex(                    record => record.secweek__userid__CST === currentUserId                );                // 如果找到了(即 index 不是 -1)                if (currentUserRankIndex !== -1) {                    const myRecord = uniqueUserRecords[currentUserRankIndex];                    finalResult.currentUser = {                        rank: currentUserRankIndex + 1, // 排名                        name: myRecord.name || '匿名用户',                        score: myRecord.secweek__score__CST,                        submissionTime: this.formatDate(myRecord.createdDate)                    };                }            }            out.result = JSON.stringify(finalResult);            return out;        } catch (error) {            const errorMessage = `生成排行榜时出错: ${error.message || '未知错误'}`;            console.error(errorMessage, { stack: error.stack });            throw new Error(`生成排行榜失败: ${error.message || '未知错误'}`);        }    }}6.3 绑定前创建相应的接口的用户的业务凭证:新建用户:6.4设置提交结果接口6.4.1提交结果接口:6.4.2添加相应的业务凭证:6.5设置加载排行榜接口6.5.1加载排行榜接口6.5.2添加相应的业务凭证:7、数据模型绑定——回到答题页面7.1绑定相应的答题数据内容:模型名设置为submit,使用服务生成:选择提交的脚本继续下一步进行生成:增加映射的类型方法,并完成。7.2接着绑定相应的数据内容到表单:7.3提交按钮事件(标记完成)参考代码如下:JavaScript$model.ref('examData').run().then(() => {// 只有在平台的隐式校验通过,且后端脚本成功执行后,才会进入这里context.$message.success("提交成功", 3);setTimeout(function () {context.$page.loadStdPage("secweek__submit", "page=secweek__exam");}, 1000);}).catch((error) => {// 如果用户有未填项,或后端脚本返回错误,都会进入这里console.error("提交失败:", error);context.$message.error('提交失败: ' + error.resMsg, 5);});8、数据模型绑定——排行榜页面8.1排行榜页面的接口加载数据:增加相应的事件:参考代码如下:JavaScriptconsole.log('页面加载事件已触发,准备执行排行榜代码...');// --- 配置区 ---const SERVICE_API_NAME = 'secweek__getranklist';const DATA_MODEL_NAME = 'rankdata';console.log('服务API Name:', SERVICE_API_NAME, '绑定的数据模型名:', DATA_MODEL_NAME);// --- 逻辑执行区 ---try {context.script(SERVICE_API_NAME).run({topN: 50}).then(function (response) {console.log('后端脚本成功返回响应:', response);if (response && response.result && response.result.value && typeof response.result.value.result === 'string') {try {const leaderboardJsonString = response.result.value.result;const leaderboardData = JSON.parse(leaderboardJsonString);let finalRankData = leaderboardData.topRanks || [];const currentUser = leaderboardData.currentUser;if (currentUser && currentUser.name) {const isCurrentUserInTopRanks = finalRankData.some(user => user.name === currentUser.name);if (!isCurrentUserInTopRanks) {finalRankData.push(currentUser);}}finalRankData.sort((a, b) => a.rank - b.rank);// [核心修复] 在将数据设置到模型前,转换数据对象的键名以匹配表格的列配置。const tableFormattedData = finalRankData.map(function(item) {return {'rank': item.rank,'name': item.name,'secweek__score__CST': item.score,'createdDate': item.submissionTime};});const dataModel = $model.ref(DATA_MODEL_NAME);if (dataModel) {try {dataModel.setData(tableFormattedData);console.log(`成功转换数据键名并调用 setData 方法,提交了 ${tableFormattedData.length} 条数据。UI应该会更新。`);} catch (e) {console.error(`向数据模型 ${DATA_MODEL_NAME} 设置数据时出错:`, e);context.$message.error('更新表格数据时发生内部错误。');}} else {console.error(`错误:在页面上找不到名为 '${DATA_MODEL_NAME}' 的数据模型。`);context.$message.error(`页面上缺少关键数据模型: ${DATA_MODEL_NAME}`);}} catch (parseError) {console.error('解析后端返回的JSON字符串时失败:', parseError);context.$message.error('解析排行榜数据失败。');}} else {console.error('响应格式不正确,未能从 response.result.value.result 获取到JSON字符串。', response);context.$message.error('加载排行榜失败:响应格式不正确。');}}).catch(function (error) {console.error("调用后端脚本时发生错误:", error);context.$message.error('加载排行榜失败: ' + (error.resMsg || '未知错误'));});} catch (e) {console.error('在调用 context.script() 时发生同步错误:', e);context.$message.error('调用后端服务API时发生错误: ' + e.message);}最后生成安装包:Plain Text一个网络安全宣传的答题程序,可以更换试题,开发自己的固定试卷。到这里就结束了,我们来演示一下吧。
  • [案例共创] 【案例共创】基于MaaS结合开发者空间Astro低代码平台开发高考大学择校推荐系统
    案例介绍2025年高考报名人数突破1300万,大部分学生在院校档次与专业兴趣的取舍焦虑,全国3005所高校、792个本科专业构成的选择矩阵远超个体认知负荷本案例开发一个大学择校推荐系统,根据学生成绩,专业兴趣,地域爱好等,基于人工智能大模型DeepSeek生成推荐的大学院校,帮助万千学子提供择校参考 案例内容一、概述1. 案例介绍本案例开发一个大学择校推荐系统,根据学生成绩,专业兴趣,地域爱好等,基于人工智能大模型DeepSeek生成推荐的大学院校通过实际操作,了解如何利用Astro低代码平台开发应用。在这个过程中,学习从模型集成、界面操作、页面布置到逻辑实现以及应用打包一系列关键步骤,从而掌握Astro低代码平台的基本使用方法及于大模型的结合,体验其在应用开发中的优势。开发者空间Astro低代码开发平台通过平台提供的界面、逻辑、对象等可视化编排工具,以“拖、拉、拽”的方式来快速构建应用,从而实现所见即所得的应用开发构建体验。华为开发者空间,是为全球开发者打造的专属开发者空间,致力于为每位开发者提供一台云主机、一套开发工具和云上存储空间,汇聚昇腾、鸿蒙、鲲鹏、GaussDB、欧拉等华为各项根技术的开发工具资源,并提供配套案例指导开发者 从开发编码到应用调测,基于华为根技术生态高效便捷的知识学习、技术体验、应用创新。ModelArts Studio(MaaS)平台:是华为云推出的一款大模型即服务平台,可以一站式的对业界主流开源大模型进行部署托管,同时开放大模型API服务,可以结合业界主流Agent开发框架,轻松构建AI Agent应用。2. 适用对象企业个人开发者高校学生3. 案例时间本案例总时长预计90分钟。4. 案例流程说明:领取华为开发者空间,登录华为开发者空间-低代码应用开发平台;新建低代码应用,进入Astro轻应用服务控制台主页,开发应用;5. 资源总览本案例预计花费0元。资源名称规格单价(元)时长(分钟)MaaS 平台商用模型DeepSeek-R1 轻量体验包(¥7.00)/ DeepSeek-V3 轻量体验包(¥3.50)领券免费90华为开发者空间 - 低代码应用开发平台系统标配免费90二、案例准备1、设计对象字段低代码平台中的对象(也可以称为Object)相当于传统方式开发业务系统时,数据库中创建的一个表。每个对象对应一张数据库表,用于保存业务系统需要的配置数据和业务数据。本用例会使用到对象来存储数据,建议提前设计好对象字段,避免后续手忙脚乱字段名称唯一标识字段类型字段说明大学择校推荐tuijian文本区用于返回推荐结果高考省份shengfen文本高考省份和文理科高考分数fenshu数字高考的分数兴趣与能力xingqu文本自身的兴趣爱好或者有哪方面的能力学校性质 xingzhi文本想选择的学校性质如本科专科性别xingbie文本性别,更好的结合性别来推荐学校希望就读城市或者地域chengshi文本希望就读的城市或地域 2、开通ModelArts Studio(MaaS)商用百万Token活动连接:每周畅领100万商用级Tokens!基于CloudMatrix384超节点,Token时延低、TPM/RPM速率高,助您开发商用级AI应用!商用百万Token代金券免费领取链接(可每周领取):DeepSeek-R1/V3-64K百万tokens代金券:cid:link_22.1、大模型领取:切换到开发者空间首页,或者点击上面连接,参与活动“百万商用服务tokens免费领!”活动,按照使用说明进行服务开通:活动页面:2.2、开通完成后,进行大模型的接入:ModelArts控制台:ModelArts - Console模型部署页:部署页面,点击调用按钮,进入调用页面,这里我们提前保存好Api地址和模型名称,点击API调用说明:2.3、创建apikey点击前往API Key管理创建apikey,点击新建创建apikey注意!!创建好API Key之后,点击后面的复制按钮,妥善保存,若未复制保存,后续无法重新复制获取。 三、华为开发者空间-低代码应用开发平台开发应用1. 登录华为开发者空间-低代码应用开发平台华为开发者空间-低代码应用开发平台是华为云推出的一款可视化应用开发平台,旨在通过"拖拽式"组件和模板化设计,降低开发门槛,提升企业数字化应用构建效率。平台主要特点包括:可视化开发:通过图形化界面和预置组件,无需编写复杂代码即可快速搭建应用;全场景支持:覆盖Web、移动端、大屏等多终端应用开发;高效集成:内置连接器可快速对接华为云及其他主流企业系统;智能辅助:提供AI辅助开发能力,如智能表单生成、流程自动化等;企业级能力:具备权限管理、数据安全、高可用等企业所需特性。Astro平台特别适合业务人员与开发者协同创新,能大幅缩短应用交付周期,典型适用于OA审批、数据看板、轻量级业务系统等场景。登录华为开发者空间,在左侧菜单列表选择华为开发者空间 -> 开发平台 -> Astro 低代码开发,进入华为开发者空间-低代码应用开发平台。2. 创建低代码应用2.1、华为开发者空间-低代码应用开发平台页面点击新建低代码应用,在弹出的新建低代码应用对话框中,选择标准应用,点击确定按钮。 注:命名空间为租户数据唯一标识,为免重复,首次创建或使用工程时需定义命名空间。请务必慎重,一旦定义,不可修改,推荐使用公司前缀。本案例中使用xiaowuyun作为命名空间。2.2、在右侧弹出的新建空白应用配置页签中,配置应用名称和标签均为university。2.3、点击右下角确认按钮,平台会自动打开一个新的页面:Astro轻应用服务控制台。注:在点击确认后,在Astro轻应用管理页会同时新增一条刚才创建的名称为xxxx__university的应用,点击编辑同样可以进入Astro轻应用服务控制台。 3. 集成连接器大模型将外部接口集成zero并编写编排流程:在应用中,点击左侧集成 - 连接器实例 - 大模型 - MaaS云平台:点击右上角加号,创建自定义连接器,输入标“标签”(这里为ds,可自定义)、“名称”(这里填入MaaS,可自定义)、“模型名称”(前步保存的模型名称)和“APIKey”(前步保存的apiKey);点击保存:测试连通性,点击“测试”,在弹出框中输入测试内容后,点击测试等待返回结果,正常返回说明添加成功:4. 添加对象和全局结构体4.1、创建大学推荐记录对象进入大学推荐系统设计器界面,在左侧导航栏中,选择“数据”;单击对象后的“新建对象”图标,进入创建新对象页面;设置对象基本信息:填写对象名称为“大学择校推荐系统”,唯一标识为“university”,单击“确定”按钮。4.2、创建字段4.2.1、 单击对象中的编辑图标,进入对象详情页:4.2.2 点击“添加”,添加字段:显示名称“高考省份”,唯一标识:“shengfen”,点击字段类型,选择“文本”类型,点击“确定”:4.2.3 、相同的操作,添加显示名称“大学择校推荐 ”,唯一标识“tuijian”,类型“文本区”:参考如让步骤,把案例准备设计的字段全部创建,添加完如下图字段名称唯一标识字段类型字段说明大学择校推荐tuijian文本区用于返回推荐结果高考省份shengfen文本高考省份和文理科高考分数fenshu数字高考的分数兴趣与能力xingqu文本自身的兴趣爱好或者有哪方面的能力学校性质 xingzhi文本想选择的学校性质如本科专科性别xingbie文本性别,更好的结合性别来推荐学校希望就读城市或者地域chengshi文本希望就读的城市或地域4.3、创建全局结构体:4.3.1、 点击左侧菜单栏数据,选择结构体新增,输入名称和唯一标识(可自定义,这里选择message为例),创建结构体4.3.2、创建完成后点击结构,选择结构体编辑按钮,添加的字段新增role和content,保存:5. 开发推荐系统页面5.1、创建系统页面在新版应用设计器的“界面”中,单击页面后的添加图标,设置页面标签为“大学择校推荐”、名称为“university”,单击“添加”,即可创建一个标准页面:5.2、添加并设置表单从左侧“组件”区域,将“表单”组件拖拽到页面中间,元数据表单配置向导点击“取消”:设置表单属性:如设置布局为宽“800px”和高“1024px”、居中对齐,设置字体大小为“16px”、行高为“23”等。(可自定义)设置数据绑定,点击数据绑定后的“设置”图标,点击“新增模型”:设置模型名称为“formData”,来源选择“对象”,单击“下一步””选择对象”下拉框选择“大学择校推荐系统(xxx__university__CST)”,“选择字段”勾选全部字段,单击“下一步”:单击“确定”:勾选“formData”,单击“确定”:注:在弹出框中,选择“只绑定模型”5.3、添加大标题。从左侧“组件”区域,将“标题”组件拖拽到表单中间:设置标题属性:点击标题,在右侧菜单栏点击基本属性,设置标题内容为“大学择校推荐系统”:点击下方字体,如设置字体颜色为“#147AEC”、字体大小为“28px”、上下间距为“50”、位置为“center”。(可自定义)当前配置会生成对应的css样式,可以查看高级设置(无具体操作,供查看学习使用)。5.4、添加图片5.4.1、从左侧“组件”区域,将“图片”组件拖拽到标题下方:5.4.2、设置图片属性:单击“图片地址”后的“选择图片”图标,在选择图片界面,选中一张图片,单击“确定”,或者单击“上传图片”按钮,从本地电脑中选择一张图片上传即可:5.4.3 设置图片宽度为“100%”注:选择或上传图片,支持上传JPG、JPEG、PNG和GIF格式的图片,图片大小不超过1MB5.5、设置小标题参考步骤5.3,设置小标题,设置标题内容为“帮你解决高考志愿填报的难题,填写你的信息,我会尽力为你提供帮助,让我们一起为你的未来规划加油吧!”(可自定义),标题类型为“Hending2”;5.6、添加采集项15.6.1、在标准页面设计界面,从“基本组件 > 表单”中,拖拽“输入框”组件至表单工作区域:点击基本属性,设置标签内容输入“1、高考省份”,在表单校验中,打开必填开关,设置必填错误信息为“请输入你的高考省份”5.6.2、设置输入框属性:点击输入框,点击右侧菜单栏“数据绑定”中的“设置”图标,勾选“xxxx__shengfen__CST”,单击“确定”:注意:数据绑定时要跟自己设计的对象字段名称一一对应5.7、添加采集项2同上:从“基本组件 > 表单”中,拖拽“输入框”组件至表单工作区域:点击基本属性,设置标签内容输入“2、高考分数”,在表单校验中,打开必填开关,设置必填错误信息为“请输入你的高考分数”点击数据绑定中的设置图标,勾选“xxx__fenshu__CST”,单击“确定”。 5.8、添加采集项3同上:从“基本组件 > 表单”中,拖拽“输入框”组件至表单工作区域:点击基本属性,设置标签内容输入“3、兴趣能力”,点击数据绑定中的设置图标,勾选“xxx__xingqu_CST”,单击“确定5.9、添加采集项4同上:从“基本组件 > 表单”中,拖拽“复选按钮”组件至表单工作区域:点击基本属性,设置标签内容输入“4、学校性质(可选多个)”,设置选项如图,点击数据绑定中的设置图标,勾选“xxx__xingzhi_CST”,单击“确定5.10、添加采集项5在标准页面设计界面,从“基本组件 - 表单”中,拖拽“单选按钮”组件至表单工作区域。设置单选按钮属性。设置标签为“5,性别”,选项为“男 - 男”和“女 - 女”,点击数据绑定中的设置图标,勾选“xxx__xingbie_CST”,单击“确定5.11、添加采集项6同上:从“基本组件 > 表单”中,拖拽“输入框”组件至表单工作区域:点击基本属性,设置标签内容输入“6、希望就读城市或地域”,点击数据绑定中的设置图标,勾选“xxx__chengshi_CST”,单击“确定5.12、添加容器在标准页面设计界面,从“基本组件 > 布局”中,拖拽“容器”组件至表单工作区域。5.13、添加提交按钮:在标准页面设计界面,从“基本组件 > 基本”中,拖拽“按钮”组件至容器区域:5.13.1设置按钮属性:设置显示名称为“提交”,大小选择“默认”。5.13.2、设置按钮事件:首先切换到“事件”标签,单击加号,在“添加动作 > 自定义动作(名称可自定义) > 动作名称”代码区域中,输入代码,单击“创建”。粘贴代码后点击保存代码部分如下:其中代码中formData在步骤《5.2、添加并设置表单:》中创建的对象模型名称xiaowuyun_ds是步骤《3. 集成连接器大模型》绑定的MaaS大模型的实例连接器定义的标签,xiaowuyun__xxx_xxx的字段名前面的部分需要更改为用户自己的命名空间。其他对应修改,可参考如下完整代码####注释的部分// 表单校验var _form = context.$component.form;var validFlag = _form.formValidateUnPromise();if (!validFlag) return false;// 序列化表单数据var model = context.$model.ref("formData").getData();var modelCopy = JSON.parse(JSON.stringify(model));// 处理非字符串字段Object.keys(modelCopy).forEach(item => { if (modelCopy[item] && typeof modelCopy[item] !== "string") { modelCopy[item] = JSON.stringify(modelCopy[item]); }});// 提取问题字段值var questionCodes = [];const arr = ['shengfen', 'fenshu', 'xingqu','xingzhi', 'xingbie', 'chengshi']; ####修改为自己定义的字段名称for (let i = 0; i < arr.length; i++) { var fieldName = "xiaowuyun__" + arr[i] + "__CST"; #####修改为自己的命名空间 questionCodes.push(modelCopy[fieldName] || "");}// 构建提示文本var suggestionText = `你是一个专业的大学推荐助手,该学生高考省份为 ${questionCodes[0]},高考分数是 ${questionCodes[1]}分,兴趣与能力是 ${questionCodes[2]},希望上的大学学校性质为:${questionCodes[3]},性别是 ${questionCodes[4]} 生,希望就读城市或者地域为 :${questionCodes[5]}。请根据以上信息给出该学生进行大学推荐,推荐内容包含大学的介绍和特色。`.replace(/"/g, "'");// 初始化Flowvar _flow = context.flow("xiaowuyun__ds"); #####修改为自己创建大模型集成器的名称// 调用AI服务获取建议try { // 提示信息 context.$message.info("信息分析中,正在生成建议。。。。。。"); const resp = await _flow.run({ input: suggestionText }); const reader = resp.body.getReader(); const decoder = new TextDecoder(); let buffer = ''; let msg = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value); const lines = buffer.split('\n'); // 保留最后一行(可能不完整) buffer = lines.pop() || ''; for (const line of lines) { if (!line.trim()) continue; try { const jsonStr = line.startsWith('data: ') ? line.substring(6) : line; if (jsonStr.trim() === '[DONE]') continue; const obj = JSON.parse(jsonStr); const newMsg = obj?.choices[0]?.delta?.content || ''; if (newMsg) msg += newMsg; } catch (err) { console.warn('解析JSON失败,保留到下一轮处理:', err.message); buffer = line + '\n' + buffer; } } } // 最终保存结果 modelCopy.xiaowuyun__tuijian__CST = msg; #### ####修改为自己命名空间和定义的字段名称 context.$model.ref("formData").setData(modelCopy); // 提交数据 const saveResult = await context.$model.ref("formData").save(); if (saveResult.resCode == 0) { const recordId = saveResult.result[0]?.id; if (recordId) { context.$page.loadStdPage('xiaowuyun__suggestion', "recordId=" + recordId); // 成功消息 context.$message.success('生成成功'); } }} catch (error) { console.error("AI服务调用失败:", error); // 可以添加错误处理逻辑,如显示错误信息}6、添加逻辑编排6.1、添加服务编排点击左侧逻辑 - 编排 - 新建编排,名称填ds,模板类型默认,点击添加:6.2、新增变量点击右侧“全局上下文”,新增变量,创建变量 - input,类型为文本:创建变量 - output,类型为任意:6.3、新增对象变量创建对象变量 - messages,使用步骤3中创建的全局结构体,选择数组:6.4、添加配置开始图元点击画布上的开始图元,点击参数,将刚才创建的变量分别拖进入参和出参:6.5、添加配置赋值图元选择左侧赋值图元,拖入界面,并将开始图元与赋值图元连接:选择赋值图元,点击赋值按钮,将变量赋值,第一行为刚才的全局结构体变量名称“messages[0].role”,我们将值设置为"user"(要用英文双引号),第二行为全局结构体变量名称“messages[0].content”,变量值可直接将变量中的input拖入:6.6、添加配置连接器图元左侧选择连接器 - 自定义连接器,选择前面步骤我们创建的连接器。将其拖拽进页面,并将赋值图元与连接图元连接:点击连接器图元,点击基本信息,选中步骤《3. 集成连接器大模型》创建的大模型连接器:选择连接器按钮,将连接器的入参message为对象变量message拖拽入,输出参数result为变量output拖拽:注意:此处可以多试几次,动作有时候显示不出来6.7、保存测试编排点击保存,启用,运行测试:输入参数{"input":"我要上大学"},测试看是否成功,参数内容可以自定义,最好简单一些防止运行时间过久:7. 开发结果推荐页面7.1、添加页面点击导航栏界面,选择+号新建页面:输入标签"推荐"和名称"suggestion",点击添加:7.2、设置表单仿照步骤《5.2、添加并设置表单》界面格式,进行页面设置,从左侧组件栏将表单组件拖拽至页面,元数据表单配置向导点击取消,属性设置布局:宽800px,高1024px,居中。(设置可根据自己需要自定义):7.3、数据绑定点击属性 - 数据绑定 - 新增模型:按前述步骤设置模型名称为"form0",选择来源为对象:点击下一步,选择"大学择校推荐系统"并勾选所有字段:点击下一步,点击确定:选择刚创建好的模型,点击确定,选择只绑定模型:7.4、添加图片参考步骤《5.4、添加图片》,添加图片;7.5、添加多行输入框在标准页面设计界面,从“基本组件 - 表单”中,拖拽“多行输入框”组件至表单工作区域,点击数据绑定中的设置图标,勾选“XXX__suggestion__CS”,单击“确定标签 填入 根据您提供的信息,有如下推荐,预祝你选上心仪的大学;高度 - 自适应高度,其余参考下图;点击页面,创建自定义脚本,写入以下代码点击保存其中“xiaowuyun_xx_xx”类的字段需更换为自身的命名空间:修改为自己创建的命名空间和对象名称,对象名称为步骤《4.1、创建大学推荐记录对象》创建的对象名称 var _object = context.object('xiaowuyun__university__CST');  完整代码如下:// json化方法function parseJSON(str) { var flag = false; try { JSON.parse(str); flag = true } catch (err) { flag = false; } return flag;}var recordId = context.$page.params.recordId;if (!recordId) return;try { // 获取Object对象 var _object = context.object('xiaowuyun__university__CST'); ####修改为自己创建的命名空间和对象名称 // 查询满足条件数据 var _condition = { conjunction: 'AND', conditions: [{ field: 'id', operator: 'eq', value: recordId }] }; const res = await _object.query(_condition); if (res.resCode !== '0' || !res.result || res.result.length === 0) return; const data = res.result[0]; // 解析JSON字符串字段 Object.keys(data).forEach(item => { if (data[item] && parseJSON(data[item])) { try { const parsed = JSON.parse(data[item]); data[item] = parsed; } catch (e) { // 不是有效JSON,保持原值 } } }); $model.ref("form0").setData(data);} catch (err) { console.error("数据查询或处理失败:", err);}8. 页面效果测试预览填报界面,进行功能调试、测试验证:点击页面左上角的预览图标如遇异常可以在数据-对象-对应对象数据里看到采集到的数据点击预览图标后会跳转大学推荐系统应用,然后填写大学推荐应用参数;提交完成时后跳转大学推荐页面; 至此案例结束,案例整体步骤比较多,后续各种调用其实都是根据定义名称来的,一定要先梳理好对象的命名规划,还有大模型、对象名称等要制定好,避免后续名字乱不好调用我正在参加【案例共创】第7期 基于MaaS商用服务 + 华为开发者空间 - Astro 低代码开发平台构建低代码应用 cid:link_3
  • 【活动截止】PaaS生态宠粉福利又双叒叕来咯,快来登录即可解锁超多惊喜!
     【活动已截止】 以为夏日漫长, 却忽而已秋,晚风凉凉,秋意初显PaaS生态宠粉福利又双叒叕来咯给你一整个惊喜和仪式感,与夏末余热告别吧登录四个开发平台,即可获得抽奖机会1次,100%中奖悄悄告诉你,奖品池大换新,一起解锁吧 活动时间2025年8月27日-8月29日活动流程登录4个平台 → 首页截图 → 发给活动助手 → 参与抽奖活动方式​第1步:活动期间,登录PaaS生态大家族四大开发平台的用户,凭登录截图联系活动助手,即可参与抽奖活动。【Astro Zero平台】Astro 低代码平台是华为云自主创新的全场景低代码平台,其中的Astro轻应用,通过简单拖拽配置完成应用搭建,轻松构建专业级应用,创新随心所欲,敏捷超乎想象,为企业提供低门槛、高效率的数字化业务应用生产新模式。登录网址:cid:link_2,重点须知:截图需包含华为云账号;以及右下角系统时间;如下图例所示【CodeArts平台】华为云软件开发生产线CodeArts是一站式、全流程、安全可信的云原生DevSecOps平台,覆盖需求、开发、测试、部署、运维等软件交付全生命周期环节,为开发者打造全云化研发体验。        登录网址:cid:link_4,截图需包含华为云账号: 【FunctionGraph平台】FunctionGraph是基于事件驱动的函数托管的计算服务,使用FunctionGraph函数,只需编写业务函数代码并设置运行的条件,无需配置和管理服务器等基础设施,函数以弹性、免运维、高可靠的方式运行,助力开发者快速上线各类应用。登录网址:cid:link_1,截图需包含华为云账号:【CodeArts IDE平台】华为云CodeArts IDE Online是轻量级WebIDE,通过浏览器即可实现环境快速获取和环境访问,完成编码、构建、调试、运行、访问代码仓库和命令执行等工作,支持第三方业务集成,内置插件市场支持插件扩展。登录网址:cid:link_3,截图需包含华为云账号:第2步:添加小助手微信号,将所有的首页截图发给其中一位工作人员即可。      第3步:经过小助手确认有效后,即发送链接进行抽奖,100%中奖。礼品池 苏泊尔保温杯、手机支架、手持电风扇、冰箱贴、熊猫小夜灯、折叠团扇活动须知奖品已实物为准,如遇缺货将为您替换同等价值奖品;请确保您的用户信息填写准确无误,以便我们及时为您送上精美奖品;请确保截图右上角华为云用户名与获奖信息保持一致,即截图、获奖信息与华为云账号保持一致视为一次有效抽奖,否则不予奖品发放;奖品将在活动结束后15个工作日内发放,如遇缺货将会替换同等价值奖品;如有任何疑问,欢迎随时联系我们的小助手;本活动最终解释权归PaaS生态宠粉活动所有。
  • [AstroZero] 关于Zero的常见问题解决方案之“应用安装包打包上传”
    我们在日常的应用开发过程中,会出现需要将应用打包好发送给其他开发者或用户体验,那么这里则会涉及俩个步骤:安装包的打包和安装包的导入。关于安装包的打包:这里打包分为源码包和安装包,俩个包的区别在与安装包是安装在运行态运行从而不能改;源码包装好之后还可以继续编辑修改。安装包的打包位置:源码包的打包位置:关于安装包的导入:易错点1:修改了对象字段的某些信息导致无法安装(对象字段的类型是无法修改的,对象字段的长度只能增不能减等等,这个都会有限制)。具体情况举例:比如某公司有两个开发环境,他们之前在开发1环境把字段长度改成255了,开发2环境把字段长度改成了60,装完环境1上的包之后,又装环境2上的包,结果就会报错。易错点2:这里结合安装包的打包来举例,源码包和安装包有不同的打包方式,也就会有不同的导入方式。源码包的导入位置:应用包的导入位置:若在源码包位置导入应用包则会出现如下报错:
  • [AstroZero] 关于Zero的常见问题解决方案之“调用外部三方接口时的若干问题”
    我们在使用低码平台连接器调用外部三方接口的时候之前,一般会使用第三方Api工具去测试一下此接口是否可以能调通(比如入参出参情况,鉴权情况等等),但实际开发中我们会遇见明明三方工具测试此接口是正确的,在低码平台的连接器中却调用错误:可能问题1:TIMEDOUT‌:连接超时,可能由网络延迟或服务器响应慢导致,在连接器动作中按下图所示将超时时间改成自定义时间,输入一个相对来说较大的可以满足业务需求的时间,即可避免。可能问题2:报错码为403(禁止访问)或401(未授权),此时需要在连接器的认证信息中确认token鉴权码或其他的鉴权信息是否正确(比如ak sk等,以具体业务需求为准)可能问题3: "编码响应体失败,内容类型’text/event-stream’,这种情况一般为接受返回的内容为流式内容,而我们的连接器动作中使用了application/json的返回类型去接受(这是最常用的类型,所以容易忽略),将类型修改即可。
  • [低码] 【Q&A】关于Zero低代码平台的常见问题解决方案之“使用脚本调用连接器会报错显示查询不到此连接器或者无权限使用”。
    我们在创建好连接器之后通过脚本调用时,最常见的问题便是:不存在该记录或无权操作该记录。可能错误1:连接器创建之后,未点击启动,导致连接器一直处于关闭状态。可能错误2:该连接器是别的应用中创建的,并非是通用的配置环境中创建,详细解决方案见:【技术干货】 【Q&A】关于Zero低代码平台的常见问题解决方案之“编排中连接器无法选取调用”可能错误3:脚本中输入的连接器名称不正确,请仔细核对,此处尤为容易出错的一点在与唯一标识与名称之间的下划线是俩个下划线而并非一个下划线,比如test_123与test__123。
  • [技术干货] 【Q&A】关于Zero低代码平台的常见问题解决方案之“编排中连接器无法选取调用”
    Q: 同一个用户下面的不同应用在编排中无法调用同一个自定义连接器如应用“AstroChat”与“心理健康测评”同属于一个用户但是在“AstroChat”应用中可以选取到需要的连接器:在“心理健康测评”应用中则无法选取到同样的连接器:这是因为该连接器是在应用AstroChat中创建的,虽然在其他应用中也可以看到此连接器,但是却无法通用,所以。。。。如果我们想创建一个连接器,可供多个应用通用,该如何解决?A 解决方案:在环境配置中>集成连接>自定义连接器中创建连接器即可以多应用通用:
  • [热门活动] 【热门活动】 PaaS生态夏日嘉年华来啦,登录即送精美好礼,限时福利别错过!
    夏日炎炎,暑气正盛PaaS生态夏日嘉年华带着满满的清爽和诚意来啦登录任意两个以上开发平台,即可获得抽奖机会1次,完成四个额外获得抽奖机会1次!无论是被高温困住脚步的你,还是在空调房里想找点乐子的你,这场夏日限定狂欢都能让你甩掉燥热,收获一整个夏天的好心情! 一、活动时间2025年7月28日-7月31日二、活动流程登录2个及以上平台 → 首页截图 → 发给活动助手 → 参与抽奖三、活动方式​第1步:活动期间,登录PaaS生态大家族2个及以上产品的用户,凭登录截图联系活动助手,即可参与抽奖活动(注意:截图需包含华为云账号)。①产品一:CodeArts华为云软件开发生产线CodeArts是一站式、全流程、安全可信的云原生DevSecOps平台,覆盖需求、开发、测试、部署、运维等软件交付全生命周期环节,为开发者打造全云化研发体验。登录网址:cid:link_3,②产品二:CodeArts IDE华为云CodeArts IDE Online是轻量级WebIDE,通过浏览器即可实现环境快速获取和环境访问,完成编码、构建、调试、运行、访问代码仓库和命令执行等工作,支持第三方业务集成,内置插件市场支持插件扩展。登录网址:cid:link_2③产品三:Astro ZeroAstro 低代码平台是华为云自主创新的全场景低代码平台,其中的Astro轻应用,通过简单拖拽配置完成应用搭建,轻松构建专业级应用,创新随心所欲,敏捷超乎想象,为企业提供低门槛、高效率的数字化业务应用生产新模式。登录网址:cid:link_1,④产品四:FunctionGraphFunctionGraph是基于事件驱动的函数托管的计算服务,使用FunctionGraph函数,只需编写业务函数代码并设置运行的条件,无需配置和管理服务器等基础设施,函数以弹性、免运维、高可靠的方式运行,助力开发者快速上线各类应用。登录网址:cid:link_0 第2步:添加小助手微信号,将所有的首页截图发给其中一位工作人员即可。         第3步:经过小助手确认有效后,即发送链接进行抽奖。登录任意两大开发平台,即可获得抽奖机会1次;完成四大开发平台登录并截图,额外获得1次抽奖机会;当用户获得 2 次抽奖机会且两次抽奖均获奖时,可从两次抽中的礼品中选择其一,另一未选择的礼品自动失效;若两次抽奖中仅有一次获奖,则获得该次抽中的礼品;若两次均未获奖,则无礼品。四、奖品展示华为智能跳绳 8个云宝公仔 50个便携茶具 10个U型枕 6个数据线 30个马克杯 14个*奖品已实物为准,如遇缺货将替换同等价值礼品。五、活动须知请确保您的用户信息填写准确无误,以便我们及时为您送上精美奖品。请确保截图右上角华为云用户名与获奖信息保持一致,即截图、获奖信息与华为云账号保持一致视为一次有效抽奖,否则不予奖品发放。奖品将在活动结束后15个工作日内发放,如遇缺货将会替换同等价值奖品。如有任何疑问,欢迎随时联系我们的小助手。本活动最终解释权归PaaS生态夏日嘉年华活动所有。特别注意:用户参与活动产品截图中的华为云账号需与参与抽奖的华为云账号一致,否则获奖信息无效。
  • [热门活动] PaaS生态夏日嘉年华来啦,登录即送精美好礼,限时福利别错过!
    夏日炎炎,暑气正盛PaaS生态夏日嘉年华带着满满的清爽和诚意来啦登录任意两个以上开发平台,即可获得抽奖机会1次,完成四个额外获得抽奖机会1次!无论是被高温困住脚步的你,还是在空调房里想找点乐子的你,这场夏日限定狂欢都能让你甩掉燥热,收获一整个夏天的好心情! 活动时间2025年7月28日-7月31日活动流程登录2个及以上平台 → 首页截图 → 发给活动助手 → 参与抽奖活动方式​第1步:活动期间,登录PaaS生态大家族2个及以上PaaS开发平台的用户,凭登录截图联系活动助手,即可参与抽奖活动。 ①【Astro Zero平台】Astro 低代码平台是华为云自主创新的全场景低代码平台,其中的Astro轻应用,通过简单拖拽配置完成应用搭建,轻松构建专业级应用,创新随心所欲,敏捷超乎想象,为企业提供低门槛、高效率的数字化业务应用生产新模式。截图需包含华为云账号登录网址:cid:link_1,  ②【CodeArts平台】华为云软件开发生产线CodeArts是一站式、全流程、安全可信的云原生DevSecOps平台,覆盖需求、开发、测试、部署、运维等软件交付全生命周期环节,为开发者打造全云化研发体验。截图需包含华为云账号登录网址:cid:link_3,  ③【FunctionGraph平台】FunctionGraph是基于事件驱动的函数托管的计算服务,使用FunctionGraph函数,只需编写业务函数代码并设置运行的条件,无需配置和管理服务器等基础设施,函数以弹性、免运维、高可靠的方式运行,助力开发者快速上线各类应用。截图需包含华为云账号登录网址:cid:link_0  ④【CodeArts IDE平台】华为云CodeArts IDE Online是轻量级WebIDE,通过浏览器即可实现环境快速获取和环境访问,完成编码、构建、调试、运行、访问代码仓库和命令执行等工作,支持第三方业务集成,内置插件市场支持插件扩展。截图需包含华为云账号登录网址:cid:link_2   第2步:添加小助手微信号,将所有的首页截图发给其中一位工作人员即可。            第3步:经过小助手确认有效后,即发送链接进行抽奖。     登录任意两大开发平台,即可获得抽奖机会1次;     完成四大开发平台登录并截图,额外获得1次抽奖机会;     当用户获得 2 次抽奖机会且两次抽奖均获奖时,可从两次抽中的礼品中选择其一,另一未选择的礼品自动失效;若两次抽奖中仅有一次获奖,则获得该次抽中的礼品;若两次均未获奖,则无礼品。奖品展示 华为智能跳绳 8个云宝公仔 50个便携茶具 10个U型枕 6个数据线 30个马克杯 14个*奖品已实物为准,如遇缺货将替换同等价值礼品。活动须知请确保您的用户信息填写准确无误,以便我们及时为您送上精美奖品。请确保截图右上角华为云用户名与获奖信息保持一致,即截图、获奖信息与华为云账号保持一致视为一次有效抽奖,否则不予奖品发放。奖品将在活动结束后15个工作日内发放,如遇缺货将会替换同等价值奖品。如有任何疑问,欢迎随时联系我们的小助手。本活动最终解释权归PaaS生态夏日嘉年华活动所有。特别注意:用户参与活动产品截图中的华为云账号需与参与抽奖的华为云账号一致,否则获奖信息无效。
  • 【热门活动】学习充电,就业添筹码, 华为云低代码应用开发实训营【武汉大学站】
     华为云低代码应用开发实训营武汉大学的全体同学们,华为云Astro低代码平台走进高校训练营系列活动,现在来啦!~现面向武汉大学全体学生,以平台+内容+实践的方式提炼Astro零代码开发、低代码开发等课程基础理论和部分实践内容,帮助学生了解行业动态,提升动手能力。华为云Astro是华为云自主研发的全场景低代码平台,提供了零码、低码、流程、大屏、高低码协同的云上开发能力,开发者可以基于平台能力,构建多场景应用,加速企业数字化转型。下面请跟随Astro小助手的步伐,开启学习体验新征程。 活动时间即日起-2025年9月 活动形式及活动流程线上训练营注册Astro——学习了解低代码产品Astro Zero——完成实践课题作业——添加小助手微信在线审核完成度——发放华为云Astro低代码结业证书活动步骤:第一步点击>>>注册Astro免费试用第二步 >>>下方扫码添加小助手微信,将注册好的华为云账号+姓名+邮箱+手机号,发送给小助手预约申请证书制作(数量有限)第三步 >>>学习低代码相关内容,资料产品学习视频:cid:link_4     点击Astro Zero部分课程进行有序学习 华为云Astro轻应用低代码使用流程:cid:link_1    可根据产品文档左侧导航自行了解相关内容 敲重点~各位同学如果在学习过程中遇到问题可以随时在Astro论坛上发帖提问我们会有小助手立即协助解决你的问题~​学习过程中遇到提问请发布至:cid:link_2​第四步点击>>>按照实验手册(cid:link_0)完成“华为云Astro轻应用智能语言助手”实验。完成实验并截取对话测试截图(注:截图需包括右上角账号,如下示例图),私信小助手啊柴发送截图核实后,提供证书制作的个人信息。等待活动结束后证书发放,邮箱查收   产品声音欢迎分享心得、体会、建议与意见,您的每条声音,都帮助华为云Astro做得更好大家在参与《华为云Astro低代码成长训练营》活动,体验产品时,可去云声平台提出优化建议,包括但不限于产品性能、操作体验、购买流程、功能建议、竞品对比等全面、深度的产品评测等等。1.用户登陆云声活动平台:cid:link_5,如图所示,点击立即参加按钮2.按照要求提出产品问题和优化建议①标题需以参与活动名称+产品体验建议的形式命名。如:【华为云Astro低代码成长训练营】+建议Astro......②内容正文:问题描述:华为云Astro以及对应的使用详细描述,方便时尽量附带截图以及链接地址等建议方案:可写具体的优化建议③标签选择:Astro Zero④确认已知晓建议内容将会被公开,且未提交敏感信息后提交。  本活动最终解释权归华为云Astro平台所有