@nstc-business/imes 1.0.34 → 1.0.35

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": "@nstc-business/imes",
3
- "version": "1.0.34",
3
+ "version": "1.0.35",
4
4
  "private": false,
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -0,0 +1,67 @@
1
+ <template>
2
+ <N20InputNumber
3
+ ref="inner"
4
+ v-bind="$attrs"
5
+ v-on="$listeners"
6
+ @copy.native="onCopy"
7
+ @cut.native="onCopy"
8
+ />
9
+ </template>
10
+
11
+ <script>
12
+ import { InputNumber as N20InputNumber } from 'n20-common-lib'
13
+ import {
14
+ resolveNumberClipboardText,
15
+ clearInputMaxlength
16
+ } from './numberCopy'
17
+
18
+ export default {
19
+ name: 'InputNumber',
20
+ inheritAttrs: false,
21
+ components: { N20InputNumber },
22
+ mounted() {
23
+ this.clearMaxlength()
24
+ },
25
+ updated() {
26
+ this.clearMaxlength()
27
+ },
28
+ methods: {
29
+ /**
30
+ * 去掉 n20 写死的 maxlength=16
31
+ * 时间:2026-09-14
32
+ * 人员:AI && 徐红飞
33
+ * 入参:无
34
+ * 出参:无
35
+ * 方法内容:带千分位的长数字展示超过 16 位时,原生复制会被截断
36
+ */
37
+ clearMaxlength() {
38
+ this.$nextTick(() => {
39
+ clearInputMaxlength(this.$el)
40
+ })
41
+ },
42
+ /**
43
+ * 复制/剪切时写入完整展示值
44
+ * 时间:2026-09-14
45
+ * 人员:AI && 徐红飞
46
+ * 入参:e 剪贴板事件
47
+ * 出参:无
48
+ * 方法内容:用 input 完整 value 覆盖被 maxlength 截断的选区
49
+ */
50
+ onCopy(e) {
51
+ const input = this.$el && this.$el.querySelector('input')
52
+ const selected =
53
+ input && typeof input.selectionStart === 'number'
54
+ ? String(input.value || '').slice(
55
+ input.selectionStart,
56
+ input.selectionEnd
57
+ )
58
+ : ''
59
+ const text = resolveNumberClipboardText(input && input.value, selected)
60
+ const clip = (e && e.clipboardData) || (e && e.originalEvent && e.originalEvent.clipboardData)
61
+ if (!text || text === selected || !clip) return
62
+ e.preventDefault()
63
+ clip.setData('text/plain', text)
64
+ }
65
+ }
66
+ }
67
+ </script>
@@ -1,10 +1,7 @@
1
1
  /**
2
2
  * measureCalc 使用的 n20-common-lib 组件集中出口。
3
3
  * 局部注册,不依赖宿主项目的 Vue.use(n20, { prefix }) 前缀。
4
+ * InputNumber 使用本地包装:去掉 maxlength=16,复制完整展示值。
4
5
  */
5
- export {
6
- InputNumber,
7
- SecondaryTab,
8
- Table,
9
- Descriptions
10
- } from 'n20-common-lib'
6
+ export { default as InputNumber } from './InputNumber.vue'
7
+ export { SecondaryTab, Table, Descriptions } from 'n20-common-lib'
@@ -0,0 +1,38 @@
1
+ /**
2
+ * 数字输入框复制文本处理
3
+ * 时间:2026-09-14
4
+ * 人员:AI && 徐红飞
5
+ * 入参:inputValue 输入框完整 value;selectedText 浏览器选区文本
6
+ * 出参:写入剪贴板的完整展示字符串
7
+ * 方法内容:n20 InputNumber 写死 maxlength=16,原生复制会截断带千分位的长数字;选区刚好是 16 位前缀时补回完整展示值
8
+ */
9
+ export function resolveNumberClipboardText(inputValue, selectedText) {
10
+ const full = inputValue == null ? '' : String(inputValue)
11
+ const selected = selectedText || ''
12
+ if (!full) return selected
13
+ if (!selected || selected === full) return full
14
+ // maxlength=16 截断选区:选中的是完整值前缀且刚好 16 位时,补回完整展示值
15
+ if (selected.length === 16 && full.startsWith(selected) && full.length > 16) {
16
+ return full
17
+ }
18
+ return selected
19
+ }
20
+
21
+ /**
22
+ * 去掉原生 input 的 maxlength,避免选区/复制被截到 16 位
23
+ * 时间:2026-09-14
24
+ * 人员:AI && 徐红飞
25
+ * 入参:rootEl 组件根节点
26
+ * 出参:找到的 input 元素,没有则 null
27
+ * 方法内容:查询内部 input 并移除 maxlength
28
+ */
29
+ export function clearInputMaxlength(rootEl) {
30
+ if (!rootEl || typeof rootEl.querySelector !== 'function') {
31
+ return null
32
+ }
33
+ const input = rootEl.querySelector('input')
34
+ if (input) {
35
+ input.removeAttribute('maxlength')
36
+ }
37
+ return input
38
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * 数字输入框复制回归:maxlength=16 会把千分位数字截成 16 个字符
3
+ */
4
+ const fs = require('fs')
5
+ const path = require('path')
6
+
7
+ const src = fs
8
+ .readFileSync(path.join(__dirname, 'numberCopy.js'), 'utf8')
9
+ .replace(/export /g, '')
10
+ const exportsFromSrc = {}
11
+ new Function('exports', src + '\nexports.resolveNumberClipboardText = resolveNumberClipboardText\nexports.clearInputMaxlength = clearInputMaxlength')(exportsFromSrc)
12
+ const { resolveNumberClipboardText, clearInputMaxlength } = exportsFromSrc
13
+
14
+ const shown = '132,898,923.6299999952'
15
+ const truncatedByMaxlength = shown.slice(0, 16)
16
+
17
+ if (truncatedByMaxlength !== '132,898,923.6299') {
18
+ throw new Error('用例前提变化:16 位截断结果不是 132,898,923.6299')
19
+ }
20
+
21
+ const copied = resolveNumberClipboardText(shown, truncatedByMaxlength)
22
+ if (copied !== shown) {
23
+ throw new Error('应复制完整展示值,实际: ' + copied)
24
+ }
25
+
26
+ const partial = resolveNumberClipboardText(shown, '132,898')
27
+ if (partial !== '132,898') {
28
+ throw new Error('部分选区应保持原样,实际: ' + partial)
29
+ }
30
+
31
+ const emptyFallback = resolveNumberClipboardText('', '132,898,923.6299')
32
+ if (emptyFallback !== '132,898,923.6299') {
33
+ throw new Error('完整值为空时应回退选区,实际: ' + emptyFallback)
34
+ }
35
+
36
+ const fakeInput = { removeAttribute(name) { this[name] = null } }
37
+ const fakeRoot = { querySelector() { return fakeInput } }
38
+ if (clearInputMaxlength(fakeRoot) !== fakeInput) {
39
+ throw new Error('应返回内部 input')
40
+ }
41
+ if (fakeInput.maxlength !== null) {
42
+ throw new Error('应移除 maxlength')
43
+ }
44
+ if (clearInputMaxlength(null) !== null) {
45
+ throw new Error('无根节点时应返回 null')
46
+ }
47
+
48
+ console.log('numberCopy.test.js passed')