Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yd-csf-h5
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
jianan
yd-csf-h5
Commits
ce3e433a
Commit
ce3e433a
authored
Nov 02, 2026
by
yuzhenWang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修改样式
parent
5491ae58
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
199 additions
and
66 deletions
+199
-66
package-lock.json
+0
-0
src/App.vue
+2
-3
src/api/types.ts
+1
-0
src/components/dev/DevBrokerSwitcher.vue
+25
-14
src/components/feature/PipelineCard.vue
+13
-4
src/components/feature/PolicyCard.vue
+4
-2
src/components/feature/StatementDetail.vue
+21
-8
src/components/feature/StatementList.vue
+2
-2
src/views/HomeView.vue
+48
-16
src/views/PipelineView.vue
+43
-7
src/views/PoliciesView.vue
+35
-10
tailwind.config.js
+5
-0
No files found.
package-lock.json
0 → 100644
View file @
ce3e433a
This source diff could not be displayed because it is too large. You can
view the blob
instead.
src/App.vue
View file @
ce3e433a
...
...
@@ -36,7 +36,7 @@ function isActive(path: string): boolean {
<div
class=
"h-[3px] bg-brand-600"
></div>
<header
class=
"sticky top-0 z-20 border-b border-silver-200/70 bg-white/80 backdrop-blur-lg"
>
<div
class=
"mx-auto flex max-w-3xl items-center justify-between px-4 py-3"
>
<div
class=
"text-[1
5
px] font-semibold tracking-tight text-brand-700"
>
{{
t
(
'app.title'
)
}}
</div>
<div
class=
"text-[1
8
px] font-semibold tracking-tight text-brand-700"
>
{{
t
(
'app.title'
)
}}
</div>
<LoginBadge
/>
</div>
</header>
...
...
@@ -67,4 +67,4 @@ function isActive(path: string): boolean {
</div>
</nav>
</div>
</
template
>
\ No newline at end of file
</
template
>
src/api/types.ts
View file @
ce3e433a
...
...
@@ -145,6 +145,7 @@ export interface PolicyCommissionYear {
status
:
CommissionStatus
/** 保留/失效原因(财务登记,可能为空) */
statusDesc
?:
string
stage
?:
string
}
export
interface
PipelineItem
{
...
...
src/components/dev/DevBrokerSwitcher.vue
View file @
ce3e433a
...
...
@@ -17,28 +17,28 @@ const open = ref(false)
const
keyword
=
ref
(
''
)
const
selectedName
=
computed
(
()
=>
brokers
.
value
.
find
(
(
b
)
=>
b
.
brokerBizId
===
selectedBizId
.
value
)?.
brokerName
??
''
()
=>
brokers
.
value
.
find
(
b
=>
b
.
brokerBizId
===
selectedBizId
.
value
)?.
brokerName
??
''
)
const
filtered
=
computed
(()
=>
{
const
kw
=
keyword
.
value
.
trim
().
toLowerCase
()
const
all
=
kw
?
brokers
.
value
.
filter
(
(
b
)
=>
b
.
brokerName
.
toLowerCase
().
includes
(
kw
))
?
brokers
.
value
.
filter
(
b
=>
b
.
brokerName
.
toLowerCase
().
includes
(
kw
))
:
brokers
.
value
// 后端已按 hasStatement 倒序返回,这里分组保持顺序
return
{
withStatement
:
all
.
filter
(
(
b
)
=>
b
.
hasStatement
),
rest
:
all
.
filter
(
(
b
)
=>
!
b
.
hasStatement
)
withStatement
:
all
.
filter
(
b
=>
b
.
hasStatement
),
rest
:
all
.
filter
(
b
=>
!
b
.
hasStatement
)
}
})
onMounted
(
async
()
=>
{
try
{
brokers
.
value
=
await
get
<
BrokerOption
[]
>
(
'/c/dev/brokers
'
)
loaded
.
value
=
true
}
catch
(
e
)
{
error
.
value
=
e
instanceof
Error
?
e
.
message
:
'error'
}
//
try {
// brokers.value = await get
<
BrokerOption
[]
>
(
'
'
)
//
loaded.value = true
//
} catch (e) {
//
error.value = e instanceof Error ? e.message : 'error'
//
}
})
function
toggle
()
{
...
...
@@ -72,7 +72,7 @@ function pick(broker: BrokerOption) {
type=
"text"
placeholder=
"搜索姓名…"
class=
"w-full border-b border-amber-200 px-2.5 py-2 text-xs outline-none placeholder:text-slate-400"
>
/
>
<ul
class=
"max-h-[50vh] overflow-y-auto py-1"
>
<li
class=
"cursor-pointer px-2.5 py-1.5 text-slate-600 hover:bg-amber-50"
...
...
@@ -81,7 +81,10 @@ function pick(broker: BrokerOption) {
— 未选择 —
</li>
<li
v-if=
"filtered.withStatement.length"
class=
"px-2.5 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-amber-700"
>
<li
v-if=
"filtered.withStatement.length"
class=
"px-2.5 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-amber-700"
>
有月结单 ·
{{
filtered
.
withStatement
.
length
}}
</li>
<li
...
...
@@ -94,7 +97,10 @@ function pick(broker: BrokerOption) {
{{
b
.
brokerName
}}
</li>
<li
v-if=
"filtered.rest.length"
class=
"px-2.5 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-slate-400"
>
<li
v-if=
"filtered.rest.length"
class=
"px-2.5 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-slate-400"
>
其他有保单归属 ·
{{
filtered
.
rest
.
length
}}
</li>
<li
...
...
@@ -107,7 +113,12 @@ function pick(broker: BrokerOption) {
{{
b
.
brokerName
}}
</li>
<li
v-if=
"filtered.withStatement.length + filtered.rest.length === 0"
class=
"px-2.5 py-2 text-slate-400"
>
无匹配
</li>
<li
v-if=
"filtered.withStatement.length + filtered.rest.length === 0"
class=
"px-2.5 py-2 text-slate-400"
>
无匹配
</li>
</ul>
</div>
...
...
src/components/feature/PipelineCard.vue
View file @
ce3e433a
...
...
@@ -18,15 +18,24 @@ function statusClass(status: PipelineItem['status']): string {
</
script
>
<
template
>
<div
class=
"rounded-2xl border border-silver-200 bg-white p-4 shadow-card"
>
<div
class=
"rounded-2xl border border-silver-200 bg-white p-4 shadow-card"
v-if=
"item.expectedAmount > 0"
>
<div
class=
"flex items-center justify-between"
>
<div>
<div
class=
"text-sm font-medium tracking-tight"
>
{{
item
.
policyNo
}}
</div>
<div
class=
"mt-1 text-xs text-slate-500"
>
{{
t
(
'pipeline.payoutMonth'
)
}}
{{
item
.
payoutMonth
}}
</div>
<div
class=
"mt-1 text-xs text-slate-500"
>
{{
t
(
'pipeline.payoutMonth'
)
}}
{{
item
.
payoutMonth
}}
</div>
</div>
<div
class=
"text-right"
>
<div
class=
"tnum text-sm font-semibold"
>
{{
formatDetailMoney
(
item
.
expectedAmount
,
item
.
currency
)
}}
</div>
<div
class=
"mt-1 text-xs font-medium"
:class=
"statusClass(item.status)"
>
{{
t
(
`stage.${item.status
}
`
)
}}
<
/div
>
<div
class=
"tnum text-sm font-semibold"
>
总保费:
{{
formatDetailMoney
(
item
.
expectedAmount
,
item
.
currency
)
}}
</div>
<div
class=
"mt-1 text-xs font-medium"
:class=
"statusClass(item.status)"
>
{{
t
(
`stage.${item.status
}
`
)
}}
<
/div
>
<
/div
>
<
/div
>
<
/div
>
...
...
src/components/feature/PolicyCard.vue
View file @
ce3e433a
...
...
@@ -30,7 +30,9 @@ const statusTone = computed(() => (props.policy.status === 'LAPSED' ? 'neutral'
<div
class=
"min-w-0"
>
<div
class=
"flex items-center gap-2"
>
<span
class=
"truncate text-sm font-medium tracking-tight"
>
{{
policy
.
policyNo
}}
</span>
<Badge
v-if=
"showStatus"
:tone=
"statusTone"
>
{{
t
(
`policyStatus.${policy.status
}
`
)
}}
<
/Badge
>
<Badge
v-if=
"showStatus"
:tone=
"statusTone"
>
{{
t
(
`policyStatus.${policy.status
}
`
)
}}
<
/Badge
>
<
/div
>
<
div
class
=
"mt-1 truncate text-xs text-silver-600"
>
{{
policy
.
productName
||
'—'
}}
<
/div
>
<
div
v
-
if
=
"policy.insurerName"
class
=
"mt-0.5 truncate text-xs text-silver-400"
>
...
...
@@ -39,7 +41,7 @@ const statusTone = computed(() => (props.policy.status === 'LAPSED' ? 'neutral'
<
/div
>
<
div
class
=
"shrink-0 text-right"
>
<
div
class
=
"tnum text-sm font-semibold"
>
{{
formatDetailMoney
(
policy
.
fullPremium
,
policy
.
currency
)
}}
总保费
:
{{
formatDetailMoney
(
policy
.
fullPremium
,
policy
.
currency
)
}}
<
/div
>
<
div
class
=
"mt-0.5 text-xs text-silver-400"
>
{{
t
(
'policies.myRatio'
)
}}
{{
policy
.
myRatio
?
formatPercent
(
policy
.
myRatio
)
:
'—'
}}
...
...
src/components/feature/StatementDetail.vue
View file @
ce3e433a
...
...
@@ -4,7 +4,11 @@ import { useI18n } from 'vue-i18n'
import
{
formatDetailMoney
,
formatHkd
}
from
'@/utils/money'
import
{
formatPercent
}
from
'@/utils/number'
import
{
calcPremiumTotals
}
from
'@/utils/premium'
import
type
{
PaymentFrequency
,
StatementDetail
as
StatementDetailType
,
StatementItem
}
from
'@/api/types'
import
type
{
PaymentFrequency
,
StatementDetail
as
StatementDetailType
,
StatementItem
}
from
'@/api/types'
const
props
=
defineProps
<
{
detail
:
StatementDetailType
...
...
@@ -81,10 +85,13 @@ function rateText(rate: number): string {
</div>
</div>
</div>
<p
class=
"mt-2 text-[1
1
px] text-silver-400"
>
{{
t
(
'statement.amountHint'
)
}}
</p>
<p
class=
"mt-2 text-[1
2
px] text-silver-400"
>
{{
t
(
'statement.amountHint'
)
}}
</p>
<!-- 减项:没值就不显示 -->
<dl
v-if=
"hasMpf || hasAdjustment"
class=
"mt-3 space-y-2 border-t border-silver-100 pt-3 text-sm"
>
<dl
v-if=
"hasMpf || hasAdjustment"
class=
"mt-3 space-y-2 border-t border-silver-100 pt-3 text-sm"
>
<div
v-if=
"hasMpf"
>
<div
class=
"flex items-center justify-between gap-3"
>
<dt
class=
"text-silver-600"
>
{{
t
(
'statement.mpfItem'
)
}}
</dt>
...
...
@@ -103,7 +110,10 @@ function rateText(rate: number): string {
</div>
</dl>
<div
v-if=
"detail.remark"
class=
"mt-3 rounded-xl bg-silver-50 px-3 py-2 text-xs text-silver-600"
>
<div
v-if=
"detail.remark"
class=
"mt-3 rounded-xl bg-silver-50 px-3 py-2 text-xs text-silver-600"
>
<span
class=
"font-medium"
>
{{
t
(
'statement.remark'
)
}}
</span>
<p
class=
"mt-1 whitespace-pre-line leading-relaxed"
>
{{
detail
.
remark
}}
</p>
</div>
...
...
@@ -165,7 +175,7 @@ function rateText(rate: number): string {
:key=
"item.id"
:class=
"index ? 'mt-3 border-t border-silver-100 pt-3' : ''"
>
<div
class=
"flex items-start justify-between gap-3"
>
<div
class=
"flex items-start justify-between gap-3"
v-if=
"item.originalAmount > 0"
>
<div
class=
"min-w-0"
>
<div
class=
"truncate text-sm font-medium"
>
{{
item
.
policyNo
}}
</div>
<div
class=
"mt-0.5 truncate text-xs text-silver-500"
>
...
...
@@ -173,10 +183,10 @@ function rateText(rate: number): string {
</div>
</div>
<div
class=
"shrink-0 text-right"
>
<div
class=
"tnum text-sm font-semibold"
>
<div
class=
"tnum text-sm font-semibold"
>
≈
{{
formatHkd
(
item
.
hkdAmount
)
}}
</div>
<div
class=
"tnum mt-0.5 text-xs text-silver-400"
>
{{
formatDetailMoney
(
item
.
originalAmount
,
item
.
originalCurrency
)
}}
</div>
<div
class=
"tnum mt-0.5 text-xs text-silver-400"
>
≈
{{
formatHkd
(
item
.
hkdAmount
)
}}
</div>
</div>
</div>
...
...
@@ -193,7 +203,9 @@ function rateText(rate: number): string {
</div>
<div
class=
"flex gap-1.5"
>
<dt
class=
"shrink-0 text-silver-500"
>
{{
t
(
'statement.ratioShare'
)
}}
</dt>
<dd
class=
"text-silver-700"
>
{{
item
.
myRatio
?
formatPercent
(
item
.
myRatio
)
:
'—'
}}
</dd>
<dd
class=
"text-silver-700"
>
{{
item
.
myRatio
?
formatPercent
(
item
.
myRatio
)
:
'—'
}}
</dd>
</div>
<div
class=
"flex gap-1.5"
>
<dt
class=
"shrink-0 text-silver-500"
>
{{
t
(
'statement.policyRate'
)
}}
</dt>
...
...
@@ -203,6 +215,7 @@ function rateText(rate: number): string {
<dt
class=
"shrink-0 text-silver-500"
>
{{
t
(
'statement.premiumTerm'
)
}}
</dt>
<dd
class=
"tnum text-silver-700"
>
{{
premiumText
(
item
)
}}
</dd>
</div>
<div
v-if=
"item.remark"
class=
"col-span-2 flex gap-1.5"
>
<dt
class=
"shrink-0 text-silver-500"
>
{{
t
(
'statement.itemRemark'
)
}}
</dt>
<dd
class=
"text-silver-600"
>
{{
item
.
remark
}}
</dd>
...
...
src/components/feature/StatementList.vue
View file @
ce3e433a
...
...
@@ -25,14 +25,14 @@ const { t } = useI18n()
<div
class=
"min-w-0"
>
<div
class=
"flex items-baseline gap-2"
>
<span
class=
"text-sm font-medium tracking-tight"
>
{{
statement
.
month
||
'—'
}}
</span>
<span
class=
"text-[1
1
px] text-silver-400"
>
{{
t
(
'statement.salaryMonth'
)
}}
</span>
<span
class=
"text-[1
4
px] text-silver-400"
>
{{
t
(
'statement.salaryMonth'
)
}}
</span>
</div>
<div
class=
"mt-1 truncate text-xs text-silver-500"
>
{{
t
(
'statement.payDate'
)
}}
{{
statement
.
payDate
||
'—'
}}
</div>
</div>
<div
class=
"shrink-0 text-right"
>
<div
class=
"text-[1
1
px] text-silver-500"
>
<div
class=
"text-[1
4
px] text-silver-500"
>
{{
t
(
'statement.gross'
)
}}
<span
class=
"tnum"
>
{{
formatHkd
(
statement
.
grossAmount
)
}}
</span>
</div>
...
...
src/views/HomeView.vue
View file @
ce3e433a
...
...
@@ -20,12 +20,14 @@ const heroCard = computed(() =>
:
null
)
const
restCards
=
computed
(()
=>
{
type
RestCard
=
{
label
:
string
;
value
:
string
;
to
?:
string
}
const
restCards
=
computed
<
RestCard
[]
>
(()
=>
{
if
(
!
metrics
.
value
)
return
[]
return
[
{
label
:
t
(
'metric.taxYearPaid'
),
value
:
formatHkd
(
metrics
.
value
.
taxYearPaidHkd
)
},
{
label
:
t
(
'metric.pipeline'
),
value
:
formatHkd
(
metrics
.
value
.
pipelineHkd
)
},
{
label
:
t
(
'metric.inforceCount'
),
value
:
String
(
metrics
.
value
.
inforceCount
)
},
{
label
:
t
(
'metric.pipeline'
),
value
:
formatHkd
(
metrics
.
value
.
pipelineHkd
)
,
to
:
'/pipeline'
},
{
label
:
t
(
'metric.inforceCount'
),
value
:
String
(
metrics
.
value
.
inforceCount
)
,
to
:
'/policies'
},
{
label
:
t
(
'metric.firstYearFyp'
),
value
:
formatHkd
(
metrics
.
value
.
firstYearFypHkd
)
}
]
})
...
...
@@ -63,9 +65,19 @@ onMounted(load)
<ApiLoader
:loading=
"loading"
:error=
"error"
@
retry=
"load"
>
<MetricCard
v-if=
"heroCard"
feature
:label=
"heroCard.label"
:value=
"heroCard.value"
/>
<div
class=
"mt-3 grid grid-cols-2 gap-3"
>
<MetricCard
v-for=
"card in restCards"
:key=
"card.label"
:label=
"card.label"
:value=
"card.value"
/>
<!--
<MetricCard
v-for=
"card in restCards"
:key=
"card.label"
:label=
"card.label"
:value=
"card.value"
/>
-->
<template
v-for=
"card in restCards"
:key=
"card.label"
>
<router-link
v-if=
"card.to"
:to=
"card.to"
class=
"block"
>
<MetricCard
:label=
"card.label"
:value=
"card.value"
/>
</router-link>
<MetricCard
v-else
:label=
"card.label"
:value=
"card.value"
/>
</
template
>
</div>
<router-link
v-if=
"metrics"
to=
"/customers"
...
...
@@ -73,37 +85,58 @@ onMounted(load)
>
<div>
<div
class=
"text-xs text-slate-500"
>
{{ t('metric.myCustomers') }}
</div>
<div
class=
"tnum mt-2 text-xl font-semibold tracking-tight text-slate-900"
>
{{
metrics
.
caseCount
}}
</div>
<div
class=
"tnum mt-2 text-xl font-semibold tracking-tight text-slate-900"
>
{{ metrics.caseCount }}
</div>
</div>
<div
class=
"flex items-center gap-1 text-xs text-slate-400"
>
{{ t('customer.followingHint', { count: metrics.followingCount }) }}
<
svg
xmlns
=
"http://www.w3.org/2000/svg"
viewBox
=
"0 0 24 24"
fill
=
"none"
stroke
=
"currentColor"
stroke
-
width
=
"2"
stroke
-
linecap
=
"round"
stroke
-
linejoin
=
"round"
class
=
"h-4 w-4"
>
<svg
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 24 24"
fill=
"none"
stroke=
"currentColor"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
class=
"h-4 w-4"
>
<polyline
points=
"9 18 15 12 9 6"
/>
</svg>
</div>
</router-link>
<
section
class
=
"mt-7"
>
<
!-- <
section class="mt-7">
<div class="mb-3 flex items-center gap-2">
<
h2
class
=
"text-[13px] font-semibold tracking-wide text-silver-600"
>
{{
t
(
'dashboard.actions'
)
}}
<
/h2
>
<h2 class="text-[13px] font-semibold tracking-wide text-silver-600">
{{ t('dashboard.actions') }}
</h2>
<span
v-if="todoDataSource === 'mock'"
class="rounded-full bg-amber-50 px-2 py-0.5 text-[11px] font-medium text-amber-700"
>
{{
t
(
'todo.sample'
)
}}
<
/span
>
>{{ t('todo.sample') }}</span
>
</div>
<div class="mb-3 flex flex-wrap gap-2 text-xs text-slate-500">
<
span
class
=
"rounded-full bg-slate-100 px-2.5 py-1"
>
{{
t
(
'todo.renewal'
)
}}
{{
countByType
.
renewal
}}
<
/span
>
<
span
class
=
"rounded-full bg-slate-100 px-2.5 py-1"
>
{{
t
(
'todo.lapse'
)
}}
{{
countByType
.
lapse
}}
<
/span
>
<
span
class
=
"rounded-full bg-slate-100 px-2.5 py-1"
>
{{
t
(
'todo.birthday'
)
}}
{{
countByType
.
birthday
}}
<
/span
>
<span class="rounded-full bg-slate-100 px-2.5 py-1"
>{{ t('todo.renewal') }} {{ countByType.renewal }}</span
>
<span class="rounded-full bg-slate-100 px-2.5 py-1"
>{{ t('todo.lapse') }} {{ countByType.lapse }}</span
>
<span class="rounded-full bg-slate-100 px-2.5 py-1"
>{{ t('todo.birthday') }} {{ countByType.birthday }}</span
>
</div>
<div class="space-y-3">
1111
<TodoCard v-for="todo in todos" :key="todo.id" :todo="todo" />
<div class="rounded-2xl border border-dashed border-silver-200 bg-white/60 p-4">
<div class="text-sm font-medium">{{ t('todo.claim') }}</div>
<div class="mt-1 text-xs text-slate-400">{{ t('todo.claimPlaceholder') }}</div>
</div>
</div>
<
/section
>
</section>
-->
</ApiLoader>
</div>
<
/template>
\ No newline at end of file
</template>
src/views/PipelineView.vue
View file @
ce3e433a
...
...
@@ -42,7 +42,11 @@ onMounted(load)
<
template
>
<div
class=
"space-y-4"
>
<div
class=
"rounded-2xl border border-amber-100 bg-amber-50 px-4 py-3 text-xs font-medium text-amber-700"
>
{{
t
(
'pipeline.adjustNote'
)
}}
</div>
<div
class=
"rounded-2xl border border-amber-100 bg-amber-50 px-4 py-3 text-xs font-medium text-amber-700"
>
{{
t
(
'pipeline.adjustNote'
)
}}
</div>
<div
class=
"grid grid-cols-2 gap-3"
>
<label
class=
"block"
>
...
...
@@ -51,26 +55,58 @@ onMounted(load)
v-model=
"policyQuery"
type=
"search"
:placeholder=
"t('pipeline.filterPolicyPlaceholder')"
class=
"w-full rounded-xl border border-silver-200 bg-white px-3 py-2 text-
sm
text-slate-900 outline-none transition-colors placeholder:text-silver-400 focus:border-brand-200"
>
class=
"w-full rounded-xl border border-silver-200 bg-white px-3 py-2 text-
base
text-slate-900 outline-none transition-colors placeholder:text-silver-400 focus:border-brand-200"
/
>
</label>
<label
class=
"block"
>
<
!--
<
label
class=
"block"
>
<span
class=
"mb-1 block text-xs text-slate-500"
>
{{
t
(
'pipeline.filterMonth'
)
}}
</span>
<select
v-model=
"selectedMonth"
class=
"w-full rounded-xl border border-silver-200 bg-white px-3 py-2
text-sm
text-slate-900 outline-none transition-colors focus:border-brand-200"
class=
"w-full rounded-xl border border-silver-200 bg-white px-3 py-2 text-slate-900 outline-none transition-colors focus:border-brand-200"
>
<option
value=
""
>
{{
t
(
'pipeline.allMonths'
)
}}
</option>
<option
v-for=
"month in months"
:key=
"month"
:value=
"month"
>
{{
month
}}
</option>
</select>
</label>
-->
<label
class=
"block"
>
<span
class=
"mb-1 block text-xs text-slate-500"
>
{{
t
(
'pipeline.filterMonth'
)
}}
</span>
<div
class=
"relative"
>
<select
v-model=
"selectedMonth"
class=
"w-full appearance-none rounded-xl border border-silver-200 bg-white px-3 py-2 pr-10 text-base text-slate-900 outline-none transition-colors focus:border-brand-200"
>
<option
value=
""
>
{{
t
(
'pipeline.allMonths'
)
}}
</option>
<option
v-for=
"month in months"
:key=
"month"
:value=
"month"
>
{{
month
}}
</option>
</select>
<!-- 自定义箭头:right-3 就是箭头离右边框的间隔,想大改这里 -->
<svg
class=
"pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-silver-400"
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 24 24"
fill=
"none"
stroke=
"currentColor"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
>
<polyline
points=
"6 9 12 15 18 9"
/>
</svg>
</div>
</label>
</div>
<ApiLoader
:loading=
"loading"
:error=
"error"
:empty=
"!loading && !error && items.length === 0"
@
retry=
"load"
>
<ApiLoader
:loading=
"loading"
:error=
"error"
:empty=
"!loading && !error && items.length === 0"
@
retry=
"load"
>
<div
v-if=
"filtered.length"
class=
"space-y-3"
>
<PipelineCard
v-for=
"item in filtered"
:key=
"item.id"
:item=
"item"
/>
</div>
<div
v-else
class=
"py-10 text-center text-sm text-slate-400"
>
{{
t
(
'pipeline.noResult'
)
}}
</div>
<div
v-else
class=
"py-10 text-center text-sm text-slate-400"
>
{{
t
(
'pipeline.noResult'
)
}}
</div>
</ApiLoader>
</div>
</
template
>
src/views/PoliciesView.vue
View file @
ce3e433a
...
...
@@ -18,8 +18,8 @@ const modalError = ref<string | null>(null)
const
commissions
=
ref
<
PolicyCommissionYear
[]
>
([])
const
selectedPolicyNo
=
ref
(
''
)
const
inforce
=
computed
(()
=>
policies
.
value
.
filter
(
(
p
)
=>
p
.
status
===
'INFORCE'
))
const
inactive
=
computed
(()
=>
policies
.
value
.
filter
(
(
p
)
=>
p
.
status
!==
'INFORCE'
))
const
inforce
=
computed
(()
=>
policies
.
value
.
filter
(
p
=>
p
.
status
===
'INFORCE'
))
const
inactive
=
computed
(()
=>
policies
.
value
.
filter
(
p
=>
p
.
status
!==
'INFORCE'
))
async
function
load
()
{
loading
.
value
=
true
...
...
@@ -59,19 +59,38 @@ onMounted(load)
</
script
>
<
template
>
<ApiLoader
:loading=
"loading"
:error=
"error"
:empty=
"!loading && !error && policies.length === 0"
@
retry=
"load"
>
<ApiLoader
:loading=
"loading"
:error=
"error"
:empty=
"!loading && !error && policies.length === 0"
@
retry=
"load"
>
<div
class=
"space-y-6"
>
<section>
<h2
class=
"mb-3 text-[13px] font-semibold tracking-wide text-silver-600"
>
{{
t
(
'policies.inforce'
)
}}
</h2>
<h2
class=
"mb-3 text-[13px] font-semibold tracking-wide text-silver-600"
>
{{
t
(
'policies.inforce'
)
}}
</h2>
<div
class=
"space-y-3"
>
<PolicyCard
v-for=
"policy in inforce"
:key=
"policy.policyNo"
:policy=
"policy"
@
select=
"openCommissions"
/>
<PolicyCard
v-for=
"policy in inforce"
:key=
"policy.policyNo"
:policy=
"policy"
@
select=
"openCommissions"
/>
</div>
</section>
<section
v-if=
"inactive.length"
>
<h2
class=
"mb-3 text-[13px] font-semibold tracking-wide text-silver-600"
>
{{
t
(
'policies.inactive'
)
}}
</h2>
<h2
class=
"mb-3 text-[13px] font-semibold tracking-wide text-silver-600"
>
{{
t
(
'policies.inactive'
)
}}
</h2>
<div
class=
"space-y-3"
>
<PolicyCard
v-for=
"policy in inactive"
:key=
"policy.policyNo"
:policy=
"policy"
@
select=
"openCommissions"
/>
<PolicyCard
v-for=
"policy in inactive"
:key=
"policy.policyNo"
:policy=
"policy"
@
select=
"openCommissions"
/>
</div>
</section>
</div>
...
...
@@ -90,10 +109,16 @@ onMounted(load)
:key=
"`$
{item.year}-${item.status}-${index}`"
class="flex items-center justify-between gap-3 text-sm"
>
<span>
{{
item
.
year
}}
·
{{
item
.
type
}}
</span>
<span
>
{{
item
.
year
}}
·
{{
item
.
type
}}
<span
v-if=
"item.status == 'PIPELINE'"
>
(预估)
</span>
</span>
<span
class=
"text-right"
>
<span
class=
"tnum"
>
{{
formatDetailMoney
(
item
.
amount
,
item
.
currency
)
}}
</span>
·
{{
t
(
`stage.${item.status
}
`
)
}}
<
span
v
-
if
=
"item.statusDesc"
class
=
"block text-xs text-slate-400"
>
{{
item
.
statusDesc
}}
<
/span
>
<span
class=
"tnum"
>
{{
formatDetailMoney
(
item
.
amount
,
item
.
currency
)
}}
</span>
·
{{
t
(
`stage.${item.status
}
`
)
}}
<
span
v
-
if
=
"item.statusDesc"
class
=
"block text-xs text-slate-400"
>
{{
item
.
statusDesc
}}
<
/span
>
<
/span
>
<
/div
>
<
/div
>
...
...
tailwind.config.js
View file @
ce3e433a
...
...
@@ -47,6 +47,11 @@ export default {
borderRadius
:
{
xl
:
'0.75rem'
,
'2xl'
:
'1rem'
},
fontSize
:
{
xs
:
[
'.9375rem'
,
{
lineHeight
:
'1.25rem'
}],
// 13px + 20px 行高
sm
:
[
'1.125rem'
],
lg
:
[
'1.25rem'
,
{
lineHeight
:
'1.25rem'
}]
// 13px + 20px 行高
}
}
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment