imeik-bizui 2.7.5 → 2.7.7
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/dist/bizui/src/FieldFloorPriceBoard/core/FloorPriceBoard.vue +319 -8
- package/dist/bizui/src/FieldFloorPriceBoard/core/FloorPriceDetailDialog.vue +20 -3
- package/dist/bizui/src/FieldFloorPriceBoard/core/displayPrefs.js +62 -0
- package/dist/bizui/src/FieldFloorPriceBoard/core/normalize.js +4 -5
- package/dist/bizui/src/FieldFloorPriceBoard/core/utils.js +100 -35
- package/dist/imeik-bizui.common.js +1086 -170
- package/dist/imeik-bizui.common.js.gz +0 -0
- package/dist/imeik-bizui.css +1 -1
- package/dist/imeik-bizui.css.gz +0 -0
- package/dist/imeik-bizui.umd.js +1086 -170
- package/dist/imeik-bizui.umd.js.gz +0 -0
- package/dist/imeik-bizui.umd.min.js +6 -6
- package/dist/imeik-bizui.umd.min.js.gz +0 -0
- package/package.json +1 -1
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<div v-if="visible" class="floor-price-board">
|
|
8
8
|
<div v-if="showTitle" class="fpb-title">
|
|
9
9
|
<span class="fpb-title__bar" />
|
|
10
|
-
<span class="fpb-title__text">{{ title }}</span>
|
|
10
|
+
<span class="fpb-title__text" @click="onSecretTitleClick">{{ title }}</span>
|
|
11
11
|
</div>
|
|
12
12
|
|
|
13
13
|
<div
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
:alt="resolvedStatusLabel"
|
|
29
29
|
aria-hidden="true"
|
|
30
30
|
>
|
|
31
|
-
<h2 class="fpb-result__title">{{ resolvedResultTitle }}</h2>
|
|
31
|
+
<h2 class="fpb-result__title" @click="onSecretTitleClick">{{ resolvedResultTitle }}</h2>
|
|
32
32
|
<span class="fpb-badge">{{ resolvedStatusLabel }}</span>
|
|
33
33
|
<button
|
|
34
34
|
v-if="useDemo"
|
|
@@ -39,6 +39,52 @@
|
|
|
39
39
|
>
|
|
40
40
|
Mock
|
|
41
41
|
</button>
|
|
42
|
+
<el-popover
|
|
43
|
+
v-if="settingsUnlocked"
|
|
44
|
+
v-model="settingsOpen"
|
|
45
|
+
placement="bottom-start"
|
|
46
|
+
width="300"
|
|
47
|
+
trigger="click"
|
|
48
|
+
>
|
|
49
|
+
<div class="fpb-settings">
|
|
50
|
+
<div class="fpb-settings__head">
|
|
51
|
+
<span class="fpb-settings__title">价格展示</span>
|
|
52
|
+
<span class="fpb-settings__hint">临时生效,刷新恢复默认</span>
|
|
53
|
+
</div>
|
|
54
|
+
<div
|
|
55
|
+
v-for="opt in displayModeOptions"
|
|
56
|
+
:key="opt.value"
|
|
57
|
+
:class="['fpb-settings__option', { 'is-active': displayMode === opt.value }]"
|
|
58
|
+
role="radio"
|
|
59
|
+
:aria-checked="displayMode === opt.value ? 'true' : 'false'"
|
|
60
|
+
@click="selectDisplayMode(opt.value)"
|
|
61
|
+
>
|
|
62
|
+
<span class="fpb-settings__radio" />
|
|
63
|
+
<span class="fpb-settings__body">
|
|
64
|
+
<span class="fpb-settings__label">
|
|
65
|
+
{{ opt.label }}
|
|
66
|
+
<em v-if="opt.value === defaultDisplayMode" class="fpb-settings__tag">默认</em>
|
|
67
|
+
</span>
|
|
68
|
+
<span class="fpb-settings__desc">{{ opt.desc }}</span>
|
|
69
|
+
</span>
|
|
70
|
+
<i v-if="displayMode === opt.value" class="el-icon-check fpb-settings__check" />
|
|
71
|
+
</div>
|
|
72
|
+
<div class="fpb-settings__foot">
|
|
73
|
+
<button type="button" class="fpb-settings__link" @click="onLockSettings">
|
|
74
|
+
隐藏设置入口
|
|
75
|
+
</button>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
<button
|
|
79
|
+
slot="reference"
|
|
80
|
+
type="button"
|
|
81
|
+
class="fpb-settings-trigger"
|
|
82
|
+
title="价格展示设置"
|
|
83
|
+
aria-label="价格展示设置"
|
|
84
|
+
>
|
|
85
|
+
<i class="el-icon-setting" />
|
|
86
|
+
</button>
|
|
87
|
+
</el-popover>
|
|
42
88
|
</div>
|
|
43
89
|
<p v-if="resolvedResultDescription" class="fpb-result__desc">
|
|
44
90
|
{{ resolvedResultDescription }}
|
|
@@ -105,9 +151,9 @@
|
|
|
105
151
|
<dt>与标准差额</dt>
|
|
106
152
|
<dd
|
|
107
153
|
:class="{ 'is-danger': row.hit, 'is-ok': !row.hit && row.gap > 0 }"
|
|
108
|
-
:title="row
|
|
154
|
+
:title="gapLabelOf(row)"
|
|
109
155
|
>
|
|
110
|
-
{{ row
|
|
156
|
+
{{ gapLabelOf(row) }}
|
|
111
157
|
</dd>
|
|
112
158
|
</div>
|
|
113
159
|
</dl>
|
|
@@ -146,9 +192,20 @@ import {
|
|
|
146
192
|
DEFAULT_STATUS_LABEL,
|
|
147
193
|
PANEL_STATE,
|
|
148
194
|
buildResultCopy,
|
|
195
|
+
formatGapLabel,
|
|
149
196
|
formatMoney,
|
|
150
197
|
formatNumber
|
|
151
198
|
} from './utils'
|
|
199
|
+
import {
|
|
200
|
+
DEFAULT_DISPLAY_MODE,
|
|
201
|
+
DISPLAY_MODE_OPTIONS,
|
|
202
|
+
getDisplayMode,
|
|
203
|
+
isSettingsUnlocked,
|
|
204
|
+
lockSettings,
|
|
205
|
+
setDisplayMode,
|
|
206
|
+
subscribeDisplayMode,
|
|
207
|
+
unlockSettings
|
|
208
|
+
} from './displayPrefs'
|
|
152
209
|
import FloorPriceSectionPager from './FloorPriceSectionPager.vue'
|
|
153
210
|
import iconBlocked from '../assets/icon-blocked.png'
|
|
154
211
|
import iconPass from '../assets/icon-pass.png'
|
|
@@ -160,6 +217,9 @@ const STATUS_ICON = {
|
|
|
160
217
|
[PANEL_STATE.EXEMPT]: iconExempt
|
|
161
218
|
}
|
|
162
219
|
|
|
220
|
+
const SECRET_CLICK_NEED = 5
|
|
221
|
+
const SECRET_CLICK_WINDOW_MS = 2500
|
|
222
|
+
|
|
163
223
|
export default {
|
|
164
224
|
name: 'FloorPriceBoard',
|
|
165
225
|
components: {
|
|
@@ -248,7 +308,7 @@ export default {
|
|
|
248
308
|
type: Boolean,
|
|
249
309
|
default: false
|
|
250
310
|
},
|
|
251
|
-
/**
|
|
311
|
+
/** 价格/金额小数位;显式传入时覆盖 displayMode */
|
|
252
312
|
numberDigits: {
|
|
253
313
|
type: Number,
|
|
254
314
|
default: null
|
|
@@ -264,7 +324,14 @@ export default {
|
|
|
264
324
|
},
|
|
265
325
|
data() {
|
|
266
326
|
return {
|
|
267
|
-
productPage: 1
|
|
327
|
+
productPage: 1,
|
|
328
|
+
displayMode: getDisplayMode(),
|
|
329
|
+
displayModeOptions: DISPLAY_MODE_OPTIONS,
|
|
330
|
+
defaultDisplayMode: DEFAULT_DISPLAY_MODE,
|
|
331
|
+
settingsUnlocked: isSettingsUnlocked(),
|
|
332
|
+
settingsOpen: false,
|
|
333
|
+
secretClickCount: 0,
|
|
334
|
+
secretClickTimer: null
|
|
268
335
|
}
|
|
269
336
|
},
|
|
270
337
|
computed: {
|
|
@@ -314,8 +381,14 @@ export default {
|
|
|
314
381
|
)
|
|
315
382
|
},
|
|
316
383
|
applyTotalFeeText() {
|
|
384
|
+
// 依赖 displayMode,切换展示偏好时同步刷新
|
|
385
|
+
const mode = this.displayMode
|
|
317
386
|
if (this.applyTotalFee == null || this.applyTotalFee === '') return ''
|
|
318
|
-
return `${formatNumber(this.applyTotalFee
|
|
387
|
+
return `${formatNumber(this.applyTotalFee, {
|
|
388
|
+
digits: this.numberDigits,
|
|
389
|
+
mode,
|
|
390
|
+
fallback: '-'
|
|
391
|
+
})} 元`
|
|
319
392
|
},
|
|
320
393
|
yearText() {
|
|
321
394
|
if (this.year == null || this.year === '') return ''
|
|
@@ -349,9 +422,36 @@ export default {
|
|
|
349
422
|
if (this.productPage > maxPage) this.productPage = 1
|
|
350
423
|
}
|
|
351
424
|
},
|
|
425
|
+
created() {
|
|
426
|
+
this._unsubDisplayMode = subscribeDisplayMode((mode) => {
|
|
427
|
+
this.displayMode = mode
|
|
428
|
+
})
|
|
429
|
+
},
|
|
430
|
+
beforeDestroy() {
|
|
431
|
+
if (this._unsubDisplayMode) this._unsubDisplayMode()
|
|
432
|
+
if (this.secretClickTimer) clearTimeout(this.secretClickTimer)
|
|
433
|
+
},
|
|
352
434
|
methods: {
|
|
435
|
+
formatNumber(v) {
|
|
436
|
+
return formatNumber(v, {
|
|
437
|
+
digits: this.numberDigits,
|
|
438
|
+
mode: this.displayMode,
|
|
439
|
+
fallback: '-'
|
|
440
|
+
})
|
|
441
|
+
},
|
|
353
442
|
formatMoney(v) {
|
|
354
|
-
return formatMoney(v, {
|
|
443
|
+
return formatMoney(v, {
|
|
444
|
+
digits: this.numberDigits,
|
|
445
|
+
mode: this.displayMode,
|
|
446
|
+
fallback: '-'
|
|
447
|
+
})
|
|
448
|
+
},
|
|
449
|
+
gapLabelOf(row) {
|
|
450
|
+
if (!row) return '-'
|
|
451
|
+
if (row.gap === undefined || row.gap === null || row.gap === '') {
|
|
452
|
+
return row.gapLabel || '-'
|
|
453
|
+
}
|
|
454
|
+
return formatGapLabel(row.gap, { mode: this.displayMode }) || row.gapLabel || '-'
|
|
355
455
|
},
|
|
356
456
|
shiftAria(row) {
|
|
357
457
|
if (!row) return ''
|
|
@@ -365,6 +465,39 @@ export default {
|
|
|
365
465
|
},
|
|
366
466
|
onProductPage(page) {
|
|
367
467
|
this.productPage = page
|
|
468
|
+
},
|
|
469
|
+
/** 连点标题 5 次:未解锁则显示设置入口,已解锁则隐藏 */
|
|
470
|
+
onSecretTitleClick() {
|
|
471
|
+
this.secretClickCount += 1
|
|
472
|
+
if (this.secretClickTimer) clearTimeout(this.secretClickTimer)
|
|
473
|
+
this.secretClickTimer = setTimeout(() => {
|
|
474
|
+
this.secretClickCount = 0
|
|
475
|
+
this.secretClickTimer = null
|
|
476
|
+
}, SECRET_CLICK_WINDOW_MS)
|
|
477
|
+
if (this.secretClickCount < SECRET_CLICK_NEED) return
|
|
478
|
+
this.secretClickCount = 0
|
|
479
|
+
if (this.secretClickTimer) {
|
|
480
|
+
clearTimeout(this.secretClickTimer)
|
|
481
|
+
this.secretClickTimer = null
|
|
482
|
+
}
|
|
483
|
+
if (this.settingsUnlocked) {
|
|
484
|
+
this.onLockSettings()
|
|
485
|
+
return
|
|
486
|
+
}
|
|
487
|
+
unlockSettings()
|
|
488
|
+
this.settingsUnlocked = true
|
|
489
|
+
// popover 的 reference 刚渲染出来,需等 DOM 就绪后再打开
|
|
490
|
+
this.$nextTick(() => {
|
|
491
|
+
this.settingsOpen = true
|
|
492
|
+
})
|
|
493
|
+
},
|
|
494
|
+
selectDisplayMode(mode) {
|
|
495
|
+
this.displayMode = setDisplayMode(mode)
|
|
496
|
+
},
|
|
497
|
+
onLockSettings() {
|
|
498
|
+
lockSettings()
|
|
499
|
+
this.settingsOpen = false
|
|
500
|
+
this.settingsUnlocked = false
|
|
368
501
|
}
|
|
369
502
|
}
|
|
370
503
|
}
|
|
@@ -372,6 +505,7 @@ export default {
|
|
|
372
505
|
|
|
373
506
|
<style lang="scss" scoped>
|
|
374
507
|
.floor-price-board {
|
|
508
|
+
position: relative;
|
|
375
509
|
width: 100%;
|
|
376
510
|
max-width: 100%;
|
|
377
511
|
min-width: 0;
|
|
@@ -415,6 +549,8 @@ export default {
|
|
|
415
549
|
font-weight: 600;
|
|
416
550
|
color: var(--fpb-text);
|
|
417
551
|
line-height: 1;
|
|
552
|
+
cursor: default;
|
|
553
|
+
user-select: none;
|
|
418
554
|
}
|
|
419
555
|
|
|
420
556
|
.fpb-body {
|
|
@@ -518,6 +654,181 @@ export default {
|
|
|
518
654
|
font-size: 17px;
|
|
519
655
|
line-height: 24px;
|
|
520
656
|
font-weight: 600;
|
|
657
|
+
cursor: default;
|
|
658
|
+
user-select: none;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
.fpb-settings-trigger {
|
|
662
|
+
display: inline-flex;
|
|
663
|
+
align-items: center;
|
|
664
|
+
justify-content: center;
|
|
665
|
+
width: 24px;
|
|
666
|
+
height: 24px;
|
|
667
|
+
padding: 0;
|
|
668
|
+
margin: 0;
|
|
669
|
+
border: none;
|
|
670
|
+
border-radius: 50%;
|
|
671
|
+
background: transparent;
|
|
672
|
+
color: var(--fpb-tertiary);
|
|
673
|
+
font-size: 16px;
|
|
674
|
+
cursor: pointer;
|
|
675
|
+
transition: color 0.15s, background-color 0.15s;
|
|
676
|
+
|
|
677
|
+
&:hover,
|
|
678
|
+
&:focus-visible {
|
|
679
|
+
color: var(--fpb-brand);
|
|
680
|
+
background: rgba(51, 112, 255, 0.08);
|
|
681
|
+
outline: none;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/*
|
|
686
|
+
* popover 内容:不用原生 label/input,避免宿主全局样式导致文字重叠。
|
|
687
|
+
* popover 挂在 body 下,拿不到 .floor-price-board 上的变量,需在此重新声明。
|
|
688
|
+
*/
|
|
689
|
+
.fpb-settings {
|
|
690
|
+
--fpb-brand: #3370ff;
|
|
691
|
+
font-size: 13px;
|
|
692
|
+
line-height: 20px;
|
|
693
|
+
color: #1f2329;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
.fpb-settings__head {
|
|
697
|
+
display: flex;
|
|
698
|
+
align-items: baseline;
|
|
699
|
+
justify-content: space-between;
|
|
700
|
+
padding: 0 4px 8px;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
.fpb-settings__title {
|
|
704
|
+
font-size: 14px;
|
|
705
|
+
font-weight: 600;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
.fpb-settings__hint {
|
|
709
|
+
font-size: 12px;
|
|
710
|
+
color: #8f959e;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
.fpb-settings__option {
|
|
714
|
+
display: flex;
|
|
715
|
+
align-items: flex-start;
|
|
716
|
+
gap: 10px;
|
|
717
|
+
padding: 8px 10px;
|
|
718
|
+
border: 1px solid transparent;
|
|
719
|
+
border-radius: 6px;
|
|
720
|
+
cursor: pointer;
|
|
721
|
+
transition: background-color 0.15s, border-color 0.15s;
|
|
722
|
+
|
|
723
|
+
& + & {
|
|
724
|
+
margin-top: 4px;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
&:hover {
|
|
728
|
+
background: #f5f7fa;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
&.is-active {
|
|
732
|
+
border-color: var(--fpb-brand);
|
|
733
|
+
background: #f0f5ff;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
.fpb-settings__radio {
|
|
738
|
+
flex: 0 0 auto;
|
|
739
|
+
position: relative;
|
|
740
|
+
width: 16px;
|
|
741
|
+
height: 16px;
|
|
742
|
+
margin-top: 2px;
|
|
743
|
+
border: 1px solid #c0c4cc;
|
|
744
|
+
border-radius: 50%;
|
|
745
|
+
box-sizing: border-box;
|
|
746
|
+
background: #fff;
|
|
747
|
+
transition: border-color 0.15s, background-color 0.15s;
|
|
748
|
+
|
|
749
|
+
.is-active & {
|
|
750
|
+
border-color: var(--fpb-brand);
|
|
751
|
+
background: var(--fpb-brand);
|
|
752
|
+
|
|
753
|
+
&::after {
|
|
754
|
+
content: '';
|
|
755
|
+
position: absolute;
|
|
756
|
+
top: 50%;
|
|
757
|
+
left: 50%;
|
|
758
|
+
width: 6px;
|
|
759
|
+
height: 6px;
|
|
760
|
+
margin: -3px 0 0 -3px;
|
|
761
|
+
border-radius: 50%;
|
|
762
|
+
background: #fff;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
.fpb-settings__body {
|
|
768
|
+
flex: 1 1 auto;
|
|
769
|
+
display: flex;
|
|
770
|
+
flex-direction: column;
|
|
771
|
+
gap: 2px;
|
|
772
|
+
min-width: 0;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
.fpb-settings__label {
|
|
776
|
+
display: flex;
|
|
777
|
+
align-items: center;
|
|
778
|
+
gap: 6px;
|
|
779
|
+
font-weight: 500;
|
|
780
|
+
|
|
781
|
+
.is-active & {
|
|
782
|
+
color: var(--fpb-brand);
|
|
783
|
+
font-weight: 600;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
.fpb-settings__check {
|
|
788
|
+
flex: 0 0 auto;
|
|
789
|
+
align-self: center;
|
|
790
|
+
color: var(--fpb-brand);
|
|
791
|
+
font-size: 16px;
|
|
792
|
+
font-weight: 700;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
.fpb-settings__tag {
|
|
796
|
+
padding: 0 5px;
|
|
797
|
+
border-radius: 3px;
|
|
798
|
+
background: #eef0f3;
|
|
799
|
+
color: #646a73;
|
|
800
|
+
font-size: 11px;
|
|
801
|
+
font-style: normal;
|
|
802
|
+
font-weight: 400;
|
|
803
|
+
line-height: 16px;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
.fpb-settings__desc {
|
|
807
|
+
font-size: 12px;
|
|
808
|
+
line-height: 18px;
|
|
809
|
+
color: #8f959e;
|
|
810
|
+
font-variant-numeric: tabular-nums;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
.fpb-settings__foot {
|
|
814
|
+
display: flex;
|
|
815
|
+
justify-content: flex-end;
|
|
816
|
+
margin-top: 6px;
|
|
817
|
+
padding: 8px 4px 0;
|
|
818
|
+
border-top: 1px solid #f0f2f5;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
.fpb-settings__link {
|
|
822
|
+
padding: 0;
|
|
823
|
+
border: none;
|
|
824
|
+
background: transparent;
|
|
825
|
+
color: #8f959e;
|
|
826
|
+
font-size: 12px;
|
|
827
|
+
cursor: pointer;
|
|
828
|
+
|
|
829
|
+
&:hover {
|
|
830
|
+
color: var(--fpb-brand);
|
|
831
|
+
}
|
|
521
832
|
}
|
|
522
833
|
|
|
523
834
|
.fpb-badge {
|
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
:key="i"
|
|
143
143
|
class="fpd-section__footer-item"
|
|
144
144
|
>
|
|
145
|
-
{{ v }}
|
|
145
|
+
{{ formatFooterValue(v) }}
|
|
146
146
|
</span>
|
|
147
147
|
</template>
|
|
148
148
|
<template v-else>{{ section.footer.text }}</template>
|
|
@@ -173,6 +173,7 @@
|
|
|
173
173
|
|
|
174
174
|
<script>
|
|
175
175
|
import { DEFAULT_DETAIL_FORMULAS, formatNumber, formatSignedNumber } from './utils'
|
|
176
|
+
import { getDisplayMode, subscribeDisplayMode } from './displayPrefs'
|
|
176
177
|
import FloorPriceSectionPager from './FloorPriceSectionPager.vue'
|
|
177
178
|
|
|
178
179
|
export default {
|
|
@@ -252,7 +253,8 @@ export default {
|
|
|
252
253
|
data() {
|
|
253
254
|
return {
|
|
254
255
|
sectionPages: {},
|
|
255
|
-
isNarrow: false
|
|
256
|
+
isNarrow: false,
|
|
257
|
+
displayMode: getDisplayMode()
|
|
256
258
|
}
|
|
257
259
|
},
|
|
258
260
|
computed: {
|
|
@@ -348,11 +350,15 @@ export default {
|
|
|
348
350
|
if (typeof window !== 'undefined') {
|
|
349
351
|
window.addEventListener('resize', this.updateNarrow)
|
|
350
352
|
}
|
|
353
|
+
this._unsubDisplayMode = subscribeDisplayMode((mode) => {
|
|
354
|
+
this.displayMode = mode
|
|
355
|
+
})
|
|
351
356
|
},
|
|
352
357
|
beforeDestroy() {
|
|
353
358
|
if (typeof window !== 'undefined') {
|
|
354
359
|
window.removeEventListener('resize', this.updateNarrow)
|
|
355
360
|
}
|
|
361
|
+
if (this._unsubDisplayMode) this._unsubDisplayMode()
|
|
356
362
|
},
|
|
357
363
|
methods: {
|
|
358
364
|
updateNarrow() {
|
|
@@ -397,9 +403,9 @@ export default {
|
|
|
397
403
|
},
|
|
398
404
|
formatCell(value, col = {}) {
|
|
399
405
|
if (col.type === 'number' || col.type === 'highlight' || col.digits != null) {
|
|
400
|
-
// 金额按接口原样展示(不千分位、不截断小数)
|
|
401
406
|
return formatNumber(value, {
|
|
402
407
|
digits: col.digits != null ? col.digits : null,
|
|
408
|
+
mode: this.displayMode,
|
|
403
409
|
fallback: '-'
|
|
404
410
|
})
|
|
405
411
|
}
|
|
@@ -409,9 +415,20 @@ export default {
|
|
|
409
415
|
formatGapCell(value, col = {}) {
|
|
410
416
|
return formatSignedNumber(value, {
|
|
411
417
|
digits: col.digits != null ? col.digits : null,
|
|
418
|
+
mode: this.displayMode,
|
|
412
419
|
fallback: '-'
|
|
413
420
|
})
|
|
414
421
|
},
|
|
422
|
+
formatFooterValue(v) {
|
|
423
|
+
if (v == null) return ''
|
|
424
|
+
if (typeof v !== 'object') return String(v)
|
|
425
|
+
if (v.kind === 'qty') {
|
|
426
|
+
const n = v.value == null ? '-' : String(v.value)
|
|
427
|
+
return v.label ? `${v.label} ${n}` : n
|
|
428
|
+
}
|
|
429
|
+
const body = formatNumber(v.value, { mode: this.displayMode, fallback: '-' })
|
|
430
|
+
return v.label ? `${v.label} ${body}` : body
|
|
431
|
+
},
|
|
415
432
|
gapClass(value, row) {
|
|
416
433
|
const n = Number(value != null ? value : row && row.gap)
|
|
417
434
|
if (Number.isNaN(n) || n >= 0) return ''
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 底价价格展示偏好(仅内存,不持久化;刷新页面恢复默认策略)
|
|
3
|
+
*
|
|
4
|
+
* fixed2 — 默认:一律两位小数
|
|
5
|
+
* padMin2 — 托底:不足两位补 0,两位及以上原样
|
|
6
|
+
* raw — 接口原始字符串 / Number 原样
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export const DISPLAY_MODE = {
|
|
10
|
+
FIXED_2: 'fixed2',
|
|
11
|
+
PAD_MIN_2: 'padMin2',
|
|
12
|
+
RAW: 'raw'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const DEFAULT_DISPLAY_MODE = DISPLAY_MODE.FIXED_2
|
|
16
|
+
|
|
17
|
+
export const DISPLAY_MODE_OPTIONS = [
|
|
18
|
+
{ value: DISPLAY_MODE.FIXED_2, label: '固定两位小数', desc: '201 → 201.00,1442.7875 → 1442.79' },
|
|
19
|
+
{ value: DISPLAY_MODE.PAD_MIN_2, label: '不足两位补齐', desc: '201 → 201.00,1442.7875 保持原样' },
|
|
20
|
+
{ value: DISPLAY_MODE.RAW, label: '展示原始数据', desc: '接口返回什么就显示什么' }
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
const listeners = new Set()
|
|
24
|
+
|
|
25
|
+
let currentMode = DEFAULT_DISPLAY_MODE
|
|
26
|
+
let settingsUnlocked = false
|
|
27
|
+
|
|
28
|
+
export function getDisplayMode() {
|
|
29
|
+
return currentMode
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function setDisplayMode(mode) {
|
|
33
|
+
const next = Object.values(DISPLAY_MODE).includes(mode) ? mode : DEFAULT_DISPLAY_MODE
|
|
34
|
+
currentMode = next
|
|
35
|
+
listeners.forEach((fn) => {
|
|
36
|
+
try {
|
|
37
|
+
fn(next)
|
|
38
|
+
} catch (e) {
|
|
39
|
+
/* ignore */
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
return next
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function subscribeDisplayMode(fn) {
|
|
46
|
+
if (typeof fn !== 'function') return () => {}
|
|
47
|
+
listeners.add(fn)
|
|
48
|
+
return () => listeners.delete(fn)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function isSettingsUnlocked() {
|
|
52
|
+
return settingsUnlocked
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function unlockSettings() {
|
|
56
|
+
settingsUnlocked = true
|
|
57
|
+
return true
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function lockSettings() {
|
|
61
|
+
settingsUnlocked = false
|
|
62
|
+
}
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
DEFAULT_STATUS_LABEL,
|
|
9
9
|
buildResultCopy,
|
|
10
10
|
computePriceGap,
|
|
11
|
-
formatNumber,
|
|
12
11
|
resolvePanelState,
|
|
13
12
|
roundMoney
|
|
14
13
|
} from './utils'
|
|
@@ -151,7 +150,7 @@ function buildSections(data = {}) {
|
|
|
151
150
|
footer: {
|
|
152
151
|
label: '合计(含本次)',
|
|
153
152
|
theme: 'purple',
|
|
154
|
-
values: [
|
|
153
|
+
values: [{ kind: 'money', label: '金额', value: sumBy(saleRows, 'amount') }]
|
|
155
154
|
}
|
|
156
155
|
})
|
|
157
156
|
}
|
|
@@ -172,8 +171,8 @@ function buildSections(data = {}) {
|
|
|
172
171
|
label: '合计(含本次)',
|
|
173
172
|
theme: 'danger',
|
|
174
173
|
values: [
|
|
175
|
-
|
|
176
|
-
|
|
174
|
+
{ kind: 'qty', label: '数量', value: sumBy(nonSaleRows, 'qty') },
|
|
175
|
+
{ kind: 'money', label: '折算费用', value: sumBy(nonSaleRows, 'amount') }
|
|
177
176
|
]
|
|
178
177
|
}
|
|
179
178
|
})
|
|
@@ -193,7 +192,7 @@ function buildSections(data = {}) {
|
|
|
193
192
|
footer: {
|
|
194
193
|
label: '合计(含本次)',
|
|
195
194
|
theme: 'danger',
|
|
196
|
-
values: [
|
|
195
|
+
values: [{ kind: 'money', value: sumBy(expenseRows, 'costAmount') }]
|
|
197
196
|
}
|
|
198
197
|
})
|
|
199
198
|
}
|