imeik-bizui 2.5.5 → 2.5.6

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.
@@ -255,3 +255,27 @@ export function queryBudgetDepartManage(data) {
255
255
  data
256
256
  })
257
257
  }
258
+
259
+ /**
260
+ * 丽臻底价概览
261
+ * POST /application-center-admin/openApi/lizhen/basePrice/overview
262
+ */
263
+ export function getLizhenBasePriceOverview(data) {
264
+ return request({
265
+ url: '/application-center-admin/openApi/lizhen/basePrice/overview',
266
+ method: 'post',
267
+ data
268
+ })
269
+ }
270
+
271
+ /**
272
+ * 丽臻底价详情
273
+ * POST /application-center-admin/openApi/lizhen/basePrice/detail
274
+ */
275
+ export function getLizhenBasePriceDetail(data) {
276
+ return request({
277
+ url: '/application-center-admin/openApi/lizhen/basePrice/detail',
278
+ method: 'post',
279
+ data
280
+ })
281
+ }
@@ -2,174 +2,171 @@
2
2
  ApplyCenterAdapter · 申请中心域底价适配器
3
3
 
4
4
  职责
5
- - 把申请中心表单字段(客户、部门、费用类型、产品行 productLines)组装成
6
- getProductPrice / getProductPriceDetail 请求体
7
- - 交给 FloorPriceDashboard 拉数与展示(本组件不写看板 UI)
5
+ - 按《丽臻底价查询接口文档》组装 overview / detail 共用请求体
6
+ - 调用申请中心 openApi,交给 FloorPriceDashboard 拉数展示
8
7
 
9
8
  入参策略
10
- - 概述、明细共用同一份 requestPayload;可带字段尽量都带上,用不用由接口决定
11
- - 新增/编辑:主要靠表单字段(客户、部门、费用类型、materialList)
12
- - 已落库详情:通常有 applyCode,后端可只认单号;前端仍附带表单字段,便于草稿/兼容
13
- - materialList 仅来自 productLines(申请中心产品明细,无组合拆分)
14
-
15
- 与物资 / 会议差异
16
- - 客户 prop 名为 customerInfo(物资为 applyCustomerInfo)
17
- - 物料来源单一:productLines,字段名兼容面更宽(含 productErpCode、count 等)
18
- - 缺客户唯一编码 / 业务线 / 部门 / 费用类型时 requestPayload 为 null(Dashboard 不发请求)
9
+ - 传 formDataCode / formDataNumber → 优先查库快照
10
+ - 未传单号 → 用表单字段实时查
11
+ - formBaseNo 有则传
12
+ - saleBasePriceList / costBasePriceList:有数据才传,无则不带该字段
13
+ - 不按 B07/B05 等表单类型分支,避免业务耦合
19
14
 
20
15
  宿主用法
21
16
  <FieldFloorPriceBoard
22
17
  scene="applyCenter"
23
18
  :customer-info="..."
24
- :cost-type="..."
25
- :apply-dept-code="..."
19
+ :form-base-no="..."
20
+ :form-data-code="..."
21
+ :form-data-number="..."
22
+ :org-code="..."
23
+ :apply-user="..."
26
24
  :cost-bear-dept-code="..."
27
- :apply-code="..."
28
25
  :product-lines="..."
26
+ :expert-lines="..."
29
27
  :show-detail-link="hasPerm"
30
28
  />
31
-
32
- scene 也可传 apply(index.vue 会映射到本适配器)
33
-
34
- 接口:api/mms.getProductPrice / getProductPriceDetail(mmsRequest,随 $bizui.env 切环境)
35
29
  -->
36
30
  <template>
37
31
  <FloorPriceDashboard
38
32
  :overview-payload="requestPayload"
39
33
  :detail-payload="requestPayload"
40
34
  :customer-name="customerName"
41
- :fetch-overview="useMock ? null : getProductPrice"
42
- :fetch-detail="useMock ? null : getProductPriceDetail"
35
+ :fetch-overview="useMock ? null : getLizhenBasePriceOverview"
36
+ :fetch-detail="useMock ? null : getLizhenBasePriceDetail"
43
37
  :use-demo="useMock"
44
38
  :show-title="false"
45
39
  :show-detail-link="showDetailLink"
