19 changed files with 827 additions and 46 deletions
After Width: | Height: | Size: 541 B |
After Width: | Height: | Size: 94 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.7 KiB |
@ -0,0 +1,3 @@
|
||||
import AppRecharge from './index.vue' |
||||
|
||||
export { AppRecharge } |
@ -0,0 +1,141 @@
|
||||
<script lang="ts" setup> |
||||
import { |
||||
CloseOutlined, |
||||
} from '@ant-design/icons-vue' |
||||
import { Button, QRCode } from 'ant-design-vue' |
||||
import { ref } from 'vue' |
||||
|
||||
defineProps({ |
||||
show: { |
||||
type: Boolean, |
||||
default: false, |
||||
}, |
||||
}) |
||||
const emits = defineEmits(['update:show']) |
||||
// 关闭弹窗 |
||||
function handleClose() { |
||||
emits('update:show', false) |
||||
} |
||||
// 下载二维码 |
||||
const qrcodeCanvasRef = ref() |
||||
async function dowloadChange() { |
||||
const url = await qrcodeCanvasRef.value.toDataURL() |
||||
const a = document.createElement('a') |
||||
a.download = 'QRCode.png' |
||||
a.href = url |
||||
document.body.appendChild(a) |
||||
a.click() |
||||
document.body.removeChild(a) |
||||
} |
||||
</script> |
||||
|
||||
<template> |
||||
<transition name="modal"> |
||||
<div v-if="show" class="modal-mask"> |
||||
<div class="modal-wrapper"> |
||||
<div class="modal-container"> |
||||
<div class="modal-body"> |
||||
<div class="closeIcon" @click="handleClose"> |
||||
<CloseOutlined style="color: #fff;" /> |
||||
</div> |
||||
|
||||
<div class="close" @click="handleClose"> |
||||
</div> |
||||
<div class="qr"> |
||||
<QRCode ref="qrcodeCanvasRef" :size="145" value="http://www.antdv.com" /> |
||||
</div> |
||||
<Button type="primary" class="save-qr" @click="dowloadChange"> |
||||
保存二维码 |
||||
</Button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</transition> |
||||
</template> |
||||
|
||||
<style scoped lang="scss"> |
||||
.modal-mask { |
||||
position: fixed; |
||||
z-index: 9999; |
||||
top: 0; |
||||
left: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
background-color: rgba(0, 0, 0, 0.5); |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
|
||||
.modal-wrapper { |
||||
background-color: #fff; |
||||
} |
||||
|
||||
.modal-body { |
||||
width: 530px; |
||||
height: 300px; |
||||
background-image: url('@/assets/images/task/invite.png'); |
||||
background-size: 100% 100%; |
||||
position: relative; |
||||
.closeIcon { |
||||
position: absolute; |
||||
top: 0; |
||||
right: 5px; |
||||
z-index: 2; |
||||
cursor: pointer; |
||||
} |
||||
.close { |
||||
position: absolute; |
||||
cursor: pointer; |
||||
top: 0; |
||||
right: 0; |
||||
width: 35px; |
||||
height: 35px; |
||||
background-image: linear-gradient(180deg, #5c94f7 0%, #4060e0 100%); |
||||
clip-path: polygon(100% 100%, 100% 0, 0 0); |
||||
z-index: 1; |
||||
} |
||||
.qr { |
||||
position: absolute; |
||||
top: 93px; |
||||
left: 50%; |
||||
transform: translate(-50%); |
||||
} |
||||
.save-qr { |
||||
cursor: pointer; |
||||
width: 130px; |
||||
height: 32px; |
||||
background: #4670e3; |
||||
border-radius: 20px; |
||||
position: absolute; |
||||
bottom: 10px; |
||||
left: 50%; |
||||
transform: translateX(-50%); |
||||
|
||||
text-align: center; |
||||
font-size: 13px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #ffffff; |
||||
|
||||
letter-spacing: 1px; |
||||
} |
||||
} |
||||
} |
||||
.modal-enter-active, |
||||
.modal-leave-active { |
||||
transition: opacity 0.3s; |
||||
} |
||||
|
||||
.modal-enter-from, |
||||
.modal-leave-to { |
||||
opacity: 0; |
||||
} |
||||
|
||||
.modal-enter-to, |
||||
.modal-leave-from { |
||||
opacity: 1; |
||||
} |
||||
</style> |
@ -0,0 +1,3 @@
|
||||
import AppUserInfo from './index.vue' |
||||
|
||||
export { AppUserInfo } |
@ -0,0 +1,129 @@
|
||||
<!-- 子菜单与内容容器布局组件 --> |
||||
<script setup lang="ts"> |
||||
import { Divider } from 'ant-design-vue' |
||||
import money from '@/assets/images/money.png' |
||||
import { useUserStore } from '@/store/moules/userStore/index' |
||||
|
||||
const userStore = useUserStore() |
||||
console.log(userStore.getChatInfo) |
||||
</script> |
||||
|
||||
<template> |
||||
<div class="app-user-info"> |
||||
<div class="app-user-info-top"> |
||||
<div class="dot"> |
||||
<img :src="money" alt=""> |
||||
<div class="dot-num"> |
||||
点数 |
||||
</div> |
||||
</div> |
||||
<div class="num"> |
||||
99 |
||||
</div> |
||||
<div class="pay"> |
||||
充值 |
||||
</div> |
||||
</div> |
||||
<div class="app-user-info-bottom"> |
||||
<div> |
||||
<div class="accumulative"> |
||||
1321 |
||||
</div> |
||||
<div class="accumulativename"> |
||||
累计提问 |
||||
</div> |
||||
</div> |
||||
<Divider type="vertical" style="height: 30px; background-color: #e1e9f9" /> |
||||
<div> |
||||
<div class="accumulative"> |
||||
3415天 |
||||
</div> |
||||
<div class="accumulativename"> |
||||
来到同聪 |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<style lang="scss" scoped> |
||||
@include app('user-info') { |
||||
position: absolute; |
||||
bottom: 0px; |
||||
left: 10px; |
||||
right: 10px; |
||||
padding: 10px; |
||||
width: 90%; |
||||
height: 120px; |
||||
background: #e1e9f9; |
||||
border-radius: 8px; |
||||
&-top { |
||||
height: 40%; |
||||
width: 100%; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
border-bottom: 1px solid #dae1ef; |
||||
.dot { |
||||
display: flex; |
||||
align-items: center; |
||||
img { |
||||
width: 14px; |
||||
height: 16px; |
||||
} |
||||
.dot-num { |
||||
font-size: 12px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #000000; |
||||
padding-left: 4px; |
||||
} |
||||
} |
||||
.num { |
||||
font-size: 14px; |
||||
font-family: DingTalk, DingTalk; |
||||
font-weight: normal; |
||||
color: #000000; |
||||
line-height: 21px; |
||||
} |
||||
.pay { |
||||
width: 45px; |
||||
height: 20px; |
||||
background: #4670e3; |
||||
border-radius: 13px; |
||||
font-size: 12px; |
||||
text-align: center; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #ffffff; |
||||
line-height: 20px; |
||||
} |
||||
} |
||||
&-bottom { |
||||
height: 60%; |
||||
width: 100%; |
||||
display: flex; |
||||
align-items: flex-end; |
||||
justify-content: space-around; |
||||
.accumulative { |
||||
text-align: center; |
||||
font-size: 15px; |
||||
font-family: DingTalk, DingTalk; |
||||
font-weight: normal; |
||||
color: #000000; |
||||
} |
||||
.accumulativename { |
||||
font-size: 12px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #000000; |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,5 @@
|
||||
import InviteForm from './index.vue' |
||||
|
||||
export { |
||||
InviteForm, |
||||
} |
@ -0,0 +1,141 @@
|
||||
<script lang="ts" setup> |
||||
import { |
||||
CloseOutlined, |
||||
} from '@ant-design/icons-vue' |
||||
import { Button, QRCode } from 'ant-design-vue' |
||||
import { ref } from 'vue' |
||||
|
||||
defineProps({ |
||||
show: { |
||||
type: Boolean, |
||||
default: false, |
||||
}, |
||||
}) |
||||
const emits = defineEmits(['update:show']) |
||||
// 关闭弹窗 |
||||
function handleClose() { |
||||
emits('update:show', false) |
||||
} |
||||
// 下载二维码 |
||||
const qrcodeCanvasRef = ref() |
||||
async function dowloadChange() { |
||||
const url = await qrcodeCanvasRef.value.toDataURL() |
||||
const a = document.createElement('a') |
||||
a.download = 'QRCode.png' |
||||
a.href = url |
||||
document.body.appendChild(a) |
||||
a.click() |
||||
document.body.removeChild(a) |
||||
} |
||||
</script> |
||||
|
||||
<template> |
||||
<transition name="modal"> |
||||
<div v-if="show" class="modal-mask"> |
||||
<div class="modal-wrapper"> |
||||
<div class="modal-container"> |
||||
<div class="modal-body"> |
||||
<div class="closeIcon" @click="handleClose"> |
||||
<CloseOutlined style="color: #fff;" /> |
||||
</div> |
||||
|
||||
<div class="close" @click="handleClose"> |
||||
</div> |
||||
<div class="qr"> |
||||
<QRCode ref="qrcodeCanvasRef" :size="145" value="http://www.antdv.com" /> |
||||
</div> |
||||
<Button type="primary" class="save-qr" @click="dowloadChange"> |
||||
保存二维码 |
||||
</Button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</transition> |
||||
</template> |
||||
|
||||
<style scoped lang="scss"> |
||||
.modal-mask { |
||||
position: fixed; |
||||
z-index: 9999; |
||||
top: 0; |
||||
left: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
background-color: rgba(0, 0, 0, 0.5); |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
|
||||
.modal-wrapper { |
||||
background-color: #fff; |
||||
} |
||||
|
||||
.modal-body { |
||||
width: 530px; |
||||
height: 300px; |
||||
background-image: url('@/assets/images/task/invite.png'); |
||||
background-size: 100% 100%; |
||||
position: relative; |
||||
.closeIcon { |
||||
position: absolute; |
||||
top: 0; |
||||
right: 5px; |
||||
z-index: 2; |
||||
cursor: pointer; |
||||
} |
||||
.close { |
||||
position: absolute; |
||||
cursor: pointer; |
||||
top: 0; |
||||
right: 0; |
||||
width: 35px; |
||||
height: 35px; |
||||
background-image: linear-gradient(180deg, #5c94f7 0%, #4060e0 100%); |
||||
clip-path: polygon(100% 100%, 100% 0, 0 0); |
||||
z-index: 1; |
||||
} |
||||
.qr { |
||||
position: absolute; |
||||
top: 93px; |
||||
left: 50%; |
||||
transform: translate(-50%); |
||||
} |
||||
.save-qr { |
||||
cursor: pointer; |
||||
width: 130px; |
||||
height: 32px; |
||||
background: #4670e3; |
||||
border-radius: 20px; |
||||
position: absolute; |
||||
bottom: 10px; |
||||
left: 50%; |
||||
transform: translateX(-50%); |
||||
|
||||
text-align: center; |
||||
font-size: 13px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #ffffff; |
||||
|
||||
letter-spacing: 1px; |
||||
} |
||||
} |
||||
} |
||||
.modal-enter-active, |
||||
.modal-leave-active { |
||||
transition: opacity 0.3s; |
||||
} |
||||
|
||||
.modal-enter-from, |
||||
.modal-leave-to { |
||||
opacity: 0; |
||||
} |
||||
|
||||
.modal-enter-to, |
||||
.modal-leave-from { |
||||
opacity: 1; |
||||
} |
||||
</style> |
@ -0,0 +1,3 @@
|
||||
import TaskList from './index.vue' |
||||
|
||||
export { TaskList } |
@ -0,0 +1,260 @@
|
||||
<script lang="ts" setup> |
||||
import { computed, ref } from 'vue' |
||||
import { |
||||
DownOutlined, |
||||
UpOutlined, |
||||
} from '@ant-design/icons-vue' |
||||
import money from '@/assets/images/task/money.png' |
||||
|
||||
const { title, list } = defineProps({ |
||||
title: { |
||||
type: String, |
||||
}, |
||||
list: { |
||||
type: Array, |
||||
default: () => [], |
||||
}, |
||||
}) |
||||
|
||||
const isExpanded = ref(false)// 伸缩 |
||||
const singleItemHeight = 45 // 单个项目的高度 |
||||
|
||||
const dynamicStyle = computed(() => { |
||||
let maxHeight |
||||
if (isExpanded.value) { |
||||
// 如果展开,那么高度应该是单个项目的高度乘以项目总数 |
||||
maxHeight = singleItemHeight * list.length |
||||
} |
||||
else { |
||||
// 如果没有展开,那么高度应该是单个项目的高度乘以默认显示的项目个数 |
||||
maxHeight = 180 |
||||
} |
||||
return { |
||||
'max-height': `${maxHeight}px`, |
||||
} |
||||
}) |
||||
</script> |
||||
|
||||
<template> |
||||
<div class="nvoice-task-box"> |
||||
<div class="title"> |
||||
{{ title }} |
||||
</div> |
||||
<div class="nvoice-contant"> |
||||
<div class="top flex justify-between"> |
||||
<div class="left"> |
||||
全部完成可获得 72 点数 |
||||
</div> |
||||
<div class="right"> |
||||
已完成 1/12 |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="content" :style="dynamicStyle"> |
||||
<div class="earn-list-box"> |
||||
<div v-for="(item, index) in list" :key="index" class="earn-list"> |
||||
<div class="earn-list-left"> |
||||
<div class="name"> |
||||
{{ item.title }} |
||||
</div> |
||||
<div v-show="item.status === 1" class="accomplish"> |
||||
已获得{{ item.dot }}点数 |
||||
</div> |
||||
<div v-show="item.status === 0" class="unfinished"> |
||||
0/{{ item.dot }} |
||||
</div> |
||||
</div> |
||||
<div class="earn-list-right"> |
||||
<div class="add-dot-box"> |
||||
<div class="flex items-center"> |
||||
<img class="add-dot-photo" :src="money" alt=""> |
||||
<div class="add-dot-num"> |
||||
+{{ item.dot }} |
||||
</div> |
||||
</div> |
||||
|
||||
<div v-show="item.status === 1" class="add-dot-btn accomplish"> |
||||
已完成 |
||||
</div> |
||||
|
||||
<div v-if="item.status === 0 " class="add-dot-btn unfinished"> |
||||
未完成 |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<div v-if="list.length > 4" class="shrink" @click="isExpanded = !isExpanded"> |
||||
<DownOutlined v-if="!isExpanded" /> |
||||
<UpOutlined v-else /> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<style lang="scss" scoped> |
||||
.nvoice-task-box { |
||||
width: 95%; |
||||
.title { |
||||
font-size: 14px; |
||||
font-family: PingFang-SC, PingFang-SC; |
||||
font-weight: bold; |
||||
color: #000000; |
||||
line-height: 22px; |
||||
letter-spacing: 1px; |
||||
margin: 16px 0; |
||||
} |
||||
.nvoice-contant { |
||||
width: 100%; |
||||
position: relative; |
||||
background-color: #edf3ff; |
||||
border-radius: 15px; |
||||
padding-bottom: 15px; |
||||
.top { |
||||
padding: 12px 40px; |
||||
.left { |
||||
font-size: 14px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #4670e3; |
||||
|
||||
letter-spacing: 1px; |
||||
} |
||||
.right { |
||||
font-size: 14px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #888c90; |
||||
|
||||
letter-spacing: 1px; |
||||
} |
||||
} |
||||
.content { |
||||
width: 95%; |
||||
background-color: #fff; |
||||
margin: 0 auto; |
||||
overflow: hidden; |
||||
transition: max-height 0.4s ease-in-out; |
||||
padding: 5px 20px; |
||||
border-radius: 10px; |
||||
position: relative; |
||||
.earn-list-box { |
||||
width: 100%; |
||||
padding: 0 10px; |
||||
.earn-list { |
||||
width: 100%; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
padding: 10px 0; |
||||
border-bottom: 1px solid #ededed; |
||||
&:last-child { |
||||
border: 0; |
||||
} |
||||
.earn-list-left { |
||||
display: flex; |
||||
align-items: center; |
||||
width: 85%; |
||||
.name { |
||||
font-size: 13px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 500; |
||||
|
||||
color: #000000; |
||||
|
||||
letter-spacing: 1px; |
||||
} |
||||
.accomplish { |
||||
font-size: 11px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #f7b606; |
||||
padding-left: 10px; |
||||
} |
||||
.unfinished { |
||||
font-size: 11px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #888c90; |
||||
padding-left: 10px; |
||||
} |
||||
} |
||||
.earn-list-right { |
||||
width: 15%; |
||||
.add-dot-box { |
||||
width: 100%; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
.add-dot-photo { |
||||
width: 13px; |
||||
height: 13px; |
||||
display: flex; |
||||
align-items: center; |
||||
} |
||||
.add-dot-num { |
||||
font-size: 12px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
color: #f7b500; |
||||
padding-left: 3px; |
||||
} |
||||
.add-dot-btn { |
||||
cursor: pointer; |
||||
|
||||
border-radius: 16px; |
||||
font-size: 11px; |
||||
font-family: |
||||
PingFangSC, |
||||
PingFang SC; |
||||
font-weight: 400; |
||||
line-height: 20px; |
||||
letter-spacing: 1px; |
||||
text-align: center; |
||||
padding: 2px 5px; |
||||
&.accomplish { |
||||
background: linear-gradient(90deg, #b5ceff 0%, #a6baff 100%); |
||||
color: #ffffff; |
||||
} |
||||
&.unfinished { |
||||
background: #ffffff; |
||||
border: 1px solid #cdcdcd; |
||||
line-height: 18px; |
||||
color: #888c90; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
.shrink { |
||||
width: 32px; |
||||
height: 32px; |
||||
text-align: center; |
||||
line-height: 32px; |
||||
border-radius: 50%; |
||||
background-color: #fff; |
||||
text-align: center; |
||||
box-shadow: 0px 2px 8px 0px rgba(131, 131, 131, 0.5); |
||||
position: absolute; |
||||
bottom: -10px; |
||||
left: 50%; |
||||
transform: translateX(-50%); |
||||
} |
||||
} |
||||
} |
||||
</style> |
Loading…
Reference in new issue