Compare commits

...

2 Commits

Author SHA1 Message Date
shenhan000 5db887bff3 update 2025-03-31 14:32:52 +08:00
shenhan000 8044855bbd uodate 2025-03-24 13:23:37 +08:00
21 changed files with 1740 additions and 1095 deletions

View File

@ -1,11 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import type { FormItemRule } from "naive-ui"; import type { FormItemRule } from 'naive-ui'
import { ref } from "vue"; import { ref } from 'vue'
const message = useMessage(); const message = useMessage()
const userStore = useUserStore(); const userStore = useUserStore()
const userInfo = userStore.userInfo; const userInfo = userStore.userInfo
const isVisible = ref(false); const isVisible = ref(false)
const rules = ref({ const rules = ref({
name: [ name: [
@ -13,13 +13,14 @@ const rules = ref({
required: true, required: true,
validator(rule: FormItemRule, value: string) { validator(rule: FormItemRule, value: string) {
if (!value) { if (!value) {
return new Error("请填写姓名"); return new Error('请填写姓名')
} else if (!/^[\u4E00-\u9FA5·]{2,16}$/.test(value)) {
return new Error("输入正确的姓名");
} }
return true; else if (!/^[\u4E00-\u9FA5·]{2,16}$/.test(value)) {
return new Error('输入正确的姓名')
}
return true
}, },
trigger: "blur", trigger: 'blur',
}, },
], ],
idCard: [ idCard: [
@ -27,29 +28,30 @@ const rules = ref({
required: true, required: true,
validator(rule: FormItemRule, value: string) { validator(rule: FormItemRule, value: string) {
if (!value) { if (!value) {
return new Error("请填身份证号"); return new Error('请填身份证号')
} else if ( }
else if (
!/(^\d{8}(0\d|10|11|12)([0-2]\d|30|31)\d{3}$)|(^\d{6}(18|19|20)\d{2}(0\d|10|11|12)([0-2]\d|30|31)\d{3}([\dX])$)/i.test( !/(^\d{8}(0\d|10|11|12)([0-2]\d|30|31)\d{3}$)|(^\d{6}(18|19|20)\d{2}(0\d|10|11|12)([0-2]\d|30|31)\d{3}([\dX])$)/i.test(
value value,
) )
) { ) {
return new Error("输入正确的身份证号"); return new Error('输入正确的身份证号')
} }
return true; return true
}, },
trigger: "blur", trigger: 'blur',
}, },
], ],
}); })
const ruleForm = ref({ const ruleForm = ref({
name: "", name: '',
idCard: "", idCard: '',
userId: userInfo.userId, userId: userInfo.userId,
}); })
const formRef = ref(null); const formRef = ref(null)
async function saveInfo(e: MouseEvent) { async function saveInfo(e: MouseEvent) {
e.preventDefault(); e.preventDefault()
formRef.value?.validate(async (errors) => { formRef.value?.validate(async (errors) => {
if (!errors) { if (!errors) {
// try{ // try{
@ -65,32 +67,34 @@ async function saveInfo(e: MouseEvent) {
// console.log('err',err) // console.log('err',err)
// } // }
try { try {
const res = await request.post("/system/user/updateIdCard", ruleForm.value); const res = await request.post('/system/user/updateIdCard', ruleForm.value)
if (res.code === 200) { if (res.code === 200) {
await userStore.getUserInfo(); await userStore.getUserInfo()
isVisible.value = false; isVisible.value = false
} else {
message.warning(res.msg);
} }
} catch (err) { else {
console.log(err); message.warning(res.msg)
} }
} }
}); catch (err) {
console.log(err)
}
}
})
} }
function onCloseModel() { function onCloseModel() {
isVisible.value = false; isVisible.value = false
ruleForm.value.name = ""; ruleForm.value.name = ''
ruleForm.value.idCard = ""; ruleForm.value.idCard = ''
} }
defineExpose({ defineExpose({
isVisible, isVisible,
}); })
// //
onMounted(() => { onMounted(() => {
// initFormData() // initFormData()
}); })
</script> </script>
<template> <template>

View File

@ -30,7 +30,7 @@
class="mr-2" class="mr-2"
size="20" size="20"
:color="item.isLike === 0 ? '#ccc' : '#ff0000'" :color="item.isLike === 0 ? '#ccc' : '#ff0000'"
@click="onLike(item)" @click.stop="onLike(item)"
> >
<Heart /> <Heart />
</n-icon> </n-icon>

View File

@ -33,10 +33,10 @@ async function onGetUUid() {
if (res.code === 200) { if (res.code === 200) {
const appid = 'wx0a72f196ec9c3a70' const appid = 'wx0a72f196ec9c3a70'
const { uuid } = res const { uuid } = res
const redirect_uri = `http://www.mc158c.com/api/wx/uuid/bind/openid?uuid=${uuid}` const redirect_uri = `http://www.mc158c.com/login-success?uuid=${uuid}`
const codeUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${encodeURIComponent( const codeUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${encodeURIComponent(
redirect_uri, redirect_uri,
)}&response_type=code&scope=snsapi_userinfo&state=123456#wechat_redirect` )}&response_type=code&scope=snsapi_userinfo&state=12345e23436#wechat_redirect`
qrUrl.value = codeUrl qrUrl.value = codeUrl
let counter = 1 let counter = 1
pollingTimer && clearTimeout(pollingTimer) pollingTimer && clearTimeout(pollingTimer)

View File

@ -30,7 +30,12 @@
processing processing
/> />
</div> </div>
<div v-if="requiredValid" class="item-valid"></div> <!-- <div v-if="requiredValid" class="item-valid"></div> -->
<!-- <div class="resume-upload">
<n-button type="primary" @click="resumeUpload">
继续上传
</n-button>
</div> -->
</div> </div>
</template> </template>
@ -77,7 +82,7 @@ const fileName = ref("");
const fileSize = ref(0); const fileSize = ref(0);
const progress = ref(0); const progress = ref(0);
const objectKey = ref(""); const objectKey = ref("");
const chunkSize = ref(3 * 1024 * 1024); const chunkSize = ref(5 * 1024 * 1024);
const totalChunks = ref(0); const totalChunks = ref(0);
const currentChunk = ref(1); const currentChunk = ref(1);
const uploadId = ref(""); const uploadId = ref("");
@ -89,6 +94,13 @@ const requiredValid = ref(false);
const hashCode = ref(""); const hashCode = ref("");
const message = useMessage(); const message = useMessage();
const currentFileSize = ref(0) const currentFileSize = ref(0)
//
const uploadStatus = ref<'idle' | 'uploading' | 'paused' | 'completed'>('idle');
const uploadedChunks = ref<Set<number>>(new Set());
const retryCount = ref<number>(0);
const maxRetries = 5; //
// //
const triggerFileSelect = () => { const triggerFileSelect = () => {
fileInputRef.value?.click(); fileInputRef.value?.click();
@ -162,6 +174,9 @@ const initParam = () => {
uploadId.value = ""; uploadId.value = "";
partArr.value = []; partArr.value = [];
requiredValid.value = false; requiredValid.value = false;
uploadStatus.value = 'idle';
uploadedChunks.value.clear();
retryCount.value = 0;
}; };
function getOssDefaultPath(name:any) { function getOssDefaultPath(name:any) {
@ -200,6 +215,18 @@ const selectFile = async (event: Event) => {
} }
try { try {
//
if (uploadStatus.value === 'paused' && file.value) {
const shouldResume = window.confirm('检测到未完成的上传,是否继续上传?');
if (shouldResume) {
await resumeUpload();
return;
} else {
//
initParam();
}
}
// //
progress.value = 0; progress.value = 0;
fileName.value = file.value.name; fileName.value = file.value.name;
@ -244,8 +271,15 @@ const selectFile = async (event: Event) => {
// //
// 0 1 // 0 1
try { try {
const res = await request.get( // const res = await request.get(
`/file/selectFile?type=${props.type}&name=${fileName.value}` // `/file/selectFile?type=${props.type}&name=${fileName.value}`
// );
const res = await request.post(
`/file/selectFile`,
{
type:props.type,
name:fileName.value
}
); );
if (res.data !== 1) { if (res.data !== 1) {
message.warning("文件名已存在"); message.warning("文件名已存在");
@ -314,6 +348,13 @@ const selectFile = async (event: Event) => {
const uploadFile = async () => { const uploadFile = async () => {
if (!file.value) return; if (!file.value) return;
while (currentChunk.value <= totalChunks.value) {
//
if (uploadedChunks.value.has(currentChunk.value)) {
currentChunk.value++;
continue;
}
const index = currentChunk.value - 1; const index = currentChunk.value - 1;
const start = index * chunkSize.value; const start = index * chunkSize.value;
const end = Math.min((index + 1) * chunkSize.value, file.value.size); const end = Math.min((index + 1) * chunkSize.value, file.value.size);
@ -325,24 +366,58 @@ const uploadFile = async () => {
formData.append("uploadId", uploadId.value); formData.append("uploadId", uploadId.value);
try { try {
uploadStatus.value = 'uploading';
const res = await request.post("/file/chunk", formData, { const res = await request.post("/file/chunk", formData, {
headers: { "Content-Type": "multipart/form-data" }, headers: { "Content-Type": "multipart/form-data" },
//
onUploadProgress: (progressEvent) => {
const percentCompleted = Math.round(
((currentChunk.value - 1) / totalChunks.value) * 100 +
(progressEvent.loaded / progressEvent.total!) * (100 / totalChunks.value)
);
progress.value = percentCompleted;
}
}); });
//
uploadedChunks.value.add(currentChunk.value);
partArr.value.push(res.data); partArr.value.push(res.data);
currentChunk.value++; currentChunk.value++;
progress.value = Math.floor((currentChunk.value / totalChunks.value) * 100); retryCount.value = 0; //
if (currentChunk.value <= totalChunks.value) { progress.value = Math.floor((currentChunk.value / totalChunks.value) * 100);
uploadFile();
} else {
progress.value = 99;
complete();
}
} catch (error) { } catch (error) {
initParam();
console.error("切片上传失败:", error); console.error("切片上传失败:", error);
message.warning("文件上传异常或上传已取消");
//
if (retryCount.value < maxRetries) {
retryCount.value++;
message.warning(`${currentChunk.value} 个分片上传失败,正在进行第 ${retryCount.value} 次重试...`);
await new Promise(resolve => setTimeout(resolve, 1000)); // 1
continue; //
}
//
uploadStatus.value = 'paused';
message.error(`上传失败,已暂停。您可以稍后继续上传。`);
return;
}
}
//
if (currentChunk.value > totalChunks.value) {
progress.value = 99;
uploadStatus.value = 'completed';
await complete();
}
};
//
const resumeUpload = async () => {
if (uploadStatus.value === 'paused' && file.value) {
retryCount.value = 0; //
message.info('正在继续上传...');
await uploadFile();
} }
}; };
@ -389,19 +464,21 @@ const emit = defineEmits<{
// //
const cancelUploadInfo = async () => { const cancelUploadInfo = async () => {
if (progress.value !== 100) { if (uploadStatus.value !== 'completed') {
try { try {
await request.post("/file/cancelUpload", { await request.post("/file/cancelUpload", {
objectKey: objectKey.value, objectKey: objectKey.value,
uploadId: uploadId.value, uploadId: uploadId.value,
}); });
uploadStatus.value = 'idle';
uploadedChunks.value.clear();
progress.value = 0;
showFileName.value = false;
initParam();
} catch (error) { } catch (error) {
message.error("取消上传失败"); message.error("取消上传失败");
} }
} }
progress.value = 0;
showFileName.value = false;
initParam();
}; };
// //

View File

@ -1,122 +1,117 @@
<script setup lang="ts"> <script setup lang="ts">
import { commonApi } from '@/api/common'; import { commonApi } from "@/api/common";
import type { FormInst } from 'naive-ui'; import type { FormInst } from "naive-ui";
import { computed, watch } from 'vue'; import { computed, watch } from "vue";
const props = defineProps({ const props = defineProps({
modelValue: { modelValue: {
type: Object, type: Object,
required: true, required: true,
}, },
}) });
const emit = defineEmits(['update:modelValue', 'createModelsNext']) const emit = defineEmits(["update:modelValue", "createModelsNext"]);
const localForm = computed({ const localForm = computed({
get() { get() {
return props.modelValue return props.modelValue;
}, },
set(value) { set(value) {
emit('update:modelValue', value) emit("update:modelValue", value);
}, },
}) });
const options: any[] = [ const options: any[] = [];
]
watch( watch(
() => localForm.value, () => localForm.value,
(newVal) => { (newVal) => {
emit('update:modelValue', newVal) emit("update:modelValue", newVal);
}, },
{ immediate: true, deep: true }, { immediate: true, deep: true }
) );
const formRef = ref<FormInst | null>(null) const formRef = ref<FormInst | null>(null);
const rules = { const rules = {
'modelProduct.modelName': { "modelProduct.modelName": {
required: true, required: true,
message: '', message: "",
trigger: 'blur', trigger: "blur",
}, },
'modelProduct.modelType': { "modelProduct.modelType": {
required: true, required: true,
message: '', message: "",
trigger: 'blur', trigger: "blur",
}, },
} };
const modelChildCategory = ref([]) // const modelChildCategory = ref([]); //
const model_category = ref([]) // const model_category = ref([]); //
const categoryList = ref([]) const categoryList = ref([]);
const work_flow_functions = ref([]) const work_flow_functions = ref([]);
async function getDictType() { async function getDictType() {
try { try {
const [res1, res2, res3, res4] = await Promise.all([ const [res1, res2, res3, res4] = await Promise.all([
commonApi.dictType({ type: 'model_part_category' }), commonApi.dictType({ type: "model_part_category" }),
commonApi.dictType({ type: 'model_child_category' }), commonApi.dictType({ type: "model_child_category" }),
commonApi.dictType({ type: 'model_type' }), commonApi.dictType({ type: "model_type" }),
commonApi.dictType({ type: 'work_flow_functions' }), commonApi.dictType({ type: "work_flow_functions" }),
]) ]);
// modelPartCategory.value = res1.data // modelPartCategory.value = res1.data
modelChildCategory.value = res2.data modelChildCategory.value = res2.data;
model_category.value = res3.data model_category.value = res3.data;
work_flow_functions.value = res4.data work_flow_functions.value = res4.data;
categoryList.value = res1.data categoryList.value = res1.data;
// //
categoryList.value.forEach((item: any) => { categoryList.value.forEach((item: any) => {
item.dictValue += 99999 item.dictValue += 99999;
// children // children
item.children = [] item.children = [];
// //
modelChildCategory.value.forEach((child) => { modelChildCategory.value.forEach((child) => {
// parentIddictValue // parentIddictValue
if (child.partId === item.dictCode) { if (child.partId === item.dictCode) {
// children // children
item.children.push(child) item.children.push(child);
} }
}) });
}) });
} } catch (error) {
catch (error) { console.log(error);
console.log(error)
} }
} }
getDictType() getDictType();
const activityList = ref([]) const activityList = ref([]);
async function getActivityList() { async function getActivityList() {
try { try {
const res = await request.post('/ToActivity/list', {}) const res = await request.post("/ToActivity/list", {});
activityList.value = res.rows activityList.value = res.rows;
} } catch (error) {
catch (error) { console.log(error);
console.log(error)
} }
} }
getActivityList() getActivityList();
const originalBtnList = ref([ const originalBtnList = ref([
{ {
label: '原创', label: "原创",
value: 1, value: 1,
}, },
{ {
label: '转载', label: "转载",
value: 0, value: 0,
}, },
]) ]);
function nextStep() { function nextStep() {
formRef.value?.validate((errors) => { formRef.value?.validate((errors) => {
if (!errors) { if (!errors) {
emit('createModelsNext') emit("createModelsNext");
} else {
console.log("error", errors);
} }
else { });
console.log('error', errors)
}
})
} }
function handleIsOriginal(value: number) { function handleIsOriginal(value: number) {
localForm.value.modelProduct.isOriginal = value localForm.value.modelProduct.isOriginal = value;
// if (value === 0) { // if (value === 0) {
// localForm.value.modelProduct.originalAuthorName = '' // localForm.value.modelProduct.originalAuthorName = ''
// } // }
@ -138,6 +133,23 @@ const isPublicList = [
value: 0, value: 0,
}, },
]; ];
const isFreeList = ref([
{
label: "免费",
value: 1,
},
{
label: "付费",
value: 0,
},
]);
function handleIsFree(value: number) {
// localForm.value.modelVersionList[index].isFree = value;
localForm.value.modelProduct.isFree = value;
}
// function changeModelType(item){ // function changeModelType(item){
// } // }
</script> </script>
@ -153,7 +165,10 @@ const isPublicList = [
size="large" size="large"
> >
<n-form-item label="模型名称" path="modelProduct.modelName"> <n-form-item label="模型名称" path="modelProduct.modelName">
<n-input v-model:value="localForm.modelProduct.modelName" placeholder="输入模型名" /> <n-input
v-model:value="localForm.modelProduct.modelName"
placeholder="输入模型名"
/>
</n-form-item> </n-form-item>
<n-form-item label="模型类型" path="modelProduct.modelType"> <n-form-item label="模型类型" path="modelProduct.modelType">
<!-- @update:value="changeModelType" --> <!-- @update:value="changeModelType" -->
@ -165,9 +180,7 @@ const isPublicList = [
:options="model_category" :options="model_category"
/> />
</n-form-item> </n-form-item>
<div> <div>内容类别</div>
内容类别
</div>
<div class="-mb-5 text-gray-400 text-[12px]"> <div class="-mb-5 text-gray-400 text-[12px]">
填写类别可让模型获得更精准的流量, 平台也有权基于标准修改你的类别标签 填写类别可让模型获得更精准的流量, 平台也有权基于标准修改你的类别标签
</div> </div>
@ -182,7 +195,11 @@ const isPublicList = [
@update:value="handleCategoryUpdateValue" @update:value="handleCategoryUpdateValue"
/> />
</n-form-item> </n-form-item>
<n-form-item path="functions" class="-mt-12" v-if="localForm.modelProduct.modelType !== '0'"> <n-form-item
path="functions"
class="-mt-12"
v-if="localForm.modelProduct.modelType !== '0'"
>
<n-select <n-select
v-model:value="localForm.modelProduct.functions" v-model:value="localForm.modelProduct.functions"
label-field="dictLabel" label-field="dictLabel"
@ -192,9 +209,7 @@ const isPublicList = [
/> />
</n-form-item> </n-form-item>
<div> <div>标签</div>
标签
</div>
<div class="-mb-5 text-gray-400 text-[12px]"> <div class="-mb-5 text-gray-400 text-[12px]">
添加标签将自动推荐给可能感兴趣的人 添加标签将自动推荐给可能感兴趣的人
</div> </div>
@ -219,12 +234,8 @@ const isPublicList = [
:show="false" :show="false"
/> />
</n-form-item> </n-form-item>
<div> <div>参与活动</div>
参与活动 <div class="-mb-5 text-gray-400 text-[12px]">参与特定活动或比赛,下拉选择</div>
</div>
<div class="-mb-5 text-gray-400 text-[12px]">
参与特定活动或比赛,下拉选择
</div>
<n-form-item path="activityId"> <n-form-item path="activityId">
<n-select <n-select
v-model:value="localForm.modelProduct.activityId" v-model:value="localForm.modelProduct.activityId"
@ -235,30 +246,15 @@ const isPublicList = [
/> />
</n-form-item> </n-form-item>
</n-form> </n-form>
<div>
原创内容
</div>
<div class="flex justify-center items-center mt-5 bg-white h-12 rounded-lg border border-gray-100">
<div
v-for="(item, index) in originalBtnList"
:key="index"
:style="{
backgroundColor:
localForm.modelProduct.isOriginal === item.value
? 'rgba(49, 98, 255, 0.1)'
: '#fff',
color: localForm.modelProduct.isOriginal === item.value ? '#3162ff' : '#000',
}" class="flex-1 rounded-lg h-full flex items-center justify-center cursor-pointer" @click="handleIsOriginal(item.value)"
>
{{ item.label }}
</div>
</div>
<div class="">权限设置</div> <div class="">权限设置</div>
<div class="mt-1 mb-2 text-gray-400 text-[12px]">可见范围</div> <div class="mt-1 mb-2 text-gray-400 text-[12px]">可见范围</div>
<div> <div>
<n-radio-group v-model:value="localForm.modelProduct.jurisdiction" name="radiogroup"> <n-radio-group
v-model:value="localForm.modelProduct.jurisdiction"
name="radiogroup"
>
<n-space> <n-space>
<n-radio <n-radio
v-for="(isPublicItem, isPublicIndex) in isPublicList" v-for="(isPublicItem, isPublicIndex) in isPublicList"
@ -270,11 +266,72 @@ const isPublicList = [
</n-space> </n-space>
</n-radio-group> </n-radio-group>
</div> </div>
<div v-if="localForm.modelProduct.jurisdiction === 1">
<div class="mt-4 mb-1 text-gray-400 text-[12px]">付费设置</div>
<div class="flex justify-center items-center bg-white h-10 rounded-lg">
<div
v-for="(item, index) in isFreeList"
:key="index"
:style="{
backgroundColor:
localForm.modelProduct.isFree === item.value ? 'rgba(49, 98, 255, 0.1)' : '#fff',
color: localForm.modelProduct.isFree === item.value ? '#3162ff' : '#000',
}"
class="flex-1 rounded-lg h-full flex items-center justify-center cursor-pointer"
@click="handleIsFree(item.value)"
>
{{ item.label }}
</div>
</div>
<!-- <div class="mt-1 mb-2 text-gray-500 text-[12px]">
选择会员专属或会员下载视为您已经阅读
<span class="text-[#3162ff] cursor-pointer underline"
>会员模型许可协议</span
>
并同意其中条款
</div> -->
<div v-if="localForm.modelProduct.isFree === 0" class="text-[12px]">
<n-form-item size="large">
<n-input
v-model:value="localForm.modelProduct.productPrice"
placeholder="请输入付费金额"
type="number"
/>
</n-form-item>
<!-- <div>会员下载模型</div>
<div class="text-gray-500">
下载模型需购买会员在线生图对所有人开放无生图次数限制会员下载的模型版本生成图片默认可商用
</div> -->
</div>
<div v-else class="mb-4">
</div>
</div>
<div>原创内容</div>
<div
class="flex justify-center items-center mt-5 bg-white h-12 rounded-lg border border-gray-100"
>
<div
v-for="(item, index) in originalBtnList"
:key="index"
:style="{
backgroundColor:
localForm.modelProduct.isOriginal === item.value
? 'rgba(49, 98, 255, 0.1)'
: '#fff',
color: localForm.modelProduct.isOriginal === item.value ? '#3162ff' : '#000',
}"
class="flex-1 rounded-lg h-full flex items-center justify-center cursor-pointer"
@click="handleIsOriginal(item.value)"
>
{{ item.label }}
</div>
</div>
<div v-if="localForm.modelProduct.isOriginal === 1" class="text-[12px]"> <div v-if="localForm.modelProduct.isOriginal === 1" class="text-[12px]">
<div class="my-3"> <div class="my-3">魔创未来原创模型加密保护计划</div>
魔创未来原创模型加密保护计划
</div>
<div class="text-gray-400"> <div class="text-gray-400">
原创模型加密保护计划是魔创未来推出的,为维护创作者权益保障平台健康发展,通过技术手段遏制爬取盗版侵权等不法行为,保证创作者的劳动成果得到合理回报,进而激励更多优秀原创模型的诞生 原创模型加密保护计划是魔创未来推出的,为维护创作者权益保障平台健康发展,通过技术手段遏制爬取盗版侵权等不法行为,保证创作者的劳动成果得到合理回报,进而激励更多优秀原创模型的诞生
</div> </div>
@ -285,29 +342,32 @@ const isPublicList = [
加入后有何好处 1.模型加密能力 2.流量扶持 3.创作激励 加入后有何好处 1.模型加密能力 2.流量扶持 3.创作激励
</div> </div>
<div class="text-gray-400"> <div class="text-gray-400">
详情查看 <a href="" class="text-[#3162ff] underline">魔创未来原创模型加密保护计划</a> 详情查看
</div> <a href="" class="text-[#3162ff] underline">魔创未来原创模型加密保护计划</a>
<div class="my-3 ">
原创声明
</div> </div>
<div class="my-3">原创声明</div>
<div class="text-gray-400"> <div class="text-gray-400">
本人声明并承诺模型是由本人原创,相关的权利和义务由本人承担 本人声明并承诺模型是由本人原创,相关的权利和义务由本人承担
</div> </div>
</div> </div>
<div v-else> <div v-else>
<n-form-item path="modelProduct.originalAuthorName" size="large"> <n-form-item path="modelProduct.originalAuthorName" size="large">
<n-input v-model:value="localForm.modelProduct.originalAuthorName" placeholder="输入原创作者" /> <n-input
v-model:value="localForm.modelProduct.originalAuthorName"
placeholder="输入原创作者"
/>
</n-form-item> </n-form-item>
</div> </div>
</div> </div>
<div class="flex w-full justify-center"> <div class="flex w-full justify-center">
<div class="flex justify-center items-center mt-5 text-white w-[200px] h-10 rounded-lg bg-[#3162ff] cursor-pointer" @click="nextStep"> <div
class="flex justify-center items-center mt-5 text-white w-[200px] h-10 rounded-lg bg-[#3162ff] cursor-pointer"
@click="nextStep"
>
下一步 下一步
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped></style>
</style>

View File

@ -110,9 +110,7 @@ const originalBtnList = ref([
value: 0, value: 0,
}, },
]); ]);
function handleIsFree(index: number, value: number) {
localForm.value.modelVersionList[index].isFree = value;
}
async function nextStep() { async function nextStep() {
for (let i = 0; i < localForm.value.modelVersionList.length; i++) { for (let i = 0; i < localForm.value.modelVersionList.length; i++) {
if ( if (
@ -329,37 +327,7 @@ function handledeleteFile(item:any){
</div> </div>
</div> --> </div> -->
</n-form> </n-form>
<div v-if="item.isPublic === 1">
<div class="mt-4 mb-1 text-gray-400 text-[12px]">付费设置</div>
<div class="flex justify-center items-center bg-white h-10 rounded-lg">
<div
v-for="(subItem, subIndex) in originalBtnList"
:key="subIndex"
:style="{
backgroundColor:
item.isFree === subItem.value ? 'rgba(49, 98, 255, 0.1)' : '#fff',
color: item.isFree === subItem.value ? '#3162ff' : '#000',
}"
class="flex-1 rounded-lg h-full flex items-center justify-center cursor-pointer"
@click="handleIsFree(index, subItem.value)"
>
{{ subItem.label }}
</div>
</div>
<div class="mt-1 mb-2 text-gray-500 text-[12px]">
选择会员专属或会员下载视为您已经阅读
<span class="text-[#3162ff] cursor-pointer underline"
>会员模型许可协议</span
>
并同意其中条款
</div>
<div v-if="item.isFree === 1" class="text-[12px]">
<div>会员下载模型</div>
<div class="text-gray-500">
下载模型需购买会员在线生图对所有人开放无生图次数限制会员下载的模型版本生成图片默认可商用
</div>
</div>
</div>
<div class="text-gray-400 text-[12px] my-4">许可范围</div> <div class="text-gray-400 text-[12px] my-4">许可范围</div>
<div class="flex flex-wrap"> <div class="flex flex-wrap">
<div class="w-[50%] mb-2"> <div class="w-[50%] mb-2">
@ -367,7 +335,7 @@ function handledeleteFile(item:any){
v-model:checked="item.isOnlineUse" v-model:checked="item.isOnlineUse"
:checked-value="1" :checked-value="1"
:unchecked-value="0" :unchecked-value="0"
disabled="true" :disabled="true"
label="允许在魔创未来在线使用" label="允许在魔创未来在线使用"
/> />
</div> </div>
@ -383,7 +351,7 @@ function handledeleteFile(item:any){
<n-checkbox <n-checkbox
v-model:checked="item.allowSoftwareUse" v-model:checked="item.allowSoftwareUse"
:checked-value="1" :checked-value="1"
disabled="true" :disabled="true"
:unchecked-value="0" :unchecked-value="0"
label="允许在魔创未来旗下其他产品在线使用" label="允许在魔创未来旗下其他产品在线使用"
/> />

View File

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { cloneDeep } from 'lodash-es'; import { cloneDeep } from 'lodash-es';
import { Asterisk } from 'lucide-vue-next'; import { Asterisk, Trash } from 'lucide-vue-next';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
const props = defineProps({ const props = defineProps({
@ -32,6 +32,8 @@ function preStep() {
} }
const showSuccessModal = ref(false) const showSuccessModal = ref(false)
//
async function handlePublish() { async function handlePublish() {
for (let i = 0; i < localForm.value.modelVersionList.length; i++) { for (let i = 0; i < localForm.value.modelVersionList.length; i++) {
if (localForm.value.modelVersionList[i].delFlag === '0' && localForm.value.modelVersionList[i].sampleImagePaths.length === 0) { if (localForm.value.modelVersionList[i].delFlag === '0' && localForm.value.modelVersionList[i].sampleImagePaths.length === 0) {
@ -55,6 +57,10 @@ async function handlePublish() {
} }
} }
if(param.modelProduct.isFree === 1){
param.modelProduct.productPrice = 0
}
if (type === 'add') { if (type === 'add') {
try { try {
const res = await request.post('/model/insert', param) const res = await request.post('/model/insert', param)
@ -92,10 +98,14 @@ watch(
const fileInput = ref<HTMLInputElement | null>(null) const fileInput = ref<HTMLInputElement | null>(null)
const uploadFileIndex = ref(0) const uploadFileIndex = ref(0)
//
function triggerFileInput(index: number) { function triggerFileInput(index: number) {
(fileInput.value as HTMLInputElement)?.click() (fileInput.value as HTMLInputElement)?.click()
uploadFileIndex.value = index uploadFileIndex.value = index
} }
//
async function handleFileChange(event: Event) { async function handleFileChange(event: Event) {
const target = event.target as HTMLInputElement const target = event.target as HTMLInputElement
const files = target.files const files = target.files
@ -117,10 +127,16 @@ async function handleFileChange(event: Event) {
target.value = '' target.value = ''
} }
//
function onPositiveClick() { function onPositiveClick() {
showSuccessModal.value = false showSuccessModal.value = false
router.push('/personal-center') router.push('/personal-center')
} }
//
const deleteSampleImage = (index:number, data:any) =>{
data.splice(index, 1)
}
</script> </script>
<template> <template>
@ -166,8 +182,9 @@ function onPositiveClick() {
</n-spin> </n-spin>
<div class="grid grid-cols-3 gap-2.5 mt-4 w-full"> <div class="grid grid-cols-3 gap-2.5 mt-4 w-full">
<div v-for="(subItem, subIndex) in item.sampleImagePaths" :key="subIndex"> <div v-for="(subItem, subIndex) in item.sampleImagePaths" :key="subIndex" class="relative">
<img class="w-full h-[200px] object-cover rounded-lg" :src="subItem" alt=""> <img class="w-full h-[200px] object-cover rounded-lg" :src="subItem" alt="">
<Trash @click="deleteSampleImage(subIndex, item.sampleImagePaths)" :size="20" class="mt-1 absolute top-2 right-2 text-gray-400 cursor-pointer hover:text-gray-100" />
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,10 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref } from "vue"; import { onMounted, ref } from 'vue'
definePageMeta({ definePageMeta({
layout: "header", layout: 'header',
}); })
const activeTab = ref("oasis"); const activeTab = ref('oasis')
// const route = useRoute(); // const route = useRoute();
// const { id } = route.params as { id: string }; // const { id } = route.params as { id: string };
@ -12,80 +12,96 @@ const activeTab = ref("oasis");
// //
const recordFinished = ref(false) const recordFinished = ref(false)
const recordParams = ref({ const recordParams = ref({
"pageNum": 1, pageNum: 1,
"pageSize": 10 pageSize: 10,
}) })
const pointsResult = ref([]); const pointsResult = ref([])
async function getPoints() { async function getPoints() {
try { try {
if(recordFinished.value) return if (recordFinished.value)
const res = await request.post("/personalCenter/getRecord",{...recordParams.value}); return
const res = await request.post('/personalCenter/getRecord', { ...recordParams.value })
if (res.code === 200) { if (res.code === 200) {
if (recordParams.value.pageNum === 1) { if (recordParams.value.pageNum === 1) {
pointsResult.value = res.rows; pointsResult.value = res.rows
} else { }
pointsResult.value = [...pointsResult.value, ...res.rows]; else {
pointsResult.value = [...pointsResult.value, ...res.rows]
} }
// //
if (pointsResult.value.length >= res.total) { if (pointsResult.value.length >= res.total) {
recordFinished.value = true; recordFinished.value = true
} }
recordParams.value.pageNum++; recordParams.value.pageNum++
}
} catch (err) {
console.log(err);
} }
} }
getPoints(); catch (err) {
console.log(err)
}
}
getPoints()
// //
const walletRecordFinished = ref(false) const walletRecordFinished = ref(false)
const walletRecordParams = ref({ const walletRecordParams = ref({
"pageNum": 1, pageNum: 1,
"pageSize": 15 pageSize: 15,
}) })
const walletRecordList = ref([]); const walletRecordList = ref([])
async function getWalletRecord() { async function getWalletRecord() {
try { try {
if(walletRecordFinished.value) return if (walletRecordFinished.value)
const res = await request.post("/personalCenter/getWalletRecord", {...walletRecordParams.value}); return
const res = await request.post('/personalCenter/getWalletRecord', { ...walletRecordParams.value })
if (res.code === 200) { if (res.code === 200) {
if (walletRecordParams.value.pageNum === 1) { if (walletRecordParams.value.pageNum === 1) {
walletRecordList.value = res.rows; walletRecordList.value = res.rows
} else { }
walletRecordList.value = [...walletRecordList.value, ...res.rows]; else {
walletRecordList.value = [...walletRecordList.value, ...res.rows]
} }
// //
if (walletRecordList.value.length >= res.total) { if (walletRecordList.value.length >= res.total) {
walletRecordFinished.value = true; walletRecordFinished.value = true
} }
walletRecordParams.value.pageNum++; walletRecordParams.value.pageNum++
}
} catch (err) {
console.log(err);
} }
} }
getWalletRecord(); catch (err) {
console.log(err)
}
}
getWalletRecord()
onMounted(() => { onMounted(() => {
// nextTick(() => { // nextTick(() => {
// activeTab.value = 'beatles' // activeTab.value = 'beatles'
// }) // })
}); })
</script> </script>
<template> <template>
<div class="flex justify-center bg-[#f2f5f8] items-center h-[calc(100vh-48px)]"> <div class="flex justify-center bg-[#f2f5f8] items-center h-[calc(100vh-48px)]">
<div class="w-[1200px] bg-white rounded-lg shadow-lg p-10 h-[calc(100%-40px)]"> <div class="w-[1200px] bg-white rounded-lg shadow-lg p-10 h-[calc(100%-40px)]">
<h1 class="text-2xl font-bold mb-4">金币明细</h1> <h1 class="text-2xl font-bold mb-4">
金币明细
</h1>
<n-tabs v-model:value="activeTab" type="line" animated> <n-tabs v-model:value="activeTab" type="line" animated>
<n-tab-pane name="oasis" tab="充值记录"> <n-tab-pane name="oasis" tab="充值记录">
<div class="border border-solid border-gray-200 rounded-lg relative"> <div class="border border-solid border-gray-200 rounded-lg relative">
<div class="mc-table flex w-full bg-gray-200 sticky top-0"> <div class="mc-table flex w-full bg-gray-200 sticky top-0">
<div class="w-[250px]">获取时间</div> <div class="w-[250px]">
<div class="w-[250px]">获取来源</div> 获取时间
<div class="flex-1">详情</div> </div>
<div class="w-[200px]">金币值</div> <div class="w-[250px]">
获取来源
</div>
<div class="flex-1">
详情
</div>
<div class="w-[200px]">
充值金币值
</div>
</div> </div>
<n-infinite-scroll <n-infinite-scroll
style="height: calc(100vh - 300px);" style="height: calc(100vh - 300px);"
@ -96,8 +112,12 @@ onMounted(() => {
<div class="w-[250px]"> <div class="w-[250px]">
{{ item.orderTime }} {{ item.orderTime }}
</div> </div>
<div class="w-[250px]">{{ item.productName }}</div> <div class="w-[250px]">
<div class="flex-1">-</div> {{ item.productName }}
</div>
<div class="flex-1">
-
</div>
<div class="w-[200px]"> <div class="w-[200px]">
{{ item.paymentAmount }} {{ item.paymentAmount }}
</div> </div>
@ -108,10 +128,18 @@ onMounted(() => {
<n-tab-pane name="beatles" tab="消费记录"> <n-tab-pane name="beatles" tab="消费记录">
<div class="border border-solid border-gray-200 rounded-lg relative"> <div class="border border-solid border-gray-200 rounded-lg relative">
<div class="mc-table flex w-full bg-gray-200 sticky top-0"> <div class="mc-table flex w-full bg-gray-200 sticky top-0">
<div class="w-[250px]">消耗时间</div> <div class="w-[250px]">
<div class="w-[250px]">消耗类型</div> 消耗时间
<div class="flex-1">详情</div> </div>
<div class="w-[200px]">充值金币值</div> <div class="w-[250px]">
消耗类型
</div>
<div class="flex-1">
详情
</div>
<div class="w-[200px]">
消费金币值
</div>
</div> </div>
<n-infinite-scroll <n-infinite-scroll
style="height: calc(100vh - 300px);" style="height: calc(100vh - 300px);"
@ -122,8 +150,12 @@ onMounted(() => {
<div class="w-[250px]"> <div class="w-[250px]">
{{ item.consumeDate }} {{ item.consumeDate }}
</div> </div>
<div class="w-[250px]">{{ item.productName }}</div> <div class="w-[250px]">
<div class="flex-1">-</div> {{ item.productName }}
</div>
<div class="flex-1">
-
</div>
<div class="w-[200px]"> <div class="w-[200px]">
{{ item.amount }} {{ item.amount }}
</div> </div>

View File

@ -0,0 +1,197 @@
<template>
<div class="min-h-screen bg-white flex items-center justify-center px-4">
<!-- <n-button @click="handleAuthorization" type="info">
授权
</n-button> -->
<div v-if="isSuccess">
<div class="text-center">
<div
class="w-16 h-16 bg-green-500 rounded-full mx-auto mb-6 flex items-center justify-center animate-scale-in"
>
<svg
class="w-8 h-8 text-white"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M5 13l4 4L19 7"
/>
</svg>
</div>
<h2 class="text-xl font-medium text-gray-900 mb-2 animate-fade-in">登录成功</h2>
<!-- <p class="text-sm text-gray-500 animate-fade-in-delay">
{{ countdownText }}
</p> -->
</div>
</div>
<div v-else>
<div class="wave-loading mb-8">
<div class="wave-circle">
<div class="wave"></div>
<div class="wave"></div>
<div class="wave"></div>
<div class="logo-container">
<!-- <svg class="logo-icon" viewBox="0 0 24 24" fill="none">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" fill="currentColor"/>
</svg> -->
<!-- <svg class="logo-icon" viewBox="0 0 24 24">
<defs>
<linearGradient id="logoGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color: #60a5fa" />
<stop offset="100%" style="stop-color: #3b82f6" />
</linearGradient>
</defs>
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"
fill="url(#logoGradient)"
/>
</svg> -->
</div>
</div>
</div>
<!-- 加载文字动画 -->
<div class="loading-text">
<span class="dot-container">
<span class="text-xl font-medium text-gray-700">登录中</span>
<span class="dots">
<span class="dot">.</span>
<span class="dot">.</span>
<span class="dot">.</span>
</span>
</span>
</div>
<!-- 提示信息 -->
<div class="mt-4 space-y-2 animate-fade-in">
<p class="text-gray-500 text-sm">正在验证您的身份</p>
<div class="flex items-center justify-center space-x-2">
<svg class="w-4 h-4 text-blue-500 animate-spin" fill="none" viewBox="0 0 24 24">
<circle
class="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
stroke-width="4"
></circle>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
<span class="text-sm text-gray-400">请稍候片刻</span>
</div>
</div>
<!-- 安全提示 -->
<div class="mt-8 flex items-center justify-center text-gray-400 text-sm">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8V7a4 4 0 00-8 0v4h8z"
/>
</svg>
安全登录中
</div>
</div>
</div>
</template>
<script setup>
import { useRoute } from "#app";
import { onMounted, onUnmounted, ref } from "vue";
const route = useRoute();
definePageMeta({
layout: "home",
});
const countdown = ref(3);
const countdownText = ref("页面即将关闭...");
let timer = null;
let urlParams = null;
// const urlParams = new URLSearchParams(window.location.search);
const isSuccess = ref(false);
const handleAuthorization = async () => {
const uuid = route.query.uuid;
const code = route.query.code;
// const uuid = urlParams.get('uuid');
// const code = urlParams.get('code');
const url = `/wx/uuid/bind/openid?uuid=${uuid}&code=${code}`;
try {
const res = await request.get(url);
isSuccess.value = true;
} catch (err) {}
};
onMounted(() => {
handleAuthorization()
// urlParams = new URLSearchParams(window.location.search);
// const uuid = urlParams.get('uuid');
// console.log(uuid);
// timer = setInterval(() => {
// countdown.value--;
// countdownText.value = `${countdown.value}...`;
// if (countdown.value <= 0) {
// clearInterval(timer);
// //
// window.close();
// // window.close()
// // window.location.href = 'URL'
// }
// }, 1000);
});
onUnmounted(() => {
if (timer) {
clearInterval(timer);
}
});
</script>
<style>
@keyframes scale-in {
0% {
transform: scale(0);
}
70% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-scale-in {
animation: scale-in 0.3s ease-out forwards;
}
.animate-fade-in {
animation: fade-in 0.3s ease-out forwards;
}
.animate-fade-in-delay {
animation: fade-in 0.3s ease-out 0.2s forwards;
opacity: 0;
}
</style>

View File

@ -1,55 +1,58 @@
<script setup> <script setup>
import { CheckmarkCircleSharp, Close } from "@vicons/ionicons5"; import { CheckmarkCircleSharp, Close } from '@vicons/ionicons5'
import { NConfigProvider, NMessageProvider } from "naive-ui"; import { NConfigProvider, NMessageProvider } from 'naive-ui'
const message = useMessage();
const message = useMessage()
definePageMeta({ definePageMeta({
layout: "header", layout: 'header',
}); })
// //
const needPayment = ref([ const needPayment = ref([
{ {
amount: "", amount: '',
productId: "", productId: '',
promotionId: "", promotionId: '',
type: "member", type: 'member',
}, },
]); ])
const userStore = useUserStore(); const userStore = useUserStore()
const userInfo = userStore.userInfo; const userInfo = userStore.userInfo
// //
// interface Payment { // interface Payment {
// isVisible: boolean; // isVisible: boolean;
// } // }
// //
const isMember = ref(false); const isMember = ref(false)
async function getIsMember() { async function getIsMember() {
try { try {
const res = await request.get("/member/isMember"); const res = await request.get('/member/isMember')
if (res.code === 200) { if (res.code === 200) {
isMember.value = res.data; isMember.value = res.data
}
} catch (err) {
console.log(err);
} }
} }
getIsMember(); catch (err) {
console.log(err)
}
}
getIsMember()
// //
const MemberBenefitList = ref([]); const MemberBenefitList = ref([])
async function getMemberBenefitList() { async function getMemberBenefitList() {
try { try {
const res = await request.get("/memberLevel/getMemberBenefitList"); const res = await request.get('/memberLevel/getMemberBenefitList')
if (res.code === 200) { if (res.code === 200) {
MemberBenefitList.value = res.data; MemberBenefitList.value = res.data
}
} catch (err) {
console.log(err);
} }
} }
getMemberBenefitList(); catch (err) {
console.log(err)
}
}
getMemberBenefitList()
// //
// interface memberLevel { // interface memberLevel {
@ -58,151 +61,159 @@ getMemberBenefitList();
// originalPrice: number; // originalPrice: number;
// subscriptionPeriod: number; // subscriptionPeriod: number;
// } // }
const memberLevelList = ref([]); const memberLevelList = ref([])
async function getMemberLevelList() { async function getMemberLevelList() {
try { try {
const res = await request.get("/memberLevel/list"); const res = await request.get('/memberLevel/list')
if (res.code === 200) { if (res.code === 200) {
memberLevelList.value = res.data; memberLevelList.value = res.data
}
} catch (err) {
console.log(err);
} }
} }
getMemberLevelList(); catch (err) {
console.log(err)
}
}
getMemberLevelList()
// //
const isShowPayment = ref(false); const isShowPayment = ref(false)
const PaymentRef = ref(null); const PaymentRef = ref(null)
function showPayment(info) { function showPayment(info) {
if (info === 1) { if (info === 1) {
needPayment.value = memberLevelList.value; needPayment.value = memberLevelList.value
} else {
needPayment.value = [info];
} }
isShowPayment.value = true; else {
needPayment.value = [info]
}
isShowPayment.value = true
if (PaymentRef.value) { if (PaymentRef.value) {
PaymentRef.value.isVisible = true; PaymentRef.value.isVisible = true
} }
} }
// //
function closePayment() { function closePayment() {
isShowPayment.value = false; isShowPayment.value = false
if (PaymentRef.value) { if (PaymentRef.value) {
PaymentRef.value.isVisible = false; PaymentRef.value.isVisible = false
} }
} }
// //
const isShowIntPayment = ref(false); const isShowIntPayment = ref(false)
const IntPaymentRef = ref(null); const IntPaymentRef = ref(null)
function showIntPayment() { function showIntPayment() {
isShowIntPayment.value = true; isShowIntPayment.value = true
if (IntPaymentRef.value) { if (IntPaymentRef.value) {
IntPaymentRef.value.isVisible = true; IntPaymentRef.value.isVisible = true
} }
} }
// //
function closeIntPayment() { function closeIntPayment() {
isShowIntPayment.value = false; isShowIntPayment.value = false
if (IntPaymentRef.value) { if (IntPaymentRef.value) {
IntPaymentRef.value.isVisible = false; IntPaymentRef.value.isVisible = false
} }
} }
// //
const isShowGoldPayment = ref(false); const isShowGoldPayment = ref(false)
const goldPaymentRef = ref(null); const goldPaymentRef = ref(null)
function closeGoldPayment() { function closeGoldPayment() {
isShowGoldPayment.value = false; isShowGoldPayment.value = false
if (goldPaymentRef.value) { if (goldPaymentRef.value) {
goldPaymentRef.value.isVisible = false; goldPaymentRef.value.isVisible = false
} }
} }
// //
function paymentSuccess() { function paymentSuccess() {
getIsMember(); // getIsMember();
integralGold(); if (import.meta.client) {
window.location.reload()
}
} }
// //
function toIntDetail() { function toIntDetail() {
const baseUrl = window.location.origin; const baseUrl = window.location.origin
window.open(`${baseUrl}/int-detail`, "_blank", "noopener,noreferrer"); window.open(`${baseUrl}/int-detail`, '_blank', 'noopener,noreferrer')
} }
// //
function toOrderManage() { function toOrderManage() {
const baseUrl = window.location.origin; const baseUrl = window.location.origin
window.open(`${baseUrl}/order-management`, "_blank", "noopener,noreferrer"); window.open(`${baseUrl}/order-management`, '_blank', 'noopener,noreferrer')
} }
// //
function toGoldDetail() { function toGoldDetail() {
const baseUrl = window.location.origin; const baseUrl = window.location.origin
window.open(`${baseUrl}/gold-detail`, "_blank", "noopener,noreferrer"); window.open(`${baseUrl}/gold-detail`, '_blank', 'noopener,noreferrer')
} }
// //
function showGoldPayment() { function showGoldPayment() {
isShowGoldPayment.value = true; isShowGoldPayment.value = true
if (goldPaymentRef.value) { if (goldPaymentRef.value) {
goldPaymentRef.value.isVisible = true; goldPaymentRef.value.isVisible = true
} }
} }
// //
const integralGold = ref({}); const integralGold = ref({})
async function getIntegralGold() { async function getIntegralGold() {
try { try {
const res = await request.post("/personalCenter/getPointAndWallet"); const res = await request.post('/personalCenter/getPointAndWallet')
if (res.code === 200) { if (res.code === 200) {
integralGold.value = res.data; integralGold.value = res.data
}
} catch (err) {
console.log(err);
} }
} }
getIntegralGold(); catch (err) {
const isShowActivity = ref(true); console.log(err)
}
}
getIntegralGold()
const isShowActivity = ref(true)
// //
function closeActivityIcon() { function closeActivityIcon() {
isShowActivity.value = false; isShowActivity.value = false
} }
// //
const activityList = ref([]) const activityList = ref([])
const isShowactivityList = ref(false); const isShowactivityList = ref(false)
async function showActivityList() { async function showActivityList() {
try { try {
const res = await request.post("/promotion/promotionList", { const res = await request.post('/promotion/promotionList', {
pageNum: 1, pageNum: 1,
pageSize: 50, pageSize: 50,
}); })
if (res.code === 200) { if (res.code === 200) {
activityList.value = res.rows activityList.value = res.rows
isShowactivityList.value = true; isShowactivityList.value = true
} }
} catch (err) { }
console.log(err); catch (err) {
console.log(err)
} }
} }
// //
async function getActivity(item) { async function getActivity(item) {
if(item.isJoin === 1) return if (item.isJoin === 1)
return
try { try {
const res = await request.get(`/promotion/joinPromotion?promotionId=${item.id}`); const res = await request.get(`/promotion/joinPromotion?promotionId=${item.id}`)
if (res.code === 200) { if (res.code === 200) {
message.success('领取成功') message.success('领取成功')
item.isJoin = 1 item.isJoin = 1
} }
} catch (err) { }
catch (err) {
if (err.code === 601) { if (err.code === 601) {
message.warning(err.msg) message.warning(err.msg)
} }
@ -217,14 +228,14 @@ async function getActivity(item) {
<!-- 左侧用户信息 --> <!-- 左侧用户信息 -->
<div class="w-60 bg-[#2b2421] rounded-lg p-6 my-3"> <div class="w-60 bg-[#2b2421] rounded-lg p-6 my-3">
<!-- 右上角订阅管理 --> <!-- 右上角订阅管理 -->
<!-- <div class="text-right"> <div class="text-right">
<button <button
class="text-[#8b8685] text-sm bg-inherit border-none cursor-pointer" class="text-[#8b8685] text-sm bg-inherit border-none cursor-pointer"
@click="toOrderManage" @click="toOrderManage"
> >
订阅管理 > 订阅管理 >
</button> </button>
</div> --> </div>
<!-- 用户头像和信息 --> <!-- 用户头像和信息 -->
<div class="flex flex-col items-center mt-2"> <div class="flex flex-col items-center mt-2">
@ -233,7 +244,7 @@ async function getActivity(item) {
:src="userInfo.avatar" :src="userInfo.avatar"
alt="头像" alt="头像"
class="w-20 h-20 rounded-full mb-3" class="w-20 h-20 rounded-full mb-3"
/> >
<span class="text-white text-sm mb-2">{{ userInfo.nickName }}</span> <span class="text-white text-sm mb-2">{{ userInfo.nickName }}</span>
</client-only> </client-only>
<div class="flex items-center text-[#8b8685] text-xs"> <div class="flex items-center text-[#8b8685] text-xs">
@ -278,7 +289,9 @@ async function getActivity(item) {
<div class="grid grid-cols-3 gap-8"> <div class="grid grid-cols-3 gap-8">
<!-- 算力余额 --> <!-- 算力余额 -->
<div> <div>
<h3 class="text-[#c3986b] mb-4">积分余额</h3> <h3 class="text-[#c3986b] mb-4">
积分余额
</h3>
<div class="flex items-center mb-2"> <div class="flex items-center mb-2">
<span class="text-[#c3986b] mr-2">{{ integralGold.point || 0 }}</span> <span class="text-[#c3986b] mr-2">{{ integralGold.point || 0 }}</span>
<button <button
@ -298,11 +311,11 @@ async function getActivity(item) {
<!-- 生图加速余额 --> <!-- 生图加速余额 -->
<div> <div>
<h3 class="text-[#c3986b] mb-4">金币余额</h3> <h3 class="text-[#c3986b] mb-4">
金币余额
</h3>
<div class="flex items-center mb-2"> <div class="flex items-center mb-2">
<span class="text-[#c3986b] mr-2" <span class="text-[#c3986b] mr-2">{{ integralGold.wallet || 0 }} </span>
>{{ integralGold.wallet || 0 }} </span
>
<button <button
class="text-[#c3986b] bg-inherit border-none cursor-pointer" class="text-[#c3986b] bg-inherit border-none cursor-pointer"
@click="showGoldPayment" @click="showGoldPayment"
@ -314,13 +327,15 @@ async function getActivity(item) {
class="text-white bg-inherit border-none cursor-pointer p-0" class="text-white bg-inherit border-none cursor-pointer p-0"
@click="toGoldDetail" @click="toGoldDetail"
> >
加速明细 > 金币明细 >
</button> </button>
</div> </div>
<!-- 训练加速余额 --> <!-- 训练加速余额 -->
<div> <div>
<h3 class="text-[#c3986b] mb-4">训练加速余额</h3> <h3 class="text-[#c3986b] mb-4">
训练加速余额
</h3>
<div class="flex items-center mb-2"> <div class="flex items-center mb-2">
<span class="text-[#c3986b]">0</span> <span class="text-[#c3986b]">0</span>
</div> </div>
@ -343,7 +358,9 @@ async function getActivity(item) {
<!-- 进度条 --> <!-- 进度条 -->
<div class="relative"> <div class="relative">
<div class="h-1 bg-[#3a322e] rounded-full"> <div class="h-1 bg-[#3a322e] rounded-full">
<div class="absolute right-0 -top-6 text-[#8b8685] text-sm">0G/3G</div> <div class="absolute right-0 -top-6 text-[#8b8685] text-sm">
0G/3G
</div>
</div> </div>
</div> </div>
@ -378,9 +395,7 @@ async function getActivity(item) {
<div class="card-item"> <div class="card-item">
<span class="text-[#814600] text-[20px] mr-2">¥</span> <span class="text-[#814600] text-[20px] mr-2">¥</span>
<span class="text-[#814600] text-[40px] mr-2">{{ item.unitPrice }}</span> <span class="text-[#814600] text-[40px] mr-2">{{ item.unitPrice }}</span>
<span class="text-gray-400 text-[20px] line-through" <span class="text-gray-400 text-[20px] line-through">¥{{ item.originalPrice }}</span>
>¥{{ item.originalPrice }}</span
>
</div> </div>
<div class="card-item text-[#e08909] w-7/10 text-center text-[12px]"> <div class="card-item text-[#e08909] w-7/10 text-center text-[12px]">
{{ item.subscriptionPeriod }} {{ item.subscriptionPeriod }}
@ -397,7 +412,9 @@ async function getActivity(item) {
</div> </div>
<div class="py-8"> <div class="py-8">
<div class="flex justify-center mb-4"> <div class="flex justify-center mb-4">
<div class="text-xl font-bold">会员权益</div> <div class="text-xl font-bold">
会员权益
</div>
</div> </div>
<!-- <div class="flex items-center"> <!-- <div class="flex items-center">
<div v-for="(item, index) in MemberBenefitList" :key="index" class="w-1/4 w-full"> <div v-for="(item, index) in MemberBenefitList" :key="index" class="w-1/4 w-full">
@ -413,35 +430,67 @@ async function getActivity(item) {
</div> --> </div> -->
<div class="text-[#525252]"> <div class="text-[#525252]">
<div class="flex gap-2"> <div class="flex gap-2">
<div class="member-item bg-[#f7f0ea]">会员权益</div> <div class="member-item bg-[#f7f0ea]">
<div class="member-item bg-[#f5f5f5]">用户免费</div> 会员权益
<div class="member-item bg-[#fdf6ea]">基础版VIP</div> </div>
<div class="member-item bg-[#fce6bf]">专业版VIP</div> <div class="member-item bg-[#f5f5f5]">
用户免费
</div>
<div class="member-item bg-[#fdf6ea]">
基础版VIP
</div>
<div class="member-item bg-[#fce6bf]">
专业版VIP
</div>
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<div class="member-item bg-[#fff]">算力</div> <div class="member-item bg-[#fff]">
<div class="member-item bg-[#fff]">每天300点</div> 算力
<div class="member-item bg-[#fff]">每月15000点</div> </div>
<div class="member-item bg-[#fff]member-item">每月35000点</div> <div class="member-item bg-[#fff]">
每天300点
</div>
<div class="member-item bg-[#fff]">
每月15000点
</div>
<div class="member-item bg-[#fff]member-item">
每月35000点
</div>
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<div class="member-item bg-[#fafafa]">云端存储空间</div> <div class="member-item bg-[#fafafa]">
<div class="member-item bg-[#fafafa]">3GB</div> 云端存储空间
<div class="member-item bg-[#fdf6ea]">20GB</div> </div>
<div class="member-item bg-[#fce6bf]">50GB</div> <div class="member-item bg-[#fafafa]">
3GB
</div>
<div class="member-item bg-[#fdf6ea]">
20GB
</div>
<div class="member-item bg-[#fce6bf]">
50GB
</div>
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<div class="member-item bg-[#fff]">生图加速特权</div> <div class="member-item bg-[#fff]">
生图加速特权
</div>
<div class="member-item bg-[#fff]member-item"> <div class="member-item bg-[#fff]member-item">
<n-icon size="20" color="#ed7470"> <n-icon size="20" color="#ed7470">
<Close /> <Close />
</n-icon> </n-icon>
</div> </div>
<div class="member-item bg-[#fff]">每月800次</div> <div class="member-item bg-[#fff]">
<div class="member-item bg-[#fff]">每月5000次</div> 每月800次
</div>
<div class="member-item bg-[#fff]">
每月5000次
</div>
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<div class="member-item bg-[#fafafa]">会员专属模型</div> <div class="member-item bg-[#fafafa]">
会员专属模型
</div>
<div class="member-item bg-[#fafafa]"> <div class="member-item bg-[#fafafa]">
<n-icon size="20" color="#ed7470"> <n-icon size="20" color="#ed7470">
<Close /> <Close />
@ -459,7 +508,9 @@ async function getActivity(item) {
</div> </div>
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<div class="member-item bg-[#fff]">生图高级功能</div> <div class="member-item bg-[#fff]">
生图高级功能
</div>
<div class="member-item bg-[#fff]"> <div class="member-item bg-[#fff]">
<n-icon size="20" color="#ed7470"> <n-icon size="20" color="#ed7470">
<Close /> <Close />
@ -477,7 +528,9 @@ async function getActivity(item) {
</div> </div>
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<div class="member-item bg-[#fafafa]">训练XL模型</div> <div class="member-item bg-[#fafafa]">
训练XL模型
</div>
<div class="member-item bg-[#fafafa]"> <div class="member-item bg-[#fafafa]">
<n-icon size="20" color="#ed7470"> <n-icon size="20" color="#ed7470">
<Close /> <Close />
@ -495,7 +548,9 @@ async function getActivity(item) {
</div> </div>
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<div class="member-item bg-[#fff]">图片去水印下载</div> <div class="member-item bg-[#fff]">
图片去水印下载
</div>
<div class="member-item bg-[#fff]"> <div class="member-item bg-[#fff]">
<n-icon size="20" color="#ed7470"> <n-icon size="20" color="#ed7470">
<Close /> <Close />
@ -513,14 +568,20 @@ async function getActivity(item) {
</div> </div>
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<div class="member-item bg-[#fafafa]">多任务并行生图</div> <div class="member-item bg-[#fafafa]">
多任务并行生图
</div>
<div class="member-item bg-[#fafafa]"> <div class="member-item bg-[#fafafa]">
<n-icon size="20" color="#58c08f"> <n-icon size="20" color="#58c08f">
<CheckmarkCircleSharp /> <CheckmarkCircleSharp />
</n-icon> </n-icon>
</div> </div>
<div class="member-item bg-[#fdf6ea]">2</div> <div class="member-item bg-[#fdf6ea]">
<div class="member-item bg-[#fce6bf]">3</div> 2
</div>
<div class="member-item bg-[#fce6bf]">
3
</div>
</div> </div>
</div> </div>
</div> </div>
@ -532,7 +593,9 @@ async function getActivity(item) {
<div class="mt-1"> <div class="mt-1">
发票或团队/企业定制需求, 请点击立即咨询联系我们, 企业合作需求也可直接联系xxxx 发票或团队/企业定制需求, 请点击立即咨询联系我们, 企业合作需求也可直接联系xxxx
</div> </div>
<div class="mt-1">更多问题可见帮助中心</div> <div class="mt-1">
更多问题可见帮助中心
</div>
</div> </div>
</div> </div>
</div> </div>
@ -561,7 +624,7 @@ async function getActivity(item) {
/> />
</NMessageProvider> </NMessageProvider>
</NConfigProvider> </NConfigProvider>
<div class="activity-box" v-if="isShowActivity"> <div v-if="isShowActivity" class="activity-box">
<div class="absolute -top-6 -right-0 cursor-pointer"> <div class="absolute -top-6 -right-0 cursor-pointer">
<n-icon size="20" color="#bbb" @click="closeActivityIcon"> <n-icon size="20" color="#bbb" @click="closeActivityIcon">
<Close /> <Close />
@ -569,10 +632,10 @@ async function getActivity(item) {
</div> </div>
<img <img
class="cursor-pointer" class="cursor-pointer"
@click="showActivityList"
src="@/assets/img/activityIcon.png" src="@/assets/img/activityIcon.png"
alt="" alt=""
/> @click="showActivityList"
>
</div> </div>
<n-modal v-model:show="isShowactivityList" transform-origin="center"> <n-modal v-model:show="isShowactivityList" transform-origin="center">
@ -588,29 +651,33 @@ async function getActivity(item) {
<div class="flex justify-end mb-4"> <div class="flex justify-end mb-4">
<n-icon <n-icon
class="cursor-pointer" class="cursor-pointer"
@click="isShowactivityList = false"
size="20" size="20"
color="#bbb" color="#bbb"
@click="isShowactivityList = false"
> >
<Close /> <Close />
</n-icon> </n-icon>
</div> </div>
<div class="flex flex-col gap-3"> <div class="flex flex-col gap-3">
<div <div
class="px-2 py-4 bg-white h-20 w-full flex rounded-lg"
v-for="(item, index) in activityList" v-for="(item, index) in activityList"
:key="index" :key="index"
class="px-2 py-4 bg-white h-20 w-full flex rounded-lg"
> >
<div class="w-[70%] flex flex-col justify-around"> <div class="w-[70%] flex flex-col justify-around">
<div>{{ item.activityName }}</div> <div>{{ item.activityName }}</div>
<div class="text-xs text-gray-500">有效期: {{item.startTime}}</div> <div class="text-xs text-gray-500">
<div class="text-xs text-gray-500">失效期: {{item.endTime}}</div> 有效期: {{ item.startTime }}
</div>
<div class="text-xs text-gray-500">
失效期: {{ item.endTime }}
</div>
</div> </div>
<div class="w-[30%] flex items-center justify-center"> <div class="w-[30%] flex items-center justify-center">
<div <div
@click="getActivity(item)"
class="w-14 h-6 flex items-center justify-center cursor-pointer text-white text-xs bg-[#e9613f] rounded-full" class="w-14 h-6 flex items-center justify-center cursor-pointer text-white text-xs bg-[#e9613f] rounded-full"
:style="{ backgroundColor: item.isJoin === 0 ? '#e9613f' : '#ccc' }" :style="{ backgroundColor: item.isJoin === 0 ? '#e9613f' : '#ccc' }"
@click="getActivity(item)"
> >
{{ item.isJoin === 0 ? '领取' : '已领取' }} {{ item.isJoin === 0 ? '领取' : '已领取' }}
</div> </div>
@ -631,7 +698,7 @@ async function getActivity(item) {
position: fixed; position: fixed;
bottom: 20px; bottom: 20px;
right: 20px; right: 20px;
justify-content: space-around justify-content: space-around;
} }
.card-item { .card-item {
@apply flex items-center justify-center h-1/4; @apply flex items-center justify-center h-1/4;

View File

@ -1,6 +1,8 @@
<script setup> <script setup>
import { commonApi } from "@/api/common"; import { commonApi } from '@/api/common'
import { Close, DiamondSharp, PersonAddOutline } from "@vicons/ionicons5"; //
import { formatFileSize } from '@/utils/index.ts'
import { Close, DiamondSharp, PersonAddOutline } from '@vicons/ionicons5'
import { import {
CircleUser, CircleUser,
Download, Download,
@ -8,75 +10,78 @@ EllipsisVertical,
Heart, Heart,
Play, Play,
SquareCheck, SquareCheck,
SquarePlus SquarePlus,
} from "lucide-vue-next"; } from 'lucide-vue-next'
// import { NConfigProvider, NMessageProvider } from 'naive-ui'
import { formatFileSize } from '@/utils/index.ts'; import { ref } from 'vue'
import { NConfigProvider, NMessageProvider } from "naive-ui"; import { useRouter } from 'vue-router'
import { ref } from "vue";
import { useRouter } from "vue-router";
const userStore = useUserStore();
const message = useMessage();
const router = useRouter(); const userStore = useUserStore()
const message = useMessage()
const router = useRouter()
// tabs // tabs
definePageMeta({ definePageMeta({
layout: "default", layout: 'default',
}); })
// const userStore = useUserStore() // const userStore = useUserStore()
const route = useRoute(); const isBuy = ref(false)
const route = useRoute()
const { id } = route.params const { id } = route.params
const activeTab = ref(null); const activeTab = ref(null)
const commentHeight = ref(800); const commentHeight = ref(800)
const detailsInfo = ref({}); const detailsInfo = ref({})
const currentUserInfo = ref({}); const currentUserInfo = ref({})
const isVisibleReport = ref(false); const isVisibleReport = ref(false)
// //
const versionByWorkInfo = ref([]); const versionByWorkInfo = ref([])
async function getInfo() { async function getInfo() {
try { try {
const res = await request.get(`/model/selectModelById?id=${id}`); const res = await request.get(`/model/selectModelById?id=${id}`)
if (res.code === 200) { if (res.code === 200) {
detailsInfo.value = res.data; detailsInfo.value = res.data
if (res.data.tags) { if (res.data.tags) {
detailsInfo.value.tagsList = JSON.parse(res.data.tags); detailsInfo.value.tagsList = JSON.parse(res.data.tags)
} }
// detailsInfo.value.styleList =JSON.parse(res.data.styleList) // detailsInfo.value.styleList =JSON.parse(res.data.styleList)
// // 1 // // 1
try { try {
const res1 = await request.get(`/ModelVersion/finbyid?id=${res.data.id}`); // const res1 = await request.get(`/ModelVersion/finbyid?id=${res.data.id}`) //
if (res1.code === 200 && res1.data.length > 0) { if (res1.code === 200 && res1.data.length > 0) {
versionByWorkInfo.value = res1.data; versionByWorkInfo.value = res1.data
versionByWorkInfo.value.forEach((item) => { versionByWorkInfo.value.forEach((item) => {
item.sampleImagePaths = item.sampleImagePaths.split(","); item.sampleImagePaths = item.sampleImagePaths.split(',')
}); })
nextTick(() => { nextTick(() => {
activeTab.value = versionByWorkInfo.value[0].id; activeTab.value = versionByWorkInfo.value[0].id
}); })
// const commentRes = await request.get(`/WorkFlowComment/comment/${res.data.id}`) // const commentRes = await request.get(`/WorkFlowComment/comment/${res.data.id}`)
} }
} catch (error) { }
console.log(error); catch (error) {
console.log(error)
} }
// // // //
try { try {
const res = await request.get( const res = await request.get(
`/system/user/selectUserById?id=${detailsInfo.value.userId}` `/system/user/selectUserById?id=${detailsInfo.value.userId}`,
); )
if (res.code === 200) { if (res.code === 200) {
currentUserInfo.value = res.data; currentUserInfo.value = res.data
}
} catch (error) {
console.log(error);
}
getAttention();
}
} catch (error) {
console.log(error);
} }
} }
getInfo(); catch (error) {
console.log(error)
}
getAttention()
}
}
catch (error) {
console.log(error)
}
}
getInfo()
// // // //
// interface SelectUserInfo { // interface SelectUserInfo {
@ -94,53 +99,57 @@ const selectUserInfo = ref({
modelDownLoadNum: 0, modelDownLoadNum: 0,
modelLikeNum: 0, modelLikeNum: 0,
modelRunNum: 0, modelRunNum: 0,
}); })
// //
async function getAttention() { async function getAttention() {
try { try {
const res = await request.get( const res = await request.get(
`/attention/selectUserInfo?userId=${detailsInfo.value.userId}` `/attention/selectUserInfo?userId=${detailsInfo.value.userId}`,
); )
if (res.code === 200) { if (res.code === 200) {
selectUserInfo.value = res.data; selectUserInfo.value = res.data
} }
} catch (err) { }
console.log(err); catch (err) {
console.log(err)
} }
} }
// // // //
const isDelete = ref(false); const isDelete = ref(false)
async function handleSelect(event, type) { async function handleSelect(event, type) {
event.stopPropagation(); // event.stopPropagation() //
if (type === "report") { if (type === 'report') {
isVisibleReport.value = true; isVisibleReport.value = true
// await request.get(`/WorkFlow/report?id=${id}`) // // await request.get(`/WorkFlow/report?id=${id}`) //
} else if (type === "edit") { }
else if (type === 'edit') {
router.push({ router.push({
path: `/publish-model`, path: `/publish-model`,
query: { query: {
type: "edit", type: 'edit',
id: detailsInfo.value.id, id: detailsInfo.value.id,
}, },
}); })
} else { }
isDelete.value = true; else {
isDelete.value = true
} }
} }
// //
async function onDelete() { async function onDelete() {
try { try {
const res = await request.get(`/model/delete?id=${detailsInfo.value.id}`); const res = await request.get(`/model/delete?id=${detailsInfo.value.id}`)
if (res.code === 200) { if (res.code === 200) {
message.success("删除成功"); message.success('删除成功')
isDelete.value = false; isDelete.value = false
router.push("/personal-center"); router.push('/personal-center')
} }
} catch (err) { }
console.log(err); catch (err) {
console.log(err)
} }
} }
@ -148,19 +157,21 @@ async function onDelete() {
async function onChangeAttention() { async function onChangeAttention() {
try { try {
const res = await request.get( const res = await request.get(
`/attention/addAttention?userId=${detailsInfo.value.userId}` `/attention/addAttention?userId=${detailsInfo.value.userId}`,
); )
if (res.code === 200) { if (res.code === 200) {
if (res.data) { if (res.data) {
detailsInfo.value.isAttention = 1; detailsInfo.value.isAttention = 1
message.success("关注成功"); message.success('关注成功')
} else { }
detailsInfo.value.isAttention = 0; else {
message.success("取消关注成功"); detailsInfo.value.isAttention = 0
message.success('取消关注成功')
} }
} }
} catch (err) { }
console.log(err); catch (err) {
console.log(err)
} }
} }
@ -168,123 +179,179 @@ async function onChangeAttention() {
async function onLike() { async function onLike() {
try { try {
const res = await request.get( const res = await request.get(
`/ModelComment/modelLike?modelId=${detailsInfo.value.id}` `/ModelComment/modelLike?modelId=${detailsInfo.value.id}`,
); )
if (res.code === 200) { if (res.code === 200) {
detailsInfo.value.isLike === 0 detailsInfo.value.isLike === 0
? (detailsInfo.value.isLike = 1) ? (detailsInfo.value.isLike = 1)
: (detailsInfo.value.isLike = 0); : (detailsInfo.value.isLike = 0)
if (detailsInfo.value.isLike === 0) { if (detailsInfo.value.isLike === 0) {
message.success("取消点赞成功"); message.success('取消点赞成功')
} else { }
message.success("点赞成功"); else {
message.success('点赞成功')
} }
} }
} catch (err) { }
console.log(err); catch (err) {
console.log(err)
} }
} }
// //
const reportParams = ref({ const reportParams = ref({
reportId: undefined, reportId: undefined,
text: "", text: '',
type: 1, type: 1,
}); })
const reportList = ref([]); const reportList = ref([])
async function getDictType() { async function getDictType() {
try { try {
const res = await commonApi.dictType({ type: "report_type" }); const res = await commonApi.dictType({ type: 'report_type' })
if (res.code === 200) { if (res.code === 200) {
reportList.value = res.data; reportList.value = res.data
}
} catch (error) {
console.log(error);
} }
} }
getDictType(); catch (error) {
console.log(error)
}
}
getDictType()
function handleChange(item) { function handleChange(item) {
reportParams.value.reportId = item.dictValue; reportParams.value.reportId = item.dictValue
if (item.dictValue !== "5") { if (item.dictValue !== '5') {
reportParams.value.text = ""; reportParams.value.text = ''
} }
console.log("object", reportParams.value); console.log('object', reportParams.value)
} }
function closeReport() { function closeReport() {
isVisibleReport.value = false; isVisibleReport.value = false
} }
//
async function onReport() { async function onReport() {
if (reportParams.value.reportId !== undefined) { if (reportParams.value.reportId !== undefined) {
reportParams.value.productId = detailsInfo.value.id; reportParams.value.productId = detailsInfo.value.id
try { try {
const res = await request.post("/report/addReport", reportParams.value); const res = await request.post('/report/addReport', reportParams.value)
if (res.code === 200) { if (res.code === 200) {
message.success("举报成功"); message.success('举报成功')
closeReport(); closeReport()
} }
} catch (err) { }
console.log(err); catch (err) {
console.log(err)
} }
} }
} }
//
function toPersonalCenter() { function toPersonalCenter() {
const baseUrl = window.location.origin; const baseUrl = window.location.origin
if (userStore?.userInfo?.userId === detailsInfo.value.userId) { if (userStore?.userInfo?.userId === detailsInfo.value.userId) {
window.open(`${baseUrl}/personal-center`, "_blank", "noopener,noreferrer"); window.open(`${baseUrl}/personal-center`, '_blank', 'noopener,noreferrer')
} else { }
else {
window.open( window.open(
`${baseUrl}/personal-publish?userId=${detailsInfo.value.userId}`, `${baseUrl}/personal-publish?userId=${detailsInfo.value.userId}`,
"_blank", '_blank',
"noopener,noreferrer" 'noopener,noreferrer',
); )
} }
} }
const currentTabsIndex = ref(0);
//
const currentTabsIndex = ref(0)
function handleTabChange(id) { function handleTabChange(id) {
for (let i = 0; i < versionByWorkInfo.value.length; i++) { for (let i = 0; i < versionByWorkInfo.value.length; i++) {
if (id === versionByWorkInfo.value[i].id) { if (id === versionByWorkInfo.value[i].id) {
currentTabsIndex.value = i; currentTabsIndex.value = i
} }
} }
} }
//
async function addCollect() { async function addCollect() {
try { try {
const params = { const params = {
"productId": versionByWorkInfo.value[currentTabsIndex.value].id, productId: versionByWorkInfo.value[currentTabsIndex.value].id,
"productType": detailsInfo.value.modelType, productType: detailsInfo.value.modelType,
collectType:0 collectType: 0,
} }
const res = await request.post("/collect/addCollect", params); const res = await request.post('/collect/addCollect', params)
if (res.code === 200) { if (res.code === 200) {
versionByWorkInfo.value[currentTabsIndex.value].isCollect = res.data versionByWorkInfo.value[currentTabsIndex.value].isCollect = res.data
if (res.data === 1) { if (res.data === 1) {
message.success("已加入模型库, 可通过在线生图使用"); message.success('已加入模型库, 可通过在线生图使用')
}else{ }
message.success("已从模型库中移除"); else {
message.success('已从模型库中移除')
} }
} }
} catch (err) { }
console.log(err); catch (err) {
console.log(err)
} }
} }
//
async function handelDown() { async function handelDown() {
try { try {
const res = await request.get(`/ModelVersion/modelFileDownload?id=${versionByWorkInfo.value[currentTabsIndex.value].id}`); const res = await request.get(
`/ModelVersion/modelFileDownload?id=${
versionByWorkInfo.value[currentTabsIndex.value].id
}`,
)
if (res.code === 200) { if (res.code === 200) {
const link = document.createElement('a'); const link = document.createElement('a')
link.href = res.data; link.href = res.data
link.download = res.msg; // link.download = res.msg //
document.body.appendChild(link); document.body.appendChild(link)
link.click(); link.click()
document.body.removeChild(link); document.body.removeChild(link)
}
}
catch (err) {
console.log(err)
}
}
//
async function onBuy() {
//
if (detailsInfo.value.userId === userStore?.userInfo?.userId) {
handelDown()
}
else if (detailsInfo.value.isBuy !== 1) { //
isBuy.value = true
}
else {
handelDown()
}
}
//
async function buyModel() {
if (detailsInfo.value.isBuy === 1) {
handelDown()
}
else {
try {
const params = {
productId: detailsInfo.value.id,
productUserId: detailsInfo.value.userId,
productType: 0,
}
const res = await request.post('/order/buy', params)
if (res.code === 200) {
handelDown()
detailsInfo.value.isBuy = 1
}
}
catch (err) {
console.log(err)
} }
} catch (err) {
console.log(err);
} }
} }
</script> </script>
@ -346,9 +413,9 @@ async function handelDown(){
<div class="w-full"> <div class="w-full">
<n-tabs <n-tabs
v-model:value="activeTab" v-model:value="activeTab"
@update:value="handleTabChange"
type="line" type="line"
animated animated
@update:value="handleTabChange"
> >
<n-tab-pane <n-tab-pane
v-for="(item, index) in versionByWorkInfo" v-for="(item, index) in versionByWorkInfo"
@ -364,7 +431,7 @@ async function handelDown(){
:src="subItem" :src="subItem"
class="w-full h-[350px] rounded-lg" class="w-full h-[350px] rounded-lg"
alt="" alt=""
/> >
</div> </div>
<div v-if="detailsInfo.original === 1" class="font-bold text-[20px] my-6"> <div v-if="detailsInfo.original === 1" class="font-bold text-[20px] my-6">
@ -451,11 +518,11 @@ async function handelDown(){
<div class="w-[60px] h-[60px] rounded-full overflow-hidden mr-4"> <div class="w-[60px] h-[60px] rounded-full overflow-hidden mr-4">
<client-only> <client-only>
<NAvatar <NAvatar
@click="toPersonalCenter"
class="w-full h-full mr-2 block cursor-pointer" class="w-full h-full mr-2 block cursor-pointer"
round round
size="small" size="small"
:src="currentUserInfo.avatar" :src="currentUserInfo.avatar"
@click="toPersonalCenter"
/> />
</client-only> </client-only>
</div> </div>
@ -476,8 +543,8 @@ async function handelDown(){
</div> </div>
</div> </div>
<div <div
class="flex-1 flex justify-end"
v-if="userStore?.userInfo?.userId !== detailsInfo.userId" v-if="userStore?.userInfo?.userId !== detailsInfo.userId"
class="flex-1 flex justify-end"
> >
<div <div
class="flex items-center font-bold px-1 justify-center w-20 h-8 rounded-full text-[#426af7] border border-[#426af7] border-solid cursor-pointer" class="flex items-center font-bold px-1 justify-center w-20 h-8 rounded-full text-[#426af7] border border-[#426af7] border-solid cursor-pointer"
@ -528,8 +595,8 @@ async function handelDown(){
<div class="flex gap-y-2"> <div class="flex gap-y-2">
<div <div
v-if="versionByWorkInfo.length > 0" v-if="versionByWorkInfo.length > 0"
@click="addCollect"
class="flex flex-1 items-center justify-center bg-[#eceef4] h-[50px] mt-4 mr-1 rounded-md cursor-pointer" class="flex flex-1 items-center justify-center bg-[#eceef4] h-[50px] mt-4 mr-1 rounded-md cursor-pointer"
@click="addCollect"
> >
<component <component
:is=" :is="
@ -540,19 +607,36 @@ async function handelDown(){
class="h-[20px] w-[20px] text-black menu-icon m-1 text-[#969798]" class="h-[20px] w-[20px] text-black menu-icon m-1 text-[#969798]"
/> />
<span class="mr-1"> <span class="mr-1">
{{ versionByWorkInfo[currentTabsIndex].isCollect === 0 ? '加入模型库' : '已加入'}} {{
versionByWorkInfo[currentTabsIndex].isCollect === 0
? "加入模型库"
: "已加入"
}}
</span> </span>
</div> </div>
<div <div
@click="handelDown" class="relative flex flex-1 items-center bg-gradient-to-r from-[#ffe9c8] to-[#ffd264] justify-center ml-1 mt-4 text-black bg-[#eceef4] w-full rounded-md h-[50px] cursor-pointer"
class="flex flex-1 items-center bg-gradient-to-r from-[#ffe9c8] to-[#ffd264] justify-center ml-1 mt-4 text-black bg-[#eceef4] w-full rounded-md h-[50px] cursor-pointer" @click="onBuy"
>
<div v-if="detailsInfo.isBuy === 0 && detailsInfo.isFree === 0" class="product-price">
{{ detailsInfo.productPrice }} 金币
</div>
<!-- {{ versionByWorkInfo[currentTabsIndex].isEncrypt }} -->
<img
v-if="versionByWorkInfo[currentTabsIndex]?.isEncrypt === 1"
class="w-10 h-10 absolute -top-1 right-0 -z-5"
src="@assets/img/encryption.png"
alt=""
> >
<component <component
:is="Download" :is="Download"
class="h-[20px] w-[20px] text-black menu-icon m-1 text-[#969798]" class="h-[20px] w-[20px] text-black menu-icon m-1 text-[#969798]"
/> />
<span class="mr-1" v-if="versionByWorkInfo.length > 0"> {{ formatFileSize(versionByWorkInfo[currentTabsIndex].fileSize) }} </span> <span v-if="versionByWorkInfo.length > 0" class="mr-1">
{{ detailsInfo.isBuy === 1 ? "下载" : "购买" }}
{{ formatFileSize(versionByWorkInfo[currentTabsIndex].fileSize) }}
</span>
</div> </div>
</div> </div>
@ -583,7 +667,9 @@ async function handelDown(){
> >
<div class="bg-white rounded-xl p-4"> <div class="bg-white rounded-xl p-4">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div class="text-xl">举报</div> <div class="text-xl">
举报
</div>
<div> <div>
<n-icon size="20" class="mr-2 cursor-pointer" @click="closeReport"> <n-icon size="20" class="mr-2 cursor-pointer" @click="closeReport">
<Close /> <Close />
@ -592,10 +678,10 @@ async function handelDown(){
</div> </div>
<div class="flex flex-col"> <div class="flex flex-col">
<n-radio <n-radio
class="m-4 text-[#fff000]"
size="large"
v-for="(item, index) in reportList" v-for="(item, index) in reportList"
:key="index" :key="index"
class="m-4 text-[#fff000]"
size="large"
:checked="reportParams.reportId === item.dictValue" :checked="reportParams.reportId === item.dictValue"
value="Definitely Maybe" value="Definitely Maybe"
name="basic-demo" name="basic-demo"
@ -616,11 +702,11 @@ async function handelDown(){
}" }"
/> />
<div <div
@click="onReport"
class="mt-4 w-[100%] h-10 flex rounded-lg text-white items-center justify-center cursor-pointer" class="mt-4 w-[100%] h-10 flex rounded-lg text-white items-center justify-center cursor-pointer"
:class="[ :class="[
reportParams.reportId !== undefined ? 'bg-[#4c79ee]' : 'bg-[#cccccc]', reportParams.reportId !== undefined ? 'bg-[#4c79ee]' : 'bg-[#cccccc]',
]" ]"
@click="onReport"
> >
确认 确认
</div> </div>
@ -632,6 +718,17 @@ async function handelDown(){
</div> </div>
</div> </div>
</div> </div>
<n-modal
v-model:show="isBuy"
:mask-closable="false"
preset="dialog"
title="提示!"
content="是否确认购买"
negative-text="取消"
positive-text="确认"
@negative-click="isBuy = false"
@positive-click="buyModel"
/>
<!-- <Report></Report> --> <!-- <Report></Report> -->
</div> </div>
</template> </template>
@ -668,8 +765,11 @@ async function handelDown(){
height: 4px; height: 4px;
background: linear-gradient(90deg, #173eff 0%, #1b7dff 100%); background: linear-gradient(90deg, #173eff 0%, #1b7dff 100%);
border-radius: 2px; border-radius: 2px;
transition: left 0.2s var(--n-bezier), max-width 0.2s var(--n-bezier), transition:
opacity 0.3s var(--n-bezier), background-color 0.3s var(--n-bezier); left 0.2s var(--n-bezier),
max-width 0.2s var(--n-bezier),
opacity 0.3s var(--n-bezier),
background-color 0.3s var(--n-bezier);
} }
.original { .original {
margin: 2px 0; margin: 2px 0;
@ -685,4 +785,26 @@ async function handelDown(){
border-radius: 4px; border-radius: 4px;
transform: skew(-10deg); transform: skew(-10deg);
} }
.product-price {
position: absolute;
top: -11px;
right: -1px;
flex-shrink: 0;
width: -moz-fit-content;
width: fit-content;
height: 24px;
padding: 0 8px;
color: #fff;
font-weight: 500;
font-size: 12px;
line-height: 24px;
text-align: center;
background: no-repeat 50% / 100% 100%;
background: linear-gradient(90deg, #ff7d1f, #ff2056 49.5%, #ff3773);
box-shadow: inset 0 -1px 0 0 rgba(234, 62, 26, 0.2);
border-top-left-radius: 8px;
border-bottom-right-radius: 8px;
border-top-right-radius: 2px;
border-bottom-left-radius: 2px;
}
</style> </style>

View File

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { nextTick, onMounted, ref } from 'vue'; import { nextTick, onMounted, ref } from 'vue'
definePageMeta({ definePageMeta({
layout: 'header', layout: 'header',
@ -15,7 +15,7 @@ interface PointsResult {
const pointsResult = ref<PointsResult>() const pointsResult = ref<PointsResult>()
async function getPoints() { async function getPoints() {
try { try {
const res = await request.get('/member/getPoints') const res = await request.get('/member/getValidMemberById')
if (res.code === 200) { if (res.code === 200) {
pointsResult.value = res.data as PointsResult pointsResult.value = res.data as PointsResult
nextTick(() => { nextTick(() => {
@ -34,13 +34,13 @@ const myMemberList = ref([
title: '基础版VIP会员', title: '基础版VIP会员',
type: '单月套餐', type: '单月套餐',
time: '2021-02-10至2024-19-23', time: '2021-02-10至2024-19-23',
payType:'支付宝' payType: '支付宝',
}, },
{ {
title: '基础版VIP会员', title: '基础版VIP会员',
type: '单月套餐', type: '单月套餐',
time: '2021-02-10至2024-19-23', time: '2021-02-10至2024-19-23',
payType:'支付宝' payType: '支付宝',
}, },
]) ])
@ -60,27 +60,29 @@ onMounted(() => {
<n-tabs v-model:value="activeTab" type="line" animated> <n-tabs v-model:value="activeTab" type="line" animated>
<n-tab-pane name="manage" tab="订单管理"> <n-tab-pane name="manage" tab="订单管理">
<div class="h-[500px] overflow-y-auto"> <div class="h-[500px] overflow-y-auto">
<div class="p-2 text-base">我的会员</div> <div class="p-2 text-base">
<div v-for="(item, index) in myMemberList" :key="index" class="p-2 bg-[#f9fbfc] rounded-lg text-gray-500 mb-2"> 我的会员
<div class="p-2 text-[#ff9e0b]">
{{ item.title }}
</div> </div>
<div class="flex justify-between p-2"> <div v-for="(item, index) in pointsResult" :key="index" class="p-2 bg-[#f9fbfc] rounded-lg text-gray-500 mb-2">
<div class="p-2 text-[#ff9e0b]">
{{ item.memberLevelName }}
</div>
<!-- <div class="flex justify-between p-2">
<div>订单类型</div> <div>订单类型</div>
<div>{{ item.type }}</div> <div>{{ item.type }}</div>
</div> </div> -->
<div class="flex justify-between p-2"> <div class="flex justify-between p-2">
<div>生效时间</div> <div>生效时间</div>
<div>{{item.time}}</div> <div>{{ item.startDate }} - {{ item.endDate }}</div>
</div> </div>
<div class="flex justify-between p-2"> <div class="flex justify-between p-2">
<div>支付方式</div> <div>支付方式</div>
<div>{{item.payType}}</div> <div>{{ item.paymentMethod }}</div>
</div> </div>
</div> </div>
</div> </div>
</n-tab-pane> </n-tab-pane>
<n-tab-pane name="record" tab="购买记录"> <!-- <n-tab-pane name="record" tab="购买记录">
<div class="h-[500px] overflow-y-auto"> <div class="h-[500px] overflow-y-auto">
<div class="mc-table flex w-full"> <div class="mc-table flex w-full">
<div class="w-[200px]"> <div class="w-[200px]">
@ -123,7 +125,7 @@ onMounted(() => {
</div> </div>
</div> </div>
</div> </div>
</n-tab-pane> </n-tab-pane> -->
</n-tabs> </n-tabs>
</div> </div>
</div> </div>

View File

@ -1,440 +1,460 @@
<script setup lang="ts"> <script setup lang="ts">
import { Close } from "@vicons/ionicons5"; import { commonApi } from '@/api/common'
const message = useMessage();
import EditUserInfo from '@/components/EditUserInfo.vue'
import { useUserStore } from '@/stores/user'
import { formatDate } from '@/utils/index.ts'
import { Close } from '@vicons/ionicons5'
import { NConfigProvider, NMessageProvider } from 'naive-ui'
import { nextTick, onMounted, onUnmounted, ref } from 'vue'
import { useRouter } from 'vue-router'
const message = useMessage()
import { commonApi } from "@/api/common";
import EditUserInfo from "@/components/EditUserInfo.vue";
import { useUserStore } from "@/stores/user";
import { formatDate } from "@/utils/index.ts";
import { NConfigProvider, NMessageProvider } from "naive-ui";
import { nextTick, onMounted, onUnmounted, ref } from "vue";
let pollingTimer: ReturnType<typeof setInterval> | undefined let pollingTimer: ReturnType<typeof setInterval> | undefined
const route = useRoute(); const route = useRoute()
const { type, status } = route.query as { type: string; status: string }; const { type, status } = route.query as { type: string, status: string }
const loading = ref(false); const loading = ref(false)
const finished = ref(false); const finished = ref(false)
const total = ref(0); // const total = ref(0) //
const loadingTrigger = ref(null); const loadingTrigger = ref(null)
import { useRouter } from "vue-router"; const router = useRouter()
const router = useRouter();
const observer = ref<IntersectionObserver | null>(null); const observer = ref<IntersectionObserver | null>(null)
definePageMeta({ definePageMeta({
layout: "default", layout: 'default',
}); })
interface UserInfo { interface UserInfo {
nickName?: string; // 使 ? nickName nickName?: string // 使 ? nickName
avatar?: string; avatar?: string
name?: string; name?: string
brief?: string; brief?: string
} }
const userStore = useUserStore(); const userStore = useUserStore()
const userInfo: UserInfo = userStore.userInfo; const userInfo: UserInfo = userStore.userInfo
// //
const currentState = ref("mallProduct"); const currentState = ref('mallProduct')
// //
const currentType = ref("0"); const currentType = ref('0')
const orderOptions = ref([ const orderOptions = ref([
{ {
dictLabel: "最新", dictLabel: '最新',
dictValue: "create_time", dictValue: 'create_time',
}, },
{ {
dictLabel: "最热", dictLabel: '最热',
dictValue: "like_num", dictValue: 'like_num',
}, },
]); ])
const stateList = ref([ const stateList = ref([
{ id: "mallProduct", title: "发布" }, { id: 'mallProduct', title: '发布' },
{ id: "like", title: "点赞" }, { id: 'like', title: '点赞' },
]); ])
const typeList = ref([ const typeList = ref([
{ id: "0", title: "模型" }, { id: '0', title: '模型' },
{ id: "1", title: "工作流" }, { id: '1', title: '工作流' },
{ id: "2", title: "图片" }, { id: '2', title: '图片' },
]); ])
// form // form
const publishParams = ref({ const publishParams = ref({
pageNum: 1, pageNum: 1,
pageSize: 20, pageSize: 20,
status: "0", status: '0',
orderByColumn: "create_time", orderByColumn: 'create_time',
date: null, date: null,
endTime: "", endTime: '',
startTime: "", startTime: '',
}); })
function initPublishParams() { function initPublishParams() {
publishParams.value = { publishParams.value = {
pageNum: 1, pageNum: 1,
pageSize: 20, pageSize: 20,
status: "0", status: '0',
orderByColumn: "create_time", orderByColumn: 'create_time',
date: null, date: null,
endTime: "", endTime: '',
startTime: "", startTime: '',
}; }
} }
// form // form
const likesParams = ref({ const likesParams = ref({
pageNum: 1, pageNum: 1,
pageSize: 20, pageSize: 20,
orderByColumn: "create_time", orderByColumn: 'create_time',
}); })
function initLikesParams() { function initLikesParams() {
likesParams.value = { likesParams.value = {
pageNum: 1, pageNum: 1,
pageSize: 20, pageSize: 20,
orderByColumn: "create_time", orderByColumn: 'create_time',
}; }
} }
const urlList = ref({ const urlList = ref({
mallProduct: { mallProduct: {
0: "/personalCenter/selectByUserIdModel", 0: '/personalCenter/selectByUserIdModel',
1: "/personalCenter/selectByUserIdWorkFlow", 1: '/personalCenter/selectByUserIdWorkFlow',
2: "/personalCenter/selectByUserIdImage", 2: '/personalCenter/selectByUserIdImage',
}, },
like: { like: {
0: "/personalCenter/likeModel", 0: '/personalCenter/likeModel',
1: "/personalCenter/likeWorkFlow", 1: '/personalCenter/likeWorkFlow',
2: "/personalCenter/likeImage", 2: '/personalCenter/likeImage',
}, },
}); })
const showInvitationModal = ref(false); const showInvitationModal = ref(false)
// //
const statusOptions = ref([]); const statusOptions = ref([])
async function getDictType() { async function getDictType() {
try { try {
const res = await commonApi.dictType({ const res = await commonApi.dictType({
type: "mall_product_status", type: 'mall_product_status',
}); })
if (res.code === 200 && res.data.length > 0) { if (res.code === 200 && res.data.length > 0) {
statusOptions.value = res.data; statusOptions.value = res.data
publishParams.value.status = res.data[0].dictValue; publishParams.value.status = res.data[0].dictValue
}
} catch (error) {
console.log(error);
} }
} }
getDictType(); catch (error) {
console.log(error)
}
}
getDictType()
// //
interface EditUserInfoType { interface EditUserInfoType {
isVisible: boolean; isVisible: boolean
} }
const editUserInfoRef = ref<EditUserInfoType | null>(null); const editUserInfoRef = ref<EditUserInfoType | null>(null)
function onEditInfo() { function onEditInfo() {
if (editUserInfoRef.value) { if (editUserInfoRef.value) {
editUserInfoRef.value.isVisible = true; editUserInfoRef.value.isVisible = true
} }
} }
// //
interface AuthComponentType { interface AuthComponentType {
isVisible: boolean; isVisible: boolean
} }
const authenticationRef = ref<AuthComponentType | null>(null); const authenticationRef = ref<AuthComponentType | null>(null)
function onAuth() { function onAuth() {
if (authenticationRef.value) { if (authenticationRef.value) {
authenticationRef.value.isVisible = true; authenticationRef.value.isVisible = true
} }
} }
function initChangeParams() { function initChangeParams() {
if (currentState.value === "mallProduct") { if (currentState.value === 'mallProduct') {
initPublishParams(); initPublishParams()
} else {
initLikesParams();
} }
finished.value = false; // else {
getList(); initLikesParams()
}
finished.value = false //
getList()
} }
// / // /
function changeTabs(id: string) { function changeTabs(id: string) {
currentState.value = id; currentState.value = id
currentType.value = "0"; currentType.value = '0'
initChangeParams(); initChangeParams()
} }
// // // //
function changeType(id: string) { function changeType(id: string) {
if (id === "2") { if (id === '2') {
statusOptions.value.forEach((item) => { statusOptions.value.forEach((item) => {
if (item.dictValue === "2") { if (item.dictValue === '2') {
item.disabled = true; item.disabled = true
} }
}); })
} else { }
else {
statusOptions.value.forEach((item) => { statusOptions.value.forEach((item) => {
if (item.dictValue === "2") { if (item.dictValue === '2') {
item.disabled = false; item.disabled = false
} }
}); })
} }
currentType.value = id; currentType.value = id
initChangeParams(); initChangeParams()
} }
function initPageNUm() { function initPageNUm() {
if (currentState.value === "mallProduct") { if (currentState.value === 'mallProduct') {
publishParams.value.pageNum = 1; publishParams.value.pageNum = 1
} else {
likesParams.value.pageNum = 1;
} }
finished.value = false; // else {
getList(); likesParams.value.pageNum = 1
}
finished.value = false //
getList()
} }
// select// // select//
function changeStatus(value: string) { function changeStatus(value: string) {
publishParams.value.status = value; publishParams.value.status = value
initPageNUm(); initPageNUm()
} }
// / // /
function changeOrder(value: string) { function changeOrder(value: string) {
publishParams.value.orderByColumn = value; publishParams.value.orderByColumn = value
initPageNUm(); initPageNUm()
} }
// / // /
function changeLikeOrder(value: string) { function changeLikeOrder(value: string) {
likesParams.value.orderByColumn = value; likesParams.value.orderByColumn = value
initPageNUm(); initPageNUm()
} }
// //
async function changeDate(value: string[]) { async function changeDate(value: string[]) {
publishParams.value.startTime = `${await formatDate(value[0] as string)} 00:00:00`; publishParams.value.startTime = `${await formatDate(value[0] as string)} 00:00:00`
publishParams.value.endTime = `${await formatDate(value[1] as string)} 23:59:59`; publishParams.value.endTime = `${await formatDate(value[1] as string)} 23:59:59`
initPageNUm(); initPageNUm()
} }
// // // //
interface SelectUserInfo { interface SelectUserInfo {
likeCount: number; likeCount: number
bean: number; bean: number
download: number; download: number
attention: number; attention: number
} }
const selectUserInfo = ref<SelectUserInfo>({ const selectUserInfo = ref<SelectUserInfo>({
likeCount: 0, likeCount: 0,
bean: 0, bean: 0,
download: 0, download: 0,
attention: 0, attention: 0,
}); })
async function getAttention() { async function getAttention() {
try { try {
const res = await request.get("/attention/selectUserInfo"); const res = await request.get('/attention/selectUserInfo')
if (res.code === 200) { if (res.code === 200) {
selectUserInfo.value = res.data; selectUserInfo.value = res.data
}
} catch (err) {
console.log(err);
} }
} }
getAttention(); catch (err) {
console.log(err)
}
}
getAttention()
// Banner // Banner
const bannerStyle = { const bannerStyle = {
backgroundImage: backgroundImage:
"url('https://img.zcool.cn/community/special_cover/3a9a64d3628c000c2a1000657eec.jpg')", 'url(\'https://img.zcool.cn/community/special_cover/3a9a64d3628c000c2a1000657eec.jpg\')',
}; }
// //
interface ApiResponse<T> { interface ApiResponse<T> {
code: number; code: number
rows: T[]; rows: T[]
message: string; message: string
} }
// //
interface UserData { interface UserData {
id: number; id: number
name: string; name: string
email: string; email: string
status: number; status: number
} }
// //
const dataList = ref([]); const dataList = ref([])
async function getList() { async function getList() {
if (loading.value || finished.value) return; if (loading.value || finished.value)
return
loading.value = true; loading.value = true
let params = {}; let params = {}
if (currentState.value === "mallProduct") { if (currentState.value === 'mallProduct') {
params = publishParams.value; params = publishParams.value
} else {
params = likesParams.value;
} }
const url = urlList.value[currentState.value][currentType.value]; else {
params = likesParams.value
}
const url = urlList.value[currentState.value][currentType.value]
try { try {
const res = await request.post<ApiResponse<UserData>>(url, params); const res = await request.post<ApiResponse<UserData>>(url, params)
if (res.code === 200) { if (res.code === 200) {
// //
if (params.pageNum === 1) { if (params.pageNum === 1) {
dataList.value = res.rows; dataList.value = res.rows
} else { }
dataList.value = [...dataList.value, ...res.rows]; else {
dataList.value = [...dataList.value, ...res.rows]
} }
total.value = res.total; // total.value = res.total //
// //
if (dataList.value.length >= total.value) { if (dataList.value.length >= total.value) {
finished.value = true; finished.value = true
} }
// //
if (currentState.value === "mallProduct") { if (currentState.value === 'mallProduct') {
publishParams.value.pageNum++; publishParams.value.pageNum++
} else { }
likesParams.value.pageNum++; else {
likesParams.value.pageNum++
} }
} }
} catch (err) { }
dataList.value = []; catch (err) {
finished.value = true; dataList.value = []
console.log(err); finished.value = true
} finally { console.log(err)
loading.value = false; }
finally {
loading.value = false
} }
} }
onMounted(() => { onMounted(() => {
window.addEventListener("scroll", topedRefresh); window.addEventListener('scroll', topedRefresh)
observer.value = new IntersectionObserver( observer.value = new IntersectionObserver(
([entry]) => { ([entry]) => {
if (entry.isIntersecting && !loading.value && !finished.value) { if (entry.isIntersecting && !loading.value && !finished.value) {
getList(); getList()
} }
}, },
{ {
threshold: 0.1, threshold: 0.1,
} },
); )
if (loadingTrigger.value) { if (loadingTrigger.value) {
observer.value.observe(loadingTrigger.value); observer.value.observe(loadingTrigger.value)
} }
if (type && type === "like") { if (type && type === 'like') {
currentState.value = type; currentState.value = type
} }
if (status === "0" || status === "1" || status === "2") { if (status === '0' || status === '1' || status === '2') {
currentType.value = status; currentType.value = status
} }
getList(); getList()
}); })
onUnmounted(() => { onUnmounted(() => {
window.removeEventListener("scroll", topedRefresh); window.removeEventListener('scroll', topedRefresh)
if (observer.value) { if (observer.value) {
observer.value.disconnect(); observer.value.disconnect()
} }
}); })
async function topedRefresh() { async function topedRefresh() {
if (import.meta.client) { if (import.meta.client) {
await nextTick(); await nextTick()
window.scrollTo({ window.scrollTo({
top: 0, top: 0,
behavior: "smooth", behavior: 'smooth',
}); })
} }
initPageNUm(); initPageNUm()
} }
function onClearDate() { function onClearDate() {
(publishParams.value.startTime = ""), (publishParams.value.endTime = ""), initPageNUm(); (publishParams.value.startTime = ''), (publishParams.value.endTime = ''), initPageNUm()
} }
// //
const isShowFan = ref(false); const isShowFan = ref(false)
const attentionFinished = ref(false); const attentionFinished = ref(false)
const attentionList = ref([]); const attentionList = ref([])
const attentionListParams = ref({ const attentionListParams = ref({
pageNumber: 1, pageNumber: 1,
pageSize: 20, pageSize: 20,
}); })
async function getAttentionList() { async function getAttentionList() {
try { try {
if (attentionFinished.value) return; if (attentionFinished.value)
return
const res = await request.post(`/attention/selectToAttention`, { const res = await request.post(`/attention/selectToAttention`, {
...attentionListParams.value, ...attentionListParams.value,
}); })
if (res.code === 200) { if (res.code === 200) {
if (attentionListParams.value.pageNumber === 1) { if (attentionListParams.value.pageNumber === 1) {
attentionList.value = res.data.list; attentionList.value = res.data.list
} else { }
attentionList.value = [...attentionList.value, ...res.data.list]; else {
attentionList.value = [...attentionList.value, ...res.data.list]
} }
total.value = res.data.total; // total.value = res.data.total //
// //
if (attentionList.value.length >= total.value) { if (attentionList.value.length >= total.value) {
attentionFinished.value = true; attentionFinished.value = true
} }
attentionListParams.value.pageNumber++; attentionListParams.value.pageNumber++
}
} catch (err) {
attentionList.value = [];
attentionFinished.value = true;
console.log(err);
} }
} }
getAttentionList(); catch (err) {
attentionList.value = []
attentionFinished.value = true
console.log(err)
}
}
getAttentionList()
// //
const likeFinished = ref(false); const likeFinished = ref(false)
const likeList = ref([]); const likeList = ref([])
const likeListParams = ref({ const likeListParams = ref({
pageNumber: 1, pageNumber: 1,
pageSize: 20, pageSize: 20,
type:null type: null,
}); })
async function getLikeList() { async function getLikeList() {
try { try {
if (likeFinished.value) return; if (likeFinished.value)
return
const res = await request.post(`/attention/selectAttentionList`, { const res = await request.post(`/attention/selectAttentionList`, {
...likeListParams.value, ...likeListParams.value,
}); })
if (res.code === 200) { if (res.code === 200) {
if (likeListParams.value.pageNumber === 1) { if (likeListParams.value.pageNumber === 1) {
likeList.value = res.data.list; likeList.value = res.data.list
} else { }
likeList.value = [...likeList.value, ...res.data.list]; else {
likeList.value = [...likeList.value, ...res.data.list]
} }
total.value = res.data.total; // total.value = res.data.total //
// //
if (likeList.value.length >= total.value) { if (likeList.value.length >= total.value) {
likeFinished.value = true; likeFinished.value = true
} }
likeListParams.value.pageNumber++; likeListParams.value.pageNumber++
}
} catch (err) {
likeList.value = [];
likeFinished.value = true;
console.log(err);
} }
} }
getLikeList(); catch (err) {
likeList.value = []
likeFinished.value = true
console.log(err)
}
}
getLikeList()
function closefanList() { function closefanList() {
isShowFan.value = false; isShowFan.value = false
} }
// / // /
@ -444,32 +464,35 @@ async function onAttention(item: any) {
if (userId === item.userId) { if (userId === item.userId) {
return message.warning('自己不能关注自己') return message.warning('自己不能关注自己')
} }
const res = await request.get(`/attention/addAttention?userId=${item.userId}`); const res = await request.get(`/attention/addAttention?userId=${item.userId}`)
if (res.code === 200) { if (res.code === 200) {
if (res.data) { if (res.data) {
message.success("关注成功"); message.success('关注成功')
} else {
message.success("取消关注成功");
} }
item.attention = !item.attention; else {
message.success('取消关注成功')
} }
} catch (err) { item.attention = !item.attention
console.log(err); }
}
catch (err) {
console.log(err)
} }
} }
// //
const invitationCode = ref(""); const invitationCode = ref('')
async function getInvitation() { async function getInvitation() {
try { try {
const res = await request.get(`/invitation/getInvitationCode`); const res = await request.get(`/invitation/getInvitationCode`)
if (res.code === 200) { if (res.code === 200) {
invitationCode.value = res.msg; invitationCode.value = res.msg
}
} catch (err) {
console.log(err);
} }
} }
getInvitation(); catch (err) {
console.log(err)
}
}
getInvitation()
// //
// async function getInvitationList() { // async function getInvitationList() {
@ -478,57 +501,58 @@ getInvitation();
// //
function copyToClipboard(text: string) { function copyToClipboard(text: string) {
const textarea = document.createElement("textarea"); const textarea = document.createElement('textarea')
textarea.value = text; textarea.value = text
document.body.appendChild(textarea); document.body.appendChild(textarea)
textarea.select(); textarea.select()
const success = document.execCommand("copy"); const success = document.execCommand('copy')
document.body.removeChild(textarea); document.body.removeChild(textarea)
if (success) { if (success) {
message.success("复制成功!"); message.success('复制成功!')
} else { }
message.success("复制成功!"); else {
message.success('复制成功!')
} }
} }
// //
function handlePositiveClick() { function handlePositiveClick() {
copyToClipboard(invitationCode.value); copyToClipboard(invitationCode.value)
} }
const activeTab = ref('like') const activeTab = ref('like')
// //
const invitationList = ref({}); const invitationList = ref({})
async function handleNegativeClick() { async function handleNegativeClick() {
try { try {
const res = await request.get(`/invitation/earningsDisplay`); const res = await request.get(`/invitation/earningsDisplay`)
if (res.code === 200) { if (res.code === 200) {
invitationList.value = res.data invitationList.value = res.data
showInvitationModal.value = true; showInvitationModal.value = true
}
} catch (err) {
console.log(err);
} }
} }
const showLike = (type:string) =>{ catch (err) {
console.log(err)
}
}
function showLike(type: string) {
isShowFan.value = true isShowFan.value = true
activeTab.value = type activeTab.value = type
} }
const toWallet = () => { function toWallet() {
router.push({ router.push({
path: `/wallet`, path: `/wallet`,
}); })
} }
// //
const zfbStatus = ref('0') const zfbStatus = ref('0')
async function getBindStatus() { async function getBindStatus() {
const res = await request.get(`/ali/pay/queryBindStatus`) const res = await request.get(`/ali/pay/queryBindStatus`)
if (res.data === '1') { //'1 0 if (res.code === 200) { // '1 0
zfbStatus.value = res.data zfbStatus.value = res.data
message.success('绑定成功!')
} }
} }
getBindStatus() getBindStatus()
@ -536,11 +560,11 @@ getBindStatus()
// //
const qrUrl = ref('') const qrUrl = ref('')
const isShowBindingModal = ref(false) const isShowBindingModal = ref(false)
const showBinding = async() =>{ async function showBinding() {
try { try {
const res = await request.get(`/ali/pay/generateQrCode`); const res = await request.get(`/ali/pay/generateQrCode`)
if (res.code === 200) { if (res.code === 200) {
qrUrl.value = res.data; qrUrl.value = res.data
isShowBindingModal.value = true isShowBindingModal.value = true
pollingTimer && clearTimeout(pollingTimer) pollingTimer && clearTimeout(pollingTimer)
@ -550,6 +574,8 @@ const showBinding = async() =>{
if (res2.data === '1') { if (res2.data === '1') {
closeBindingModal() closeBindingModal()
message.success('绑定成功!') message.success('绑定成功!')
// window.location.reload()
getBindStatus()
} }
} }
catch (err) { catch (err) {
@ -558,16 +584,16 @@ const showBinding = async() =>{
} }
}, 2000) }, 2000)
} }
} catch (err) { }
console.log(err); catch (err) {
console.log(err)
} }
} }
const closeBindingModal = () =>{ function closeBindingModal() {
pollingTimer && clearTimeout(pollingTimer) pollingTimer && clearTimeout(pollingTimer)
isShowBindingModal.value = false isShowBindingModal.value = false
} }
</script> </script>
<template> <template>
@ -587,7 +613,7 @@ const closeBindingModal = () =>{
class="head-img m-1 h-16 w-16 rounded-full bg-white" class="head-img m-1 h-16 w-16 rounded-full bg-white"
:src="userStore?.userInfo?.avatar" :src="userStore?.userInfo?.avatar"
alt="User Avatar" alt="User Avatar"
/> >
</client-only> </client-only>
<!-- {{ userStore.userInfo.avatar }} --> <!-- {{ userStore.userInfo.avatar }} -->
</div> </div>
@ -602,7 +628,7 @@ const closeBindingModal = () =>{
</div> </div>
<!-- Real Name Verification --> <!-- Real Name Verification -->
<div <div
v-if="userInfo.name" v-if="userStore?.userInfo.name"
class="edit-info rounded-full bg-white px-5 py-2 shadow-md" class="edit-info rounded-full bg-white px-5 py-2 shadow-md"
> >
已经实名 已经实名
@ -624,7 +650,9 @@ const closeBindingModal = () =>{
@negative-click="handleNegativeClick" @negative-click="handleNegativeClick"
> >
<template #trigger> <template #trigger>
<n-button class="ml-2 rounded-lg" type="info" round>获取邀请码</n-button> <n-button class="ml-2 rounded-lg" type="info" round>
获取邀请码
</n-button>
</template> </template>
邀请码: {{ invitationCode }} 邀请码: {{ invitationCode }}
</n-popconfirm> </n-popconfirm>
@ -632,10 +660,10 @@ const closeBindingModal = () =>{
<div class="ml-4 cursor-pointer" @click="toWallet()"> <div class="ml-4 cursor-pointer" @click="toWallet()">
<img src="@/assets/img/wallet.png" alt=""> <img src="@/assets/img/wallet.png" alt="">
</div> </div>
<div v-if="zfbStatus === '1'" class="bg-[#3875f6] rounded-full px-4 py-2"> <div v-if="zfbStatus === '1'" class="bg-[#3875f6] rounded-full px-4 py-2 ml-4 text-white">
已绑定支付宝 已绑定支付宝
</div> </div>
<div v-else @click="showBinding" class="text-xs px-3 py-2 border border-solid border-[#ccc] rounded-full ml-4 bg-white cursor-pointer"> <div v-else class="text-xs px-3 py-2 border border-solid border-[#ccc] rounded-full ml-4 bg-white cursor-pointer" @click="showBinding">
绑定支付宝 绑定支付宝
</div> </div>
</div> </div>
@ -788,10 +816,14 @@ const closeBindingModal = () =>{
/> />
</div> </div>
<div ref="loadingTrigger" class="h-10"> <div ref="loadingTrigger" class="h-10">
<div v-if="loading" class="text-center text-gray-500">...</div> <div v-if="loading" class="text-center text-gray-500">
<div v-if="finished" class="text-center text-gray-500"></div> 加载中...
</div> </div>
<div class="fan-centent" v-if="isShowFan"> <div v-if="finished" class="text-center text-gray-500">
没有更多数据了
</div>
</div>
<div v-if="isShowFan" class="fan-centent">
<div <div
class="w-[550px] h-[calc(100vh-100px)] max-h-[700px] m-auto py-0 px-8 pb-[43px] bg-[#fff] rounded-lg relative" class="w-[550px] h-[calc(100vh-100px)] max-h-[700px] m-auto py-0 px-8 pb-[43px] bg-[#fff] rounded-lg relative"
> >
@ -825,7 +857,7 @@ const closeBindingModal = () =>{
:src="item.avatar || ''" :src="item.avatar || ''"
alt="" alt=""
class="w-14 h-14 rounded-full mr-2" class="w-14 h-14 rounded-full mr-2"
/> >
{{ item.nickName }} {{ item.nickName }}
</div> </div>
<div <div
@ -861,7 +893,7 @@ const closeBindingModal = () =>{
:src="item.avatar || ''" :src="item.avatar || ''"
alt="" alt=""
class="w-14 h-14 rounded-full mr-2" class="w-14 h-14 rounded-full mr-2"
/> >
{{ item.nickName }} {{ item.nickName }}
</div> </div>
<div <div
@ -895,28 +927,40 @@ const closeBindingModal = () =>{
</template> --> </template> -->
<div class="py-4 flex justify-between"> <div class="py-4 flex justify-between">
<div class="text-xl font-bold">邀请列表</div> <div class="text-xl font-bold">
邀请列表
</div>
<div class="text-sm text-gray-600"> <div class="text-sm text-gray-600">
总收益: {{ invitationList.totalAmount }} 总收益: {{ invitationList.totalAmount }}
</div> </div>
</div> </div>
<div class="rounded-lg"> <div class="rounded-lg">
<div class="flex w-[100%]"> <div class="flex w-[100%]">
<div class="w-[180px] flex items-center py-2">头像</div> <div class="w-[180px] flex items-center py-2">
<div class="w-[180px] flex items-center py-2">邀请人购买数量</div> 头像
<div class="w-[180px] flex items-center py-2">邀请人名字</div> </div>
<div class="w-[180px] flex items-center py-2">
邀请人购买数量
</div>
<div class="w-[180px] flex items-center py-2">
邀请人名字
</div>
</div> </div>
<div class="max-h-[500px] overflow-y-auto"> <div class="max-h-[500px] overflow-y-auto">
<div <div
class="flex w-[100%] hover:bg-[#f3f3f3] px-2"
v-for="(item, index) in invitationList.earningsDisplayList" v-for="(item, index) in invitationList.earningsDisplayList"
:key="index" :key="index"
class="flex w-[100%] hover:bg-[#f3f3f3] px-2"
> >
<div class="w-[180px] flex items-center py-2"> <div class="w-[180px] flex items-center py-2">
<img class="w-10 h-10 rounded-full" :src="item.user.avatar" alt="" /> <img class="w-10 h-10 rounded-full" :src="item.user.avatar" alt="">
</div>
<div class="w-[180px] flex items-center py-2">
{{ item.count }}
</div>
<div class="w-[180px] flex items-center py-2">
{{ item.user.userName }}
</div> </div>
<div class="w-[180px] flex items-center py-2">{{ item.count }}</div>
<div class="w-[180px] flex items-center py-2">{{ item.user.userName }}</div>
</div> </div>
</div> </div>
</div> </div>
@ -924,7 +968,7 @@ const closeBindingModal = () =>{
</n-modal> </n-modal>
<div v-if="isShowBindingModal" class="fan-centent"> <div v-if="isShowBindingModal" class="fan-centent">
<div class="relative flex flex-col items-center"> <div class="relative flex flex-col items-center">
<div class="bg-[#000] py-10 px-20 flex flex-col items-center justify-center rounded-lg"> <div class="bg-[#000] bg-opacity-80 py-10 px-20 flex flex-col items-center justify-center rounded-lg">
<div class="text-xl text-white mb-4"> <div class="text-xl text-white mb-4">
扫码绑定 扫码绑定
</div> </div>

View File

@ -2,6 +2,7 @@
import CreateModels from "@/components/publishModel/CreateModels.vue"; import CreateModels from "@/components/publishModel/CreateModels.vue";
import EditVersion from "@/components/publishModel/EditVersion.vue"; import EditVersion from "@/components/publishModel/EditVersion.vue";
import UploadImg from "@/components/publishModel/UploadImg.vue"; import UploadImg from "@/components/publishModel/UploadImg.vue";
import { CirclePlus } from "lucide-vue-next";
import { NConfigProvider, NMessageProvider } from "naive-ui"; import { NConfigProvider, NMessageProvider } from "naive-ui";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
const message = useMessage(); const message = useMessage();
@ -29,6 +30,8 @@ async function initFormData() {
activityId: null, // string activityId: null, // string
isOriginal: 1, // isOriginal: 1, //
originalAuthorName: "", originalAuthorName: "",
isFree: 1, //0
productPrice:0, //
}, },
modelVersionList: [ modelVersionList: [
@ -46,7 +49,6 @@ async function initFormData() {
sampleImagePaths: [], // 20, sampleImagePaths: [], // 20,
triggerWords: "", // triggerWords: "", //
isPublic: 1, // 1 0 isPublic: 1, // 1 0
isFree: 0, //
isOnlineUse: 1, // 线使 isOnlineUse: 1, // 线使
allowDownloadImage: 1, // allowDownloadImage: 1, //

View File

@ -1,11 +1,118 @@
<script setup>
import { isAmount } from '@/utils/index.ts'
import { Close } from '@vicons/ionicons5'
import { ref } from 'vue'
const activeTab = ref('withdrawDetail')
const showWalletModal = ref(false)
function showModal() {
showWalletModal.value = true
}
const message = useMessage()
function closeWalletModal() {
showWalletModal.value = false
needWalletNum.value = 0
}
// const allDetailList = ref([]);
//
const integralGold = ref({})
async function getIntegralGold() {
try {
const res = await request.post('/personalCenter/getPointAndWallet')
if (res.code === 200) {
integralGold.value = res.data
}
}
catch (err) {
console.log(err)
}
}
getIntegralGold()
//
const needWalletNum = ref(0)
async function handleWallet() {
if (isAmount(needWalletNum.value)) {
if (needWalletNum.value > integralGold.value.wallet)
return message.warning('可提现金额不足')
try {
const res = await request.get(`/ali/pay/fetch?amount=${needWalletNum.value}`)
if (res.code === 200) {
message.success('提现成功!')
closeWalletModal()
location.reload()
// getIntegralGold()
}
}
catch (err) {
console.log(err)
}
}
else {
message.warning('请输入正确的金额')
}
}
//
const totalAmount = ref(0)
async function getTotalAmount() {
try {
const res = await request.get('/invitation/totalAmount')
if (res.code === 200) {
totalAmount.value = res.data
}
}
catch (err) {
console.log(err)
}
}
getTotalAmount()
//
const withdrawFinished = ref(false)
const withdrawDetailList = ref([])
const withdrawParams = ref({
pageNum: 1,
pageSize: 10,
})
async function getWithdrawDetail() {
try {
if (withdrawFinished.value)
return
const res = await request.post('/invitation/withdrawalRecord', withdrawParams.value)
if (res.code === 200) {
if (withdrawParams.value.pageNum === 1) {
withdrawDetailList.value = res.rows
}
else {
withdrawDetailList.value = [...withdrawDetailList.value, ...res.rows]
}
//
if (withdrawDetailList.value.length >= res.total) {
withdrawFinished.value = true
}
withdrawParams.value.pageNum++
}
}
catch (err) {
console.log(err)
}
}
getWithdrawDetail()
</script>
<template> <template>
<div> <div>
<div class="p-4 flex text-white gap-3"> <div class="p-4 flex text-white gap-3">
<div <div
class="w-60 h-28 bg-[#a494f7] px-8 py-6 rounded-lg flex flex-col justify-around" class="w-60 h-28 bg-[#a494f7] px-8 py-6 rounded-lg flex flex-col justify-around"
> >
<div class="text-xl">累计收入金额</div> <div class="text-xl">
<div class="text-base">¥ {{ totalAmount || 0 }}</div> 累计收入金额
</div>
<div class="text-base">
¥ {{ totalAmount || 0 }}
</div>
</div> </div>
<div <div
class="w-60 h-28 bg-[#e87988] px-8 py-6 rounded-lg flex flex-col justify-around" class="w-60 h-28 bg-[#e87988] px-8 py-6 rounded-lg flex flex-col justify-around"
@ -19,7 +126,9 @@
提现 > 提现 >
</div> </div>
</div> </div>
<div class="text-base">¥ {{ integralGold.wallet || 0 }}</div> <div class="text-base">
¥ {{ integralGold.wallet || 0 }}
</div>
</div> </div>
</div> </div>
<div class="p-4 text-[#06186d]"> <div class="p-4 text-[#06186d]">
@ -55,10 +164,18 @@
<n-tab-pane name="withdrawDetail" tab="提现明细"> <n-tab-pane name="withdrawDetail" tab="提现明细">
<div class="border border-solid border-gray-200 rounded-lg relative"> <div class="border border-solid border-gray-200 rounded-lg relative">
<div class="mc-table flex w-full bg-[#e5ecf4] sticky top-0"> <div class="mc-table flex w-full bg-[#e5ecf4] sticky top-0">
<div class="w-[250px]">提现时间</div> <div class="w-[250px]">
<div class="w-[250px]">账户类型</div> 提现时间
<div class="flex-1">详情</div> </div>
<div class="w-[200px]">提现金额</div> <div class="w-[250px]">
账户类型
</div>
<div class="flex-1">
详情
</div>
<div class="w-[200px]">
提现金额
</div>
</div> </div>
<n-infinite-scroll <n-infinite-scroll
style="height: calc(100vh - 300px)" style="height: calc(100vh - 300px)"
@ -73,8 +190,12 @@
<div class="w-[250px]"> <div class="w-[250px]">
{{ item.createTime }} {{ item.createTime }}
</div> </div>
<div class="w-[250px]">{{ item.account }}</div> <div class="w-[250px]">
<div class="flex-1">-</div> {{ item.account }}
</div>
<div class="flex-1">
-
</div>
<div class="w-[200px]"> <div class="w-[200px]">
{{ item.amount }} {{ item.amount }}
</div> </div>
@ -108,115 +229,26 @@
</div> </div>
<div class="mt-6"> <div class="mt-6">
<n-input-number <n-input-number
placeholder="输入要提现的金额"
v-model:value="needWalletNum" v-model:value="needWalletNum"
placeholder="输入要提现的金额"
:precision="2" :precision="2"
clearable clearable
/> />
</div> </div>
</div> </div>
<div class="flex justify-center mt-6"> <div class="flex justify-center mt-6">
<n-button type="error" @click="closeWalletModal"> </n-button> <n-button type="error" @click="closeWalletModal">
<n-button type="primary" class="ml-8" @click="handleWallet"> </n-button> 取消
</n-button>
<n-button type="primary" class="ml-8" @click="handleWallet">
确定
</n-button>
</div> </div>
</n-card> </n-card>
</n-modal> </n-modal>
</div> </div>
</template> </template>
<script setup>
import { isAmount } from '@/utils/index.ts';
import { Close } from "@vicons/ionicons5";
import { ref } from "vue";
const activeTab = ref("withdrawDetail");
const showWalletModal = ref(false);
const showModal = () => {
showWalletModal.value = true;
};
const message = useMessage();
const closeWalletModal = () => {
showWalletModal.value = false;
needWalletNum.value = 0
};
// const allDetailList = ref([]);
//
const integralGold = ref({});
async function getIntegralGold() {
try {
const res = await request.post("/personalCenter/getPointAndWallet");
if (res.code === 200) {
integralGold.value = res.data;
}
} catch (err) {
console.log(err);
}
}
getIntegralGold();
//
const needWalletNum = ref(0)
const handleWallet = async() =>{
if(isAmount(needWalletNum.value)){
if(needWalletNum.value > integralGold.value.wallet) return message.warning('可提现金额不足')
try {
const res = await request.get(`/ali/pay/fetch?amount=${needWalletNum.value}`);
if (res.code === 200) {
closeWalletModal()
getIntegralGold()
}
} catch (err) {
console.log(err);
}
}else{
message.warning('请输入正确的金额')
}
}
//
const totalAmount = ref(0);
async function getTotalAmount() {
try {
const res = await request.get("/invitation/totalAmount");
if (res.code === 200) {
totalAmount.value = res.data;
}
} catch (err) {
console.log(err);
}
}
getTotalAmount();
//
const withdrawFinished = ref(false);
const withdrawDetailList = ref([]);
const withdrawParams = ref({
pageNum: 1,
pageSize: 10,
});
async function getWithdrawDetail() {
try {
if (withdrawFinished.value) return;
const res = await request.post("/invitation/withdrawalRecord", withdrawParams.value);
if (res.code === 200) {
// withdrawDetailList.value = res.data;
if (withdrawParams.value.pageNum === 1) {
withdrawDetailList.value = res.rows;
} else {
withdrawDetailList.value = [...withdrawDetailList.value, ...res.rows];
}
//
if (withdrawDetailList.value.length >= res.total) {
withdrawFinished.value = true;
}
withdrawParams.value.pageNum++;
}
} catch (err) {
console.log(err);
}
}
getWithdrawDetail();
</script>
<style scoped> <style scoped>
.mc-table { .mc-table {
padding: 10px; padding: 10px;

View File

@ -1,17 +1,22 @@
<script setup> <script setup>
import { commonApi } from "@/api/common"; import { commonApi } from '@/api/common'
import { formatFileSize } from '@/utils/index.ts'; import { formatFileSize } from '@/utils/index.ts'
import { Close, DiamondSharp, PersonAddOutline } from '@vicons/ionicons5'; import { Close, DiamondSharp, PersonAddOutline } from '@vicons/ionicons5'
import { import {
CircleUser, CircleUser,
Download, Download,
EllipsisVertical, Heart, Play, SquareCheck, SquarePlus EllipsisVertical,
} from 'lucide-vue-next'; Heart,
Play,
SquareCheck,
SquarePlus,
} from 'lucide-vue-next'
// import { NConfigProvider, NMessageProvider } from 'naive-ui'; // import { NConfigProvider, NMessageProvider } from 'naive-ui';
import { nextTick, ref } from 'vue'; import { nextTick, ref } from 'vue'
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router'
const userStore = useUserStore();
const userStore = useUserStore()
const message = useMessage() const message = useMessage()
const router = useRouter() const router = useRouter()
@ -26,7 +31,7 @@ const activeTab = ref(null)
const commentHeight = ref(800) const commentHeight = ref(800)
const detailsInfo = ref({}) const detailsInfo = ref({})
const currentUserInfo = ref({}) const currentUserInfo = ref({})
const isVisibleReport = ref(false); const isVisibleReport = ref(false)
// //
const versionByWorkInfo = ref([]) const versionByWorkInfo = ref([])
@ -104,10 +109,10 @@ async function getAttention() {
// // // //
const isDelete = ref(false) const isDelete = ref(false)
async function handleSelect(event, type) { async function handleSelect(event, type) {
event.stopPropagation(); // event.stopPropagation() //
if (type === 'report') { if (type === 'report') {
// await request.get(`/WorkFlow/report?id=${id}`) // // await request.get(`/WorkFlow/report?id=${id}`) //
isVisibleReport.value = true; isVisibleReport.value = true
} }
else if (type === 'edit') { else if (type === 'edit') {
router.push({ router.push({
@ -177,35 +182,35 @@ async function onLike() {
} }
} }
// //
const reportParams = ref({ const reportParams = ref({
reportId: undefined, reportId: undefined,
text: "", text: '',
type:3 type: 3,
}); })
const reportList = ref([]); const reportList = ref([])
async function getDictType() { async function getDictType() {
try { try {
const res = await commonApi.dictType({ type: "report_type" }); const res = await commonApi.dictType({ type: 'report_type' })
if (res.code === 200) { if (res.code === 200) {
reportList.value = res.data; reportList.value = res.data
}
} catch (error) {
console.log(error);
} }
} }
getDictType(); catch (error) {
console.log(error)
}
}
getDictType()
function handleChange(item) { function handleChange(item) {
reportParams.value.reportId = item.dictValue; reportParams.value.reportId = item.dictValue
if (item.dictValue !== "5") { if (item.dictValue !== '5') {
reportParams.value.text = ""; reportParams.value.text = ''
} }
console.log("object", reportParams.value); console.log('object', reportParams.value)
} }
function closeReport() { function closeReport() {
isVisibleReport.value = false; isVisibleReport.value = false
} }
async function onReport() { async function onReport() {
@ -214,11 +219,12 @@ async function onReport(){
try { try {
const res = await request.post('/report/addReport', reportParams.value) const res = await request.post('/report/addReport', reportParams.value)
if (res.code === 200) { if (res.code === 200) {
message.success("举报成功"); message.success('举报成功')
closeReport() closeReport()
} }
}catch(err){ }
console.log(err); catch (err) {
console.log(err)
} }
} }
} }
@ -227,52 +233,56 @@ function toPersonalCenter(){
const baseUrl = window.location.origin const baseUrl = window.location.origin
if (userStore?.userInfo?.userId === detailsInfo.value.userId) { if (userStore?.userInfo?.userId === detailsInfo.value.userId) {
window.open(`${baseUrl}/personal-center`, '_blank', 'noopener,noreferrer') window.open(`${baseUrl}/personal-center`, '_blank', 'noopener,noreferrer')
}else{ }
else {
window.open(`${baseUrl}/personal-publish?userId=${detailsInfo.value.userId}`, '_blank', 'noopener,noreferrer') window.open(`${baseUrl}/personal-publish?userId=${detailsInfo.value.userId}`, '_blank', 'noopener,noreferrer')
} }
} }
const currentTabsIndex = ref(0); const currentTabsIndex = ref(0)
function handleTabChange(id) { function handleTabChange(id) {
for (let i = 0; i < versionByWorkInfo.value.length; i++) { for (let i = 0; i < versionByWorkInfo.value.length; i++) {
if (id === versionByWorkInfo.value[i].id) { if (id === versionByWorkInfo.value[i].id) {
currentTabsIndex.value = i; currentTabsIndex.value = i
} }
} }
} }
async function addCollect() { async function addCollect() {
try { try {
const params = { const params = {
"productId": versionByWorkInfo.value[currentTabsIndex.value].id, productId: versionByWorkInfo.value[currentTabsIndex.value].id,
"collectType": 1, collectType: 1,
} }
const res = await request.post("/collect/addCollect", params); const res = await request.post('/collect/addCollect', params)
if (res.code === 200) { if (res.code === 200) {
versionByWorkInfo.value[currentTabsIndex.value].isCollect = res.data versionByWorkInfo.value[currentTabsIndex.value].isCollect = res.data
if (res.data === 1) { if (res.data === 1) {
message.success("已加入收藏"); message.success('已加入收藏')
}else{ }
message.success("已取消收藏"); else {
message.success('已取消收藏')
} }
} }
} catch (err) { }
console.log(err); catch (err) {
console.log(err)
} }
} }
async function handelDown() { async function handelDown() {
try { try {
const res = await request.get(`/WorkFlowVersion/workFlowFileDownload?id=${versionByWorkInfo.value[currentTabsIndex.value].id}`); const res = await request.get(`/WorkFlowVersion/workFlowFileDownload?id=${versionByWorkInfo.value[currentTabsIndex.value].id}`)
if (res.code === 200) { if (res.code === 200) {
const link = document.createElement('a'); const link = document.createElement('a')
link.href = res.data; link.href = res.data
link.download = res.msg; // link.download = res.msg //
document.body.appendChild(link); document.body.appendChild(link)
link.click(); link.click()
document.body.removeChild(link); document.body.removeChild(link)
} }
} catch (err) { }
console.log(err); catch (err) {
console.log(err)
} }
} }
</script> </script>
@ -316,7 +326,7 @@ async function handelDown(){
:is="Heart" :is="Heart"
class="h-[12px] w-[12px] mr-1 text-[#000]" class="h-[12px] w-[12px] mr-1 text-[#000]"
/> />
<span>{{ detailsInfo.likeCount }} </span> <span>{{ detailsInfo.likeNum || 0 }} </span>
</div> </div>
</template> </template>
点赞数 点赞数
@ -335,7 +345,8 @@ async function handelDown(){
<div class="flex w-full gap-1"> <div class="flex w-full gap-1">
<div class="w-2/3"> <div class="w-2/3">
<div class="w-full"> <div class="w-full">
<n-tabs v-model:value="activeTab" type="line" animated <n-tabs
v-model:value="activeTab" type="line" animated
@update:value="handleTabChange" @update:value="handleTabChange"
> >
<n-tab-pane <n-tab-pane
@ -438,11 +449,11 @@ async function handelDown(){
> --> > -->
<client-only> <client-only>
<NAvatar <NAvatar
@click="toPersonalCenter"
class="w-full h-full mr-2 block cursor-pointer" class="w-full h-full mr-2 block cursor-pointer"
round round
size="small" size="small"
:src="currentUserInfo.avatar" :src="currentUserInfo.avatar"
@click="toPersonalCenter"
/> />
</client-only> </client-only>
</div> </div>
@ -463,7 +474,7 @@ async function handelDown(){
</div> </div>
</div> </div>
<client-only> <client-only>
<div class="flex-1 flex justify-end" v-if="userStore?.userInfo?.userId !== detailsInfo.userId"> <div v-if="userStore?.userInfo?.userId !== detailsInfo.userId" class="flex-1 flex justify-end">
<div class="flex items-center font-bold px-1 justify-center w-20 h-8 rounded-full text-[#426af7] border border-[#426af7] border-solid cursor-pointer" @click="onChangeAttention"> <div class="flex items-center font-bold px-1 justify-center w-20 h-8 rounded-full text-[#426af7] border border-[#426af7] border-solid cursor-pointer" @click="onChangeAttention">
<n-icon v-if="detailsInfo.isAttention === 0" size="16" class="mr-2"> <n-icon v-if="detailsInfo.isAttention === 0" size="16" class="mr-2">
<PersonAddOutline /> <PersonAddOutline />
@ -521,8 +532,8 @@ async function handelDown(){
<div class="flex gap-y-2"> <div class="flex gap-y-2">
<div <div
v-if="versionByWorkInfo.length > 0" v-if="versionByWorkInfo.length > 0"
@click="addCollect"
class="flex flex-1 items-center justify-center bg-[#eceef4] h-[50px] mt-4 mr-1 rounded-md cursor-pointer" class="flex flex-1 items-center justify-center bg-[#eceef4] h-[50px] mt-4 mr-1 rounded-md cursor-pointer"
@click="addCollect"
> >
<component <component
:is=" :is="
@ -538,14 +549,14 @@ async function handelDown(){
</div> </div>
<div <div
@click="handelDown"
class="flex flex-1 items-center bg-gradient-to-r from-[#ffe9c8] to-[#ffd264] justify-center ml-1 mt-4 text-black bg-[#eceef4] w-full rounded-md h-[50px] cursor-pointer" class="flex flex-1 items-center bg-gradient-to-r from-[#ffe9c8] to-[#ffd264] justify-center ml-1 mt-4 text-black bg-[#eceef4] w-full rounded-md h-[50px] cursor-pointer"
@click="handelDown"
> >
<component <component
:is="Download" :is="Download"
class="h-[20px] w-[20px] text-black menu-icon m-1 text-[#969798]" class="h-[20px] w-[20px] text-black menu-icon m-1 text-[#969798]"
/> />
<span class="mr-1" v-if="versionByWorkInfo.length > 0"> {{ formatFileSize(versionByWorkInfo[currentTabsIndex].fileSize) }} </span> <span v-if="versionByWorkInfo.length > 0" class="mr-1"> {{ formatFileSize(versionByWorkInfo[currentTabsIndex].fileSize) }} </span>
</div> </div>
</div> </div>
<!-- <div style="background: linear-gradient(135deg,#3cc9ff, #8fa6ff, 41%, #d8b4ff 74%,#326bff)" class="flex items-center justify-center mt-4 w-full h-14 text-black bg-[#fff] w-full rounded-md h-[80px] cursor-pointer hover:bg-[#f1f2f7]"> <!-- <div style="background: linear-gradient(135deg,#3cc9ff, #8fa6ff, 41%, #d8b4ff 74%,#326bff)" class="flex items-center justify-center mt-4 w-full h-14 text-black bg-[#fff] w-full rounded-md h-[80px] cursor-pointer hover:bg-[#f1f2f7]">
@ -575,7 +586,9 @@ async function handelDown(){
> >
<div class="bg-white rounded-xl p-4"> <div class="bg-white rounded-xl p-4">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div class="text-xl">举报</div> <div class="text-xl">
举报
</div>
<div> <div>
<n-icon size="20" class="mr-2 cursor-pointer" @click="closeReport"> <n-icon size="20" class="mr-2 cursor-pointer" @click="closeReport">
<Close /> <Close />
@ -584,10 +597,10 @@ async function handelDown(){
</div> </div>
<div class="flex flex-col"> <div class="flex flex-col">
<n-radio <n-radio
class="m-4 text-[#fff000]"
size="large"
v-for="(item, index) in reportList" v-for="(item, index) in reportList"
:key="index" :key="index"
class="m-4 text-[#fff000]"
size="large"
:checked="reportParams.reportId === item.dictValue" :checked="reportParams.reportId === item.dictValue"
value="Definitely Maybe" value="Definitely Maybe"
name="basic-demo" name="basic-demo"
@ -606,13 +619,13 @@ async function handelDown(){
}" }"
/> />
<div <div
@click="onReport"
class="mt-4 w-[100%] h-10 flex rounded-lg text-white items-center justify-center cursor-pointer" class="mt-4 w-[100%] h-10 flex rounded-lg text-white items-center justify-center cursor-pointer"
:class="[ :class="[
reportParams.reportId !== undefined reportParams.reportId !== undefined
? 'bg-[#4c79ee]' ? 'bg-[#4c79ee]'
: 'bg-[#cccccc]', : 'bg-[#cccccc]',
]" ]"
@click="onReport"
> >
确认 确认
</div> </div>

View File

@ -1,8 +1,9 @@
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
// utils/request.ts // utils/request.ts
import { useModalStore } from '@/stores/modal.ts'; import { useModalStore } from '@/stores/modal.ts'
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'; import axios from 'axios'
import axios from 'axios'; import { createDiscreteApi } from 'naive-ui'
import { createDiscreteApi } from 'naive-ui';
const { message, loadingBar } = createDiscreteApi(['message', 'loadingBar']) const { message, loadingBar } = createDiscreteApi(['message', 'loadingBar'])
// 定义响应数据接口 // 定义响应数据接口
@ -54,19 +55,18 @@ class RequestHttp {
if (config.loading) { if (config.loading) {
loadingBar.finish() loadingBar.finish()
} }
// 处理业务状态码 // 处理业务状态码
if (data.code !== 200) { if (data.code !== 200) {
this.handleError(data.code) this.handleError(data.code, data)
// token过期以后需要重新登录 // token过期以后需要重新登录
if (data.code === 401) { if (data.code === 401) {
// message.error(data.message || '登录已过期,请重新登录') // message.error(data.message || '登录已过期,请重新登录')
// const modalStore = useModalStore() // const modalStore = useModalStore()
const modalStore = useModalStore(); const modalStore = useModalStore()
modalStore.showLoginModal(); modalStore.showLoginModal()
const userStore = useUserStore() const userStore = useUserStore()
try { try {
// eslint-disable-next-line ts/no-use-before-define
// await request.post('/logout') // await request.post('/logout')
// userStore.logout() // userStore.logout()
// navigateTo('/model-square') // navigateTo('/model-square')
@ -75,6 +75,11 @@ class RequestHttp {
console.log(error) console.log(error)
} }
} }
// if(data.code === 12202){
// message.error(data.msg)
// }
return Promise.reject(data) return Promise.reject(data)
} }
@ -83,10 +88,9 @@ class RequestHttp {
(error: any) => { (error: any) => {
// 关闭 loading // 关闭 loading
loadingBar.error() loadingBar.error()
// 处理错误 // 处理错误
if (error.response) { if (error.response) {
this.handleError(error.response.status) this.handleError(error.response.status, {})
} }
else { else {
message.error('网络连接异常') message.error('网络连接异常')
@ -98,7 +102,10 @@ class RequestHttp {
} }
// 处理错误状态码 // 处理错误状态码
private handleError(status: number): void { private handleError(status: number, data: any): void {
if (data.code && data.code === 12202) {
return message.error(data.msg)
}
switch (status) { switch (status) {
case 400: case 400:
message.error('请求参数错误') message.error('请求参数错误')

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

View File

@ -5,6 +5,7 @@ import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'
import Components from 'unplugin-vue-components/vite' import Components from 'unplugin-vue-components/vite'
import { pwa } from './app/config/pwa' import { pwa } from './app/config/pwa'
import { appDescription } from './app/constants/index' import { appDescription } from './app/constants/index'
const __filename = fileURLToPath(import.meta.url) const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename) const __dirname = dirname(__filename)
@ -83,16 +84,16 @@ export default defineNuxtConfig({
preset: 'node-server', preset: 'node-server',
devProxy: { devProxy: {
'/api': { '/api': {
// target: 'http://1.13.246.108:8080', // 线上 // target: 'http://113.45.190.154:8080', // 线上
target: 'http://192.168.2.10:8080', // 代 // target: 'http://192.168.2.29:8080', // 代
// target: 'http://192.168.2.5:8080', // 嗨 target: 'http://192.168.2.4:8080', // 嗨
// target: 'https://2d1a399f.r27.cpolar.top', // 嗨 // target: 'https://2d1a399f.r27.cpolar.top', // 嗨
changeOrigin: true, changeOrigin: true,
prependPath: true, prependPath: true,
}, },
}, },
esbuild: { esbuild: {
options: { target: 'esnext' }, options: { target: 'es2019' },
}, },
prerender: { prerender: {
crawlLinks: false, crawlLinks: false,

View File

@ -1,13 +1,13 @@
{ {
"name": "mcwl", "name": "mcwl",
"version": "1.0.0",
"type": "module", "type": "module",
"version": "1.0.0",
"private": true, "private": true,
"packageManager": "pnpm@9.15.1", "packageManager": "pnpm@9.15.1",
"scripts": { "scripts": {
"build": "nuxi build --dotenv .env.pro", "build": "nuxi build --dotenv .env.pro",
"dev:pwa": "VITE_PLUGIN_PWA=true nuxi dev", "dev:pwa": "VITE_PLUGIN_PWA=true nuxi dev",
"dev": "nuxi dev --port 3002", "dev": "nuxi dev --port 3080",
"generate": "nuxi generate", "generate": "nuxi generate",
"prepare": "nuxi prepare", "prepare": "nuxi prepare",
"start": "node .output/server/index.mjs", "start": "node .output/server/index.mjs",