全部產品
Search
文件中心

AnalyticDB:基於Qoder和AnalyticDB Supabase快速構建AI原生移動端APP

更新時間:Feb 28, 2026

本文介紹如何利用Qoder、AnalyticDB for PostgreSQLSupabase和千問影像編輯模型(Qwen Image Edit),快速搭建一個無需傳統後端的AI手辦生圖Flutter應用。內容涵蓋從前端代碼自動產生、後端即服務(BaaS)配置,到AI模型整合,適合希望快速驗證AI原生應用原型並實現敏捷開發的開發人員。

概述

在AI原生應用開發的時代,傳統的後端架構正在被重新定義。本方案採用輕量、敏捷的架構,通過組合以下核心技術,實現全程無需自建傳統後端,即可快速構建AI手辦生圖Flutter應用。

  • 前端:由Qoder根據需求自動產生Flutter代碼,負責介面與互動。Qoder作為AI驅動的IDE Agent,能夠根據需求自動產生高品質的Flutter代碼。使用Flutter外掛程式建立Empty Project後,您只需描述核心功能,配合幾輪調試,就能得到可啟動並執行移動端應用。

  • 後端即服務(BaaS):AnalyticDB Supabase提供資料存放區、Object Storage Service和邊緣函數能力,簡化了傳統後端開發的複雜性。

  • AI能力整合:AnalyticDB Supabase Edge Function接入千問影像編輯模型,實現圖片編輯。

前提條件

操作步驟

步驟一:產生Flutter應用代碼

  1. 環境準備。

    1. 安裝QoderFlutter外掛程式。

    2. 安裝Flutter環境

  2. 建立Flutter專案。

    在VS Code中使用快速鍵Command + Shift + P(Mac)或Ctrl + Shift + P(Windows/Linux),搜尋“flutter”,選擇Flutter: New Project

  3. 使用Qoder產生代碼。

    向Qoder描述功能需求,並調試產生代碼。本文原始碼樣本請參見adb-supabase-flutter-demo

    功能需求描述樣本如下:

    build a flutter image edit app, powered by supabase, using edge function invoke image model to edit image by uploaded by users

步驟二:配置AnalyticDB Supabase

  1. 配置API訪問。

    在專案根目錄下新增.env檔案,複製以下資訊並將相關配置替換為實際值。配置資訊擷取請參見擷取API Keys。

    SUPABASE_URL=https://sbp-xxxxx.supabase.opentrust.net
    SUPABASE_SERVICE_KEY=xxxxxxxx
  2. 設計資料庫表結構。

    登入Supabase Dashboard,建立資料庫表。此表用於儲存使用者編輯圖片的記錄,包括原始圖片URL、編輯後圖片URL、使用者輸入的提示詞等關鍵資訊。

    CREATE TABLE public.edited_images (
        id TEXT PRIMARY KEY,
        user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
        prompt TEXT NOT NULL,
        original_image_url TEXT NOT NULL,
        edited_image_url TEXT NOT NULL,
        created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
    );
    
    -- Enable Row Level Security
    ALTER TABLE edited_images ENABLE ROW LEVEL SECURITY;
    
    -- Create policy that allows users to see only their own images
    CREATE POLICY "Users can view their own edited images"
    ON edited_images
    FOR SELECT
    TO authenticated
    USING (auth.uid() = user_id);
    
    -- Create policy that allows users to insert their own images
    CREATE POLICY "Users can insert their own edited images"
    ON edited_images
    FOR INSERT
    TO authenticated
    WITH CHECK (auth.uid() = user_id);
    
    -- Create policy that allows users to delete their own images
    CREATE POLICY "Users can delete their own edited images"
    ON edited_images
    FOR DELETE
    TO authenticated
    USING (auth.uid() = user_id);
  3. 建立Object Storage Service桶。

    1. 在Supabase Dashboard側邊欄,單擊Storage

    2. 建立一個名為images的儲存桶,並開啟Public bucket,用於儲存使用者上傳的圖片資料。

    3. 執行以下SQL設定權限原則。

      -- Allow authenticated users to upload files to their own folder
      CREATE POLICY "Allow authenticated users to upload images"
      ON storage.objects
      FOR INSERT
      TO authenticated
      WITH CHECK (
        bucket_id = 'images' AND
        auth.uid()::text = (storage.foldername(name))[1]
      );
      
      -- Allow authenticated users to read their own files
      CREATE POLICY "Allow authenticated users to read their own images"
      ON storage.objects
      FOR SELECT
      TO authenticated
      USING (
        bucket_id = 'images' AND
        auth.uid()::text = (storage.foldername(name))[1]
      );
      
      -- Allow public read access (for public URLs)
      CREATE POLICY "Allow public read access to images"
      ON storage.objects
      FOR SELECT
      TO public
      USING (bucket_id = 'images');

