Yao 折騰手記:如何快速創(chuàng)建一套管理系統(tǒng)

文章首發(fā)于個(gè)人公號(hào):阿拉平平

有開(kāi)發(fā)經(jīng)驗(yàn)的小伙伴肯定知道,要獨(dú)立開(kāi)發(fā)一套管理系統(tǒng)并非易事月匣。從設(shè)計(jì)數(shù)據(jù)庫(kù)钻洒,到開(kāi)發(fā)接口奋姿,再到編寫(xiě)前端頁(yè)面,想想就讓人頭大航唆。如果需求不是很復(fù)雜,我們可以借助低代碼應(yīng)用引擎來(lái)快速開(kāi)發(fā)院刁。

項(xiàng)目介紹

Yao[1] 是一款 Go 語(yǔ)言驅(qū)動(dòng)的低代碼應(yīng)用引擎糯钙,通過(guò)編寫(xiě) JSON 文件即可快速制作 API 接口,數(shù)據(jù)管理系統(tǒng) 退腥,命令行工具等應(yīng)用程序任岸,應(yīng)用可以運(yùn)行在本地、云端和物聯(lián)網(wǎng)設(shè)備上狡刘。

快速安裝

Yao 可以通過(guò)腳本或容器來(lái)安裝享潜,官方推薦后者,所以這里我們使用 Docker 來(lái)部署嗅蔬。

運(yùn)行以下命令創(chuàng)建容器:

# 注意修改掛載的目錄
docker run -d --name yao -v <project root>:/data/app -p 5099:5099 yaoapp/yao:0.9.2-amd64-dev

容器啟動(dòng)后剑按,進(jìn)入容器:

docker exec -it yao bash

在項(xiàng)目目錄中,運(yùn)行初始化命令:

yao init

接著創(chuàng)建數(shù)據(jù)表:

yao migrate

初始化菜單:

yao run flows.setmenu

完成以上步驟后澜术,啟動(dòng)服務(wù):

yao start

服務(wù)啟動(dòng)后艺蝴,用瀏覽器訪問(wèn) https://<server-ip>:5099/xiang/login/admin,輸入用戶名:xiang@iqka.com鸟废, 密碼: A123456p+ 登錄猜敢。

使用說(shuō)明

接下來(lái),我將介紹 Yao 的用法盒延,其中包含:

  1. 基本用法:借助測(cè)試數(shù)據(jù)缩擂,了解 Yao 界面上的功能。
  2. 新建內(nèi)容:新建新的內(nèi)容添寺,包括數(shù)據(jù)胯盯、接口和界面。

基本用法

Yao 在初始化后會(huì)有些測(cè)試數(shù)據(jù)计露,在界面中可以看到表單信息:

我們可以查看陨闹、編輯數(shù)據(jù):

Yao 還有張用戶表,支持增刪改查:

在菜單界面可以配置左側(cè)顯示的內(nèi)容:

新建內(nèi)容

Yao 界面上的功能大致如此薄坏,接下來(lái)我們建下自己的內(nèi)容趋厉。這里我打算實(shí)現(xiàn)一個(gè)簡(jiǎn)單的圖書(shū)管理功能。

先從數(shù)據(jù)開(kāi)始胶坠。我們回到項(xiàng)目目錄君账,在 models 下新建一個(gè) book.mod.json 文件,內(nèi)容如下:

{
    "name": "Book",
    "table": {
        "name": "book",
        "comment": "Book"
    },
    "columns": [{
            "label": "ID",
            "name": "id",
            "type": "ID",
            "comment": "ID"
        },
        {
            "label": "SN",
            "name": "sn",
            "type": "string",
            "unique": true
        },
        {
            "label": "Name",
            "name": "name",
            "type": "string",
            "index": true
        },
        {
            "label": "Kind",
            "name": "kind",
            "type": "enum",
            "option": ["科幻", "名著"],
            "default": "科幻",
            "index": true
        },
        {
            "label": "Description",
            "name": "desc",
            "type": "string",
            "comment": "Description"
        },
        {
            "label": "Score",
            "name": "score",
            "type": "integer",
            "comment": "Score"
        }
    ],
    "values": [{
            "sn": "100001",
            "name": "水滸傳",
            "kind": "名著",
            "desc": "三個(gè)女人和一百零五個(gè)男人的故事",
            "score": 9
        },
        {
            "sn": "100002",
            "name": "三體",
            "kind": "科幻",
            "desc": "不要回答沈善!不要回答乡数!不要回答椭蹄!",
            "score": 9
        }
    ],
    "option": {
        "timestamps": true,
        "soft_deletes": true
    }
}

