| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551 |
- <template>
- <view class="package-detail">
- <view class="package-detail__header">
- <view class="package-detail__title">
- {{ packageDetail?.scorePackageName || '积分包详情' }}
- </view>
- <view class="package-detail__sub">编号:{{ packageDetail?.packageSn || '-' }}</view>
- </view>
- <view class="detail-card">
- <view class="detail-card__title">基础信息</view>
- <view
- v-for="item in detailRows"
- :key="item.label"
- class="detail-row"
- :class="{ 'detail-row--long': item.long }"
- >
- <text class="detail-row__label">{{ item.label }}</text>
- <text class="detail-row__value">{{ item.value }}</text>
- </view>
- </view>
- <view v-if="ruleSections.length" class="rule-card">
- <view class="rule-card__title">积分规则</view>
- <view v-for="section in ruleSections" :key="section.title" class="rule-section">
- <view class="rule-section__title">{{ section.title }}</view>
- <view v-for="item in section.items" :key="item.id" class="rule-item">
- <text class="rule-item__name">{{ item.taskTypeName }}</text>
- <text class="rule-item__score">+{{ item.score }} 积分</text>
- </view>
- </view>
- </view>
- <view v-if="!loading && !packageDetail" class="empty">暂无详情数据</view>
- <view v-if="showExportButton" class="bottom-action">
- <wd-button block type="primary" @click="openExportPopup">发送报告</wd-button>
- </view>
- <wd-popup
- v-model="exportPopupVisible"
- position="bottom"
- custom-style="border-radius: 32rpx 32rpx 0 0;"
- @close="resetExportError"
- >
- <view class="export-popup">
- <view class="export-popup__close" @click="exportPopupVisible = false">×</view>
- <view class="export-popup__header">
- <view class="export-popup__title">报告发送</view>
- <view class="export-popup__desc">报告将发送至填写的邮箱,请确认邮箱地址有效。</view>
- </view>
- <view class="export-popup__body">
- <view
- class="export-popup__input-wrap"
- :class="{ 'export-popup__input-wrap--error': emailError }"
- >
- <input
- v-model="email"
- class="export-popup__input"
- placeholder="请输入邮箱"
- placeholder-class="export-popup__placeholder"
- type="text"
- confirm-type="send"
- cursor-spacing="120"
- :focus="emailInputFocus"
- :adjust-position="true"
- @focus="emailError = ''"
- @confirm="submitExportReport"
- />
- </view>
- <view v-if="emailError" class="export-popup__error">
- {{ emailError }}
- </view>
- </view>
- <view class="export-popup__footer">
- <wd-button block type="primary" :loading="exportLoading" @click="submitExportReport">
- 提交
- </wd-button>
- </view>
- </view>
- </wd-popup>
- </view>
- </template>
- <script setup lang="ts">
- import { computed, nextTick, ref } from 'vue'
- import { onLoad } from '@dcloudio/uni-app'
- import {
- exportZbInfoFormWeiNewApi,
- getPackageCanTaskListApi,
- getScorePackagePageByIdApi,
- } from '@/services/modules/task/package/index'
- import { useUserStore } from '@/stores/modules/user'
- const userStore = useUserStore()
- const id = ref('')
- const loading = ref(false)
- const exportLoading = ref(false)
- const exportPopupVisible = ref(false)
- const emailInputFocus = ref(false)
- const emailError = ref('')
- const email = ref('')
- const packageDetail = ref(null)
- const ruleSections = ref([])
- const EMPTY_TEXT = '无'
- const roles = computed(() => userStore.currentUserInfo?.roles || [])
- const showExportButton = computed(() => {
- return roles.value.includes(6) && packageDetail.value?.exportFlag === '1'
- })
- const formatDrugList = (val) => {
- if (!val) return EMPTY_TEXT
- if (Array.isArray(val)) return val.join('、') || EMPTY_TEXT
- return (
- String(val)
- .replace(/^\[|\]$/g, '')
- .replace(/"/g, '')
- .split(',')
- .filter(Boolean)
- .join('、') || EMPTY_TEXT
- )
- }
- const areaName = computed(() => {
- const area = packageDetail.value?.area
- if (!Array.isArray(area) || area.length === 0) return EMPTY_TEXT
- return (
- area
- .map((item) => `${item.province ?? ''}${item.city ?? ''}${item.area ?? ''}`)
- .filter(Boolean)
- .join(',') || EMPTY_TEXT
- )
- })
- const quizNames = computed(() => {
- const list = packageDetail.value?.quizRelations
- if (!Array.isArray(list) || list.length === 0) return EMPTY_TEXT
- return (
- list
- .map((item) => item.title)
- .filter(Boolean)
- .join(',') || EMPTY_TEXT
- )
- })
- const detailRows = computed(() => {
- const d = packageDetail.value
- return [
- { label: '截止日期', value: d?.endTimeValue || EMPTY_TEXT },
- { label: '接单对象类型', value: d?.typeidName || EMPTY_TEXT },
- {
- label: '接单对象',
- value: Array.isArray(d?.usernameList)
- ? d.usernameList.join(',')
- : d?.usernameList || EMPTY_TEXT,
- },
- { label: '结算渠道', value: d?.subjectLocationName || EMPTY_TEXT },
- { label: '关联服务企业', value: d?.relatedServiceName || EMPTY_TEXT },
- { label: '关联任务积分包', value: d?.relationScoreName || EMPTY_TEXT },
- { label: '可分配积分值', value: d?.kfpjf || EMPTY_TEXT },
- { label: '积分包值', value: d?.score || EMPTY_TEXT },
- { label: '接单对象范围', value: d?.packageUserScopeName || EMPTY_TEXT },
- { label: '推广药品', value: formatDrugList(d?.drugtableName), long: true },
- { label: '推广区域', value: areaName.value },
- {
- label: '派工范围',
- value: Array.isArray(d?.dispatchUserScopeName)
- ? d.dispatchUserScopeName.join(',')
- : d?.dispatchUserScopeName || EMPTY_TEXT,
- },
- { label: '测试试卷', value: quizNames.value },
- { label: '描述', value: d?.description || EMPTY_TEXT, long: true },
- ]
- })
- onLoad((query) => {
- const packageId = String(query?.id || '')
- if (!packageId) {
- uni.showToast({ title: '缺少ID', icon: 'none' })
- return
- }
- id.value = packageId
- initPage()
- })
- const initPage = async () => {
- loading.value = true
- uni.showLoading({ title: '加载中' })
- try {
- await Promise.all([getScorePackagePageById(), getPackageCanTaskList()])
- } finally {
- loading.value = false
- uni.hideLoading()
- }
- }
- const getScorePackagePageById = async () => {
- const res = await getScorePackagePageByIdApi(id.value)
- packageDetail.value = res.data || null
- email.value = res.data?.email || ''
- }
- const getPackageCanTaskList = async () => {
- const res = await getPackageCanTaskListApi(id.value)
- ruleSections.value = normalizeRuleSections(res.data)
- }
- const openExportPopup = async () => {
- resetExportError()
- exportPopupVisible.value = true
- await nextTick()
- setTimeout(() => {
- emailInputFocus.value = true
- }, 300)
- }
- const resetExportError = () => {
- emailError.value = ''
- emailInputFocus.value = false
- }
- const submitExportReport = async () => {
- const value = email.value.trim()
- if (!validateEmail(value)) {
- emailError.value = '请输入正确的邮箱地址'
- emailInputFocus.value = true
- return
- }
- exportLoading.value = true
- try {
- await exportZbInfoFormWeiNewApi({
- id: id.value,
- email: value,
- })
- exportPopupVisible.value = false
- uni.showToast({
- title: '报告已发送',
- icon: 'none',
- })
- } finally {
- exportLoading.value = false
- }
- }
- const validateEmail = (value) => {
- return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)
- }
- const normalizeRuleSections = (raw) => {
- if (!raw) return []
- if (Array.isArray(raw)) {
- return raw.length ? [{ title: '积分规则', items: raw }] : []
- }
- if (Object.prototype.toString.call(raw) === '[object Object]') {
- return Object.entries(raw)
- .filter(([, v]) => Array.isArray(v) && v.length > 0)
- .map(([title, items]) => ({ title, items }))
- }
- return []
- }
- </script>
- <style lang="scss" scoped>
- .package-detail {
- min-height: 100vh;
- padding: 24rpx 24rpx 164rpx;
- background: #f5f7fa;
- .package-detail__header {
- padding: 36rpx 32rpx;
- margin-bottom: 24rpx;
- color: #ffffff;
- background: linear-gradient(135deg, #3fa3f1 0%, #2176e8 100%);
- border-radius: 24rpx;
- box-shadow: 0 12rpx 28rpx rgba(47, 134, 230, 0.24);
- }
- .package-detail__title {
- font-size: 38rpx;
- font-weight: 700;
- line-height: 52rpx;
- }
- .package-detail__sub {
- margin-top: 10rpx;
- font-size: 26rpx;
- line-height: 36rpx;
- opacity: 0.8;
- }
- .detail-card,
- .rule-card {
- margin-bottom: 24rpx;
- overflow: hidden;
- background: #ffffff;
- border-radius: 20rpx;
- box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.04);
- }
- .detail-card__title,
- .rule-card__title {
- padding: 28rpx 32rpx 18rpx;
- color: #1f2937;
- font-size: 32rpx;
- font-weight: 700;
- line-height: 44rpx;
- border-bottom: 1rpx solid #eef0f3;
- }
- .detail-row {
- display: flex;
- align-items: flex-start;
- gap: 24rpx;
- padding: 26rpx 32rpx;
- border-bottom: 1rpx solid #f1f2f4;
- }
- .detail-row:last-child {
- border-bottom: none;
- }
- .detail-row__label {
- flex-shrink: 0;
- width: 260rpx;
- color: #6b7280;
- font-size: 28rpx;
- line-height: 40rpx;
- white-space: nowrap;
- }
- .detail-row__value {
- flex: 1;
- min-width: 0;
- color: #111827;
- font-size: 28rpx;
- line-height: 40rpx;
- text-align: right;
- word-break: break-all;
- }
- .detail-row--long {
- display: block;
- }
- .detail-row--long .detail-row__label {
- display: block;
- width: auto;
- margin-bottom: 16rpx;
- white-space: nowrap;
- }
- .detail-row--long .detail-row__value {
- display: block;
- padding: 20rpx 24rpx;
- color: #374151;
- font-size: 28rpx;
- line-height: 44rpx;
- text-align: left;
- word-break: break-all;
- background: #f8fafc;
- border-radius: 12rpx;
- }
- .rule-section {
- padding: 28rpx 32rpx;
- }
- .rule-section + .rule-section {
- border-top: 1rpx dashed #e5e7eb;
- }
- .rule-section__title {
- position: relative;
- padding-left: 18rpx;
- margin-bottom: 20rpx;
- color: #111827;
- font-size: 30rpx;
- font-weight: 700;
- line-height: 42rpx;
- }
- .rule-section__title::before {
- content: '';
- position: absolute;
- top: 8rpx;
- left: 0;
- width: 6rpx;
- height: 28rpx;
- background: #3fa3f1;
- border-radius: 999rpx;
- }
- .rule-item {
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 24rpx;
- padding: 18rpx 0;
- }
- .rule-item__name {
- flex: 1;
- min-width: 0;
- color: #374151;
- font-size: 28rpx;
- line-height: 40rpx;
- word-break: break-all;
- }
- .rule-item__score {
- flex-shrink: 0;
- padding: 8rpx 18rpx;
- color: #2f86e6;
- font-size: 26rpx;
- font-weight: 600;
- line-height: 34rpx;
- background: rgba(63, 163, 241, 0.1);
- border-radius: 999rpx;
- }
- .bottom-action {
- position: fixed;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 0;
- padding: 20rpx 24rpx calc(20rpx + env(safe-area-inset-bottom));
- background: #ffffff;
- box-shadow: 0 -8rpx 24rpx rgba(15, 23, 42, 0.08);
- }
- .export-popup {
- position: relative;
- padding: 40rpx 32rpx 24rpx;
- background: #ffffff;
- }
- .export-popup__close {
- position: absolute;
- top: 28rpx;
- right: 32rpx;
- width: 48rpx;
- height: 48rpx;
- color: #9ca3af;
- font-size: 44rpx;
- line-height: 44rpx;
- text-align: center;
- }
- .export-popup__header {
- padding-right: 64rpx;
- margin-bottom: 34rpx;
- }
- .export-popup__title {
- color: #111827;
- font-size: 38rpx;
- font-weight: 700;
- line-height: 52rpx;
- }
- .export-popup__desc {
- margin-top: 10rpx;
- color: #6b7280;
- font-size: 26rpx;
- line-height: 38rpx;
- }
- .export-popup__body {
- margin-bottom: 40rpx;
- }
- .export-popup__input-wrap {
- display: flex;
- align-items: center;
- height: 88rpx;
- padding: 0 24rpx;
- background: #ffffff;
- border: 2rpx solid #e5e7eb;
- border-radius: 16rpx;
- box-sizing: border-box;
- }
- .export-popup__input-wrap--error {
- border-color: #ef4444;
- background: #fff7f7;
- }
- .export-popup__input {
- width: 100%;
- height: 88rpx;
- color: #111827;
- font-size: 30rpx;
- line-height: 88rpx;
- }
- .export-popup__placeholder {
- color: #9ca3af;
- font-size: 30rpx;
- }
- .export-popup__error {
- margin-top: 12rpx;
- color: #ef4444;
- font-size: 24rpx;
- line-height: 34rpx;
- }
- .export-popup__footer {
- padding-bottom: max(20rpx, env(safe-area-inset-bottom));
- }
- .empty {
- padding: 80rpx 24rpx;
- color: #9ca3af;
- font-size: 28rpx;
- line-height: 40rpx;
- text-align: center;
- }
- }
- </style>
|