40
+ empty-text="请选择合作机构后查看底价"
46
41
  />
47
42
  </template>
48
43
 
49
44
  <script>
50
45
  import FloorPriceDashboard from '../core/FloorPriceDashboard.vue'
51
- import { getProductPrice, getProductPriceDetail } from '../../../api/mms'
46
+ import { getLizhenBasePriceOverview, getLizhenBasePriceDetail } from '../../../api/applycenter'
52
47
 
53
48
  export default {
54
49
  name: 'ApplyCenterAdapter',
55
50
  components: { FloorPriceDashboard },
56
51
  props: {
57
52
  /**
58
- * 申请客户信息(选客组件 / 表单 customerInfo)
59
- *
60
- * 读取字段(大小写兼容):
61
- * - customUniqueCode / CustomUniqueCode → 客户唯一编码(缺则不发请求)
62
- * - businessLineNumber / BusinessLineNumber → 业务线(缺则不发请求)
63
- * - isGroupCustomer → 是否集团客户(原样透传)
64
- * - CustomerName / customerName / customName → 看板展示用客户名
53
+ * 申请客户信息
54
+ * - customUniqueCode / customerUniqueCode
55
+ * - businessCode → businessLineNumber(文档约定)
56
+ * - customerName
65
57
  */
66
58
  customerInfo: { type: Object, default: () => ({}) },
67
- /**
68
- * 费用类型(表单 costType);为空则不发请求
69
- */
70
- costType: { type: [String, Number], default: undefined },
71
- /**
72
- * 申请部门业务编码;为空则不发请求
73
- */
74
- applyDeptCode: { type: [String, Number], default: undefined },
75
- /**
76
- * 费用承担部门业务编码;为空则不发请求
77
- */
59
+ /** 表单基础编号,有则透传 */
60
+ formBaseNo: { type: String, default: '' },
61
+ /** 申请单数据 code;有则优先查库快照 */
62
+ formDataCode: { type: String, default: '' },
63
+ /** 申请单号;formDataCode 优先 */
64
+ formDataNumber: { type: String, default: '' },
65
+ /** 申请人部门编码 orgCode */
66
+ orgCode: { type: [String, Number], default: undefined },
67
+ /** 申请人编码 applyUser */
68
+ applyUser: { type: [String, Number], default: undefined },
69
+ /** 费用承担部门,有则透传 */
78
70
  costBearDeptCode: { type: [String, Number], default: undefined },
79
71
  /**
80
- * 已落库申请单编码(objectCode / applyCode)
81
- * - 草稿 / 新增未保存:传空,payload 里为 undefined
82
- * - 编辑 / 查看:有值则带上;详情接口可主要依赖此字段,其它字段仍一并传递
72
+ * 业务线兜底(客户无 businessCode 时,如合作主体 belongCompany)
83
73
  */
84
- applyCode: { type: String, default: '' },
74
+ businessLineNumberFallback: { type: [String, Number], default: undefined },
85
75
  /**
86
- * 申请中心产品明细行 → 映射为接口 materialList
87
- *
88
- * 编码候选:erpCode / productCode / 物料编码 / productErpCode
89
- * 数量候选:applyCount / 数量 / qty / count / quantity
90
- * 过滤:无 erpCode 或 applyCount<=0 的行丢弃;无产品时 materialList 为 []
76
+ * 产品行 → saleBasePriceList(有数据才进请求体)
91
77
  */
92
78
  productLines: { type: Array, default: () => [] },
93
79
  /**
94
- * 是否展示「查看底价明细」入口
95
- * 权限由宿主页传入,本组件不读权限中心
80
+ * 专家行 → costBasePriceList(有合计金额才进请求体;costType 固定「专家费(非会议)」)
96
81
  */
82
+ expertLines: { type: Array, default: () => [] },
97
83
  showDetailLink: { type: Boolean, default: true },
98
- /**
99
- * 本地演示:true 时不调真实接口,Dashboard 走 mock 数据
100
- * 联调 / 上线请传 false
101
- */
102
84
  useMock: { type: Boolean, default: false }
103
85
  },
104
86
  computed: {
105
- /** 看板标题旁展示的客户名称 */
106
87
  customerName() {
107
88
  const c = this.customerInfo || {}
108
89
  return c.CustomerName || c.customerName || c.customName || ''
109
90
  },
110
- /**
111
- * productLines → 接口 materialList[{ erpCode, applyCount }]
112
- * 仅普通行映射,不做物资组合(isGroup)拆分
113
- */
114
- materialList() {
91
+ /** applicationApplyMaterial → saleBasePriceList */
92
+ saleBasePriceList() {
115
93
  const rows = this.productLines
116
94
  if (!Array.isArray(rows) || !rows.length) return []
117
- const erpCodeKeys = ['erpCode', 'productCode', '物料编码', 'productErpCode']
118
- const countKeys = ['applyCount', '数量', 'qty', 'count', 'quantity']
119
- const pick = (row, keys) => {
120
- for (let i = 0; i < keys.length; i++) {
121
- const k = keys[i]
122
- if (row[k] != null && row[k] !== '') return row[k]
123
- }
124
- return ''
125
- }
126
95
  return rows
127
96
  .filter(Boolean)
128
- .map((row) => ({
129
- erpCode: String(pick(row, erpCodeKeys) || ''),
130
- applyCount: Number(pick(row, countKeys)) || 0
131
- }))
132
- .filter((r) => r.erpCode && r.applyCount > 0)
97
+ .map((row) => {
98
+ const productCode = String(row.productCode || row.materialCode || row.erpCode || row.productErpCode || '')
99
+ const productQuantity = Number(row.materialQuantity ?? row.productQuantity ?? row.applyCount ?? row.quantity) || 0
100
+ const productPrice = Number(row.orderPrice ?? row.productPrice ?? row.unitPrice)
101
+ return {
102
+ productCode,
103
+ abbreviation: row.abbreviation || row.materialName || row.productShortName || row.productName || '',
104
+ productQuantity,
105
+ productPrice: Number.isFinite(productPrice) ? productPrice : undefined
106
+ }
107
+ })
108
+ .filter((r) => r.productCode && r.productQuantity > 0)
109
+ },
110
+ /** applicationCostDoctor → 合计一条专家费 */
111
+ costBasePriceList() {
112
+ const rows = this.expertLines
113
+ if (!Array.isArray(rows) || !rows.length) return []
114
+ const costAmount = rows.filter(Boolean).reduce((sum, row) => sum + (Number(row.costAmount) || 0), 0)
115
+ if (costAmount <= 0) return []
116
+ return [
117
+ {
118
+ costType: '专家费(非会议)',
119
+ costAmount
120
+ }
121
+ ]
133
122
  },
134
123
  /**
135
- * 概述 / 明细共用请求体
136
- *
137
- * 必填缺一则返回 null(Dashboard 不发请求):
138
- * customUniqueCode、businessLineNumber、applyDeptCode、costBearDeptCode、costType
139
- *
140
- * 字段说明:
141
- * - applyCode 可选;有则带上
142
- * - customUniqueCode 客户唯一编码
143
- * - businessLineNumber 业务线
144
- * - isGroupCustomer 是否集团客户(透传)
145
- * - applyDeptCode 申请部门
146
- * - costBearDeptCode 费用承担部门
147
- * - costType 费用类型
148
- * - materialList 产品行;允许 []
124
+ * 丽臻底价共用请求体;无法发起查询时返回 null(Dashboard 不发请求)
125
+ * 实时查:只要有合作机构(客户唯一编码)就调;列表有数据才带上对应字段
149
126
  */
150
127
  requestPayload() {
151
- const c = this.customerInfo || {}
152
- const customUniqueCode = c.customUniqueCode || c.CustomUniqueCode || ''
153
- const businessLineNumber = c.businessLineNumber || c.BusinessLineNumber || ''
154
- const { applyDeptCode, costBearDeptCode, costType, materialList } = this
155
- if (!customUniqueCode || !businessLineNumber) return null
156
- if (!applyDeptCode || !costBearDeptCode) return null
157
- if (costType == null || costType === '') return null
158
- return {
159
- applyCode: this.applyCode || undefined,
160
- customUniqueCode: String(customUniqueCode),
161
- businessLineNumber: String(businessLineNumber),
162
- isGroupCustomer: c.isGroupCustomer,
163
- applyDeptCode: String(applyDeptCode),
164
- costBearDeptCode: String(costBearDeptCode),
165
- costType: String(costType),
166
- materialList: Array.isArray(materialList) ? materialList : []
128
+ const formDataCode = this.formDataCode || ''
129
+ const formDataNumber = this.formDataNumber || ''
130
+ // 有单号:按文档可只传单号查快照
131
+ if (formDataCode || formDataNumber) {
132
+ const payload = {}
133
+ if (formDataCode) payload.formDataCode = String(formDataCode)
134
+ if (formDataNumber) payload.formDataNumber = String(formDataNumber)
135
+ Object.assign(payload, this.buildRealtimeFields())
136
+ return payload
167
137
  }
138
+ // 实时查:仅要求合作机构(客户唯一编码)
139
+ const realtime = this.buildRealtimeFields()
140
+ if (!realtime.customUniqueCode) return null
141
+ return realtime
168
142
  }
169
143
  },
170
144
  methods: {
171
- getProductPrice,
172
- getProductPriceDetail
145
+ getLizhenBasePriceOverview,
146
+ getLizhenBasePriceDetail,
147
+ /** 组装实时查询字段(不含单号);列表仅在有数据时挂载 */
148
+ buildRealtimeFields() {
149
+ const c = this.customerInfo || {}
150
+ const customUniqueCode = c.customUniqueCode || c.CustomUniqueCode || c.customerUniqueCode || ''
151
+ const businessLineNumber =
152
+ c.businessCode || c.businessLineNumber || c.BusinessLineNumber || this.businessLineNumberFallback || ''
153
+ const payload = {}
154
+ if (this.formBaseNo) payload.formBaseNo = String(this.formBaseNo)
155
+ if (customUniqueCode) payload.customUniqueCode = String(customUniqueCode)
156
+ if (businessLineNumber) payload.businessLineNumber = String(businessLineNumber)
157
+ if (this.orgCode != null && this.orgCode !== '') payload.orgCode = String(this.orgCode)
158
+ if (this.applyUser != null && this.applyUser !== '') payload.applyUser = String(this.applyUser)
159
+ if (this.costBearDeptCode != null && this.costBearDeptCode !== '') {
160
+ payload.costBearDeptCode = String(this.costBearDeptCode)
161
+ }
162
+ if (this.saleBasePriceList.length) {
163
+ payload.saleBasePriceList = this.saleBasePriceList
164
+ }
165
+ if (this.costBasePriceList.length) {
166
+ payload.costBasePriceList = this.costBasePriceList
167
+ }
168
+ return payload
169
+ }
173
170
  }
174
171
  }
175
172
  </script>
@@ -13,9 +13,10 @@
13
13
  <div v-if="error" class="fpb-msg fpb-msg--error">{{ error }}</div>
14
14
 
15
15
  <div v-else-if="hasContent" :class="['fpb-panel', panelThemeClass]">
16
- <!-- 状态标识:申请后触底 / 申请后正常 -->
17
- <div v-if="resolvedStatusLabel" class="fpb-status-row">
18
- <span :class="['fpb-tag', statusTagClass]">{{ resolvedStatusLabel }}</span>
16
+ <!-- 状态标识:申请后触底 / 申请后正常;Mock 时同排展示 -->
17
+ <div v-if="resolvedStatusLabel || useDemo" class="fpb-status-row">
18
+ <span v-if="resolvedStatusLabel" :class="['fpb-tag', statusTagClass]">{{ resolvedStatusLabel }}</span>
19
+ <span v-if="useDemo" class="fpb-tag fpb-tag--mock">Mock 演示数据</span>
19
20
  </div>
20
21
 
21
22
  <!-- 左元信息 · 右查看明细 -->
@@ -160,6 +161,11 @@ export default {
160
161
  type: String,
161
162
  default: '查看底价明细 →'
162
163
  },
164
+ /** 演示数据标识:为 true 时在看板内展示 Mock 徽标 */
165
+ useDemo: {
166
+ type: Boolean,
167
+ default: false
168
+ },
163
169
  numberDigits: {
164
170
  type: Number,
165
171
  default: null
@@ -197,8 +203,12 @@ export default {
197
203
  panelThemeClass() {
198
204
  return this.resolvedStatus === 'hit' ? 'fpb-panel--hit' : 'fpb-panel--ok'
199
205
  },
206
+ /**
207
+ * 有产品 / 元信息 / 接口显式状态才算有内容
208
+ * 不用 resolvedStatusLabel:空数据时默认「申请后正常」会误出空看板
209
+ */
200
210
  hasContent() {
201
- return this.displayProducts.length > 0 || !!this.metaText || !!this.resolvedStatusLabel
211
+ return this.displayProducts.length > 0 || !!this.metaText || !!this.statusLabel
202
212
  },
203
213
  pagedProducts() {
204
214
  const size = this.resolvedPageSize
@@ -333,6 +343,7 @@ export default {
333
343
  .fpb-status-row {
334
344
  display: flex;
335
345
  align-items: center;
346
+ gap: 8px;
336
347
  margin-bottom: 8px;
337
348
  min-width: 0;
338
349
  }
@@ -375,6 +386,12 @@ export default {
375
386
  background: #f6ffed;
376
387
  }
377
388
 
389
+ .fpb-tag--mock {
390
+ color: #d48806;
391
+ border: 1px solid #ffc53d;
392
+ background: #fffbe6;
393
+ }
394
+
378
395
  .fpb-meta-row {
379
396
  display: flex;
380
397
  align-items: center;
@@ -29,6 +29,8 @@
29
29
  :meta-text="board.metaText"
30
30
  :footer-text="board.footerText"
31
31
  :show-detail-link="showDetailLink"
32
+ :use-demo="useDemo"
33
+ :empty-text="emptyText"
32
34
  @view-detail="onViewDetail"
33
35
  />
34
36
  <FloorPriceDetailDialog
@@ -111,7 +113,9 @@ export default {
111
113
  showTitle: { type: Boolean, default: false },
112
114
  showDetailLink: { type: Boolean, default: true },
113
115
  useDemo: { type: Boolean, default: false },
114
- customerName: { type: String, default: '' }
116
+ customerName: { type: String, default: '' },
117
+ /** 无概览数据时的空态文案 */
118
+ emptyText: { type: String, default: '请选择客户并添加产品/专家后查看底价' }
115
119
  },
116
120
  data() {
117
121
  return {
@@ -43,29 +43,13 @@ export function createDemoOverview() {
43
43
  applyThisFeeAmount: 4792,
44
44
  applyAfterGenuineNum: 90,
45
45
  applyAfterFreeNum: 6
46
- },
47
- {
48
- productCode: 'haiti25',
49
- erpCode: 'haiti25',
50
- productName: '嗨体 2.5ml',
51
- productShortName: '嗨体2.5ml',
52
- applyBeforePrice: 612,
53
- applyAfterPrice: 598,
54
- productBasePrice: 605,
55
- touchBottom: true,
56
- applyAfterSaleOrderAmount: 45600,
57
- applyAfterNoSaleOrderAmount: 900,
58
- applyAfterFeeAmount: 1500,
59
- applyThisFeeAmount: 2100,
60
- applyAfterGenuineNum: 66,
61
- applyAfterFreeNum: 6
62
46
  }
63
47
  ]
64
48
  }
65
49
  }
66
50
 
67
51
  function buildSalesOrderRows() {
68
- const products = ['灵塑100', '塑菲200', '嗨体2.5ml']
52
+ const products = ['灵塑100', '塑菲200']
69
53
  const types = ['GENUINE', 'FREE']
70
54
  const rows = []
71
55
  for (let i = 1; i <= 12; i++) {
@@ -76,14 +60,14 @@ function buildSalesOrderRows() {
76
60
  productName,
77
61
  saleType: types[i % types.length],
78
62
  qty,
79
- amount: qty * (productName === '塑菲200' ? 1040 : productName === '嗨体2.5ml' ? 680 : 820)
63
+ amount: qty * (productName === '塑菲200' ? 1040 : 820)
80
64
  })
81
65
  }
82
66
  return rows
83
67
  }
84
68
 
85
69
  function buildNonSalesRows() {
86
- const products = ['灵塑100', '塑菲200', '嗨体2.5ml']
70
+ const products = ['灵塑100', '塑菲200']
87
71
  const rows = []
88
72
  for (let i = 1; i <= 8; i++) {
89
73
  const qty = 2 + (i % 5)