步驟三:整合AI服務

  1. 配置安全密鑰。

    說明

    在AnalyticDB Supabase中,阿里雲提供原生的Edge Function Secrets配置與集中管理能力,可將AI API Token(如DashScope和百鍊)安全地存放在函數運行環境的密鑰庫中,通過Deno.env.get讀取,避免寫入程式碼或用戶端暴露。

    1. 在Supabase Dashboard側邊欄,單擊Edge Function>Secrets

    2. 配置BAILIAN_API_KEY,其值為前提條件中擷取的阿里雲百鍊API Key。

  2. 部署Edge Function。

    1. 在Supabase Dashboard側邊欄,單擊Edge Function>Functions

    2. 單擊頁面右上方的Deploy a new function,在下拉選項中選擇Via Editor

    3. 建立並部署名為image-edit的function。

      程式碼範例如下,請根據網路訪問方式替換BASE_URL。私網訪問,請參見通過終端節點私網訪問阿里雲百鍊平台;公網訪問,請參見影像編輯-千問

      const DASHSCOPE_API_KEY = Deno.env.get('BAILIAN_API_KEY');
      const BASE_URL = 'https://vpc-cn-beijing.dashscope.aliyuncs.com/api/v1';
      async function callImageEditAPI(image_url, prompt) {
        const messages = [
          {
            role: "user",
            content: [
              {
                image: image_url
              },
              {
                text: prompt
              }
            ]
          }
        ];
        const payload = {
          model: "qwen-image-edit",
          input: {
            messages
          },
          parameters: {
            negative_prompt: "",
            watermark: false
          }
        };
        try {
          const response = await fetch(`${BASE_URL}/services/aigc/multimodal-generation/generation`, {
            method: 'POST',
            headers: {
              'Authorization': `Bearer ${DASHSCOPE_API_KEY}`,
              'Content-Type': 'application/json'
            },
            body: JSON.stringify(payload)
          });
          if (!response.ok) {
            console.error(`Request failed: ${response.status} ${response.statusText}`);
            return null;
          }
          const data = await response.json();
          return data.output?.choices?.[0]?.message?.content ?? null;
        } catch (error) {
          console.error("Request error:", error.message);
          return null;
        }
      }
      Deno.serve(async (req)=>{
        try {
          const { image_url, prompt } = await req.json();
          if (!image_url || !prompt) {
            return new Response(JSON.stringify({
              error: "Missing image_url or prompt"
            }), {
              status: 400,
              headers: {
                'Content-Type': 'application/json'
              }
            });
          }
          const result = await callImageEditAPI(image_url, prompt);
          return new Response(JSON.stringify({
            message: result
          }), {
            headers: {
              'Content-Type': 'application/json',
              'Connection': 'keep-alive'
            }
          });
        } catch (error) {
          console.error("Server error:", error);
          return new Response(JSON.stringify({
            error: "Internal server error"
          }), {
            status: 500,
            headers: {
              'Content-Type': 'application/json'
            }
          });
        }
      });

工作流程

  1. 上傳原圖:使用者選擇圖片後,前端將其上傳至Supabase Storage的images儲存桶,並產生簽名URL。

  2. 調用編輯:前端將簽名URL與編輯指令(prompt)發送給Edge Function。Edge Function利用BAILIAN_API_KEY調用千問影像編輯模型,處理圖片並擷取產生圖的URL。

  3. 寫入記錄:前端將原始圖片URL、編輯後圖片URL及prompt等資訊寫入edited_images資料庫表,作為記錄。

測試與驗證

  1. 依次執行以下命令,安裝依賴並啟動應用。

    flutter pub get
    flutter run
  2. 啟動應用後,您可在裝置或模擬器上體驗AI手辦生圖功能。

    提示詞樣本

    繪製圖中角色的1/7比例的商業化手辦,寫實風格,真實環境,手辦放在電腦桌上,電腦螢幕裡的內容為該手辦的C4D建模過程,電腦螢幕旁放著印有原畫的塑料玩具封裝盒,電腦桌上還有製作手辦的工具,如畫筆,顏料,小刀等。

    測試樣本

    效果樣本

    image

    image