@hedeqiang/dsh-nl2sql 0.14.0 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -1
- package/lib/client.js +36 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.14.1] - 2026-11-13
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Charts, the ER graph and forecast charts were blurry on Retina / HiDPI screens: ECharts runs in a sandboxed chunk without access to the real `window`, so it rendered at 1×. Charts now render at the screen's device pixel ratio (re-rendering when it changes, e.g. moving to another monitor or zooming), and PNG export uses at least 2×.
|
|
12
|
+
|
|
8
13
|
## [0.14.0] - 2026-11-13
|
|
9
14
|
|
|
10
15
|
### Added
|
|
@@ -139,7 +144,8 @@ These features are tested with local databases and fake IM / Lark servers; real
|
|
|
139
144
|
|
|
140
145
|
- Redesigned UI; Lark push (Markdown and native charts); access control, feedback loop, dashboard global filters; PostgreSQL / Elasticsearch, SSH tunnels, privacy settings, automatic overviews, scheduled reports; semantic layer, ER graph, scan guard, history and audit, dashboards; first version.
|
|
141
146
|
|
|
142
|
-
[Unreleased]: https://github.com/hedeqiang/dsh-nl2sql/compare/v0.14.
|
|
147
|
+
[Unreleased]: https://github.com/hedeqiang/dsh-nl2sql/compare/v0.14.1...HEAD
|
|
148
|
+
[0.14.1]: https://github.com/hedeqiang/dsh-nl2sql/compare/v0.14.0...v0.14.1
|
|
143
149
|
[0.14.0]: https://github.com/hedeqiang/dsh-nl2sql/compare/v0.13.1...v0.14.0
|
|
144
150
|
[0.13.1]: https://github.com/hedeqiang/dsh-nl2sql/compare/v0.13.0...v0.13.1
|
|
145
151
|
[0.13.0]: https://github.com/hedeqiang/dsh-nl2sql/compare/v0.12.2...v0.13.0
|
package/lib/client.js
CHANGED
|
@@ -2836,6 +2836,26 @@ window.__ModuleLoader__.load({
|
|
|
2836
2836
|
}
|
|
2837
2837
|
// ----------------------------------------------------------- charts
|
|
2838
2838
|
|
|
2839
|
+
// ECharts is loaded in a sandboxed wrapper (lib/client.echarts.js) whose `window` is an empty
|
|
2840
|
+
// object, so it cannot read the screen's devicePixelRatio and would draw at 1x (blurry on
|
|
2841
|
+
// Retina / HiDPI). Every chart passes the real ratio explicitly and re-inits when it changes
|
|
2842
|
+
// (moving between screens, browser zoom).
|
|
2843
|
+
const chartDpr = () => Math.max(1, Math.min(3, (typeof window !== 'undefined' && window.devicePixelRatio) || 1))
|
|
2844
|
+
function initChart(echarts, el, opts = {}) {
|
|
2845
|
+
return echarts.init(el, null, { renderer: 'canvas', devicePixelRatio: chartDpr(), ...opts })
|
|
2846
|
+
}
|
|
2847
|
+
/** Call `onChange` when the device pixel ratio changes; returns a cleanup. */
|
|
2848
|
+
function watchDpr(onChange) {
|
|
2849
|
+
if (typeof window === 'undefined' || !window.matchMedia) return () => {}
|
|
2850
|
+
let mq
|
|
2851
|
+
const listen = () => {
|
|
2852
|
+
mq = window.matchMedia(`(resolution: ${window.devicePixelRatio || 1}dppx)`)
|
|
2853
|
+
mq.addEventListener?.('change', handler, { once: true })
|
|
2854
|
+
}
|
|
2855
|
+
const handler = () => { onChange(); listen() }
|
|
2856
|
+
listen()
|
|
2857
|
+
return () => mq?.removeEventListener?.('change', handler)
|
|
2858
|
+
}
|
|
2839
2859
|
let echartsPromise
|
|
2840
2860
|
function loadEcharts() {
|
|
2841
2861
|
echartsPromise ??= require.async('./client.echarts.js')
|
|
@@ -2942,17 +2962,27 @@ window.__ModuleLoader__.load({
|
|
|
2942
2962
|
useEffect(() => {
|
|
2943
2963
|
let disposed = false
|
|
2944
2964
|
let observer
|
|
2965
|
+
let stopDpr
|
|
2945
2966
|
loadEcharts().then((echarts) => {
|
|
2946
2967
|
if (disposed || !ref.current) return
|
|
2947
|
-
|
|
2948
|
-
|
|
2968
|
+
const create = () => {
|
|
2969
|
+
const prev = instance.current
|
|
2970
|
+
const option = prev?.getOption?.()
|
|
2971
|
+
prev?.dispose()
|
|
2972
|
+
instance.current = initChart(echarts, ref.current)
|
|
2973
|
+
instance.current.on('click', (p) => { if (pointRef.current && p.name !== undefined && p.name !== '') pointRef.current(p.name) })
|
|
2974
|
+
if (option) instance.current.setOption(option, true)
|
|
2975
|
+
onInstance?.(instance.current)
|
|
2976
|
+
}
|
|
2977
|
+
create()
|
|
2978
|
+
stopDpr = watchDpr(() => { if (!disposed && ref.current) create() })
|
|
2949
2979
|
observer = new ResizeObserver(() => instance.current?.resize())
|
|
2950
2980
|
observer.observe(ref.current)
|
|
2951
2981
|
setReady(true)
|
|
2952
|
-
onInstance?.(instance.current)
|
|
2953
2982
|
}, (e) => setError(e.message))
|
|
2954
2983
|
return () => {
|
|
2955
2984
|
disposed = true
|
|
2985
|
+
stopDpr?.()
|
|
2956
2986
|
observer?.disconnect()
|
|
2957
2987
|
instance.current?.dispose()
|
|
2958
2988
|
instance.current = null
|
|
@@ -3095,7 +3125,7 @@ window.__ModuleLoader__.load({
|
|
|
3095
3125
|
const [flash, setFlash] = useFlash()
|
|
3096
3126
|
const copySql = () => { navigator.clipboard?.writeText(result.sql); setFlash(t('result.copied')) }
|
|
3097
3127
|
const exportPng = () => {
|
|
3098
|
-
const url = chartInstance?.getDataURL({ type: 'png', pixelRatio: 2, backgroundColor: cssVar(document.body, '--dsw-alias-bg-base', '#fff') })
|
|
3128
|
+
const url = chartInstance?.getDataURL({ type: 'png', pixelRatio: Math.max(2, chartDpr()), backgroundColor: cssVar(document.body, '--dsw-alias-bg-base', '#fff') })
|
|
3099
3129
|
if (url) fetch(url).then(r => r.blob()).then(b => download(`${safeName(result.title)}.png`, b))
|
|
3100
3130
|
}
|
|
3101
3131
|
const isChart = chart.type !== 'table' && chart.type !== 'kpi'
|
|
@@ -3761,7 +3791,7 @@ window.__ModuleLoader__.load({
|
|
|
3761
3791
|
let observer
|
|
3762
3792
|
loadEcharts().then((echarts) => {
|
|
3763
3793
|
if (disposed || !ref.current) return
|
|
3764
|
-
chart = echarts
|
|
3794
|
+
chart = initChart(echarts, ref.current)
|
|
3765
3795
|
observer = new ResizeObserver(() => chart?.resize())
|
|
3766
3796
|
observer.observe(ref.current)
|
|
3767
3797
|
const el = ref.current
|
|
@@ -7227,7 +7257,7 @@ window.__ModuleLoader__.load({
|
|
|
7227
7257
|
let observer
|
|
7228
7258
|
loadEcharts().then((echarts) => {
|
|
7229
7259
|
if (disposed || !ref.current) return
|
|
7230
|
-
inst.current = echarts
|
|
7260
|
+
inst.current = initChart(echarts, ref.current)
|
|
7231
7261
|
observer = new ResizeObserver(() => inst.current?.resize())
|
|
7232
7262
|
observer.observe(ref.current)
|
|
7233
7263
|
try { inst.current.setOption(proForecastOption(forecast, ref.current, t), true) } catch (e) { setError(e.message) }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hedeqiang/dsh-nl2sql",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "Ask MySQL, PostgreSQL, Elasticsearch and CSV/Excel in plain language inside DeepSeek Harness: charts, dashboards, alerts, and IM push and bots for Lark/Feishu, Telegram, WeCom and DingTalk.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|