然后在項(xiàng)目目錄中運(yùn)行以下命令:

yao migrate -n book

需要注意的是,該命令的結(jié)果不會(huì)在前臺(tái)顯示净赴,而是寫(xiě)到 logs/application.log 中绳矩。

針對(duì)這種情況,我們可以先查詢下數(shù)據(jù)玖翅,如果數(shù)據(jù)能夠正常顯示翼馆,則說(shuō)明數(shù)據(jù)表已創(chuàng)建:

yao run models.book.get '::{}'

Run: models.book.get
args[0]: {}
--------------------------------------
models.book.get Response
--------------------------------------
[
    {
        "created_at": "2022-07-27 05:41:32",
        "deleted_at": null,
        "desc": "三個(gè)女人和一百零五個(gè)男人的故事",
        "id": 1,
        "kind": "名著",
        "name": "水滸傳",
        "score": 9,
        "sn": "100001",
        "updated_at": null
    },
    {
        "created_at": "2022-07-27 05:41:32",
        "deleted_at": null,
        "desc": "不要回答!不要回答金度!不要回答应媚!",
        "id": 2,
        "kind": "科幻",
        "name": "三體",
        "score": 9,
        "sn": "100002",
        "updated_at": null
    }
]
--------------------------------------
?DONE?

再編寫(xiě)接口。在 apis 下新建一個(gè) book.http.json 文件猜极,內(nèi)容如下:

{
    "name": "書(shū)籍",
    "version": "1.0.0",
    "description": "書(shū)籍接口",
    "group": "book",
    "guard": "bearer-jwt",
    "paths": [{
            "path": "/search",
            "method": "GET",
            "guard": "-",
            "process": "models.book.Paginate",
            "in": [":query-param", "$query.page", "$query.pagesize"],
            "out": {
                "status": 200,
                "type": "application/json"
            }
        },
        {
            "path": "/save",
            "method": "POST",
            "guard": "-",
            "process": "models.book.Save",
            "in": [":payload"],
            "out": {
                "status": 200,
                "type": "application/json"
            }
        }
    ]
}

在這個(gè)文件中中姜,我定義了兩個(gè)接口:/search/save,用于查詢和創(chuàng)建跟伏。我們先用接口創(chuàng)建新的數(shù)據(jù):

curl -X POST http://127.0.0.1:5099/api/book/save \
   -H 'Content-Type: application/json' \
   -d '{ "sn": "100003", "name": "三國(guó)演義", "kind": "名著", "desc": "東漢末年分三國(guó)", "score": 9 }'

查詢剛剛創(chuàng)建的數(shù)據(jù)丢胚,如果結(jié)果返回正常,說(shuō)明接口功能無(wú)誤受扳。

curl 'http://127.0.0.1:5099/api/book/search?where.name.match=三國(guó)演義&page=1&pagesize=1'

最后編寫(xiě)界面嗜桌。在 tables 目錄下新建一個(gè) book.tab.json 文件,內(nèi)容如下:

