gm-printer 10.42.4-beta.7 → 10.42.4-beta.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-printer",
3
- "version": "10.42.4-beta.7",
3
+ "version": "10.42.4-beta.9",
4
4
  "description": "diy printer",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -8,6 +8,33 @@ import _ from 'lodash'
8
8
  import { dispatchMsg } from '../util'
9
9
  import PropTypes from 'prop-types'
10
10
 
11
+ /**
12
+ * 本机字体可用性检测(DOM 宽度法):
13
+ * 用同一文本分别以「不存在的字体(强制走浏览器 fallback 默认)」和「目标字体栈」
14
+ * 离屏渲染量宽,宽度差 >0.5px 说明栈中有字体真实命中(未安装时会 fallback 到与
15
+ * 假字体相同的系统默认,宽度一致)。基线不能用 monospace:中文等宽字体自身会
16
+ * fallback 到系统默认,与目标字体栈的 fallback 同源,导致未安装也判 true。
17
+ */
18
+ const isFontInstalled = (fontFamily) => {
19
+ if (typeof document === 'undefined' || !fontFamily) return true
20
+ const host = document.body
21
+ if (!host) return true
22
+ const probe = document.createElement('div')
23
+ probe.textContent = '配送单验收签字汉字测试123'
24
+ probe.style.cssText =
25
+ 'position:absolute;left:-9999px;top:0;font-size:32px;white-space:nowrap;'
26
+ const widthOf = (ff) => {
27
+ probe.style.fontFamily = ff
28
+ host.appendChild(probe)
29
+ const w = probe.getBoundingClientRect().width
30
+ host.removeChild(probe)
31
+ return w
32
+ }
33
+ // 基线:一个肯定不存在的字体名 → 浏览器对中文回落系统默认;目标栈若全未安装,回落结果与之等宽
34
+ const base = widthOf('GmDefinitelyNotAFont999')
35
+ return Math.abs(widthOf(fontFamily) - base) > 0.5
36
+ }
37
+
11
38
  @inject('editStore')
12
39
  @observer
