master
shenhan000 2025-04-28 17:11:58 +08:00
parent 448895a1e6
commit 9ae2729807
17 changed files with 691 additions and 170 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 845 B

9
app/components.d.ts vendored
View File

@ -12,6 +12,8 @@ declare module 'vue' {
NButton: typeof import('naive-ui')['NButton']
NCard: typeof import('naive-ui')['NCard']
NCarousel: typeof import('naive-ui')['NCarousel']
NCascader: typeof import('naive-ui')['NCascader']
NCheckbox: typeof import('naive-ui')['NCheckbox']
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NDatePicker: typeof import('naive-ui')['NDatePicker']
NDropdown: typeof import('naive-ui')['NDropdown']
@ -20,19 +22,26 @@ declare module 'vue' {
NForm: typeof import('naive-ui')['NForm']
NFormItem: typeof import('naive-ui')['NFormItem']
NIcon: typeof import('naive-ui')['NIcon']
NImage: typeof import('naive-ui')['NImage']
NImageGroup: typeof import('naive-ui')['NImageGroup']
NInfiniteScroll: typeof import('naive-ui')['NInfiniteScroll']
NInput: typeof import('naive-ui')['NInput']
NInputGroup: typeof import('naive-ui')['NInputGroup']
NInputNumber: typeof import('naive-ui')['NInputNumber']
NModal: typeof import('naive-ui')['NModal']
NPagination: typeof import('naive-ui')['NPagination']
NPopconfirm: typeof import('naive-ui')['NPopconfirm']
NProgress: typeof import('naive-ui')['NProgress']
NQrCode: typeof import('naive-ui')['NQrCode']
NRadio: typeof import('naive-ui')['NRadio']
NRadioGroup: typeof import('naive-ui')['NRadioGroup']
NSelect: typeof import('naive-ui')['NSelect']
NSkeleton: typeof import('naive-ui')['NSkeleton']
NSpace: typeof import('naive-ui')['NSpace']
NSpin: typeof import('naive-ui')['NSpin']
NTabPane: typeof import('naive-ui')['NTabPane']
NTabs: typeof import('naive-ui')['NTabs']
NTooltip: typeof import('naive-ui')['NTooltip']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
}

View File

@ -82,7 +82,7 @@ async function getQrCode() {
}
}
//
//
const isVisible = ref(true)
//

View File

