熟悉我的朋友可能會知道,我一向是不寫熱點的。為什么不寫呢?是因為我不關注熱點嗎?其實也不是。有些事件我還是很關注的,也確實有不少想法和觀點。但我一直奉行一個原則,就是:要做有生命力的內容。
這篇文章是一篇應用性極強的文章,我們通過一個實際的應用場景,去解決某一類的問題,提供一種或者幾種解決方案,來探索技術的魅力。接下來筆者主要分析表單定制平臺的實現思路和技術方案,來實現一個類似于金數據或者問卷星一樣的表單配置平臺,大家也可以基于此方案,擴展出功能更加強大的可視化平臺。
為什么要做一個這樣的平臺呢?一方面是因為筆者多年來一直服務于B端產品,對于動態表單以及配置化表單有一定的項目積累,并且深知配置化表單的價值所在。舉一個很傳統的B端表單配置化的例子:傳統2B企業在提供saas服務時,為了滿足不同企業的定制化需求,往往會給企業客戶提供定制化或者自由配置的功能,如下圖:
圖片
對于saas系統而言,軟件即服務,在提供基礎服務的同時,同樣要滿足用戶個性化需求,所以傳統的saas軟件提供商往往會提供給客戶自由配置的空間,這種自由配置的橋梁就是通過表單,舉一個簡單的例子:
圖片
通過這種方法就可以定制不同風格的企業產品,這里只是舉了個比較簡單的例子,往往實際項目中會更加復雜,可能會有幾十個配置項,當然這種模式是比較傳統的配置化方案,也僅僅是saas軟件提供的很小的一個服務模塊。目前主流的做法是采用可視化方案,而且國內也有非常成熟的方案,但基本的思想是一致的,只不過后者的體驗更好,操作難度更低。
筆者簡單介紹一下saas,方便大家更容易理解其模式:
saas(軟件即服務)是一種云計算產品,為用戶提供對供應商云端軟件的訪問。用戶無需在其本地設備上安裝應用。相反,應用駐留在遠程云網絡中,通過 Web 或 API 進行訪問。通過應用,用戶可以存儲和分析數據,并可進行項目協作。
類似的云計算產品也有很多,比如Paas(平臺即服務),Iaas(基礎架構即服務)等,感興趣的朋友可以學習了解一下。
以上介紹更多的是為了讓大家理解筆者設計這套平臺的基本背景,我們還可以舉個更實際的例子就是金數據或者問卷星的表單配置模式,用戶可以在管理后臺定制自己的表單,并生成一個可訪問的鏈接來向目標用戶發放問卷,填寫信息,收集信息,最后實現數據分析的目的。
本文介紹的表單定制平臺,也同樣支持表單管理,表單數據分析, 表單數據收集, 表單定制等功能, 筆者將采用比較熟悉的技術棧react以及第三方ui庫antd4.0來開發, 后端采用node + koa來設計路由接口.
圖片
圖片
管理列表主要用來查看我們配置的表單模板,分析不同表單模板收集的數據,對表單模板進行編輯刪除等操作.
圖片
圖片
由上圖可知表單定制頁面主要用來編輯自定義表單模板,我們可以添加表單標題,表單字段等,目前提供了幾種自定義表單控件如下:
基本涵蓋了我們所需要的所有表單業務場景.由上圖可知我們可以在任意位置插入自定義字段,同時可以編輯修改刪除表單字段.如果想象力再大一點,我們可以基于它來實現不僅僅是表單問卷型應用,還可以實現答題,發布內容等場景.(后期可支持富文本控件)
圖片
草稿箱設計的目的是方便使用者在配置表單的過程中不確定是否符合需求或者由于某種臨時性舉動而無法繼續配置,這個時候可以將以配置好的內容存入草稿箱,下次繼續編輯,所以筆者專門設計了草稿箱管理列表,一旦用戶存在草稿,會在管理頁面通知用戶并顯示草稿的數量.作為一個追求體驗的技術人,這一塊的設計還是相當有必要的.
圖片
當我們配置好表單之后,我們點擊保存, 會生成一個前臺訪問地址,實時訪問表單信息,如下圖為點擊鏈接之后的頁面:
圖片
我們也可以根據自己的風格,設計自己的表單錄入頁面, 具體如何實現這樣的過程, 后面我會詳細介紹.
圖片
圖片
我們可以通過點擊"查看數據"來訪問收集到的表單數據,并通過可視化的工具對數據做分析比較,同時我們也可以在數據列表中刪除數據,來控制我們數據展示的純凈.
圖片
圖片
圖片
收集到數據只有,我們會自動集成幾個可視化組件來分析表單數據,以上是筆者列出的幾個可視化組件,基于antv G2來封裝.
以上主要介紹了自定義表單定制平臺的一些功能和交互效果, 我們可以利用該平臺做很多有意思的事情.因為表單的抽象是數據,我們拿到定制化的表單json數據之后,我們可以有不同的展現形式,比如用戶的問卷調查, 網站平臺的投票, 答題頁面, 發布動態等功能,如下圖配置:
圖片
圖片
以上配置可以實現類似于微信的發布朋友圈的功能, 然后我們可以通過前端的手段根據用戶發表的數據渲染成一個朋友圈列表.
如果我們再打開自己的腦洞,我們可以這樣配置,配置一個這樣的表單,表單包括一個文件上傳控件和n個文本輸入控件,如下圖:
圖片
將這樣的表單配置到H5管理模塊,我們只需要上傳三張圖,然后填寫好對應的配文,然后利用市面上成熟的H5全屏滾動插件,就能輕松的定制各種H5活動頁面了。該方案已被筆者的很多子系統使用,效果還是非常好的。
當然基于該平臺甚至能直接配置小型的宣傳網站,還有更多想象空間,期待大家去挖掘。
要想開發這樣一個表單定制平臺, 核心在于如何實現表單動態配置的機制.這里筆者將其劃分為兩部分:基礎表單物料和表單編輯生成器, 如下圖所示拆分圖:
圖片
接下來我們一步步實現以上兩個核心模塊。
基礎表單物料主要是為了用戶選擇自定義表單控件使用,我們常用的表單動態渲染有map循環+條件判斷和單層map+對象法,前者如果要渲染一個動態表單,可能實現如下:
{ list.map((item, i) => { return <React.Fragment key={i}> { item.type === 'input' && <Input /> } { item.type === 'radio' && <Radio /> } // ... </React.Fragment> })}
但是這樣做有個明顯的缺點就是會產生很多沒必要的判斷,如果對于復雜表單,性能往往很低,所以筆者采用后者來實現,復雜度可以降到O(n).我們先來做配置模版:
// 基礎模版數據const tpl = [ { label: '文本框', placeholder: '請輸入內容', type: 'text', value: '', index: uuid(5) }, { label: '單選框', type: 'radio', option: [{label: '男', value: 0}, {label: '女', value: 1}], index: uuid(5) }, { label: '復選框', type: 'checkbox', option: [{label: '男', value: 0}, {label: '女', value: 1}], index: uuid(5) }, { label: '多行文本', placeholder: '請輸入內容', type: 'textarea', index: uuid(5) }, { label: '選擇框', placeholder: '請選擇', type: 'select', option: [{label: '中國', value: 0}, {label: '俄羅斯', value: 1}], index: uuid(5) }, { label: '文件上傳', type: 'upload', index: uuid(5) }]// 模版渲染組件const tplMap = { text: { component: (props) => { const { placeholder, label } = props return <div className={styles.fieldOption}><span className={styles.fieldLabel}>{label}:</span><Input placeholder={placeholder} /></div> } }, textarea: { component: (props) => { const { placeholder, label } = props return <div className={styles.fieldOption}><span className={styles.fieldLabel}>{label}:</span><TextArea placeholder={placeholder} /></div> } }, radio: { component: (props) => { const { option, label } = props return <div className={styles.fieldOption}> <span className={styles.fieldLabel}>{label}:</span> <Radio.Group> { option && option.map((item, i) => { return <Radio style={radioStyle} value={item.value} key={item.label}> { item.label } </Radio> }) } </Radio.Group> </div> } }, checkbox: { component: (props) => { const { option, label } = props return <div className={styles.fieldOption}> <span className={styles.fieldLabel}>{label}:</span> <Checkbox.Group> <Row> { option && option.map(item => { return <Col span={16} key={item.label}> <Checkbox value={item.value} style={{ lineHeight: '32px' }}> { item.label } </Checkbox> </Col> }) } </Row> </Checkbox.Group> </div> } }, select: { component: (props) => { const { placeholder, option, label } = props return <div className={styles.fieldOption}> <span className={styles.fieldLabel}>{label}:</span> <Select placeholder={placeholder} style={{width: '100%'}}> { option && option.map(item => { return <Option value={item.value} key={item.label}>{item.label}</Option> }) } </Select> </div> } }, upload: { component: (props) => { return <div className={styles.fieldOption}> <span className={styles.fieldLabel}>{props.label}:</span> <Upload listType="picture-card" className="avatar-uploader" showUploadList={false} actinotallow="https://www.mocky.io/v2/5cc8019d300000980a055e76" > <div>+</div> </Upload> </div> } }}export { tpl, tplMap}
基礎物料在下圖所示中使用:
圖片
當我們要添加一個表單項時,我們就可以在左邊預覽操作區看到添加的項,并可以基于表單編輯生成器來編輯表單字段。
表單編輯生成器分為2部分, 第一部分是用來生成表單項的容器組件,封裝了添加,刪除,編輯操作功能,代碼如下:
// 表單容器組件const BaseFormEl = (props) => { const {isEdit, onEdit, onDel, onAdd} = props const handleEdit = (v) => { onEdit && onEdit(v) } return <div className={styles.formControl}> <div className={styles.formItem}>{ props.children }</div> <div className={styles.actionBar}> <span className={styles.actionItem} onClick={onDel}><MinusCircleOutlined /></span> <span className={styles.actionItem} onClick={onAdd}><PlusCircleOutlined /></span> <span className={styles.actionItem} onClick={handleEdit}><EditOutlined /></span> </div> </div>}
第二部分主要用來渲染操作區模版,基于BaseFormEl包裝不同類型的表單組件, 這里舉一個比較復雜的select來說明,其他表單控件類似:
const formMap = { title: {}, text: {}, textarea: {}, radio: {}, checkbox: {}, select: { component: (props) => { const { onDel, onAdd, onEdit, curIndex, index, type, label, placeholder, required, message, option } = props return <BaseFormEl onDel={onDel.bind(this, index)} onAdd={onAdd.bind(this, index)} onEdit={onEdit.bind(this, {index, type, placeholder, label, option, required})} isEdit={curIndex === index} > <Form.Item name={label} label={label} rules={[{ message, required }]}> <Select placeholder={placeholder}> { option && option.map(item => { return <Option value={item.value} key={item.label}>{item.label}</Option> }) } </Select> </Form.Item> </BaseFormEl> }, editAttrs: [ { title: '字段名稱', key: 'label' }, { title: '選項', key: 'option' }, { title: '提示文本', key: 'placeholder' }, { title: '是否必填', key: 'required' }, ] }, upload: {}}
editAttrs主要用來渲染編輯列表,說明哪些表單項可以編輯,這部分代碼比較簡單,這里直接用圖舉例:
圖片
最后我們來渲染表單生成器組件:
export default (props) => { const { formData, handleDelete, handleAdd, handleEdit, curEditRowIdx } = props return <Form name="customForm"> { formData && formData.map(item => { let CP = formMap[item.type].component return <CP {...item} key={item.index} onDel={handleDelete} onAdd={handleAdd} onEdit={handleEdit} curIndex={curEditRowIdx} /> }) } </Form>}
至此,基本功能模塊已經開發完成,我們只需要將這些物料和組件導入到編輯頁面,基于業務來操作和請求即可。由于實現該案例還是有一定復雜度的,筆者沒有將所有組件都一一寫出來,希望為大家提供一個思考空間,后續筆者將會把該平臺整合到筆者的開源CMS系統中,供大家學習使用。有關nodejs部分的內容,由于筆者后期會陸續整理,如果有其他疑問,可以和筆者多交流。
本文鏈接:http://www.tebozhan.com/showinfo-26-12107-0.html基于React/Vue搭建一個通用的表單管理配置平臺
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com