13
40
  class EditorSelector extends React.Component {
@@ -56,7 +83,7 @@ class EditorSelector extends React.Component {
56
83
  computedSelectedRegionTip,
57
84
  selectedRegion
58
85
  } = this.props.editStore
59
- const { showFontFamily } = this.props
86
+ const { showFontFamily, fontFamilies } = this.props
60
87
  const isDIY = page.type === 'DIY'
61
88
  const isLongPrint = page.type === LONG_PRINT
62
89
  return (
@@ -134,11 +161,23 @@ class EditorSelector extends React.Component {
134
161
  value={page.fontFamily || ''}
135
162
  onChange={this.handleFontFamily}
136
163
  >
137
- {_.map(fontFamilyList, v => (
138
- <Option key={v.value} value={v.value}>
139
- {v.text}
140
- </Option>
141
- ))}
164
+ {_.map(fontFamilies || fontFamilyList, v => {
165
+ // 非默认字体且本机未安装时,选项标注提示:选中后打印/导出会退化为默认字体
166
+ const installed = isFontInstalled(v.value)
167
+ return (
168
+ <Option key={v.value} value={v.value}>
169
+ {v.text}
170
+ {!installed && (
171
+ <span
172
+ className='gm-text-red gm-padding-left-5'
173
+ style={{ fontSize: '11px' }}
174
+ >
175
+ (本机未安装,将退化默认字体)
176
+ </span>
177
+ )}
178
+ </Option>
179
+ )
180
+ })}
142
181
  </Select>
143
182
  </Flex>
144
183
  )}
@@ -213,6 +252,8 @@ class EditorSelector extends React.Component {
213
252
  EditorSelector.propTypes = {
214
253
  isPurchase: PropTypes.bool,
215
254
  showFontFamily: PropTypes.bool,
255
+ // 自定义打印字体列表(扩展接口):[{ value, text }];不传用内置 fontFamilyList
256
+ fontFamilies: PropTypes.array,
216
257
  editStore: PropTypes.object
217
258
  }
218
259
  EditorSelector.defaultProps = {
@@ -49,7 +49,8 @@ class Editor extends React.Component {
49
49
  showNewDate,
50
50
  mockData,
51
51
  mergeClassificationAndLabel,
52
- customTableConfigs
52
+ customTableConfigs,
53
+ fontFamilies
53
54
  } = this.props
54
55
 
55
56
  return (
@@ -85,7 +86,7 @@ class Editor extends React.Component {
85
86
  <span>{':' + i18next.t('商户配送单')}</span>
86
87
  </>
87
88
  <Gap height='10px' />
88
- <EditorSelect showFontFamily />
89
+ <EditorSelect showFontFamily fontFamilies={fontFamilies} />
89
90
  <Gap height='5px' />
90
91
  <SpecialField addFields={addFields} mockData={mockData} />
91
92
  <SpecialOtherField addFields={addFields} mockData={mockData} />
@@ -125,7 +126,10 @@ Editor.propTypes = {
125
126
  addFields: PropTypes.object.isRequired,
126
127
  showNewDate: PropTypes.bool,
127
128
  mergeClassificationAndLabel: PropTypes.bool,
128
- customTableConfigs: PropTypes.array
129
+ customTableConfigs: PropTypes.array,
130
+ // 自定义打印字体列表(扩展接口):[{ value: 'KaiTi, Kaiti SC, 楷体', text: '楷体' }],
131
+ // 不传用内置 fontFamilyList;value 建议「Windows 名, macOS 名, 中文名」三段 fallback
132
+ fontFamilies: PropTypes.array
129
133
  }
130
134
 
131
135
  Editor.defaultProps = {
@@ -49,7 +49,8 @@ class Editor extends React.Component {
49
49
  mockData,
50
50
  mergeClassificationAndLabel,
51
51
  customTableConfigs,
52
- menuConfig
52
+ menuConfig,
53
+ fontFamilies
53
54
  } = this.props
54
55
  return (
55
56
  <div className='gm-printer-edit'>
@@ -84,7 +85,7 @@ class Editor extends React.Component {
84
85
  <span>{':' + i18next.t('商户配送单')}</span>
85
86
  </>
86
87
  <Gap height='10px' />
87
- <EditorSelect showFontFamily />
88
+ <EditorSelect showFontFamily fontFamilies={fontFamilies} />
88
89
  <Gap height='5px' />
89
90
  <SpecialField addFields={addFields} mockData={mockData} />
90
91
  <SpecialOtherField addFields={addFields} mockData={mockData} />
@@ -126,6 +127,8 @@ Editor.propTypes = {
126
127
  showNewDate: PropTypes.bool,
127
128
  mergeClassificationAndLabel: PropTypes.bool,
128
129
  customTableConfigs: PropTypes.array,
130
+ // 自定义打印字体列表(扩展接口),透传给 EditorSelect;不传用内置 fontFamilyList
131
+ fontFamilies: PropTypes.array,
129
132
  menuConfig: PropTypes.oneOfType([
130
133
  PropTypes.arrayOf(PropTypes.string),
131
134
  PropTypes.object
@@ -216,9 +216,12 @@ class Table extends React.Component {
216
216
 
217
217
  if (!width) return tdStyle
218
218
  if (fontSize) minWidth = _.parseInt(fontSize) * 2
219
+ // 宽列也要锁 width:只设 minWidth 时打印阶段列宽会被该页内容重新分配,
220
+ // 与测量阶段(全量行 auto 布局)不一致,边界文本换行数漂移导致分页后页尾空白/溢出
219
221
  if (width >= 150) {
220
222
  tdStyle = {
221
- minWidth: width
223
+ minWidth: width,
224
+ width
222
225
  }
223
226
  } else {
224
227
  tdStyle = {
@@ -246,11 +249,16 @@ class Table extends React.Component {
246
249
  const needDiyTag = config.diyTagSubtotal?.show && dataKey.includes('tagDiy')
247
250
  const diyTagGroups = needDiyTag ? collectGroups(tableData, range) : []
248
251
 
252
+ // 列宽齐全(走过分页测量)时用 fixed:列宽锁定为测量值,不再随每页内容重新分配,
253
+ // 保证打印阶段换行/行高与测量阶段一致,分页边界才准确。
254
+ // 测量阶段自身(renderBefore)与合并打印首渲染(tablesInfo 为空)仍走 auto。
255
+ const isFixedLayout = thWidths.length === columns.length
256
+
249
257
  return (
250
258
  <table
251
259
  style={{
252
260
  // td会撑开table的宽度
253
- tableLayout: 'inherit',
261
+ tableLayout: isFixedLayout ? 'fixed' : 'inherit',
254
262
  wordBreak: 'break-all'
255
263
  }}
256
264
  >