This commit is contained in:
aaron 2025-03-17 00:00:39 +08:00
parent 132eb9b063
commit 674b67065a
3 changed files with 155 additions and 25 deletions

10
package-lock.json generated
View File

@ -8,9 +8,11 @@
"name": "beefast-admin",
"version": "0.1.0",
"dependencies": {
"@vue/cli-service": "^5.0.8",
"ant-design-vue": "^3.2.20",
"axios": "^1.7.9",
"nprogress": "^0.2.0",
"qrcode.vue": "^3.6.0",
"vue": "^3.3.4",
"vue-router": "^4.5.0",
"vuedraggable": "^4.1.0",
@ -6939,6 +6941,14 @@
"node": ">=6"
}
},
"node_modules/qrcode.vue": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/qrcode.vue/-/qrcode.vue-3.6.0.tgz",
"integrity": "sha512-vQcl2fyHYHMjDO1GguCldJxepq2izQjBkDEEu9NENgfVKP6mv/e2SU62WbqYHGwTgWXLhxZ1NCD1dAZKHQq1fg==",
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/qs": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",

View File

@ -3,14 +3,15 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@vue/cli-service": "^5.0.8",
"ant-design-vue": "^3.2.20",
"axios": "^1.7.9",
"nprogress": "^0.2.0",
"qrcode.vue": "^3.6.0",
"vue": "^3.3.4",
"vue-router": "^4.5.0",
"vuedraggable": "^4.1.0",
"vuex": "^4.0.2",
"@vue/cli-service": "^5.0.8"
"vuex": "^4.0.2"
},
"devDependencies": {
"@vue/cli-service": "^5.0.8",

View File

@ -34,8 +34,9 @@
{{ formatDateTime(record.create_time) }}
</template>
<template v-if="column.key === 'action'">
<a-space>
<a-space size="small" class="action-column">
<a @click="handleEdit(record)">编辑</a>
<a @click="handleGetLink(record)">获取链接</a>
</a-space>
</template>
</template>
@ -219,12 +220,41 @@
</a-card>
</a-form>
</a-modal>
<!-- 链接二维码模态框 -->
<a-modal
v-model:visible="qrCodeModalVisible"
title="活动链接"
@cancel="handleQrCodeModalCancel"
:footer="null"
width="400px"
centered
>
<div class="qrcode-container">
<div v-if="linkLoading" class="qrcode-loading">
<a-spin />
<p>获取链接中...</p>
</div>
<template v-else>
<div class="qrcode-wrapper">
<qrcode-vue :value="activityLink" :size="200" level="H" />
</div>
<div class="link-container">
<a-input v-model:value="activityLink" readonly />
<a-button type="primary" @click="copyLink">复制链接</a-button>
</div>
<div class="qrcode-tip">
<p>扫描二维码或复制链接分享给用户</p>
</div>
</template>
</div>
</a-modal>
</div>
</page-container>
</template>
<script>
import { defineComponent, ref, onMounted, watch } from 'vue'
import { defineComponent, ref, onMounted, watch, nextTick } from 'vue'
import {
message,
DatePicker,
@ -237,11 +267,13 @@ import {
Table,
Checkbox,
Card,
Divider
Divider,
Spin
} from 'ant-design-vue'
import PageContainer from '@/components/PageContainer.vue'
import dayjs from 'dayjs'
import request from '@/utils/request'
import QrcodeVue from 'qrcode.vue'
export default defineComponent({
components: {
@ -257,7 +289,9 @@ export default defineComponent({
ATable: Table,
ACheckbox: Checkbox,
ACard: Card,
ADivider: Divider
ADivider: Divider,
QrcodeVue,
ASpin: Spin
},
setup() {
@ -286,13 +320,6 @@ export default defineComponent({
key: 'name',
width: 200
},
{
title: '活动说明',
dataIndex: 'description',
key: 'description',
width: 200,
ellipsis: true
},
{
title: '活动时间',
key: 'time_range',
@ -304,17 +331,17 @@ export default defineComponent({
width: 120
},
{
title: '用户可领数',
title: '用户可领数',
dataIndex: 'user_limit',
key: 'user_limit',
width: 100,
width: 90,
align: 'center'
},
{
title: '总限领',
dataIndex: 'total_limit',
key: 'total_limit',
width: 100,
width: 80,
align: 'center',
customRender: ({ text }) => {
return text || '不限'
@ -324,7 +351,7 @@ export default defineComponent({
title: '已领取次数',
dataIndex: 'receive_count',
key: 'receive_count',
width: 100,
width: 90,
align: 'center',
customRender: ({ text }) => {
return text || 0
@ -333,18 +360,13 @@ export default defineComponent({
{
title: '状态',
key: 'is_active',
width: 100,
width: 80,
align: 'center'
},
{
title: '创建时间',
key: 'create_time',
width: 180
},
{
title: '操作',
key: 'action',
width: 80,
width: 100,
fixed: 'right'
}
]
@ -650,6 +672,49 @@ export default defineComponent({
}
})
const qrCodeModalVisible = ref(false)
const activityLink = ref('')
const linkLoading = ref(false)
//
const handleGetLink = async (record) => {
//
qrCodeModalVisible.value = true
linkLoading.value = true
try {
const res = await request.get(`/api/coupon-activities/${record.id}/get_url_link`)
if (res.code === 200) {
activityLink.value = res.data
} else {
message.error('获取活动链接失败')
qrCodeModalVisible.value = false
}
} catch (error) {
console.error('获取活动链接失败:', error)
message.error('获取活动链接失败')
qrCodeModalVisible.value = false
} finally {
linkLoading.value = false
}
}
//
const copyLink = () => {
const input = document.createElement('input')
input.value = activityLink.value
document.body.appendChild(input)
input.select()
document.execCommand('copy')
document.body.removeChild(input)
message.success('链接已复制到剪贴板')
}
//
const handleQrCodeModalCancel = () => {
qrCodeModalVisible.value = false
}
onMounted(() => {
fetchData()
})
@ -676,7 +741,13 @@ export default defineComponent({
disabledDailyEndTime,
handleEdit,
isSelectedCoupon,
handleCouponSelect
handleCouponSelect,
qrCodeModalVisible,
activityLink,
linkLoading,
handleGetLink,
copyLink,
handleQrCodeModalCancel
}
}
})
@ -813,4 +884,52 @@ export default defineComponent({
.coupon-activity-form :deep(.ant-card) {
background: transparent;
}
.qrcode-container {
display: flex;
flex-direction: column;
align-items: center;
}
.qrcode-wrapper {
margin-bottom: 16px;
}
.link-container {
display: flex;
align-items: center;
margin-bottom: 16px;
width: 100%;
gap: 8px;
}
.link-container .ant-input {
flex: 1;
}
.qrcode-tip {
text-align: center;
color: rgba(0, 0, 0, 0.65);
}
.action-column {
white-space: nowrap;
}
.action-column a {
display: inline-block;
}
.qrcode-loading {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 200px;
}
.qrcode-loading p {
margin-top: 16px;
color: rgba(0, 0, 0, 0.65);
}
</style>