| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- <template>
- <view class="agreement-container">
- <view class="agreement-list">
- <view
- v-for="item in staticAgreementList"
- :key="item.path"
- class="agreement-card"
- hover-class="agreement-card--active"
- @click="navigateToAgreementPage(item.path)"
- >
- <text class="agreement-card__title">《{{ item.name }}》</text>
- <text class="agreement-card__arrow">›</text>
- </view>
- <view
- v-for="item in certSuccessList"
- :key="item.templateUrl"
- class="agreement-card"
- hover-class="agreement-card--active"
- @click="handlePreviewAgreement(item)"
- >
- <text class="agreement-card__title">《{{ item.name }}》</text>
- <text class="agreement-card__arrow">›</text>
- </view>
- </view>
- </view>
- </template>
- <script setup lang="ts">
- import { computed, ref } from 'vue'
- import { onLoad } from '@dcloudio/uni-app'
- import { getSubjectLocationAgreementApi } from '@/services/modules/mine/common'
- import type { agreementInfosItem } from '@/services/modules/mine/common/type'
- import { useUserStore } from '@/stores/modules/user'
- import { previewAgreementPdf } from '@/utils/agreementPdfPreview'
- interface StaticAgreementItem {
- name: string
- path: string
- }
- interface AgreementItem {
- name: string
- templateUrl: string
- subjectLocation: string
- }
- const AGREEMENT_PAGE_BASE = '/pages-mine/agreement'
- const CERT_SUCCESS_STATUS = 'CERT'
- const WEB_VIEW_AGREEMENT_SUBJECT_LOCATION = 'CLOUD_ACCOUNT_LXLW'
- const WEB_VIEW_AGREEMENT_PAGE = `${AGREEMENT_PAGE_BASE}/web-view`
- const userStore = useUserStore()
- const currentUserInfo = computed(() => userStore.currentUserInfo)
- const certSuccessList = ref<AgreementItem[]>([])
- const hasSignedAgreement = (agreementCode: string): boolean => {
- const signedAgreement = currentUserInfo.value?.signedAgreement ?? []
- return Array.isArray(signedAgreement) && signedAgreement.includes(agreementCode)
- }
- const showHonestAgreement = computed(() => {
- return hasSignedAgreement('HONEST_AGREEMENT')
- })
- const showHonestAgreementV2 = computed(() => {
- return hasSignedAgreement('HONEST_AGREEMENT_V2')
- })
- const staticAgreementList = computed<StaticAgreementItem[]>(() => {
- const list: StaticAgreementItem[] = [
- {
- name: '要易云平台用户协议',
- path: 'platform-user-agreement',
- },
- {
- name: '隐私权政策',
- path: 'privacy-policy',
- },
- {
- name: '个人信息使用授权书',
- path: 'personal-info-authorization',
- },
- ]
- if (showHonestAgreement.value) {
- list.push({
- name: '廉洁承诺书',
- path: 'integrity-commitment',
- })
- }
- if (showHonestAgreementV2.value) {
- list.push({
- name: '承诺书2.0',
- path: 'integrity-commitment-v2',
- })
- }
- return list
- })
- const getCertifiedSubjectLocations = (): string[] => {
- const certList = currentUserInfo.value?.certList ?? []
- const subjectLocations = certList
- .filter((item) => item.commonCertStatus === CERT_SUCCESS_STATUS)
- .map((item) => item.subjectLocation?.trim())
- .filter((subjectLocation): subjectLocation is string => Boolean(subjectLocation))
- return Array.from(new Set(subjectLocations))
- }
- const normalizeAgreementInfos = (
- list: agreementInfosItem[] = [],
- subjectLocation: string
- ): AgreementItem[] => {
- return list
- .filter((item) => Boolean(item.templateUrl?.trim()))
- .map((item) => {
- return {
- name: item.name?.trim() || '协议',
- templateUrl: item.templateUrl.trim(),
- subjectLocation,
- }
- })
- }
- const dedupeAgreementInfos = (list: AgreementItem[]): AgreementItem[] => {
- const map = new Map<string, AgreementItem>()
- list.forEach((item) => {
- if (!map.has(item.templateUrl)) {
- map.set(item.templateUrl, item)
- }
- })
- return Array.from(map.values())
- }
- const getCertSuccessList = async (): Promise<void> => {
- const subjectLocations = getCertifiedSubjectLocations()
- if (!subjectLocations.length) {
- certSuccessList.value = []
- return
- }
- uni.showLoading({
- title: '加载中...',
- mask: true,
- })
- try {
- const agreementInfoGroups = await Promise.all(
- subjectLocations.map(async (subjectLocation) => {
- try {
- const res = await getSubjectLocationAgreementApi({
- subjectLocation,
- })
- return normalizeAgreementInfos(res.data?.agreementInfos, subjectLocation)
- } catch (error) {
- console.log('getSubjectLocationAgreementApi error:', error)
- return []
- }
- })
- )
- certSuccessList.value = dedupeAgreementInfos(agreementInfoGroups.flat())
- } finally {
- uni.hideLoading()
- }
- }
- const navigateToAgreementPage = (path: string): void => {
- uni.navigateTo({
- url: `${AGREEMENT_PAGE_BASE}/${path}`,
- })
- }
- const handlePreviewAgreement = (item: AgreementItem): void => {
- if (item.subjectLocation === WEB_VIEW_AGREEMENT_SUBJECT_LOCATION) {
- uni.navigateTo({
- url: `${WEB_VIEW_AGREEMENT_PAGE}?url=${encodeURIComponent(item.templateUrl)}`,
- })
- return
- }
- void previewAgreementPdf({
- url: item.templateUrl,
- })
- }
- onLoad(() => {
- void getCertSuccessList()
- })
- </script>
- <style lang="scss" scoped>
- .agreement-container {
- min-height: 100vh;
- padding: 28rpx 24rpx 40rpx;
- box-sizing: border-box;
- background:
- radial-gradient(
- circle at 50% -120rpx,
- rgba(47, 140, 255, 0.14) 0%,
- rgba(47, 140, 255, 0) 420rpx
- ),
- linear-gradient(180deg, #f6f8fc 0%, #f7f8fa 100%);
- }
- .agreement-list {
- display: flex;
- flex-direction: column;
- gap: 18rpx;
- }
- .agreement-card {
- position: relative;
- display: flex;
- align-items: center;
- min-height: 112rpx;
- padding: 0 28rpx 0 32rpx;
- box-sizing: border-box;
- border: 1rpx solid rgba(31, 41, 55, 0.06);
- border-radius: 24rpx;
- background:
- linear-gradient(180deg, rgba(255, 255, 255, 0.96) 0%, rgba(255, 255, 255, 0.9) 100%), #ffffff;
- box-shadow:
- 0 16rpx 40rpx rgba(15, 23, 42, 0.05),
- 0 2rpx 8rpx rgba(15, 23, 42, 0.03);
- overflow: hidden;
- transition:
- transform 0.18s ease,
- opacity 0.18s ease;
- }
- .agreement-card--active {
- opacity: 0.86;
- transform: scale(0.985);
- }
- .agreement-card__title {
- flex: 1;
- min-width: 0;
- padding-right: 24rpx;
- font-size: 31rpx;
- font-weight: 600;
- line-height: 44rpx;
- color: #1f2937;
- letter-spacing: 0.2rpx;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- .agreement-card__arrow {
- flex-shrink: 0;
- font-size: 48rpx;
- font-weight: 300;
- line-height: 1;
- color: #aeb8c6;
- }
- </style>
|