在superset0.3.6的看板,在新增和編輯時,是可以直接添加css樣式去控制整個看板頁面任意元素的樣式?;蛘咴诠芾聿藛?-css模板添加相應(yīng)css模板,然后編輯看板時直接選擇應(yīng)用css模板。
這個功能確實(shí)是香,這可以實(shí)現(xiàn)不用修改一句源代碼就將看板的風(fēng)格、樣式完全改變,比如如下這樣:

但說實(shí)話,直接在看板的樣式編輯彈窗里寫樣式,實(shí)在是太痛苦了,或者說這**完全接受不了呀!
痛點(diǎn)如下:
- 實(shí)時預(yù)覽效果太差--需要先保存,然后試下效果,然后繼續(xù)編輯看板,選擇編輯CSS模板,再接著寫,如此往復(fù);
- 沒有代碼提示;
- 不可以使用css預(yù)處理語言;
這是簡單分享,我是使用使用gulp+electron解決這些問題的。
項(xiàng)目初始化
mkdir theme_editor
cd theme_editor
npm init -y
使用electron加載頁面注入css
安裝electron,下載electron會需要一點(diǎn)時間,可嘗試使用cnpm
npm install electron -D
根目錄下添加main.js
const { app, BrowserWindow } = require('electron')
// 創(chuàng)建electron window
function createWindow () {
const win = new BrowserWindow({
webPreferences: {
// 開啟開發(fā)工具,方便調(diào)試
devTools: true
}
})
// superset web服務(wù)地址
// 建議使用生產(chǎn)地址,本地就可以不需要啟動superset后端服務(wù)了
const url = 'http://127.0.0.1:5000'
// 這個是要插入css樣式文件的頁面路徑
// 并不需要所有頁面都插入css樣式
// 所有的看板頁面都插入css樣式
const insertCssPath = new RegExp('/superset/dashboard/')
// 如果是在本地superset的服務(wù)
// 可直接把css文件放在superset項(xiàng)目的superset/static/assets目錄下,然后如下使用
// 如果是加載的生產(chǎn)地址,則可使用IIS或者Nginx搭建一個本地web服務(wù),返回css文件
// 直接如:http://localhost:8080/style/theme.css,使用
const cssUrl = '/static/assets/theme.css'
// 加載頁面
win.loadURL(url)
// 監(jiān)聽頁面準(zhǔn)備完成,插入樣式
win.webContents.on('dom-ready', () => {
let webUrl = win.webContents.getURL()
if (insertCssPath.test(webUrl)) {
// 如果是需要插入樣式文件
// 執(zhí)行js代碼往當(dāng)前頁面插入樣式文件
win.webContents.executeJavaScript(`
const link = document.createElement('link');
link.setAttribute('type','text/css');
link.setAttribute('rel','stylesheet');
link.setAttribute('href','${cssUrl}');
document.head.appendChild(link);`
)
return false
}
})
}
app.whenReady().then(createWindow)
package.json添加一個腳本,修改main屬性:
{
"name": "theme_editor",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "electron ."
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"electron": "^10.1.2"
}
}
在superset項(xiàng)目,superset/static/assets目錄下添加theme.css
#app {
height: 100%;
overflow: hidden;
background: linear-gradient(180deg, #3F4685 0%, #222648 100%);
}
然后,跑起superset前后端服務(wù)。當(dāng)前目錄執(zhí)行命令
npm run start
如果一切正常,上面命令會彈出一個electron窗口,加載superset的web服務(wù),登陸后打開任意一個看板,看板的背景會變成theme文件設(shè)置成的顏色,如下:

這里有幾個需要強(qiáng)調(diào)注意的地方:
- loadURL的URL請根據(jù)實(shí)際情況配置(本地也可能并非5000端口),建議使用線上服務(wù);
- 關(guān)于css文件的路徑,使用superset才可直接放在superset/static目錄下,如何使用線上地址,需要在本地搭建web服務(wù)來訪問css文件地址;
- 如果使用superset服務(wù)加載css文件,會有緩存,需要在開發(fā)者工具的network中禁用緩存(Disable cache);
- electron窗口中使用;
以上,我們就實(shí)現(xiàn)了如何使用electron實(shí)現(xiàn)可以在自己喜歡的編輯器中,編輯樣式了。但還是有以下問題:
- 雖然預(yù)覽比之前好了,但每次修改后還是要ctrl+r去刷新,沒有做到自動刷新。
- 如果我想使用CSS預(yù)編譯語言呢?
接下來,用gulp解決上面兩個問題。
使用gulp結(jié)合electron-connect實(shí)現(xiàn)自動刷新
安裝相關(guān)依賴:
npm install gulp gulp-cli electron-connect -D
添加gulpfile.js:
const { watch, task } = require('gulp');
const elecConnect = require('electron-connect').server.create();
// 樣式修改使用electron-connect刷新,electron窗體
function reload (cb) {
elecConnect.reload()
cb()
}
task('watch', function () {
elecConnect.start()
watch(['./theme.css'], reload)
})
同時,在main.js中使用connect:
// 修改main.js,在第二行引入connect
const client = require('electron-connect').client
...
// 在win.loadURL(url)后添加
client.create(win)
在當(dāng)前目標(biāo)下添加theme.css,起個IIS服務(wù)指向theme_editor,**我這里端口是88,所以需要把main.js的cssUrl值修改為http://localhost:88/theme.css
// main.js
...
const cssUrl = 'http://localhost:88/theme.css'
...
最后,當(dāng)前目錄執(zhí)行命令:
npx gulp watch
如果這里沒出問題,那么,你修改theme.css后,electron-connect就會自動把electron窗口當(dāng)前的頁面刷新一下。這里我碰到一個問題,提示electron不存在,刪除node_modules再重新install一次解決。這里還有一點(diǎn)要注意下,如果npm版本小于5.2,是無法使用npx,要么升級node版本,要么全局安裝gulp-cli然后直接跑gulp watch。
好了,到目前為止,我們又解決了一個自動刷新的需求。下面,我們來實(shí)現(xiàn)一下預(yù)處理。
使用gulp-less實(shí)現(xiàn)預(yù)處理
安裝gulp-less,如果想使用其它css預(yù)編譯語言,可以安裝相關(guān)的gulp插件
npm install gulp-less -D
修改gulpfile.js
const { watch, task, dest, src, series } = require('gulp')
const elecConnect = require('electron-connect').server.create()
const less = require('gulp-less')
// 樣式修改使用electron-connect刷新,electron窗體
function reload (cb) {
elecConnect.reload()
cb()
}
// 編譯less
function lessCompier () {
return src('./*.less')
.pipe(less())
.pipe(dest('./'))
}
task('watch', function () {
elecConnect.start()
series(lessCompier)()
// 修改為監(jiān)聽less改變
watch(['./theme.less'], series(lessCompier, reload))
})
添加theme.less
#app{
height: 100%;
overflow: hidden;
background: linear-gradient(180deg, #3F4685 0%, #222648 100%);
}
再次運(yùn)行npx gulp watch,這時,只要你修改theme.less,頁面也會自動刷新了。
其它
到這里,我們的需求已經(jīng)實(shí)在。但依然還有幾個不完美的地方,比如每次啟動electron我們都需要重新登錄下,可以這樣處理下:
// 在main.js的dom-ready事件的回調(diào)函數(shù)里面
// 判斷下如果是進(jìn)行了登錄頁面,自動輸入密碼并登陸
if (/\/login\/$/.test(webUrl)) {
win.webContents.insertCSS('html, body { background-color: #f00; }')
// 下面輸入你系統(tǒng)的用戶名,密碼
win.webContents.executeJavaScript(`
$("#username")[0].value="admin";
$("#password")[0].value="123456";
$("form[name=login]")[0].submit();
`, true)
.then(() => {
console.log('login success')
})
.catch(err => {
console.log('login Error:', err)
})
return false
}
如果覺得,希望每次都直接登陸,并跳轉(zhuǎn)到具體看板,我們可以粥在main.js的dom-ready事件的回調(diào)函數(shù)后面添加代碼:
// href填入指定url
win.webContents.executeJavaScript(`location.`)
以上,完整代碼: theme-editor。
有時,我們想做的可能更復(fù)雜,比如對小圖片轉(zhuǎn)base64,對于未轉(zhuǎn)base64的圖片希望可以自動輸出到指定目錄并在css文件中做替換,壓縮css代碼,打包前先壓縮圖片等等,這些gulp都有相應(yīng)的插件去實(shí)現(xiàn)。相應(yīng)可以看theme-editor,dev分支的gulpfile文件。