{
    "name": "Book",
    "version": "1.0.0",
    "decription": "Book",
    "bind": {
        "model": "book"
    },
    "apis": {},
    "columns": {
        "ID": {
            "label": "ID",
            "view": {
                "type": "label",
                "props": {
                    "value": ":id"
                }
            }
        },
        "SN": {
            "label": "SN",
            "view": {
                "type": "label",
                "props": {
                    "value": ":sn"
                }
            },
            "edit": {
                "type": "input",
                "props": {
                    "value": ":sn"
                }
            }
        },
        "Name": {
            "label": "Name",
            "view": {
                "type": "label",
                "props": {
                    "value": ":name"
                }
            },
            "edit": {
                "type": "input",
                "props": {
                    "value": ":name"
                }
            }
        },
        "Kind": {
            "label": "Kind",
            "view": {
                "type": "label",
                "props": {
                    "value": ":kind"
                }
            },
            "edit": {
                "type": "select",
                "props": {
                    "value": ":kind",
                    "options": [{
                            "label": "科幻",
                            "value": "科幻"
                        },
                        {
                            "label": "名著",
                            "value": "名著"
                        }
                    ]
                }
            }
        },
        "Score": {
            "label": "Score",
            "view": {
                "type": "label",
                "props": {
                    "value": ":score"
                }
            },
            "edit": {
                "type": "input",
                "props": {
                    "value": ":score"
                }
            }
        },
        "Description": {
            "label": "Description",
            "view": {
                "type": "label",
                "props": {
                    "value": ":desc"
                }
            },
            "edit": {
                "type": "textArea",
                "props": {
                    "value": ":desc",
                    "rows": 4
                }
            }
        }
    },
    "filters": {
        "Keywords": {
            "@": "f.Keywords",
            "in": ["where.name.match"]
        }
    },
    "list": {
        "primary": "id",
        "layout": {
            "columns": [{
                    "name": "SN",
                    "width": 100
                },
                {
                    "name": "Name",
                    "width": 200
                },
                {
                    "name": "Score",
                    "width": 300
                },
                {
                    "name": "Kind"
                }
            ],
            "filters": [{
                "name": "Keywords"
            }]
        },
        "actions": {
            "create": {
                "type": "button",
                "props": {
                    "label": "添加書(shū)籍",
                    "icon": "fas fa-plus"
                }
            },
            "pagination": {
                "props": {
                    "showTotal": true
                }
            }
        },
        "option": {
            "operation": {
                "unfold": true
            }
        }
    },
    "edit": {
        "primary": "id",
        "layout": {
            "fieldset": [{
                "columns": [{
                        "name": "SN",
                        "width": 6
                    },
                    {
                        "name": "Name",
                        "width": 6
                    },
                    {
                        "name": "Kind",
                        "width": 6
                    },
                    {
                        "name": "Score",
                        "width": 6
                    },
                    {
                        "name": "Description",
                        "width": 24
                    }
                ]
            }]
        },
        "actions": {
            "cancel": {},
            "save": {
                "type": "button",
                "props": {
                    "label": "Save"
                }
            },
            "delete": {
                "type": "button",
                "props": {
                    "label": "Delete"
                }
            }
        }
    }
}

回到菜單界面辞色,把建好的書(shū)籍界面添加進(jìn)去:

重新登錄系統(tǒng)骨宠,可以看到書(shū)籍界面:

寫(xiě)在最后

可以看到,我們用 Yao 添加新內(nèi)容時(shí)相满,基本都是在和 JSON 打交道层亿,沒(méi)有涉及到代碼。所以對(duì)于需求不復(fù)雜的系統(tǒng)立美,使用低代碼引擎來(lái)開(kāi)發(fā)或許是個(gè)不錯(cuò)的選擇匿又。

References

[1] Yao: https://github.com/YaoApp/yao

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市建蹄,隨后出現(xiàn)的幾起案子碌更,更是在濱河造成了極大的恐慌,老刑警劉巖洞慎,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痛单,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡劲腿,警方通過(guò)查閱死者的電腦和手機(jī)旭绒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人挥吵,你說(shuō)我怎么就攤上這事重父。” “怎么了忽匈?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵房午,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我丹允,道長(zhǎng)郭厌,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任嫌松,我火速辦了婚禮沪曙,結(jié)果婚禮上奕污,老公的妹妹穿的比我還像新娘萎羔。我一直安慰自己,他們只是感情好碳默,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布贾陷。 她就那樣靜靜地躺著,像睡著了一般嘱根。 火紅的嫁衣襯著肌膚如雪髓废。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天该抒,我揣著相機(jī)與錄音慌洪,去河邊找鬼。 笑死凑保,一個(gè)胖子當(dāng)著我的面吹牛冈爹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播欧引,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼频伤,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了芝此?” 一聲冷哼從身側(cè)響起憋肖,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎婚苹,沒(méi)想到半個(gè)月后岸更,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡膊升,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年坐慰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡结胀,死狀恐怖赞咙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情糟港,我是刑警寧澤攀操,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站秸抚,受9級(jí)特大地震影響速和,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜剥汤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一颠放、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吭敢,春花似錦碰凶、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至畜晰,卻和暖如春砾莱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凄鼻。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工腊瑟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人块蚌。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓闰非,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親匈子。 傳聞我的和親對(duì)象是個(gè)殘疾皇子河胎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容