修复已知问题
This commit is contained in:
4
.env
4
.env
@@ -1,6 +1,6 @@
|
||||
# API
|
||||
# VITE_SYSTEM_URL = "http://ha699de6.natappfree.cc"
|
||||
VITE_SYSTEM_URL = "https://dev.cqjcteach.cn/prod-api"
|
||||
VITE_SYSTEM_URL = "http://ea252b67.natappfree.cc"
|
||||
# VITE_SYSTEM_URL = "https://dev.cqjcteach.cn/prod-api"
|
||||
|
||||
# 第三方客户 channelId
|
||||
VITE_CHANNEL_ID = "7b81ec142eca42baa045820793b821bb"
|
||||
|
||||
@@ -30,11 +30,12 @@
|
||||
import backSVG from '../../../assets/icon/back.svg'
|
||||
import { useUI } from '../../../../utils/use-ui'
|
||||
import { endUserService } from '../../../../api/my-index'
|
||||
import { navigateBack, reLaunch } from '../../../../utils/router'
|
||||
|
||||
const { showDialog, showToast } = useUI()
|
||||
|
||||
const emits = defineEmits(['openGroupManagement'])
|
||||
const props = defineProps(['isGroup', 'serviceID'])
|
||||
const props = defineProps(['isGroup', 'serviceID', 'type'])
|
||||
|
||||
const currentConversation = ref<IConversationModel>()
|
||||
const typingStatus = ref(false)
|
||||
@@ -91,15 +92,19 @@
|
||||
}
|
||||
|
||||
const back = async () => {
|
||||
if (props.type === 'GROUP') {
|
||||
reLaunch('/')
|
||||
return
|
||||
}
|
||||
if (props.serviceID) {
|
||||
const show = await showDialog('提示', '确定要退出当前会话吗?')
|
||||
if (show) {
|
||||
await endUserService(props.serviceID)
|
||||
await showToast('结束服务成功')
|
||||
uni.navigateBack()
|
||||
navigateBack()
|
||||
}
|
||||
} else {
|
||||
uni.navigateBack()
|
||||
navigateBack()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="chat" :style="{ marginBottom: keywordHight + 'px' }">
|
||||
<TUICallKit></TUICallKit>
|
||||
<div :class="['tui-chat', !isPC && 'tui-chat-h5']">
|
||||
<div
|
||||
v-if="!currentConversationID"
|
||||
@@ -15,6 +16,7 @@
|
||||
:isGroup="!isNotInGroup ? isGroup : null"
|
||||
:headerExtensionList="headerExtensionList"
|
||||
:serviceID="serviceID"
|
||||
:type="backStatusName"
|
||||
@closeChat="closeChat"
|
||||
@openGroupManagement="handleGroup"
|
||||
/>
|
||||
@@ -101,6 +103,7 @@
|
||||
TUIConstants,
|
||||
ExtensionInfo
|
||||
} from '@tencentcloud/tui-core-lite'
|
||||
import { TUICallKit } from '@trtc/calls-uikit-vue'
|
||||
import ChatHeader from './chat-header/index.vue'
|
||||
import MessageList from './message-list/index.vue'
|
||||
import MessageInput from './message-input/index.vue'
|
||||
@@ -121,7 +124,11 @@
|
||||
import { onLoad, onUnload } from '@dcloudio/uni-app'
|
||||
import { initChat, logout } from './entry-chat-only.ts'
|
||||
|
||||
// 返回状态
|
||||
const backStatusName = ref('')
|
||||
|
||||
onLoad(options => {
|
||||
backStatusName.value = options?.type || ''
|
||||
serviceID.value = options?.id || ''
|
||||
initChat(options)
|
||||
})
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
v-else-if="item.type === TYPES.MSG_LOCATION"
|
||||
:content="item.getMessageContent()"
|
||||
/>
|
||||
<!-- 自定义消息,目前只支持【红包】 -->
|
||||
<!-- 自定义消息,目前只支持:红包,商品详情 -->
|
||||
<MessageCustom
|
||||
v-else-if="item.type === TYPES.MSG_CUSTOM"
|
||||
ref="customRefMessage"
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
>
|
||||
<Avatar
|
||||
useSkeletonAnimation
|
||||
:type="message.conversationType"
|
||||
:id="message.from"
|
||||
:url="message.avatar || ''"
|
||||
:style="{ flex: '0 0 auto' }"
|
||||
/>
|
||||
|
||||
@@ -100,6 +100,22 @@
|
||||
</text> -->
|
||||
</view>
|
||||
</template>
|
||||
<!-- 商品详情 -->
|
||||
<template
|
||||
v-else-if="customData.businessID === CHAT_MSG_CUSTOM_TYPE.GOODS"
|
||||
>
|
||||
<view class="goods-box" @click="onGoods">
|
||||
<image
|
||||
mode="heightFix"
|
||||
:src="goodsData.cover"
|
||||
class="img-box"
|
||||
></image>
|
||||
<view class="right-box">
|
||||
<text class="name">{{ goodsData.title }}</text>
|
||||
<text class="price">¥ {{ goodsData.price }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span v-html="content.custom" />
|
||||
</template>
|
||||
@@ -125,6 +141,7 @@
|
||||
import star from '../../../../assets/icon/star-light.png'
|
||||
import unopenedEnvelope from '../../../../assets/icon/unopened-envelope.svg'
|
||||
import kaiEnvelope from '../../../../assets/icon/kai-unopened-envelope.svg'
|
||||
import { navigateTo } from '../../../../../utils/router'
|
||||
|
||||
interface Props {
|
||||
messageItem: IMessageModel
|
||||
@@ -173,6 +190,16 @@
|
||||
}
|
||||
})
|
||||
|
||||
/** 商品详情显示数据 */
|
||||
const goodsData = computed(() => {
|
||||
return JSON.parse(props.messageItem.payload.data)
|
||||
})
|
||||
|
||||
/** 点击商品详情 */
|
||||
const onGoods = () => {
|
||||
navigateTo('/pages/mall/detail', { productId: goodsData.value.id })
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
custom.value = props.content
|
||||
message.value = props.messageItem
|
||||
@@ -298,4 +325,38 @@
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-box {
|
||||
display: flex;
|
||||
.img-box {
|
||||
flex-shrink: 0;
|
||||
width: 180rpx;
|
||||
height: 240rpx;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
background: rgb(182, 182, 182);
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
.right-box {
|
||||
width: 50vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
.name {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
}
|
||||
.price {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #ff7201;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -171,7 +171,7 @@ const isHoverFingerPointer = computed<boolean>(() => {
|
||||
|
||||
function openReadUserPanel() {
|
||||
if (isHoverFingerPointer.value) {
|
||||
emits('openReadUserPanel');
|
||||
// emits('openReadUserPanel');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -380,19 +380,25 @@
|
||||
|
||||
/** 是否最开始创建群聊 */
|
||||
const isFirstCreateGroup = (item: IConversationModel) => {
|
||||
// 打印
|
||||
if (item.type === 'GROUP' && item?.lastMessage?.payload?.data) {
|
||||
const data = JSON.parse(item?.lastMessage?.payload?.data)
|
||||
return data.content === 'Create Group'
|
||||
? `${item.getLastMessage('text')?.split(':')[0]}:创建群聊`
|
||||
: ''
|
||||
}
|
||||
// if (item.type === 'GROUP' && item?.lastMessage?.payload?.data) {
|
||||
// const data = JSON.parse(item?.lastMessage?.payload?.data)
|
||||
// return data.content === 'Create Group'
|
||||
// ? `${item.getLastMessage('text')?.split(':')[0]}:创建群聊`
|
||||
// : ''
|
||||
// }
|
||||
if (item?.lastMessage?.payload?.data) {
|
||||
const data = JSON.parse(item?.lastMessage?.payload?.data)
|
||||
const text = item.getLastMessage('text')?.split(':')
|
||||
const isText = text && text.length > 1
|
||||
if (data.businessID === CHAT_MSG_CUSTOM_TYPE.GOODS) {
|
||||
console.log(item, '==2222222=')
|
||||
|
||||
return `自定义数据--`
|
||||
if (isText) {
|
||||
return `${text[0]}:[商品信息] ${data.title}`
|
||||
} else {
|
||||
return `[商品信息]:${data.title}`
|
||||
}
|
||||
}
|
||||
if (data.content === 'Create Group' && item.type === 'GROUP') {
|
||||
return `${item.getLastMessage('text')?.split(':')[0]}:创建群聊`
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
height: avatarSize,
|
||||
borderRadius: '80rpx'
|
||||
}"
|
||||
@click="onTopAvatar"
|
||||
>
|
||||
<template v-if="isUniFrameWork">
|
||||
<image
|
||||
@@ -42,14 +43,26 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import TUICore, { TUIConstants } from '@tencentcloud/tui-core-lite'
|
||||
import { ref, toRefs } from '../../../adapter-vue'
|
||||
import { isUniFrameWork } from '../../../utils/env'
|
||||
import TUIChatEngine, {
|
||||
TUIFriendService
|
||||
} from '@tencentcloud/chat-uikit-engine-lite'
|
||||
import { useAuthUser } from '../../../../composables/useAuthUser'
|
||||
import { navigateTo } from '@/utils/router'
|
||||
import { useUI } from '../../../../utils/use-ui'
|
||||
|
||||
const { tencentUserSig } = useAuthUser()
|
||||
const { showLoading, hideLoading } = useUI()
|
||||
|
||||
interface IProps {
|
||||
url: string
|
||||
size?: string
|
||||
borderRadius?: string
|
||||
useSkeletonAnimation?: boolean
|
||||
id?: string
|
||||
type?: string
|
||||
}
|
||||
|
||||
interface IEmits {
|
||||
@@ -66,7 +79,9 @@
|
||||
url: 'https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png',
|
||||
size: '36px',
|
||||
borderRadius: '5px',
|
||||
useSkeletonAnimation: false
|
||||
useSkeletonAnimation: false,
|
||||
id: '',
|
||||
type: ''
|
||||
})
|
||||
|
||||
const {
|
||||
@@ -97,6 +112,52 @@
|
||||
}
|
||||
emits('onError', e)
|
||||
}
|
||||
|
||||
/** 点击头像跳转 */
|
||||
const onTopAvatar = () => {
|
||||
console.log(props.type)
|
||||
if (props.id) {
|
||||
showLoading()
|
||||
TUICore.callService({
|
||||
serviceName: TUIConstants.TUISearch.SERVICE.NAME,
|
||||
method: TUIConstants.TUISearch.SERVICE.METHOD.SEARCH_USER,
|
||||
params: {
|
||||
userID: props.id
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
console.log(res.data, '==')
|
||||
const searchList = res.data
|
||||
if (searchList.length > 0) {
|
||||
TUIFriendService.checkFriend({
|
||||
type: TUIChatEngine.TYPES.SNS_CHECK_TYPE_BOTH,
|
||||
userIDList: [searchList[0].userID]
|
||||
})
|
||||
.then(v => {
|
||||
const isShow =
|
||||
v.data.successUserIDList[0].relation ===
|
||||
TUIChatEngine.TYPES.SNS_TYPE_BOTH_WAY
|
||||
hideLoading()
|
||||
navigateTo('/pages/adduser/details', {
|
||||
id: searchList[0].userID,
|
||||
state: props.type,
|
||||
type: isShow
|
||||
? '1'
|
||||
: searchList[0].userID == tencentUserSig.value.userId
|
||||
? '99'
|
||||
: ''
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
hideLoading()
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
hideLoading()
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@@ -122,9 +183,7 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #ececec;
|
||||
transition:
|
||||
opacity 0.3s,
|
||||
background-color 0.1s ease-out;
|
||||
transition: opacity 0.3s, background-color 0.1s ease-out;
|
||||
|
||||
&.skeleton-animation {
|
||||
animation: breath 2s linear 0.3s infinite;
|
||||
|
||||
@@ -70,3 +70,12 @@ export const getGroupDetail = id => {
|
||||
loading: false
|
||||
})
|
||||
}
|
||||
|
||||
/** 获取可参与的拼团列表 */
|
||||
export const getParticipateList = id => {
|
||||
return http({
|
||||
url: `/api/service/groupOrder/available/${id}`,
|
||||
method: 'get',
|
||||
loading: false
|
||||
})
|
||||
}
|
||||
|
||||
@@ -35,6 +35,11 @@
|
||||
cover: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/** 多少钱 */
|
||||
price: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
@@ -119,59 +124,71 @@
|
||||
}
|
||||
}
|
||||
|
||||
/** 发送自定义信息数据 */
|
||||
const sendCustomData = async item => {
|
||||
let to = ''
|
||||
let isGroup = false
|
||||
if (item.id.includes('GROUP')) {
|
||||
// 分割 GROUP
|
||||
to = item.id.split('GROUP')[1]
|
||||
isGroup = true
|
||||
} else {
|
||||
to = item.id.split('C2C')[1]
|
||||
isGroup = false
|
||||
}
|
||||
const payload = {
|
||||
data: JSON.stringify({
|
||||
id: props.id,
|
||||
businessID: CHAT_MSG_CUSTOM_TYPE.GOODS,
|
||||
title: props.text,
|
||||
cover: props.cover,
|
||||
price: props.price
|
||||
}),
|
||||
description: props.text,
|
||||
extension: props.text
|
||||
}
|
||||
const options = {
|
||||
to,
|
||||
payload,
|
||||
conversationType: isGroup
|
||||
? TUIChatEngine.TYPES.CONV_GROUP
|
||||
: TUIChatEngine.TYPES.CONV_C2C,
|
||||
needReadReceipt: isEnabledMessageReadReceiptGlobal()
|
||||
}
|
||||
await TUIChatService.sendCustomMessage(options)
|
||||
}
|
||||
|
||||
/** 多选分享 */
|
||||
const multiSelectShare = async () => {
|
||||
showLoading()
|
||||
const requests = selectedList.value.map(v => sendCustomData(v))
|
||||
await Promise.all(requests)
|
||||
hideLoading()
|
||||
await showToast('分享成功', 'success')
|
||||
isShow.value = false
|
||||
}
|
||||
|
||||
/**
|
||||
* 确定分享
|
||||
* @param state 1 多选 0 单选
|
||||
* @param data
|
||||
*/
|
||||
const onConfirm = async (state, item) => {
|
||||
const show = await showDialog(
|
||||
'提示',
|
||||
`确定分享${props.type == 1 ? '直播间' : '商品'}吗?`
|
||||
)
|
||||
if (!show) {
|
||||
return
|
||||
}
|
||||
if (state) {
|
||||
console.log('多选分享?')
|
||||
multiSelectShare()
|
||||
} else {
|
||||
// props
|
||||
const show = await showDialog(
|
||||
'提示',
|
||||
`确定分享${props.type == 1 ? '直播间' : '商品'}吗?`
|
||||
)
|
||||
if (!show) {
|
||||
return
|
||||
}
|
||||
console.log('单选数据', item.id)
|
||||
// 字符串匹配 GROUP C2C
|
||||
let to = ''
|
||||
let isGroup = false
|
||||
if (item.id.includes('GROUP')) {
|
||||
// 分割 GROUP
|
||||
to = item.id.split('GROUP')[1]
|
||||
isGroup = true
|
||||
} else {
|
||||
to = item.id.split('C2C')[1]
|
||||
isGroup = false
|
||||
}
|
||||
const payload = {
|
||||
data: JSON.stringify({
|
||||
id: props.id,
|
||||
businessID: CHAT_MSG_CUSTOM_TYPE.GOODS,
|
||||
title: props.text,
|
||||
cover: props.cover
|
||||
}),
|
||||
description: props.text,
|
||||
extension: props.text
|
||||
}
|
||||
const options = {
|
||||
to,
|
||||
payload,
|
||||
conversationType: isGroup
|
||||
? TUIChatEngine.TYPES.CONV_GROUP
|
||||
: TUIChatEngine.TYPES.CONV_C2C,
|
||||
needReadReceipt: isEnabledMessageReadReceiptGlobal()
|
||||
}
|
||||
showLoading()
|
||||
await TUIChatService.sendCustomMessage(options)
|
||||
await sendCustomData(item)
|
||||
hideLoading()
|
||||
await showToast('分享成功', 'success')
|
||||
isShow.value = false
|
||||
console.log(options)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
58
package-lock.json
generated
58
package-lock.json
generated
@@ -13,6 +13,7 @@
|
||||
"@tencentcloud/chat-uikit-uniapp": "3.1.0",
|
||||
"@tencentcloud/tui-core-lite": "1.0.0",
|
||||
"@tencentcloud/universal-api": "^2.4.0",
|
||||
"@trtc/calls-uikit-vue": "^4.4.2",
|
||||
"dayjs": "^1.11.10",
|
||||
"unplugin-vue2-script-setup": "^0.11.4"
|
||||
}
|
||||
@@ -766,15 +767,46 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@trtc/calls-uikit-vue": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://repo.huaweicloud.com/repository/npm/@trtc/calls-uikit-vue/-/calls-uikit-vue-4.2.2.tgz",
|
||||
"integrity": "sha512-xAHBo2RXb/PDCcd07sdftgE2HtiW3QC3hXY8g5yWfTkJ3WIPfDi5OsG9lti0KgzF9ZnfMf4i08ptAoC3k72iHQ==",
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://repo.huaweicloud.com/repository/npm/@trtc/calls-uikit-vue/-/calls-uikit-vue-4.4.2.tgz",
|
||||
"integrity": "sha512-a5oaNSO4qN0FSsDb65Kl9BEghDdWV0l5RdjMgaWEjrqNVVCuz7p5s7/6AYaB78dpdsIC9U9FXTVbM2+u79r4zw==",
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@tencentcloud/lite-chat": "^1.5.0",
|
||||
"@tencentcloud/lite-chat": "^1.6.3",
|
||||
"@tencentcloud/tui-core-lite": "1.0.0",
|
||||
"@trtc/call-engine-lite-js": "~3.4.0"
|
||||
"@trtc/call-engine-lite-js": "~3.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@trtc/calls-uikit-vue/node_modules/@trtc/call-engine-lite-js": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://repo.huaweicloud.com/repository/npm/@trtc/call-engine-lite-js/-/call-engine-lite-js-3.5.2.tgz",
|
||||
"integrity": "sha512-qwZTOO99dYIlGTrg++iVmxTSZzQ3yHyJ2NvOyibCttgQG2By3fJZNYN1thk7JG3C96FcCZ3+pjGqfRheG79pMA==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@tencentcloud/lite-chat": "^1.6.3",
|
||||
"core-js": "^3.8.3",
|
||||
"eventemitter3": "^4.0.7",
|
||||
"rtc-detect": "^0.0.5",
|
||||
"trtc-cloud-js-sdk": "2.10.10",
|
||||
"tuikit-logger": "latest"
|
||||
}
|
||||
},
|
||||
"node_modules/@trtc/calls-uikit-vue/node_modules/trtc-cloud-js-sdk": {
|
||||
"version": "2.10.10",
|
||||
"resolved": "https://repo.huaweicloud.com/repository/npm/trtc-cloud-js-sdk/-/trtc-cloud-js-sdk-2.10.10.tgz",
|
||||
"integrity": "sha512-nYBR4bQnwMCrXeOuN+ih8OgPjYd4JynBatVWHPa5h/PGdeHuldpN0Fi+4f0+ybJ0SYY82ksFetNAh6888rXSOA==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"trtc-sdk-v5": "5.15.1-beta.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@trtc/calls-uikit-vue/node_modules/trtc-sdk-v5": {
|
||||
"version": "5.15.1-beta.8",
|
||||
"resolved": "https://repo.huaweicloud.com/repository/npm/trtc-sdk-v5/-/trtc-sdk-v5-5.15.1-beta.8.tgz",
|
||||
"integrity": "sha512-3u5P3O9aS33Ja+HFTDiFF6/hkq7+KlfslnInSyYeHuAr5b6p26k6rBn3PZ6kXf+onzQhnCV1q2mMPePKgkomig==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"webrtc-adapter": "^8.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@trtc/calls-uikit-vue2.6": {
|
||||
@@ -1373,7 +1405,6 @@
|
||||
"integrity": "sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/core-js"
|
||||
@@ -1542,8 +1573,7 @@
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://repo.huaweicloud.com/repository/npm/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/events": {
|
||||
"version": "3.3.0",
|
||||
@@ -1969,8 +1999,7 @@
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://repo.huaweicloud.com/repository/npm/rtc-detect/-/rtc-detect-0.0.5.tgz",
|
||||
"integrity": "sha512-VANIELbaoIkZRj4gyiCCbTM+/ASy0eNgF35jCs+rrGxzYvD7YIBajEbGGZeh+5ZCNAX8/rT8IVRdpuallf174Q==",
|
||||
"license": "ISC",
|
||||
"peer": true
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
@@ -2072,8 +2101,7 @@
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://repo.huaweicloud.com/repository/npm/sdp/-/sdp-3.2.1.tgz",
|
||||
"integrity": "sha512-lwsAIzOPlH8/7IIjjz3K0zYBk7aBVVcvjMwt3M4fLxpjMYyy7i3I97SLHebgn4YBjirkzfp3RvRDWSKsh/+WFw==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "6.3.1",
|
||||
@@ -2321,8 +2349,7 @@
|
||||
"version": "0.0.4-beta.1",
|
||||
"resolved": "https://repo.huaweicloud.com/repository/npm/tuikit-logger/-/tuikit-logger-0.0.4-beta.1.tgz",
|
||||
"integrity": "sha512-Ky83B1p88xakmfZ2f92cU0YxfolyxnQBv14tQpvnuHcMTnVR2Rjy8tityDGwF+pnxrAhJ7H7OPB/4rFdWVncIw==",
|
||||
"license": "ISC",
|
||||
"peer": true
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.9.5",
|
||||
@@ -2580,7 +2607,6 @@
|
||||
"resolved": "https://repo.huaweicloud.com/repository/npm/webrtc-adapter/-/webrtc-adapter-8.2.4.tgz",
|
||||
"integrity": "sha512-VwtwbYNKnVQW8koB9qb8YcxNwpSVHTvvKEZLzY6uQ3gFrA9E87VPbB5xE+m1AGwUjL1UgN35jRR9hQgteZI5bg==",
|
||||
"license": "BSD-3-Clause",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"sdp": "^3.2.0"
|
||||
},
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
"@tencentcloud/chat-uikit-uniapp": "3.1.0",
|
||||
"@tencentcloud/tui-core-lite": "1.0.0",
|
||||
"@tencentcloud/universal-api": "^2.4.0",
|
||||
"unplugin-vue2-script-setup": "^0.11.4",
|
||||
"dayjs": "^1.11.10"
|
||||
"@trtc/calls-uikit-vue": "^4.4.2",
|
||||
"dayjs": "^1.11.10",
|
||||
"unplugin-vue2-script-setup": "^0.11.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,14 +437,15 @@
|
||||
{
|
||||
"path": "pages/adduser/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "添加地址",
|
||||
"navigationBarTitleText": "添加朋友/群组",
|
||||
"navigationBarBackgroundColor": "#ffffff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/adduser/details",
|
||||
"style": {
|
||||
"navigationBarTitleText": "发送好友申请"
|
||||
"navigationBarTitleText": "发送好友申请",
|
||||
"navigationBarBackgroundColor": "#ffffff"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -93,6 +93,7 @@
|
||||
}
|
||||
|
||||
onLoad(e => {
|
||||
formData.defaultAddress = e?.defaultAddress == 1
|
||||
if (props.type === 'edit') {
|
||||
getData(e.id)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
}
|
||||
|
||||
const onAdd = () => {
|
||||
navigateTo('/pages/address/add')
|
||||
navigateTo('/pages/address/add', {
|
||||
defaultAddress: listData.value.length === 0 ? '1' : ''
|
||||
})
|
||||
}
|
||||
|
||||
const onGo = id => {
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
const isBlack = ref(false)
|
||||
/** 点击备注弹框 */
|
||||
const showRemark = ref(false)
|
||||
/** 好友详情进入状态:C2C 个人 GROUP 群组 */
|
||||
const isDetailState = ref('')
|
||||
/** 点击查看头像 */
|
||||
const onViewAvatar = url => {
|
||||
uni.previewImage({
|
||||
@@ -87,8 +89,11 @@
|
||||
})
|
||||
}
|
||||
|
||||
/** 获取好友信息 */
|
||||
const getFriendInfo = async () => {
|
||||
/**
|
||||
* 获取好友信息
|
||||
* @param state 99 为自己
|
||||
*/
|
||||
const getFriendInfo = async state => {
|
||||
loading.value = true
|
||||
showLoading()
|
||||
if (isDetail.value) {
|
||||
@@ -97,10 +102,10 @@
|
||||
})
|
||||
.then(res => {
|
||||
const data = res.data.friendList[0]
|
||||
friendInfo.value = data.profile
|
||||
friendInfo.value = { ...data.profile, cbType: 'C2C' }
|
||||
confirmRemark.value = data.remark
|
||||
remark.value = data.remark
|
||||
console.log('好友信息==', data)
|
||||
console.log('好友信息==', friendInfo.value)
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
@@ -111,7 +116,10 @@
|
||||
userIDList: [userId.value]
|
||||
})
|
||||
.then(res => {
|
||||
friendInfo.value = res.data[0]
|
||||
friendInfo.value = {
|
||||
...res.data[0],
|
||||
cbType: state == 99 ? 'me' : 'C2C'
|
||||
}
|
||||
console.log('获取好友信息成功', friendInfo.value)
|
||||
})
|
||||
.finally(() => {
|
||||
@@ -291,31 +299,38 @@
|
||||
|
||||
/** 发送消息 */
|
||||
const onSendMessage = () => {
|
||||
if (isDetailState.value == 'C2C') {
|
||||
navigateBack()
|
||||
return
|
||||
}
|
||||
const data =
|
||||
friendInfo.value?.cbType === 'group'
|
||||
? `GROUP${friendInfo.value?.groupID}`
|
||||
: `C2C${friendInfo.value.userID}`
|
||||
TUIConversationService.switchConversation(data).then(() => {
|
||||
TUIGlobal?.navigateTo({
|
||||
url: `/TUIKit/components/TUIChat/index`
|
||||
url: `/TUIKit/components/TUIChat/index?type=${
|
||||
isDetailState.value == 'GROUP' ? 'GROUP' : ''
|
||||
}`
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
onLoad(e => {
|
||||
isDetailState.value = e?.state || ''
|
||||
userId.value = e?.id || ''
|
||||
/** type: 不传为添加 1 为详情页 9 为群信息 */
|
||||
/** type: 不传为添加 1 为详情页 9 为群信息 99 为自己 */
|
||||
if (e?.type == 9) {
|
||||
uni.setNavigationBarTitle({
|
||||
title: '群聊信息'
|
||||
})
|
||||
getGroupInfo()
|
||||
} else {
|
||||
isDetail.value = e?.type == 1 || false
|
||||
isDetail.value = ['1'].includes(e?.type) || false
|
||||
uni.setNavigationBarTitle({
|
||||
title: isDetail.value ? '好友信息' : '发送好友申请'
|
||||
})
|
||||
getFriendInfo()
|
||||
getFriendInfo(e?.type)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
@@ -334,18 +349,23 @@
|
||||
<uni-icons v-else type="contact-filled" size="80"></uni-icons>
|
||||
<view class="right-box">
|
||||
<text>{{ friendInfo.nick || '未知名称' }}</text>
|
||||
<text v-if="!friendInfo?.cbType == 'group'">
|
||||
<text v-if="friendInfo?.cbType !== 'group'">
|
||||
手机号: {{ friendInfo.userID }}
|
||||
</text>
|
||||
<text v-if="!friendInfo?.cbType == 'group'">
|
||||
<text v-if="friendInfo?.cbType !== 'group'">
|
||||
个性签名: {{ friendInfo.selfSignature || '暂无个性签名' }}
|
||||
</text>
|
||||
<text v-else>ID: {{ friendInfo.groupID }}</text>
|
||||
<text v-else>
|
||||
ID: {{ friendInfo.groupID || friendInfo.userID }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 验证信息输入 -->
|
||||
<view v-if="!isDetail" class="input-wrapper">
|
||||
<view
|
||||
v-if="!isDetail && friendInfo.cbType !== 'me'"
|
||||
class="input-wrapper"
|
||||
>
|
||||
<text class="title">请填写验证信息</text>
|
||||
<textarea
|
||||
v-model="verificationInfo"
|
||||
@@ -357,7 +377,7 @@
|
||||
|
||||
<!-- 备注 -->
|
||||
<view
|
||||
v-if="!friendInfo?.cbType == 'group' && !isDetail"
|
||||
v-if="!['group', 'me'].includes(friendInfo?.cbType) && !isDetail"
|
||||
class="remark"
|
||||
>
|
||||
<text>备注名</text>
|
||||
@@ -370,13 +390,33 @@
|
||||
</view>
|
||||
|
||||
<!-- 发送申请按钮 -->
|
||||
<view v-if="!isDetail" class="send-btn" @tap="submit">
|
||||
<view
|
||||
v-if="!isDetail && friendInfo.cbType !== 'me'"
|
||||
class="send-btn"
|
||||
@tap="submit"
|
||||
>
|
||||
<text>发送申请</text>
|
||||
</view>
|
||||
|
||||
<!-- 去朋友圈 -->
|
||||
<view
|
||||
v-if="friendInfo?.cbType == 'me'"
|
||||
class="remark"
|
||||
@click="
|
||||
navigateTo('/pages/discover/dynamic/dynamic', {
|
||||
id: friendInfo.userID
|
||||
})
|
||||
"
|
||||
>
|
||||
<text>朋友圈</text>
|
||||
<view style="display: flex; align-items: center">
|
||||
<uni-icons type="right" color="#999999" size="36rpx"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 修改好友信息======================== -->
|
||||
<view
|
||||
v-if="!friendInfo?.cbType == 'group' && isDetail"
|
||||
v-if="friendInfo?.cbType !== 'group' && isDetail"
|
||||
class="remark"
|
||||
@click="showRemark = true"
|
||||
>
|
||||
@@ -391,15 +431,14 @@
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
v-if="!friendInfo?.cbType == 'group' && isDetail"
|
||||
v-if="friendInfo?.cbType !== 'group' && isDetail"
|
||||
class="remark"
|
||||
>
|
||||
<text>加入黑名单</text>
|
||||
<SwitchBar :value="isBlack" @click="switchChange" />
|
||||
</view>
|
||||
|
||||
<view
|
||||
v-if="!friendInfo?.cbType == 'group' && isDetail"
|
||||
v-if="friendInfo?.cbType !== 'group' && isDetail"
|
||||
class="send-btn"
|
||||
@tap="onDeleteFriend"
|
||||
>
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
TUIFriendService,
|
||||
TUIGroupService
|
||||
} from '@tencentcloud/chat-uikit-engine-lite'
|
||||
import { useAuthUser } from '../../composables/useAuthUser'
|
||||
|
||||
const { tencentUserSig } = useAuthUser()
|
||||
const { showLoading, hideLoading } = useUI()
|
||||
const loading = ref(false)
|
||||
const searchValue = ref('')
|
||||
@@ -97,7 +99,10 @@
|
||||
}
|
||||
|
||||
const onAdd = item => {
|
||||
navigateTo('/pages/adduser/details', { id: item.userID })
|
||||
navigateTo('/pages/adduser/details', {
|
||||
id: item.userID,
|
||||
type: item.userID == tencentUserSig.value.userId ? '99' : ''
|
||||
})
|
||||
}
|
||||
|
||||
const onDetails = (item, state) => {
|
||||
@@ -155,8 +160,10 @@
|
||||
<text>{{ item.nick || '未知名称' }}</text>
|
||||
<text>{{ item.userID }}</text>
|
||||
</view>
|
||||
<text v-if="isFriend" class="tag">已添加</text>
|
||||
<button v-else @click.stop="onAdd(item)">添加</button>
|
||||
<view v-if="item.userID !== tencentUserSig.userId">
|
||||
<text v-if="isFriend" class="tag">已添加</text>
|
||||
<button v-else @click.stop="onAdd(item)">添加</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 群列表 -->
|
||||
@@ -180,7 +187,8 @@
|
||||
<text>{{ item.name || '未知名称' }}</text>
|
||||
<text>{{ item.groupID }}</text>
|
||||
</view>
|
||||
<text class="tag-but">群聊</text>
|
||||
<!-- <text class="tag-but">群聊</text> -->
|
||||
<button style="background: #828bff">群聊</button>
|
||||
<!-- <text v-if="isFriend" class="tag">已添加</text>
|
||||
<button v-else @click.stop="onAdd(item)">添加</button> -->
|
||||
</view>
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
const contentData = ref('')
|
||||
const inputId = ref('')
|
||||
const isType = ref('')
|
||||
const targetUserId = ref('')
|
||||
|
||||
const onScroll = e => {
|
||||
cbNavBar.value?.updateScroll(e.detail.scrollTop)
|
||||
@@ -57,7 +58,7 @@
|
||||
const res = await getUserMomentsList({
|
||||
pageNum,
|
||||
pageSize,
|
||||
targetUserId: isType.value == 1 ? userInfo.value.userId : ''
|
||||
targetUserId: isType.value == 1 ? userInfo.value.userId : targetUserId.value
|
||||
})
|
||||
const list = res.rows.map(item => {
|
||||
return {
|
||||
@@ -123,6 +124,7 @@
|
||||
})
|
||||
|
||||
onLoad(async e => {
|
||||
targetUserId.value = e?.id || ''
|
||||
isType.value = e?.type || ''
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -84,12 +84,13 @@
|
||||
const getData = async productId => {
|
||||
const res = await getProductDetail(productId)
|
||||
viewData.value = res.data
|
||||
|
||||
const {
|
||||
id,
|
||||
price,
|
||||
stockQuantity,
|
||||
originalPrice: nub
|
||||
} = res.data.skuList.find(v => v.isDefault == 1)
|
||||
} = res.data.skuList[0]
|
||||
originalPrice.value = nub
|
||||
formData.maxNum = stockQuantity
|
||||
formData.spec = id
|
||||
@@ -142,7 +143,7 @@
|
||||
const res = await addOrder(data)
|
||||
await refreshUserInfo()
|
||||
await showToast('订单提交成功', 'success')
|
||||
navigateBack()
|
||||
navigateTo('/pages/shop-together/detail', { id: res.data.groupId })
|
||||
}
|
||||
|
||||
onShow(() => {
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
<script setup>
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||
import { getProductDetail, getProductCommentList } from '@/api/mall'
|
||||
import {
|
||||
getProductDetail,
|
||||
getProductCommentList,
|
||||
getParticipateList
|
||||
} from '@/api/mall'
|
||||
import { ref, computed } from 'vue'
|
||||
import { navigateTo } from '@/utils/router'
|
||||
import { navigateTo, navigateBack } from '@/utils/router'
|
||||
import { getRemainingTime, parseDateTime } from '../../utils/dateUtils'
|
||||
|
||||
const viewData = ref({})
|
||||
const productId = ref('')
|
||||
@@ -12,9 +17,31 @@
|
||||
const commentNum = ref(0)
|
||||
/** 分享弹窗 */
|
||||
const shareDialog = ref(false)
|
||||
/** 是否显示拼团数据 */
|
||||
const isPingTuan = ref(false)
|
||||
/** 拼团列表 */
|
||||
const pingtuanList = ref([])
|
||||
const getData = async productId => {
|
||||
const res = await getProductDetail(productId)
|
||||
viewData.value = res.data
|
||||
try {
|
||||
const res = await getProductDetail(productId)
|
||||
viewData.value = res.data
|
||||
if (res.data.groupActivities.length > 0) {
|
||||
const c = await getParticipateList(res.data.groupActivities[0].id)
|
||||
console.log(c.data, '====')
|
||||
console.log(getRemainingTime('2026-01-28 23:46:40'))
|
||||
pingtuanList.value = c.data.map(v => {
|
||||
return {
|
||||
...v,
|
||||
showDate: true
|
||||
}
|
||||
})
|
||||
isPingTuan.value = c.data.length > 0
|
||||
} else {
|
||||
isPingTuan.value = false
|
||||
}
|
||||
} catch (error) {
|
||||
navigateBack()
|
||||
}
|
||||
}
|
||||
|
||||
/** 评论数量获取 */
|
||||
@@ -36,14 +63,6 @@
|
||||
return viewData.value.groupActivities[0].totalPeople
|
||||
})
|
||||
|
||||
/**
|
||||
* 顶部导航按钮点击事件
|
||||
* @param index 0 返回 1 分享
|
||||
*/
|
||||
const onTopNav = index => {
|
||||
console.log(index)
|
||||
}
|
||||
|
||||
const onConfirm = () => {
|
||||
navigateTo('/pages/mall/confirm-order', {
|
||||
productId: productId.value,
|
||||
@@ -82,11 +101,21 @@
|
||||
</nav-bar>
|
||||
<!-- 顶部图片 -->
|
||||
<view class="top-img">
|
||||
<image
|
||||
:src="viewData.mainImage"
|
||||
mode="scaleToFill"
|
||||
class="img"
|
||||
></image>
|
||||
<swiper
|
||||
class="swiper"
|
||||
circular
|
||||
indicator-dots
|
||||
autoplay
|
||||
:interval="4000"
|
||||
:duration="500"
|
||||
>
|
||||
<swiper-item
|
||||
v-for="(item, index) in viewData.imageGallery"
|
||||
:key="index"
|
||||
>
|
||||
<image :src="item" mode="scaleToFill" class="img"></image>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
|
||||
<!-- 商品详情 -->
|
||||
@@ -100,37 +129,64 @@
|
||||
<text>拼单数量:{{ viewData.salesCount }}件</text>
|
||||
<text>好评率:99%</text>
|
||||
</view>
|
||||
<!-- 拼单量 -->
|
||||
<view class="line-box">
|
||||
<view class="left-img">
|
||||
<text>拼单</text>
|
||||
<image
|
||||
src="/static/images/public/random1.png"
|
||||
mode="scaleToFill"
|
||||
class="avatar"
|
||||
></image>
|
||||
<image
|
||||
src="/static/images/public/random2.png"
|
||||
mode="scaleToFill"
|
||||
class="avatar"
|
||||
></image>
|
||||
<image
|
||||
src="/static/images/public/random3.png"
|
||||
mode="scaleToFill"
|
||||
class="avatar"
|
||||
></image>
|
||||
</view>
|
||||
<text class="right-name">还需{{ getPeople }}人拼单</text>
|
||||
</view>
|
||||
<!-- 去拼团 -->
|
||||
<!-- <view class="bottom-name">
|
||||
<view class="count-down">
|
||||
<text>拼单倒计时:</text>
|
||||
<text>23:53:00</text>
|
||||
</view>
|
||||
<button>去拼单</button>
|
||||
</view>-->
|
||||
|
||||
<view v-if="!groupId && isPingTuan" class="ping-box">
|
||||
<view v-for="(item, index) in pingtuanList" :key="index">
|
||||
<!-- 拼单量 -->
|
||||
<view class="line-box">
|
||||
<view class="left-img">
|
||||
<text>拼单</text>
|
||||
<image
|
||||
src="/static/images/public/random1.png"
|
||||
mode="scaleToFill"
|
||||
class="avatar"
|
||||
></image>
|
||||
<image
|
||||
src="/static/images/public/random2.png"
|
||||
mode="scaleToFill"
|
||||
class="avatar"
|
||||
></image>
|
||||
<image
|
||||
src="/static/images/public/random3.png"
|
||||
mode="scaleToFill"
|
||||
class="avatar"
|
||||
></image>
|
||||
</view>
|
||||
<text class="right-name">
|
||||
还需{{ item.needPeople }}人拼单
|
||||
</text>
|
||||
</view>
|
||||
<!-- 去拼团 -->
|
||||
<view class="bottom-name">
|
||||
<view class="count-down">
|
||||
<text>拼单倒计时:</text>
|
||||
<uni-countdown
|
||||
:day="parseDateTime(item.endTime).day"
|
||||
:hour="parseDateTime(item.endTime).hour"
|
||||
:minute="parseDateTime(item.endTime).minute"
|
||||
:second="parseDateTime(item.endTime).second"
|
||||
:show-colon="false"
|
||||
@timeup="
|
||||
() => {
|
||||
item.showDate = false
|
||||
}
|
||||
"
|
||||
/>
|
||||
</view>
|
||||
<button
|
||||
v-if="item.showDate"
|
||||
@click="
|
||||
navigateTo('/pages/mall/confirm-order', {
|
||||
productId: productId,
|
||||
groupId: item.id
|
||||
})
|
||||
"
|
||||
>
|
||||
去拼单
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 评论入口 -->
|
||||
<view
|
||||
class="comment-box"
|
||||
@@ -168,11 +224,17 @@
|
||||
:id="productId"
|
||||
:text="viewData.productName"
|
||||
:cover="viewData.mainImage"
|
||||
:price="viewData.minPrice"
|
||||
></share-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ping-box {
|
||||
max-height: 500rpx;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.left-icon,
|
||||
.right-icon {
|
||||
height: 64rpx;
|
||||
@@ -183,13 +245,17 @@
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
bottom: -2rpx;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 56rpx;
|
||||
background: #fff;
|
||||
border-radius: 32rpx 32rpx 0 0;
|
||||
}
|
||||
.swiper {
|
||||
width: 100%;
|
||||
height: 628rpx;
|
||||
}
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 628rpx;
|
||||
@@ -197,9 +263,7 @@
|
||||
}
|
||||
.detail-box {
|
||||
padding: 0 58rpx 150rpx;
|
||||
font-family:
|
||||
PingFang SC,
|
||||
PingFang SC;
|
||||
font-family: PingFang SC, PingFang SC;
|
||||
font-style: normal;
|
||||
text-transform: none;
|
||||
.title {
|
||||
@@ -257,7 +321,8 @@
|
||||
}
|
||||
.bottom-name {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
.count-down {
|
||||
display: flex;
|
||||
@@ -307,9 +372,7 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-family:
|
||||
PingFang SC,
|
||||
PingFang SC;
|
||||
font-family: PingFang SC, PingFang SC;
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
text-transform: none;
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
const { userInfo } = useAuthUser()
|
||||
|
||||
const inviteLink = computed(() => {
|
||||
const { href } = window.location
|
||||
return `${href}/pages/login/phone-register/phone-register?invitationCode=${userInfo.value.invitationCode}`
|
||||
const { origin } = window.location
|
||||
return `${origin}/pages/login/phone-register/phone-register?invitationCode=${userInfo.value.invitationCode}`
|
||||
})
|
||||
|
||||
|
||||
// 复制文本通用函数
|
||||
const copyText = text => {
|
||||
uni.setClipboardData({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { useUI } from '../../utils/use-ui'
|
||||
|
||||
const { showToast } = useUI()
|
||||
@@ -9,13 +9,29 @@
|
||||
const productId = ref('')
|
||||
const qrcodeRef = ref(null)
|
||||
|
||||
const BASE_URL = computed(() => {
|
||||
const { origin } = window.location
|
||||
return `${origin}/pages/mall/detail?productId=${productId.value}&groupId=${groupId.value}`
|
||||
})
|
||||
|
||||
// 复制文本通用函数
|
||||
const copyText = text => {
|
||||
uni.setClipboardData({
|
||||
data: BASE_URL.value,
|
||||
success: () => {
|
||||
console.log('已复制到剪贴板')
|
||||
},
|
||||
fail: () => {
|
||||
console.log('复制失败')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onLoad(e => {
|
||||
groupId.value = e.id
|
||||
productId.value = e.productId
|
||||
// /pages/mall/detail
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -36,10 +52,60 @@
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 复制连接 -->
|
||||
<!-- #ifdef H5 -->
|
||||
<view class="copy-box">
|
||||
<text class="link">拼单链接:{{ BASE_URL }}</text>
|
||||
<button @click="copyText">复制</button>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.copy-box {
|
||||
margin-top: 118rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.link {
|
||||
// 超过宽度显示省略号
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
width: 544rpx;
|
||||
font-family: PingFang SC, PingFang SC;
|
||||
font-weight: 500;
|
||||
font-size: 32rpx;
|
||||
font-style: normal;
|
||||
text-transform: none;
|
||||
color: #00d993;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-top: 48rpx;
|
||||
width: 256rpx;
|
||||
height: 64rpx;
|
||||
line-height: 60rpx;
|
||||
border-radius: 100rpx;
|
||||
border: 2rpx solid #00d993;
|
||||
color: #00d993;
|
||||
padding: 0;
|
||||
background: none;
|
||||
|
||||
font-family: PingFang SC, PingFang SC;
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
text-align: center;
|
||||
font-style: normal;
|
||||
text-transform: none;
|
||||
&::after {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.share-box {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
|
||||
30
uni_modules/uni-countdown/changelog.md
Normal file
30
uni_modules/uni-countdown/changelog.md
Normal file
@@ -0,0 +1,30 @@
|
||||
## 1.2.5(2025-04-14)
|
||||
- 修复 filterShow 导致的运行报错
|
||||
## 1.2.4(2024-09-21)
|
||||
- 新增 支持控制显示位数 默认显示2位
|
||||
## 1.2.3(2024-02-20)
|
||||
- 新增 支持控制小时,分钟的显隐:showHour showMinute
|
||||
## 1.2.2(2022-01-19)
|
||||
- 修复 在微信小程序中样式不生效的bug
|
||||
## 1.2.1(2022-01-18)
|
||||
- 新增 update 方法 ,在动态更新时间后,刷新组件
|
||||
## 1.2.0(2021-11-19)
|
||||
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-countdown](https://uniapp.dcloud.io/component/uniui/uni-countdown)
|
||||
## 1.1.3(2021-10-18)
|
||||
- 重构
|
||||
- 新增 font-size 支持自定义字体大小
|
||||
## 1.1.2(2021-08-24)
|
||||
- 新增 支持国际化
|
||||
## 1.1.1(2021-07-30)
|
||||
- 优化 vue3下小程序事件警告的问题
|
||||
## 1.1.0(2021-07-30)
|
||||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||
## 1.0.5(2021-06-18)
|
||||
- 修复 uni-countdown 重复赋值跳两秒的 bug
|
||||
## 1.0.4(2021-05-12)
|
||||
- 新增 组件示例地址
|
||||
## 1.0.3(2021-05-08)
|
||||
- 修复 uni-countdown 不能控制倒计时的 bug
|
||||
## 1.0.2(2021-02-04)
|
||||
- 调整为uni_modules目录规范
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"uni-countdown.day": "day",
|
||||
"uni-countdown.h": "h",
|
||||
"uni-countdown.m": "m",
|
||||
"uni-countdown.s": "s"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import en from './en.json'
|
||||
import zhHans from './zh-Hans.json'
|
||||
import zhHant from './zh-Hant.json'
|
||||
export default {
|
||||
en,
|
||||
'zh-Hans': zhHans,
|
||||
'zh-Hant': zhHant
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"uni-countdown.day": "天",
|
||||
"uni-countdown.h": "时",
|
||||
"uni-countdown.m": "分",
|
||||
"uni-countdown.s": "秒"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"uni-countdown.day": "天",
|
||||
"uni-countdown.h": "時",
|
||||
"uni-countdown.m": "分",
|
||||
"uni-countdown.s": "秒"
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
<template>
|
||||
<view class="uni-countdown">
|
||||
<text v-if="showDay" :style="[timeStyle]" class="uni-countdown__number">{{ d }}</text>
|
||||
<text v-if="showDay" :style="[splitorStyle]" class="uni-countdown__splitor">{{dayText}}</text>
|
||||
<text v-if="showHour" :style="[timeStyle]" class="uni-countdown__number">{{ h }}</text>
|
||||
<text v-if="showHour" :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : hourText }}</text>
|
||||
<text v-if="showMinute" :style="[timeStyle]" class="uni-countdown__number">{{ i }}</text>
|
||||
<text v-if="showMinute" :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : minuteText }}</text>
|
||||
<text :style="[timeStyle]" class="uni-countdown__number">{{ s }}</text>
|
||||
<text v-if="!showColon" :style="[splitorStyle]" class="uni-countdown__splitor">{{secondText}}</text>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
initVueI18n
|
||||
} from '@dcloudio/uni-i18n'
|
||||
import messages from './i18n/index.js'
|
||||
const {
|
||||
t
|
||||
} = initVueI18n(messages)
|
||||
/**
|
||||
* Countdown 倒计时
|
||||
* @description 倒计时组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=25
|
||||
* @property {String} backgroundColor 背景色
|
||||
* @property {String} color 文字颜色
|
||||
* @property {Number} day 天数
|
||||
* @property {Number} hour 小时
|
||||
* @property {Number} minute 分钟
|
||||
* @property {Number} second 秒
|
||||
* @property {Number} timestamp 时间戳
|
||||
* @property {Boolean} showDay = [true|false] 是否显示天数
|
||||
* @property {Boolean} showHour = [true|false] 是否显示小时
|
||||
* @property {Boolean} showMinute = [true|false] 是否显示分钟
|
||||
* @property {Boolean} show-colon = [true|false] 是否以冒号为分隔符
|
||||
* @property {String} splitorColor 分割符号颜色
|
||||
* @event {Function} timeup 倒计时时间到触发事件
|
||||
* @example <uni-countdown :day="1" :hour="1" :minute="12" :second="40"></uni-countdown>
|
||||
*/
|
||||
export default {
|
||||
name: 'UniCountdown',
|
||||
emits: ['timeup'],
|
||||
props: {
|
||||
showDay: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showHour: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showMinute: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showColon: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
start: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#333'
|
||||
},
|
||||
fontSize: {
|
||||
type: Number,
|
||||
default: 14
|
||||
},
|
||||
splitorColor: {
|
||||
type: String,
|
||||
default: '#333'
|
||||
},
|
||||
day: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
hour: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
minute: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
second: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
timestamp: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
filterShow : {
|
||||
type:Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
timer: null,
|
||||
syncFlag: false,
|
||||
d: '00',
|
||||
h: '00',
|
||||
i: '00',
|
||||
s: '00',
|
||||
leftTime: 0,
|
||||
seconds: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dayText() {
|
||||
return t("uni-countdown.day")
|
||||
},
|
||||
hourText(val) {
|
||||
return t("uni-countdown.h")
|
||||
},
|
||||
minuteText(val) {
|
||||
return t("uni-countdown.m")
|
||||
},
|
||||
secondText(val) {
|
||||
return t("uni-countdown.s")
|
||||
},
|
||||
timeStyle() {
|
||||
const {
|
||||
color,
|
||||
backgroundColor,
|
||||
fontSize
|
||||
} = this
|
||||
return {
|
||||
color,
|
||||
backgroundColor,
|
||||
fontSize: `${fontSize}px`,
|
||||
width: `${fontSize * 22 / 14}px`, // 按字体大小为 14px 时的比例缩放
|
||||
lineHeight: `${fontSize * 20 / 14}px`,
|
||||
borderRadius: `${fontSize * 3 / 14}px`,
|
||||
}
|
||||
},
|
||||
splitorStyle() {
|
||||
const { splitorColor, fontSize, backgroundColor } = this
|
||||
return {
|
||||
color: splitorColor,
|
||||
fontSize: `${fontSize * 12 / 14}px`,
|
||||
margin: backgroundColor ? `${fontSize * 4 / 14}px` : ''
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
day(val) {
|
||||
this.changeFlag()
|
||||
},
|
||||
hour(val) {
|
||||
this.changeFlag()
|
||||
},
|
||||
minute(val) {
|
||||
this.changeFlag()
|
||||
},
|
||||
second(val) {
|
||||
this.changeFlag()
|
||||
},
|
||||
start: {
|
||||
immediate: true,
|
||||
handler(newVal, oldVal) {
|
||||
if (newVal) {
|
||||
this.startData();
|
||||
} else {
|
||||
if (!oldVal) return
|
||||
clearInterval(this.timer)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
created: function(e) {
|
||||
this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
|
||||
this.countDown()
|
||||
},
|
||||
// #ifndef VUE3
|
||||
destroyed() {
|
||||
clearInterval(this.timer)
|
||||
},
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
unmounted() {
|
||||
clearInterval(this.timer)
|
||||
},
|
||||
// #endif
|
||||
methods: {
|
||||
toSeconds(timestamp, day, hours, minutes, seconds) {
|
||||
if (timestamp) {
|
||||
return timestamp - parseInt(new Date().getTime() / 1000, 10)
|
||||
}
|
||||
return day * 60 * 60 * 24 + hours * 60 * 60 + minutes * 60 + seconds
|
||||
},
|
||||
timeUp() {
|
||||
clearInterval(this.timer)
|
||||
this.$emit('timeup')
|
||||
},
|
||||
countDown() {
|
||||
let seconds = this.seconds
|
||||
let [day, hour, minute, second] = [0, 0, 0, 0]
|
||||
if (seconds > 0) {
|
||||
day = Math.floor(seconds / (60 * 60 * 24))
|
||||
hour = Math.floor(seconds / (60 * 60)) - (day * 24)
|
||||
minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60)
|
||||
second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60)
|
||||
} else {
|
||||
this.timeUp()
|
||||
}
|
||||
this.d = String(day).padStart(this.validFilterShow(this.filterShow.d), '0')
|
||||
this.h = String(hour).padStart(this.validFilterShow(this.filterShow.h), '0')
|
||||
this.i = String(minute).padStart(this.validFilterShow(this.filterShow.m), '0')
|
||||
this.s = String(second).padStart(this.validFilterShow(this.filterShow.s), '0')
|
||||
},
|
||||
validFilterShow(filter){
|
||||
return (filter && filter > 0) ? filter : 2;
|
||||
},
|
||||
startData() {
|
||||
this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
|
||||
if (this.seconds <= 0) {
|
||||
this.seconds = this.toSeconds(0, 0, 0, 0, 0)
|
||||
this.countDown()
|
||||
return
|
||||
}
|
||||
clearInterval(this.timer)
|
||||
this.countDown()
|
||||
this.timer = setInterval(() => {
|
||||
this.seconds--
|
||||
if (this.seconds < 0) {
|
||||
this.timeUp()
|
||||
return
|
||||
}
|
||||
this.countDown()
|
||||
}, 1000)
|
||||
},
|
||||
update(){
|
||||
this.startData();
|
||||
},
|
||||
changeFlag() {
|
||||
if (!this.syncFlag) {
|
||||
this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
|
||||
this.startData();
|
||||
this.syncFlag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
$font-size: 14px;
|
||||
|
||||
.uni-countdown {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
&__splitor {
|
||||
margin: 0 2px;
|
||||
font-size: $font-size;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
&__number {
|
||||
border-radius: 3px;
|
||||
text-align: center;
|
||||
font-size: $font-size;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
86
uni_modules/uni-countdown/package.json
Normal file
86
uni_modules/uni-countdown/package.json
Normal file
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"id": "uni-countdown",
|
||||
"displayName": "uni-countdown 倒计时",
|
||||
"version": "1.2.5",
|
||||
"description": "CountDown 倒计时组件",
|
||||
"keywords": [
|
||||
"uni-ui",
|
||||
"uniui",
|
||||
"countdown",
|
||||
"倒计时"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": ""
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
|
||||
"type": "component-vue"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": ["uni-scss"],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y",
|
||||
"alipay": "n"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y",
|
||||
"app-harmony": "u",
|
||||
"app-uvue": "u"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
uni_modules/uni-countdown/readme.md
Normal file
10
uni_modules/uni-countdown/readme.md
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
## CountDown 倒计时
|
||||
> **组件名:uni-countdown**
|
||||
> 代码块: `uCountDown`
|
||||
|
||||
倒计时组件。
|
||||
|
||||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-countdown)
|
||||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||
12
uni_modules/uni-swiper-dot/changelog.md
Normal file
12
uni_modules/uni-swiper-dot/changelog.md
Normal file
@@ -0,0 +1,12 @@
|
||||
## 1.2.0(2021-11-19)
|
||||
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-swiper-dot](https://uniapp.dcloud.io/component/uniui/uni-swiper-dot)
|
||||
## 1.1.0(2021-07-30)
|
||||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||
## 1.0.6(2021-05-12)
|
||||
- 新增 示例地址
|
||||
- 修复 示例项目缺少组件的Bug
|
||||
## 1.0.5(2021-02-05)
|
||||
- 调整为uni_modules目录规范
|
||||
- 新增 clickItem 事件,支持指示点控制轮播
|
||||
- 新增 支持 pc 可用
|
||||
@@ -0,0 +1,218 @@
|
||||
<template>
|
||||
<view class="uni-swiper__warp">
|
||||
<slot />
|
||||
<view v-if="mode === 'default'" :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box" key='default'>
|
||||
<view v-for="(item,index) in info" @click="clickItem(index)" :style="{
|
||||
'width': (index === current? dots.width*2:dots.width ) + 'px','height':dots.width/2 +'px' ,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border-radius':'0px'}"
|
||||
:key="index" class="uni-swiper__dots-item uni-swiper__dots-bar" />
|
||||
</view>
|
||||
<view v-if="mode === 'dot'" :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box" key='dot'>
|
||||
<view v-for="(item,index) in info" @click="clickItem(index)" :style="{
|
||||
'width': dots.width + 'px','height':dots.height +'px' ,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border':index !==current ? dots.border:dots.selectedBorder}"
|
||||
:key="index" class="uni-swiper__dots-item" />
|
||||
</view>
|
||||
<view v-if="mode === 'round'" :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box" key='round'>
|
||||
<view v-for="(item,index) in info" @click="clickItem(index)" :class="[index === current&&'uni-swiper__dots-long']" :style="{
|
||||
'width':(index === current? dots.width*3:dots.width ) + 'px','height':dots.height +'px' ,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border':index !==current ? dots.border:dots.selectedBorder}"
|
||||
:key="index" class="uni-swiper__dots-item " />
|
||||
</view>
|
||||
<view v-if="mode === 'nav'" key='nav' :style="{'background-color':dotsStyles.backgroundColor,'bottom':'0'}" class="uni-swiper__dots-box uni-swiper__dots-nav">
|
||||
<text :style="{'color':dotsStyles.color}" class="uni-swiper__dots-nav-item">{{ (current+1)+"/"+info.length +' ' +info[current][field] }}</text>
|
||||
</view>
|
||||
<view v-if="mode === 'indexes'" key='indexes' :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box">
|
||||
<view v-for="(item,index) in info" @click="clickItem(index)" :style="{
|
||||
'width':dots.width + 'px','height':dots.height +'px' ,'color':index === current?dots.selectedColor:dots.color,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border':index !==current ? dots.border:dots.selectedBorder}"
|
||||
:key="index" class="uni-swiper__dots-item uni-swiper__dots-indexes"><text class="uni-swiper__dots-indexes-text">{{ index+1 }}</text></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
/**
|
||||
* SwiperDod 轮播图指示点
|
||||
* @description 自定义轮播图指示点
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=284
|
||||
* @property {Number} current 当前指示点索引,必须是通过 `swiper` 的 `change` 事件获取到的 `e.detail.current`
|
||||
* @property {String} mode = [default|round|nav|indexes] 指示点的类型
|
||||
* @value defualt 默认指示点
|
||||
* @value round 圆形指示点
|
||||
* @value nav 条形指示点
|
||||
* @value indexes 索引指示点
|
||||
* @property {String} field mode 为 nav 时,显示的内容字段(mode = nav 时必填)
|
||||
* @property {String} info 轮播图的数据,通过数组长度决定指示点个数
|
||||
* @property {Object} dotsStyles 指示点样式
|
||||
* @event {Function} clickItem 组件触发点击事件时触发,e={currentIndex}
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'UniSwiperDot',
|
||||
emits:['clickItem'],
|
||||
props: {
|
||||
info: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
current: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
dotsStyles: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
// 类型 :default(默认) indexes long nav
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'default'
|
||||
},
|
||||
// 只在 nav 模式下生效,变量名称
|
||||
field: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dots: {
|
||||
width: 6,
|
||||
height: 6,
|
||||
bottom: 10,
|
||||
color: '#fff',
|
||||
backgroundColor: 'rgba(0, 0, 0, .3)',
|
||||
border: '1px rgba(0, 0, 0, .3) solid',
|
||||
selectedBackgroundColor: '#333',
|
||||
selectedBorder: '1px rgba(0, 0, 0, .9) solid'
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
dotsStyles(newVal) {
|
||||
this.dots = Object.assign(this.dots, this.dotsStyles)
|
||||
},
|
||||
mode(newVal) {
|
||||
if (newVal === 'indexes') {
|
||||
this.dots.width = 14
|
||||
this.dots.height = 14
|
||||
} else {
|
||||
this.dots.width = 6
|
||||
this.dots.height = 6
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
created() {
|
||||
if (this.mode === 'indexes') {
|
||||
this.dots.width = 12
|
||||
this.dots.height = 12
|
||||
}
|
||||
this.dots = Object.assign(this.dots, this.dotsStyles)
|
||||
},
|
||||
methods: {
|
||||
clickItem(index) {
|
||||
this.$emit('clickItem', index)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.uni-swiper__warp {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-swiper__dots-box {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-swiper__dots-item {
|
||||
width: 8px;
|
||||
border-radius: 100px;
|
||||
margin-left: 6px;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
/* #ifndef APP-NVUE */
|
||||
cursor: pointer;
|
||||
/* #endif */
|
||||
/* #ifdef H5 */
|
||||
// border-width: 5px 0;
|
||||
// border-style: solid;
|
||||
// border-color: transparent;
|
||||
// background-clip: padding-box;
|
||||
/* #endif */
|
||||
// transition: width 0.2s linear; 不要取消注释,不然会不能变色
|
||||
}
|
||||
|
||||
.uni-swiper__dots-item:first-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.uni-swiper__dots-default {
|
||||
border-radius: 100px;
|
||||
}
|
||||
|
||||
.uni-swiper__dots-long {
|
||||
border-radius: 50px;
|
||||
}
|
||||
|
||||
.uni-swiper__dots-bar {
|
||||
border-radius: 50px;
|
||||
}
|
||||
|
||||
.uni-swiper__dots-nav {
|
||||
bottom: 0px;
|
||||
// height: 26px;
|
||||
padding: 8px 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.uni-swiper__dots-nav-item {
|
||||
/* overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; */
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
margin: 0 15px;
|
||||
}
|
||||
|
||||
.uni-swiper__dots-indexes {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
// flex: 1;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-swiper__dots-indexes-text {
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
line-height: 14px;
|
||||
}
|
||||
</style>
|
||||
87
uni_modules/uni-swiper-dot/package.json
Normal file
87
uni_modules/uni-swiper-dot/package.json
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"id": "uni-swiper-dot",
|
||||
"displayName": "uni-swiper-dot 轮播图指示点",
|
||||
"version": "1.2.0",
|
||||
"description": "自定义轮播图指示点组件",
|
||||
"keywords": [
|
||||
"uni-ui",
|
||||
"uniui",
|
||||
"轮播图指示点",
|
||||
"dot",
|
||||
"swiper"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": ""
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"category": [
|
||||
"前端组件",
|
||||
"通用组件"
|
||||
],
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": ["uni-scss"],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
uni_modules/uni-swiper-dot/readme.md
Normal file
11
uni_modules/uni-swiper-dot/readme.md
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
|
||||
## SwiperDot 轮播图指示点
|
||||
> **组件名:uni-swiper-dot**
|
||||
> 代码块: `uSwiperDot`
|
||||
|
||||
|
||||
自定义轮播图指示点
|
||||
|
||||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-swiper-dot)
|
||||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||
@@ -80,3 +80,53 @@ export function formatRelativeTime(timeStr) {
|
||||
return timeStr.split(' ')[0] // 或使用更美观的格式
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取天,时,分,秒
|
||||
* @param {*} dateTimeStr
|
||||
* @returns
|
||||
*/
|
||||
export const parseDateTime = dateTimeStr => {
|
||||
const date = new Date(dateTimeStr)
|
||||
|
||||
// 检查日期是否有效
|
||||
if (isNaN(date.getTime())) {
|
||||
throw new Error('Invalid date string')
|
||||
}
|
||||
|
||||
return {
|
||||
day: date.getDate(), // 月份中的第几天(1-31)
|
||||
hour: date.getHours(), // 小时(0-23)
|
||||
minute: date.getMinutes(), // 分钟(0-59)
|
||||
second: date.getSeconds() // 秒(0-59)
|
||||
}
|
||||
}
|
||||
|
||||
export const getRemainingTime = endTimeStr => {
|
||||
const now = new Date().getTime() // 当前时间戳(毫秒)
|
||||
const end = new Date(endTimeStr.replace(' ', 'T')).getTime() // 转为 ISO 格式并获取时间戳
|
||||
|
||||
if (isNaN(end)) {
|
||||
throw new Error('无效的结束时间格式')
|
||||
}
|
||||
|
||||
const diff = end - now // 剩余毫秒数
|
||||
|
||||
if (diff <= 0) {
|
||||
return { day: 0, hour: 0, minute: 0, second: 0, isExpired: true }
|
||||
}
|
||||
|
||||
const totalSeconds = Math.floor(diff / 1000)
|
||||
const day = Math.floor(totalSeconds / (24 * 3600))
|
||||
const hour = Math.floor((totalSeconds % (24 * 3600)) / 3600)
|
||||
const minute = Math.floor((totalSeconds % 3600) / 60)
|
||||
const second = totalSeconds % 60
|
||||
|
||||
return {
|
||||
day,
|
||||
hour,
|
||||
minute,
|
||||
second,
|
||||
isExpired: false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user