@ -126,8 +126,6 @@ async function handleUserSelect(key: string) {
}
//
async function handlePublishSelect(key: string) {
if (!userStore?.userInfo.name)
return
if (!userStore.isLoggedIn) {
modalStore.showLoginModal()
}
@ -140,7 +138,6 @@ async function handlePublishSelect(key: string) {
}
else {
const baseUrl = window.location.origin
debugger
window.open(`${baseUrl}/${key}?type=add`, '_blank', 'noopener,noreferrer')
// router.push({
// path: `/${key}`,

View File

@ -14,12 +14,13 @@ defineExpose({
const regex = /^1[3-9]\d{9}$/
const rules: FormRules = {
phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{ pattern: regex, message: '手机号格式不正确', trigger: 'blur' },
// , trigger: 'blur'
{ required: true, message: '请输入手机号' },
{ pattern: regex, message: '手机号格式不正确' },
],
code: [
{ required: true, message: '请输入验证码', trigger: 'blur' },
{ len: 6, message: '验证码长度为6位', trigger: 'blur' },
{ required: true, message: '请输入验证码' },
{ len: 6, message: '验证码长度为6位' },
],
}
//

View File

@ -158,23 +158,24 @@ watchEffect(() => {
{{ planetInfo.communityName }}
</h1>
</div>
<div class="flex items-center gap-8 text-xs text-[#878d95] mt-1 mb-4">
<div class="flex items-center gap-8 text-xs text-[#878d95] mt-1">
<div>创建{{ planetInfo.validityDay }}</div>
</div>
<div class="text-sm text-[#4a5563] line-clamp-3">
<!-- line-clamp-3 -->
<div class="text-sm text-[#4a5563] py-3">
{{ planetInfo.description }}
</div>
</div>
</div>
<div
class="flex items-center bg-[#F4F9FF] px-2 py-3 rounded-lg mt-4 text-sm text-gray-800 cursor-pointer"
class="flex items-center bg-[#F4F9FF] px-2 py-3 rounded-lg text-sm text-gray-800 cursor-pointer"
@click="toFileList"
>
<FileChartColumnIncreasing class="w-4 h-4 mr-2" />
全部文件
</div>
<!-- 在线咨询 -->
<div class="mt-6">
<div class="">
<button
class="w-full bg-[#1e80ff] hover:bg-[#3b8fff] text-white rounded-lg py-3 mt-4"
@click="handleShowQuestion"

View File

@ -1,7 +1,10 @@
<script setup lang="ts">
import { commonApi } from '@/api/common'
// import { NConfigProvider, NInfiniteScroll, NInput } from 'naive-ui'
import {
EllipsisVertical,
FileChartColumn,
Star,
ThumbsUp,
} from 'lucide-vue-next'
@ -33,7 +36,6 @@ const props = defineProps({
default: () => ({}),
},
})
// const $props = defineProps(['headUrl', 'dataList', 'height'])
const userStore = useUserStore()
@ -256,6 +258,7 @@ async function handleDel(type: string, item: any) {
if (type === 'parent') {
params.publishId = item.item.id
params.communityId = item.item.communityId
params.tenantId = item.item.tenantId
}
else {
const { id, communityId, tenantId } = item.sub
@ -277,11 +280,14 @@ async function handleDel(type: string, item: any) {
}
}
//
const isVisibleReport = ref(false)
async function handleSelect(event: any, type: string, item: any) {
event.stopPropagation() //
if (type === 'choiceness') {
try {
const res = await request.get(`publish/elite?publishId=${item.id}&communityId=${item.communityId}`)
const res = await request.get(`publish/elite?publishId=${item.id}&communityId=${item.communityId}&tenantId=${item.tenantId}`)
if (res.code === 200) {
message.success(item.isElite === 1 ? '取消精选成功!' : '精选成功!')
getCommentList()
@ -292,20 +298,30 @@ async function handleSelect(event: any, type: string, item: any) {
}
}
else if (type === 'complaint') {
console.log('投诉')
isVisibleReport.value = true
}
else if (type === 'delete') {
console.log('删除')
}
}
//
function handleDownload(url: string) {
const a = document.createElement('a')
a.href = url
a.download = url.split('/').pop() || 'downloaded_file'
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}
</script>
<template>
<div class="bg-white py-4 rounded min-h-[320px]">
<div class="min-h-[320px]">
<div
v-for="(item, index) in commentList"
:key="index"
class="px-4"
class="p-4 mb-2 rounded bg-white"
>
<div class="nav-wrap">
<div class="left-img">
@ -313,7 +329,7 @@ async function handleSelect(event: any, type: string, item: any) {
</div>
<div class="right">
<div class="name flex justify-between items-center relative">
<span>{{ item.userName }}</span>
<span class="text-[#4a5563] text-sm">{{ item.userName }}</span>
<img
v-if="item.isElite === 1"
class="cursor-pointer absolute right-0 top-[4px] w-10 h-10"
@ -354,11 +370,11 @@ async function handleSelect(event: any, type: string, item: any) {
</div>
</div>
</div>
<div class="des">
{{ item.content }}
<div class="text-gray-500 text-xs">
{{ item. createTime }}
</div>
<div class="star-wrap">
<span class="time">{{ item.createTime }}</span>
<span class="text-[#192029] text-sm">{{ item.content }}</span>
<div class="star-operator">
<div class="icon-wrap">
<ThumbsUp size="16" class="mr-1" :color="item.isLike !== 0 ? '#ff0000' : '#000000'" @click="handleFocus('parent', { item })" />
@ -370,7 +386,51 @@ async function handleSelect(event: any, type: string, item: any) {
<span class="cursor-pointer m-r16" @click="handleMessage(item)"></span>
<span class="cursor-pointer" @click="handleDel('parent', { item })">删除</span>
<span v-if="item.userId === userStore?.userInfo?.userId || userStore?.userInfo?.userId === Number(props.publishListParams.tenantId)" class="cursor-pointer" @click="handleDel('parent', { item })"></span>
</div>
</div>
<div>
<div v-if="item.fileName" class="my-2">
<!-- <n-image-group>
<n-space>
<n-image
v-for="(subItem, subIndex) in item.fileName.split(',')"
:key="subIndex"
width="100"
:src="subItem"
/>
</n-space>
</n-image-group> -->
<div
v-for="(subItem, subIndex) in item.fileName.split(',')"
:key="subIndex"
title="点击下载"
class="text-[#4a5563] text-sm cursor-pointer flex items-center hover:text-[#4a5563]/80"
@click="handleDownload(subItem)"
>
<FileChartColumn size="16" class="mr-1" />
{{ subItem }}
</div>
</div>
<div v-if="item.imageUrl" class="flex items-center my-1 gap-2">
<n-image-group>
<n-space>
<n-image
v-for="(subItem, subIndex) in item.imageUrl.split(',')"
:key="subIndex"
width="80"
height="70"
:src="subItem"
/>
</n-space>
</n-image-group>
<!-- <img
v-for="(subItem, subIndex) in item.imageUrl.split(',')"
:key="subIndex"
class="w-14 h-14 rounded-lg"
:src="subItem"
alt=""
> -->
</div>
</div>
<!-- 父项评论回复操作 -->
@ -392,7 +452,7 @@ async function handleSelect(event: any, type: string, item: any) {
</div>
</div>
</div>
<div class="child-wrap">
<div v-if="item.commentList.length > 0" class="child-wrap bg-[#f9fbff] ml-12 p-2 rounded">
<div v-for="(ele, subIndex) in item.commentList" :key="subIndex" class="child-wrap-item">
<div class="left-img">
<img :src="ele.userAvatar">
@ -419,7 +479,7 @@ async function handleSelect(event: any, type: string, item: any) {
<span style="vertical-align: middle">{{ ele.likeNum }}</span>
</div>
<span class="cursor-pointer m-r16" @click="handleMessage(ele)"></span>
<span v-if="item.userId === userStore?.userInfo?.userId" class="cursor-pointer" @click="handleDel('sub', { item, sub: ele })"></span>
<span v-if="item.userId === userStore?.userInfo?.userId || userStore?.userInfo?.userId === Number(props.publishListParams.tenantId)" class="cursor-pointer" @click="handleDel('sub', { item, sub: ele })"></span>
</div>
</div>
<!-- 子项评论回复操作 -->
@ -443,6 +503,67 @@ async function handleSelect(event: any, type: string, item: any) {
</div>
</div>
</div>
<div>
<PlanetReport
v-model="isVisibleReport"
:publish-list-params="props.publishListParams"
/>
</div>
<!-- <n-modal
v-model:show="isVisibleReport"
:preset="null"
:mask-closable="false"
transform-origin="center"
class="custom-modal"
>
<div class="bg-white rounded-xl p-4">
<div class="flex items-center justify-between">
<div class="text-xl">
举报
</div>
<div>
<n-icon size="20" class="mr-2 cursor-pointer" @click="closeReport">
<Close />
</n-icon>
</div>
</div>
<div class="flex flex-col p-4">
<n-radio
v-for="(item, index) in reportList"
:key="index"
class="m-4 text-[#fff000]"
size="large"
:checked="reportType === item.dictValue"
value="Definitely Maybe"
name="basic-demo"
@change="handleChange(item)"
>
{{ item.dictLabel }}
</n-radio>
<n-input
v-if="
reportType !== undefined && reportType === '6'
"
v-model:value="reportTypeText"
placeholder="点击输入"
type="textarea"
:autosize="{
minRows: 5,
maxRows: 10,
}"
/>
<div
class="mt-4 w-[100%] h-10 flex rounded-lg text-white items-center justify-center cursor-pointer"
:class="[
reportType !== undefined ? 'bg-[#4c79ee]' : 'bg-[#cccccc]',
]"
@click="onReport"
>
确认
</div>
</div>
</div>
</n-modal> -->
<div class="no-more">
暂时没有更多评论
</div>
@ -576,7 +697,6 @@ async function handleSelect(event: any, type: string, item: any) {
}
.child-wrap {
padding-left: 52px;
.child-wrap-item {
display: flex;
font-size: 14px;

View File

@ -109,7 +109,7 @@ function handleShowMessage() {
<!-- 右侧功能区 -->
<div class="flex items-center ml-auto space-x-4">
<!-- 搜索框 -->
<div class="relative flex items-center w-[360px]">
<!-- <div class="relative flex items-center w-[360px]">
<input
v-model="searchQuery"
type="text"
@ -122,7 +122,7 @@ function handleShowMessage() {
</svg>
<span class="text-sm font-bold">搜索</span>
</button>
</div>
</div> -->
<!-- 通知铃铛 -->
<button class="relative p-2 hover:bg-gray-50 rounded-lg" @click="handleShowMessage">

View File

@ -1,5 +1,6 @@
<script setup lang="ts">
import {
CalendarCheck,
ThumbsUp,
} from 'lucide-vue-next'
import { watch } from 'vue'
@ -217,38 +218,38 @@ async function handleFocus(type: string, item: any) {
}
//
function handleMessage(item: any) {
if (!item.isShowInput) {
item.word = ''
}
item.isShowInput = !item.isShowInput
}
// function handleMessage(item: any) {
// if (!item.isShowInput) {
// item.word = ''
// }
// item.isShowInput = !item.isShowInput
// }
//
async function handleDel(type: string, item: any) {
const params = {}
if (type === 'parent') {
params.publishId = item.item.id
params.communityId = item.item.communityId
}
else {
const { id, communityId, tenantId } = item.sub
params.id = id
params.communityId = communityId
params.tenantId = tenantId
params.publishId = item.item.id
}
try {
const url = type === 'sub' ? '/publishComment/delete' : '/publish/remove'
const res = await request.post(url, params)
if (res.code === 200) {
message.success('删除成功!')
getCommentList()
}
}
catch (error) {
console.log(error)
}
}
// async function handleDel(type: string, item: any) {
// const params = {}
// if (type === 'parent') {
// params.publishId = item.item.id
// params.communityId = item.item.communityId
// }
// else {
// const { id, communityId, tenantId } = item.sub
// params.id = id
// params.communityId = communityId
// params.tenantId = tenantId
// params.publishId = item.item.id
// }
// try {
// const url = type === 'sub' ? '/publishComment/delete' : '/publish/remove'
// const res = await request.post(url, params)
// if (res.code === 200) {
// message.success('')
// getCommentList()
// }
// }
// catch (error) {
// console.log(error)
// }
// }
//
async function handlePublish() {
@ -271,6 +272,26 @@ async function handlePublish() {
console.log(error)
}
}
//
async function handleAccept(item: any, ele: any) {
const params = {
commentId: ele.id,
tenantId: props.publishListParams.tenantId,
communityId: props.publishListParams.communityId,
questionId: item.id,
}
try {
const res = await request.post('questionComment/adopt', params)
if (res.code === 200) {
message.success('采纳成功!')
getCommentList()
}
}
catch (error) {
console.log(error)
}
}
</script>
<template>
@ -346,7 +367,7 @@ async function handlePublish() {
</div> -->
</div>
<div v-if="item.questionUrl" class="flex flex-wrap gap-2">
<img v-for="(ele, index) in item.questionUrl.split(',')" :key="index" class="w-16 h-16 rounded-md" :src="ele">
<img v-for="(ele, subIndex) in item.questionUrl.split(',')" :key="subIndex" class="w-16 h-16 rounded-md" :src="ele">
</div>
<!-- 父项评论回复操作 -->
<!-- <div v-if="item.isShowInput" class="input-wrap" style="margin-top: 10px;">
@ -388,6 +409,13 @@ async function handlePublish() {
</div>
<div class="star-wrap">
<span class="time">{{ ele.createTime }}</span>
<div v-if="ele.isAccept === 0 && item.status === 0 && userStore?.userInfo?.userId === Number(props.publishListParams.tenantId) && ele.userId !== userStore?.userInfo?.userId" class="cursor-pointer m-r16 text-xs flex items-center text-[#3f7ef7] bg-[#ecf1fc] rounded-lg px-2 py-1" @click="handleAccept(item, ele)">
<CalendarCheck size="16" fill="currentColor" color="#fff" class="mr-1" />
<span>采纳</span>
</div>
<div v-if="ele.isAccept === 1" class="text-xs flex items-center text-[#3f7ef7] bg-[#ecf1fc] rounded-lg px-2 py-1">
<span>已采纳</span>
</div>
<!-- <div class="star-operator">
<div class="icon-wrap">
<ThumbsUp size="16" class="mr-1" :color="ele.isLike !== 0 ? '#ff0000' : '#000000'" @click="handleFocus('sub', { sub: ele, item })" />

View File

@ -0,0 +1,134 @@
<script setup lang="ts">
//
import { commonApi } from '@/api/common'
import { Close } from '@vicons/ionicons5'
import {
EllipsisVertical,
FileChartColumn,
Star,
ThumbsUp,
} from 'lucide-vue-next'
interface PublishListParams {
communityId: string | number
tenantId: string | number
publishId: string | number
[key: string]: any
}
const props = defineProps<{
publishListParams: PublishListParams
modelValue: boolean
}>()
const emit = defineEmits<{
(e: 'update:modelValue', value: boolean): void
}>()
const message = useMessage()
const reportTypeText = ref('')
const reportType = ref('')
const reportList = ref([])
async function getDictType() {
try {
const res = await commonApi.dictType({ type: 'community_report' })
if (res.code === 200) {
reportList.value = res.data
}
}
catch (error) {
console.error(error)
}
}
getDictType()
function handleChange(item: any) {
reportType.value = item.dictValue
if (item.dictValue !== '6') {
reportTypeText.value = ''
}
}
async function onReport() {
if (reportType.value !== undefined) {
const params = {
communityId: props.publishListParams.communityId,
content: reportTypeText.value,
reportType: reportType.value,
publishId: props.publishListParams.publishId,
tenantId: props.publishListParams.tenantId,
}
const res = await request.post('/report/addReport', params)
if (res.code === 200) {
message.success('举报成功!')
emit('update:modelValue', false)
}
}
}
function closeReport() {
emit('update:modelValue', false)
}
</script>
<template>
<div>
<n-modal
:show="modelValue"
:preset="null"
:mask-closable="false"
transform-origin="center"
class="custom-modal"
@update:show="(value) => emit('update:modelValue', value)"
>
<div class="bg-white rounded-xl p-4">
<div class="flex items-center justify-between">
<div class="text-xl">
举报
</div>
<div>
<n-icon size="20" class="mr-2 cursor-pointer" @click="closeReport">
<Close />
</n-icon>
</div>
</div>
<div class="flex flex-col p-4">
<n-radio
v-for="(item, index) in reportList"
:key="index"
class="m-4 text-[#fff000]"
size="large"
:checked="reportType === item.dictValue"
value="Definitely Maybe"
name="basic-demo"
@change="handleChange(item)"
>
{{ item.dictLabel }}
</n-radio>
<n-input
v-if="reportType !== undefined && reportType === '6'"
v-model:value="reportTypeText"
placeholder="点击输入"
type="textarea"
:autosize="{
minRows: 5,
maxRows: 10,
}"
/>
<div
class="mt-4 w-[100%] h-10 flex rounded-lg text-white items-center justify-center cursor-pointer"
:class="[
reportType !== undefined ? 'bg-[#4c79ee]' : 'bg-[#cccccc]',
]"
@click="onReport"
>
确认
</div>
</div>
</div>
</n-modal>
</div>
</template>

View File

@ -170,7 +170,7 @@ async function handlePictureChange(event: Event) {
class="w-[125px] h-[125px] rounded"
>
<n-icon color="#fff" class="absolute top-1 right-1 p-1 z-40 cursor-pointer w-6 h-6">
<CloseOutline class="text-[20px]" size="20" @click="questionUrlList.splice(index, 1)" />
<CloseOutline class="text-[20px]" size="20" @click="imageUrl.splice(index, 1)" />
</n-icon>
</div>
</div>

View File

@ -23,7 +23,7 @@ const formData = ref({
type: 0, // 01
amount: 10, //
content: '', //
isAnonymous: 0, // 1 0
// isAnonymous: 0, // 1 0
questionUrl: '', //
})
@ -72,7 +72,7 @@ async function handlePublish() {
type: 0,
amount: undefined,
content: '',
isAnonymous: 0,
// isAnonymous: 0,
questionUrl: '',
}
fileList.value = []
@ -180,9 +180,9 @@ async function handlePictureChange(event: Event) {
</n-radio>
</n-radio-group>
<n-checkbox v-model:checked="formData.isAnonymous" unchecked-value="0" checked-value="1">
<!-- <n-checkbox v-model:checked="formData.isAnonymous" unchecked-value="0" checked-value="1">
匿名提问
</n-checkbox>
</n-checkbox> -->
<n-button
type="primary"

View File

@ -1,106 +1,114 @@
<template>
<n-modal
v-model:show="isVisibleReport"
:preset="null"
:mask-closable="false"
transform-origin="center"
class="custom-modal"
>
<div class="bg-white rounded-xl p-4">
<div class="flex items-center justify-between">
<div class="text-xl">举报</div>
<div>
<n-icon size="20" class="mr-2 cursor-pointer" @click="closeReport">
<Close />
</n-icon>
</div>
</div>
<div class="flex flex-col">
<n-radio
class="m-4 text-[#fff000]"
size="large"
v-for="(item, index) in reportList"
:key="index"
:checked="reportParams.reportId === item.dictValue"
value="Definitely Maybe"
name="basic-demo"
@change="handleChange(item)"
>
{{ item.dictLabel }}
</n-radio>
<n-input
v-if="reportParams.reportId !== undefined && reportParams.reportId === '5'"
v-model:value="reportParams.text"
placeholder="点击输入"
type="textarea"
:autosize="{
minRows: 5,
maxRows: 10,
}"
/>
<div
@click="onReport"
class="mt-4 w-[100%] h-10 flex rounded-lg text-white items-center justify-center cursor-pointer"
:class="[
reportParams.reportId !== undefined
? 'bg-[#4c79ee]'
: 'bg-[#cccccc]',
]"
>
确认
</div>
</div>
</div>
</n-modal>
</template>
<script setup lang="ts">
import { commonApi } from "@/api/common";
import { Close } from "@vicons/ionicons5";
import { commonApi } from '@/api/common'
import { Close } from '@vicons/ionicons5'
const message = useMessage()
//
const isVisibleReport = ref(true);
const isVisibleReport = ref(true)
const reportParams = ref({
reportId: undefined,
text: "",
type:1
});
const reportList = ref([]);
text: '',
type: 1,
})
const reportList = ref([])
async function getDictType() {
try {
const res = await commonApi.dictType({ type: "report_type" });
const res = await commonApi.dictType({ type: 'report_type' })
if (res.code === 200) {
reportList.value = res.data;
reportList.value = res.data
}
} catch (error) {
console.log(error);
}
catch (error) {
console.log(error)
}
}
getDictType();
getDictType()
function handleChange(item: any) {
reportParams.value.reportId = item.dictValue;
if (item.dictValue !== "5") {
reportParams.value.text = "";
reportParams.value.reportId = item.dictValue
if (item.dictValue !== '5') {
reportParams.value.text = ''
}
console.log("object", reportParams.value);
console.log('object', reportParams.value)
}
function closeReport() {
isVisibleReport.value = false;
isVisibleReport.value = false
}
async function onReport(){
if( reportParams.value.reportId !== undefined){
async function onReport() {
if (reportParams.value.reportId !== undefined) {
reportParams.value.productId = detailsInfo.value.id
const res = await request.post('/report/addReport', reportParams.value)
if (res.code === 200) {
isVisibleReport.value = false
message.success('举报成功')
}
}
}
</script>
<template>
<n-modal
v-model:show="isVisibleReport"
:preset="null"
:mask-closable="false"
transform-origin="center"
class="custom-modal"
>
<div class="bg-white rounded-xl p-4">
<div class="flex items-center justify-between">
<div class="text-xl">
举报
</div>
<div>
<n-icon size="20" class="mr-2 cursor-pointer" @click="closeReport">
<Close />
</n-icon>
</div>
</div>
<div class="flex flex-col">
<n-radio
v-for="(item, index) in reportList"
:key="index"
class="m-4 text-[#fff000]"
size="large"
:checked="reportParams.reportId === item.dictValue"
value="Definitely Maybe"
name="basic-demo"
@change="handleChange(item)"
>
{{ item.dictLabel }}
</n-radio>
<n-input
v-if="reportParams.reportId !== undefined && reportParams.reportId === '5'"
v-model:value="reportParams.text"
placeholder="点击输入"
type="textarea"
:autosize="{
minRows: 5,
maxRows: 10,
}"
/>
<div
class="mt-4 w-[100%] h-10 flex rounded-lg text-white items-center justify-center cursor-pointer"
:class="[
reportParams.reportId !== undefined
? 'bg-[#4c79ee]'
: 'bg-[#cccccc]',
]"
@click="onReport"
>
确认
</div>
</div>
</div>
</n-modal>
</template>
<style scoped>
.container{
/* position: fixed;
.container {
/* position: fixed;
top: 0;
left: 0;
width: 100vw;
@ -108,4 +116,4 @@ async function onReport(){
opacity: 0.4;
background: #000; */
}
</style>
</style>

View File

@ -109,18 +109,29 @@ function handleSuccess() {
}
function goDetail(item: any) {
const params = {
communityId: item.id,
tenantId: item.tenantId,
id: item.id,
userId: item.userId,
}
if (item.isJoin === 0) {
router.push({
path: '/public-planet-detail',
state: {
communityId: item.id,
tenantId: item.tenantId,
userId: item.userId,
},
state: params,
})
}
else {
router.push(`/planet-detail?communityId=${item.id}&tenantId=${item.tenantId}`)
router.push({
path: '/planet-detail',
state: {
communityId: item.id,
tenantId: item.tenantId,
publishId: item.id,
userId: item.userId,
},
})
// router.push(`/planet-detail?communityId=${item.id}&tenantId=${item.tenantId}&publishId=${item.id}&userId=${item.userId}`)
}
}
</script>
@ -130,7 +141,7 @@ function goDetail(item: any) {
<div class="bg-white rounded-lg shadow-sm flex p-4 cursor-pointer hover:shadow-[0_4px_14px_0_rgba(0,0,0,0.1)]" @click="goDetail(item)">
<div class="w-[161px] h-[161px] relative rounded-lg">
<img class="w-full h-full object-cover rounded-lg" :src="item.imageUrl" alt="">
<span class="absolute bottom-2 left-2 text-white text-xs">{{ item.publishNum || 0 }}人已经加入</span>
<span class="absolute bottom-2 left-2 text-white text-xs">{{ item.joinNum || 0 }}人已经加入</span>
</div>
<div class="flex flex-col gap-2 px-4 flex-1 justify-between">
<div class="flex flex-col gap-2">
@ -154,12 +165,12 @@ function goDetail(item: any) {
@mouseleave="hideMenu"
>
<div
v-for="item in menuItems"
:key="item.label"
v-for="subItem in menuItems"
:key="subItem.label"
class="px-4 py-2 text-sm hover:bg-gray-100 cursor-pointer"
@click="item.action"
@click="subItem.action"
>
{{ item.label }}
{{ subItem.label }}
</div>
</div>
</div>
@ -221,7 +232,7 @@ function goDetail(item: any) {
:mask-closable="false"
preset="dialog"
title="提示!"
content="退出后将无法查看/操作该星球的内容,是否确认退出该星球"
:content="props.item.joinNum === 1 ? '退出后该星球的内容将会被删除,若你是最后一个成员,退出后星球将被解散,是否确认退出该星球' : '退出后将无法查看/操作该星球的内容,是否确认退出该星球'"
negative-text="取消"
positive-text="确认退出"
@negative-click="isDelete = false"

View File

@ -140,6 +140,9 @@ onMounted(() => {
<div class="w-[200px]">
消费金币值
</div>
<div class="w-[200px]">
金币余额
</div>
</div>
<n-infinite-scroll
style="height: calc(100vh - 300px);"
@ -148,7 +151,7 @@ onMounted(() => {
>
<div v-for="item in walletRecordList" :key="item" class="mc-table flex w-full">
<div class="w-[250px]">
{{ item.consumeDate }}
{{ item.createTime }}
</div>
<div class="w-[250px]">
{{ item.productName }}
@ -156,8 +159,11 @@ onMounted(() => {
<div class="flex-1">
-
</div>
<div class="w-[200px]" :class="{ 'text-[#FFD700]': item.amount > 0 }">
{{ item.amount > 0 ? `+${item.amount}` : item.amount }}
</div>
<div class="w-[200px]">
{{ item.amount }}
{{ item.wallet }}
</div>
</div>
</n-infinite-scroll>

View File

@ -6,7 +6,6 @@ import { NConfigProvider, NImage, NMessageProvider } from 'naive-ui'
import { onMounted, ref } from 'vue'
import { useRoute } from 'vue-router'
const message = useMessage()
definePageMeta({
layout: 'planet',
})
@ -34,6 +33,7 @@ const showPublishModal = ref(false)
const publishListParams = ref({
communityId: route.query.communityId,
tenantId: route.query.tenantId,
publishId: route.query.id,
type: null,
pageNum: 1,
pageSize: 10,
@ -45,28 +45,35 @@ const questionParams = ref({
pageNum: 1,
pageSize: 10,
})
const questionList = ref([])
// const questionList = ref([])
const isShow = ref('publish')
async function handleTypeChange(type: number | null) {
publishListParams.value.type = type
questionParams.value.pageNum = 1
if (type === 999) { //
isShow.value = 'question'
try {
const res = await request.post('/question/list', questionParams.value)
if (res.code === 200) {
questionList.value = res.rows
}
}
catch (error) {
console.error(error)
}
// try {
// const res = await request.post('/question/list', questionParams.value)
// if (res.code === 200) {
// questionList.value = res.rows
// }
// }
// catch (error) {
// console.error(error)
// }
}
else {
publishListParams.value.pageNum = 1
isShow.value = 'publish'
}
}
const PublishComponentKey = ref(0)
function closePublishModal() {
showPublishModal.value = false
nextTick(() => {
PublishComponentKey.value++
})
}
</script>
<template>
@ -114,6 +121,7 @@ async function handleTypeChange(type: number | null) {
<NConfigProvider>
<NMessageProvider>
<PlanetComment
:key="PublishComponentKey"
:publish-list-params="publishListParams"
/>
</NMessageProvider>
@ -123,6 +131,7 @@ async function handleTypeChange(type: number | null) {
<NConfigProvider>
<NMessageProvider>
<PlanetQuestionComment
:key="PublishComponentKey"
:publish-list-params="questionParams"
/>
</NMessageProvider>
@ -142,7 +151,7 @@ async function handleTypeChange(type: number | null) {
<PublishContent
:community-id="route.query.communityId"
:tenant-id="route.query.tenantId"
@success="showPublishModal = false"
@success="closePublishModal"
/>
</n-modal>
</div>

View File

@ -1,5 +1,6 @@
<script setup lang="ts">
import planetBg from '@/assets/img/planetBg.png'
import { X } from 'lucide-vue-next'
import { NConfigProvider, NImage, NMessageProvider } from 'naive-ui'
import { onMounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
@ -14,6 +15,7 @@ const params = ref({
tenantId: '',
userId: '',
})
// const goldPaymentRef = ref(null)
onMounted(() => {
const state = history.state
@ -84,7 +86,31 @@ async function getAttention() {
console.log(err)
}
}
// const isShowGoldPayment = ref(false)
const paymentModal = ref(false)
//
const showConfirmModal = ref(false)
function onPositiveClick() {
showConfirmModal.value = false
paymentModal.value = true
getQrCode()
}
function onNegativeClick() {
showConfirmModal.value = false
}
const formRef = ref(null)
const paymentParams = ref({
amount: 10,
type: 'wallet',
})
const amount = ref(10)
const qrUrl = ref('')
//
const paymentStatus = ref(1)
async function handleJoin() {
try {
const data = {
@ -99,10 +125,85 @@ async function handleJoin() {
}, 1000)
}
}
catch (err) {
if (err.code === 12202) {
// isShowGoldPayment.value = true
showConfirmModal.value = true
}
// isShowGoldPayment.value = true
// if (goldPaymentRef.value) {
// goldPaymentRef.value.isVisible = true
// }
// console.log(err)
}
}
function closePayment() {
paymentModal.value = false
}
let pollingTimer: ReturnType<typeof setInterval> | undefined
async function getQrCode() {
try {
paymentParams.value.amount = amount.value
const res = await request.post(`/ali/pay/doPay`, paymentParams.value)
if (res.code === 200) {
paymentStatus.value = 1
qrUrl.value = res.data.url
pollingTimer && clearTimeout(pollingTimer)
pollingTimer = setInterval(async () => {
try {
const res2 = await request.get(`/order/queryTradeStatus?outTradeNo=${res.data.orderNo}`)
if (res2.data === 2) { // 1 2 4
paymentStatus.value = 2
clearTimeout(pollingTimer)
paymentModal.value = false
message.success('支付成功!')
}
else if (res2.data === 4) {
paymentStatus.value = 4
clearTimeout(pollingTimer)
}
}
catch (err) {
console.log('object', err)
}
}, 2000)
}
}
catch (err) {
console.log(err)
}
}
//
// function paymentSuccess() {
// // getIsMember();
// if (import.meta.client) {
// window.location.reload()
// }
// }
// function closeGoldPayment() {
// isShowGoldPayment.value = false
// if (goldPaymentRef.value) {
// goldPaymentRef.value.isVisible = false
// }
// }
// //
// const isMember = ref(false)
// async function getIsMember() {
// try {
// const res = await request.get('/member/isMember')
// if (res.code === 200) {
// isMember.value = res.data
// }
// }
// catch (err) {
// console.log(err)
// }
// }
// getIsMember()
//
// async function getAttention() {
// try {
@ -159,7 +260,7 @@ async function handleJoin() {
<div class="flex justify-between p-2 rounded bg-white items-center">
<div class="flex items-center gap-2 text-[#fc4141]">
<span class="font-bold text-[28px]">{{ communityDetail.price ? communityDetail.price : '免费' }}</span> <span v-if="communityDetail.price" class="text-[16px]"></span>
<span class="font-bold text-[28px]">{{ communityDetail.price ? communityDetail.price : '免费' }}</span> <span v-if="communityDetail.price" class="text-[16px]"></span>
</div>
<div
class="text-white text-[14px] flex items-center justify-center cursor-pointer w-[128px] h-[40px] bg-[linear-gradient(207deg,#3BEDFF_0%,#328AFE_100%)] rounded-lg"
@ -177,7 +278,7 @@ async function handleJoin() {
</div>
<div class="flex gap-4 bg-[#F9FBFF] rounded-lg p-2">
<div class="w-[80px] h-[80px] rounded">
<img class="rounded-full" :src="userInfo.avatar" alt="星球概况">
<img class="rounded-full w-full h-full object-cover" :src="userInfo.avatar" alt="星球概况">
</div>
<div class="flex flex-col justify-between py-2">
<div class="flex gap-4">
@ -211,5 +312,101 @@ async function handleJoin() {
</div>
</div>
</div>
<!-- <NConfigProvider>
<NMessageProvider>
<GoldPayment
v-if="isShowGoldPayment"
ref="goldPaymentRef"
:is-member="isMember"
@payment-success="paymentSuccess"
@close-payment="closeGoldPayment"
/>
</NMessageProvider>
</NConfigProvider> -->
<n-modal
v-model:show="showConfirmModal"
:mask-closable="false"
preset="dialog"
title="确认"
content="余额不足,是否确认充值?"
positive-text="确认"
negative-text="算了"
@positive-click="onPositiveClick"
@negative-click="onNegativeClick"
/>
<n-modal
v-model:show="paymentModal"
:preset="null"
:mask-closable="false"
transform-origin="center"
class="custom-modal"
>
<div class="bg-white rounded-xl w-200 p-4">
<X class="absolute top-1 right-1 cursor-pointer" @click="closePayment" />
<div class="mb-4 mt-6 flex">
<n-form
ref="formRef"
:label-width="80"
:model="paymentParams"
size="large"
label-placement="left"
style="width: 240px"
>
<n-form-item label="输入金币" path="modelProduct.modelName">
<n-input v-model:value="amount" type="number" placeholder="输入积分" />
</n-form-item>
</n-form>
<n-button type="primary" class="mt-1 ml-2" @click="getQrCode">
确定
</n-button>
</div>
<div class="flex justify-center items-center my-4">
<div class="w-30 h-30 flex justify-center items-center relative">
<n-qr-code :value="qrUrl" :size="90" style="padding: 0;" />
<div v-if="paymentStatus === 4" class="absolute top-0 left-0 w-full h-full flex cursor-pointer flex-col justify-center items-center bg-opacity-50 bg-black text-white" @click="getQrCode">
请点击刷新<RotateCcw />
</div>
</div>
<div class="flex justify-center ml-2 flex-col pb-[14px]">
<div class="flex items-baseline">
<div class="text-[#222] font-medium mr-1">
支付
</div>
<div class="text-[#814600] mr-1">
<span class="text-[16px] mr-1">¥</span>
<span class="text-[40px]">{{ paymentParams.amount }}</span>
</div>
</div>
<div class="flex items-center mb-1">
<img src="@/assets/img/alipay.png" class="mr-1"> 请扫码完成支付
</div>
<div class="text-[12px]">
<span class="text-[#999]">
开通即代表同意
</span>
<span class="text-[#814600]">
魔创未来会员协议
</span>
</div>
</div>
</div>
</div>
</n-modal>
</div>
</template>
<style lang="scss" scoped>
.member-item {
display: flex;
justify-content: center;
align-items: center;
width: 16.66%;
height: 40px;
border: 1px solid #f0f0f0;
font-size: 12px;
font-weight: 400;
margin-right: -1px;
margin-bottom: -1px;
}
</style>