1
This commit is contained in:
183
pages/case/[id].vue
Normal file
183
pages/case/[id].vue
Normal file
@@ -0,0 +1,183 @@
|
||||
<template>
|
||||
|
||||
<!-- 主体部分 -->
|
||||
<div class="xl:w-screen-xl m-auto py-4 mt-12 px-4 sm:px-0 sm:mt-2">
|
||||
<el-page-header :icon="ArrowLeft" @back="goBack">
|
||||
<template #content>
|
||||
<span class="text-large font-600"> {{ page.title }} </span>
|
||||
</template>
|
||||
<el-row :gutter="24" id="container" class="clearfix">
|
||||
<el-col v-for="(item,index) in list" :key="index" :span="6" :xs="24" class="left mb-8">
|
||||
<el-card :body-style="{ padding: '0px' }" class=" hover:bg-gray-50 cursor-pointer" shadow="hover" @click="navigateTo(`/detail/${item.articleId}.html`)">
|
||||
<el-image
|
||||
:src="item.image"
|
||||
fit="cover"
|
||||
:lazy="true" class="w-full md:h-[166px] h-[199px] cursor-pointer bg-gray-50"/>
|
||||
<div class="flex-1 px-4 py-5 sm:p-6 !p-4">
|
||||
<div class="text-gray-700 dark:text-white text-base font-semibold flex flex-col gap-1.5">
|
||||
<div class="text-xl cursor-pointer items-center line-clamp-1">
|
||||
{{ item.title }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5 py-2 text-gray-500 justify-between">
|
||||
<div class="text-gray-500 line-clamp-2">{{ item.comments }}</div>
|
||||
</div>
|
||||
<div class="button-group flex justify-between items-center mt-3 text-sm">
|
||||
<el-space class="flex items-end">
|
||||
<div class="text-gray-400 gap-1 flex items-center"><el-icon><View /></el-icon><span>{{ getViews(item) }}</span></div>
|
||||
</el-space>
|
||||
<div class="text-gray-400">
|
||||
<el-avatar v-if="item.avatar" size="small" :src="`${item.avatar}`" />
|
||||
{{ dayjs(item.createTime).format('YYYY-MM-DD') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-page-header>
|
||||
|
||||
<Pagination :total="total" @done="search" />
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import Banner from "@/components/Banner.vue";
|
||||
import { ArrowLeft,View, Search } from '@element-plus/icons-vue'
|
||||
import { ElNotification as notify } from 'element-plus'
|
||||
import {useConfigInfo, useLayout, usePage} from "~/composables/configState";
|
||||
import type {CmsNavigation} from "~/api/cms/cmsNavigation/model";
|
||||
import type {CmsArticle, CmsArticleParam} from "~/api/cms/cmsArticle/model";
|
||||
import type { ComponentSize } from 'element-plus'
|
||||
import { ElNotification } from 'element-plus'
|
||||
import type { TabsPaneContext } from 'element-plus'
|
||||
import { h } from 'vue'
|
||||
import dayjs from "dayjs";
|
||||
import {detail, getNavIdByParamsId, navTo, paramsId} from "~/utils/common";
|
||||
import Left from "~/components/Left.vue";
|
||||
import {getCmsNavigation, listCmsNavigation} from "~/api/cms/cmsNavigation";
|
||||
import {pageCmsArticle} from "~/api/cms/cmsArticle";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const navId = ref();
|
||||
// 页面信息
|
||||
const list = ref<CmsArticle[]>([]);
|
||||
const i18n = useI18n();
|
||||
const category = ref<CmsNavigation[]>([]);
|
||||
const total = ref(0);
|
||||
const activeName = ref('2839');
|
||||
|
||||
// 获取状态
|
||||
const page = usePage();
|
||||
const layout = useLayout();
|
||||
|
||||
// 搜索表单
|
||||
const where = reactive<CmsArticleParam>({
|
||||
keywords: '',
|
||||
page: 1,
|
||||
limit: 12,
|
||||
status: 0,
|
||||
recommend: 1,
|
||||
order: 'desc',
|
||||
sort: 'actualViews',
|
||||
parentId: undefined,
|
||||
categoryId: undefined,
|
||||
lang: i18n.locale.value
|
||||
});
|
||||
|
||||
const goBack = () => {
|
||||
router.back();
|
||||
}
|
||||
|
||||
// 加载页面数据
|
||||
const reload = async () => {
|
||||
await getCmsNavigation(navId.value).then(data => {
|
||||
page.value = data;
|
||||
layout.value.banner = data.banner;
|
||||
|
||||
// seo
|
||||
useSeoMeta({
|
||||
description: data.comments || data.title,
|
||||
keywords: data.title,
|
||||
titleTemplate: `${data?.title}` + ' - %s',
|
||||
})
|
||||
|
||||
// 二级栏目分类
|
||||
listCmsNavigation({
|
||||
parentId: data.parentId == 0 ? data.navigationId : data.parentId
|
||||
}).then(navigation => {
|
||||
category.value = navigation;
|
||||
// 加载文章列表
|
||||
if(data.parentId == 0 && category.value.length > 0){
|
||||
where.parentId = page.value.navigationId;
|
||||
}else {
|
||||
where.categoryId = page.value.navigationId;
|
||||
}
|
||||
pageCmsArticle(where).then(response => {
|
||||
if(response){
|
||||
total.value = response.count;
|
||||
list.value = response.list;
|
||||
}
|
||||
})
|
||||
})
|
||||
}).catch(() => {})
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
* @param data
|
||||
*/
|
||||
const search = (data: CmsArticleParam) => {
|
||||
where.page = data.page;
|
||||
reload();
|
||||
}
|
||||
|
||||
const handleClick = (tab: TabsPaneContext, event: Event) => {
|
||||
console.log(tab, event)
|
||||
}
|
||||
const value = ref('')
|
||||
const options = [
|
||||
{
|
||||
value: 'Option1',
|
||||
label: 'Option1',
|
||||
},
|
||||
{
|
||||
value: 'Option2',
|
||||
label: 'Option2',
|
||||
},
|
||||
{
|
||||
value: 'Option3',
|
||||
label: 'Option3',
|
||||
},
|
||||
{
|
||||
value: 'Option4',
|
||||
label: 'Option4',
|
||||
},
|
||||
{
|
||||
value: 'Option5',
|
||||
label: 'Option5',
|
||||
},
|
||||
]
|
||||
|
||||
watch(
|
||||
() => route.params.id,
|
||||
(id) => {
|
||||
navId.value = getNavIdByParamsId(id);
|
||||
reload();
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.right .content img{
|
||||
width: auto !important;
|
||||
}
|
||||
.demo-tabs > .el-tabs__content {
|
||||
padding: 32px;
|
||||
color: #6b778c;
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
89
pages/case/components/AppInfo.vue
Normal file
89
pages/case/components/AppInfo.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<div v-if="form" class="app-info bg-white py-5 flex justify-around items-center">
|
||||
<div class="item text-center">
|
||||
<div class="rate text-gray-400">评分</div>
|
||||
<div class="text-2xl font-bold">3.1</div>
|
||||
<el-rate v-model="form.rate" disabled size="small"/>
|
||||
</div>
|
||||
<el-divider class="opacity-40" style="height: 40px" direction="vertical" />
|
||||
<div class="item text-center flex flex-col items-center">
|
||||
<div class="text-gray-400">类别</div>
|
||||
<el-icon size="24" class="py-1"><Monitor /></el-icon>
|
||||
<span class="text-gray-500">{{ form.industryParent || '网站' }}</span>
|
||||
</div>
|
||||
<el-divider class="opacity-40" style="height: 40px" direction="vertical" />
|
||||
<nuxt-link :to="`https://${form.domain}`" class="item text-center flex flex-col items-center">
|
||||
<div class="text-gray-400">域名</div>
|
||||
<div>
|
||||
<svg t="1739721752315" class="icon pt-2" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11933" width="22" height="22"><path d="M319.9 428.9h37.7l-66.1 216.7H259c-28.9-98-43.9-149.1-44.9-154.3-2.1-4.6-3.1-12.4-3.1-23.2h-1c0 4.6-1 12.4-3.1 23.2-2.1 4.6-18.1 56.2-48 154.3h-32.5l-63-216.7h37.7c23.7 91.3 36.6 141.4 38.7 149.6 0 0.5 0.5 1.5 1 3.1 1.5 9.8 2.1 17 2.1 21.2h1c0-7.7 1.5-15.5 4.1-24.3 2.1-5.7 17-55.7 44.9-149.6h35.6c25.8 94.4 39.7 144.5 41.8 149.6 2.6 8.3 4.1 16.5 4.1 24.3h1c0-4.1 0.5-11.4 2.1-21.2 0.5-1.5 1-2.6 1-3.1 2.7-8.2 16.1-58.2 41.4-149.6z m300.8 0h37.7l-66.1 216.7h-32.5c-28.9-98-43.9-149.1-44.9-154.3-2.1-4.6-3.1-12.4-3.1-23.2h-1c0 4.6-1 12.4-3.1 23.2-2.1 4.6-18.1 56.2-48 154.3h-32.5l-63-216.7h37.7c23.7 91.3 36.6 141.4 38.7 149.6 0 0.5 0.5 1.5 1 3.1 1.5 9.8 2.1 17 2.1 21.2h0.5c0-7.7 1.5-15.5 4.1-24.3 2.1-5.7 17-55.7 44.9-149.6h35.6c25.8 94.4 39.7 144.5 41.8 149.6 2.6 8.3 4.1 16.5 4.1 24.3h1c0-4.1 0.5-11.4 2.1-21.2 0.5-1.5 1-2.6 1-3.1 3.2-8.2 16.6-58.2 41.9-149.6z m300.9 0h37.7l-66.1 216.7h-32.5c-28.9-98-43.9-149.1-44.9-154.3-2.1-4.6-3.1-12.4-3.1-23.2h-1c0 4.6-1 12.4-3.1 23.2-2.1 4.6-18.1 56.2-48 154.3h-32.5l-63-216.7h37.7c23.7 91.3 36.6 141.4 38.7 149.6 0 0.5 0.5 1.5 1 3.1 1.5 9.8 2.1 17 2.1 21.2h1c0-7.7 1.5-15.5 4.1-24.3 2.1-5.7 17-55.7 44.9-149.6h35.6C856 523.4 870 573.4 872 578.6c2.6 8.3 4.1 16.5 4.1 24.3h1c0-4.1 0.5-11.4 2.1-21.2 0.5-1.5 1-2.6 1-3.1 2.7-8.3 16.1-58.3 41.4-149.7z m-755.5-39.2C222.9 254 357 158.5 513.4 158.5S803.9 254 860.7 389.7h45.9c-58.8-160-212.6-274-393.2-274s-333.9 114-393.2 274h45.9z m691 299.3c-58.8 131.1-190.4 222.9-343.7 222.9-153.3 0-284.8-91.3-343.7-222.9h-46.4c61.4 155.3 212.6 265.2 390.1 265.2 177 0 328.7-109.9 390.1-265.2h-46.4z" fill="" p-id="11934"></path><path d="M513.4 217.8c-123.2 0-230.1 69.7-283.4 171.9h-14.9c54.4-109.8 167.6-185.2 298.4-185.2" fill="" p-id="11935"></path></svg>
|
||||
</div>
|
||||
<!-- <el-icon size="24" class="py-1"><Compass /></el-icon>-->
|
||||
<span class="text-gray-500">{{ form.domain }}</span>
|
||||
</nuxt-link>
|
||||
<el-divider class="opacity-40" style="height: 40px" direction="vertical" />
|
||||
<nuxt-link :to="`/market/user/${form.userId}`" class="item text-center flex flex-col items-center">
|
||||
<div class="text-gray-400">开发者</div>
|
||||
<el-icon size="24" class="py-1"><Avatar /></el-icon>
|
||||
<span class="text-gray-500">{{'WebSoft Inc.'}}</span>
|
||||
</nuxt-link>
|
||||
<el-divider class="opacity-40" style="height: 40px" direction="vertical" />
|
||||
<nuxt-link :to="`http://git.gxwebsoft.com`" class="item text-center">
|
||||
<div class="text-gray-400">仓库</div>
|
||||
<div class="text-2xl font-bold">
|
||||
<!-- <svg t="1739721615244" class="icon pt-2" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10773" width="22" height="22"><path d="M512 64c81.636 0 156.8 19.911 225.493 59.733s122.951 94.08 162.773 162.773S960 430.364 960 512s-19.911 156.8-59.733 225.493-94.08 122.951-162.773 162.773S593.636 960 512 960s-156.8-19.911-225.493-59.733-122.951-94.08-162.773-162.773S64 593.636 64 512s19.911-156.8 59.733-225.493 94.08-122.951 162.773-162.773S430.364 64 512 64z m119.467 812.373c57.742-17.92 108.516-48.782 152.32-92.587 43.804-43.805 75.164-94.578 94.08-152.32 18.916-57.742 23.396-117.476 13.44-179.2-9.956-61.724-32.853-117.476-68.693-167.253-35.84-49.778-81.138-88.604-135.893-116.48C631.964 140.658 573.724 126.72 512 126.72s-119.964 13.938-174.72 41.813-100.053 66.702-135.893 116.48-58.738 105.529-68.693 167.253c-9.956 61.724-5.476 121.458 13.44 179.2s50.276 108.516 94.08 152.32c43.804 43.804 94.578 74.667 152.32 92.587h2.987c5.973 0 10.951-1.493 14.933-4.48 3.982-2.987 5.973-7.467 5.973-13.44v-65.707l-20.907 2.987H377.6c-19.911 1.991-38.329-1.991-55.253-11.947S293.974 759.893 288 741.973l-17.92-32.853-11.947-11.947-23.893-17.92c-3.982-3.982-5.973-6.969-5.973-8.96s0.996-3.982 2.987-5.973l14.933-2.987c5.973 0 11.947 1.493 17.92 4.48 5.973 2.987 11.947 5.476 17.92 7.467l11.947 14.933 11.947 11.947c7.964 13.938 17.422 24.889 28.373 32.853 10.951 7.964 23.893 11.449 38.827 10.453 14.933-0.996 29.369-4.48 43.307-10.453 1.991-9.956 4.978-19.413 8.96-28.373 3.982-8.96 8.96-16.427 14.933-22.4-25.884-1.991-49.778-7.467-71.68-16.427-21.902-8.96-40.818-21.404-56.747-37.333-15.929-15.929-26.88-34.844-32.853-56.747-7.964-25.884-11.947-52.764-11.947-80.64 0-17.92 3.484-35.84 10.453-53.76 6.969-17.92 16.427-33.849 28.373-47.787-1.991-7.964-3.484-15.431-4.48-22.4s-1.493-14.933-1.493-23.893 0.996-17.92 2.987-26.88c1.991-8.96 3.982-18.418 5.973-28.373h8.96c7.964 0 16.427 0.996 25.387 2.987s17.422 4.978 25.387 8.96l26.88 14.933 20.907 11.947c63.716-17.92 127.431-17.92 191.147 0l20.907-11.947 26.88-14.933c7.964-3.982 15.929-6.969 23.893-8.96 7.964-1.991 16.924-2.987 26.88-2.987h5.973c3.982 9.956 6.969 19.413 8.96 28.373 1.991 8.96 2.987 17.92 2.987 26.88 0 8.96-0.498 16.924-1.493 23.893s-2.489 14.436-4.48 22.4c11.947 13.938 21.404 29.867 28.373 47.787 6.969 17.92 10.453 35.84 10.453 53.76 0 27.876-3.982 54.756-11.947 80.64-5.973 21.902-16.924 40.818-32.853 56.747-15.929 15.929-35.342 28.373-58.24 37.333-22.898 8.96-47.289 14.436-73.173 16.427 9.956 7.964 16.924 18.418 20.907 31.36 3.982 12.942 5.973 26.382 5.973 40.32v104.533c0 5.973 1.991 10.453 5.973 13.44 3.982 2.987 7.964 4.48 11.947 4.48h5.972z" p-id="10774"></path></svg>-->
|
||||
<svg t="1739720696276" class="icon pt-2" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4176" width="22" height="22"><path d="M511.6 76.3C264.3 76.2 64 276.4 64 523.5 64 718.9 189.3 885 363.8 946c23.5 5.9 19.9-10.8 19.9-22.2v-77.5c-135.7 15.9-141.2-73.9-150.3-88.9C215 726 171.5 718 184.5 703c30.9-15.9 62.4 4 98.9 57.9 26.4 39.1 77.9 32.5 104 26 5.7-23.5 17.9-44.5 34.7-60.8-140.6-25.2-199.2-111-199.2-213 0-49.5 16.3-95 48.3-131.7-20.4-60.5 1.9-112.3 4.9-120 58.1-5.2 118.5 41.6 123.2 45.3 33-8.9 70.7-13.6 112.9-13.6 42.4 0 80.2 4.9 113.5 13.9 11.3-8.6 67.3-48.8 121.3-43.9 2.9 7.7 24.7 58.3 5.5 118 32.4 36.8 48.9 82.7 48.9 132.3 0 102.2-59 188.1-200 212.9 23.5 23.2 38.1 55.4 38.1 91v112.5c0.8 9 0 17.9 15 17.9 177.1-59.7 304.6-227 304.6-424.1 0-247.2-200.4-447.3-447.5-447.3z" p-id="4177"></path></svg>
|
||||
</div>
|
||||
<span class="text-gray-500">3.12 MB</span>
|
||||
</nuxt-link>
|
||||
<el-divider class="opacity-40" style="height: 40px" direction="vertical" />
|
||||
<div class="item text-center flex flex-col items-center">
|
||||
<div class="text-gray-400">插件ID</div>
|
||||
<el-icon size="24" class="py-1"><Cpu /></el-icon>
|
||||
<span class="text-gray-500">{{ form.websiteId }}</span>
|
||||
</div>
|
||||
<!-- <el-divider class="opacity-40" style="height: 40px" direction="vertical" />-->
|
||||
<!-- <div class="item text-center flex flex-col items-center">-->
|
||||
<!-- <div class="text-gray-400">下载次数</div>-->
|
||||
<!-- <el-icon size="24" class="py-1"><Download /></el-icon>-->
|
||||
<!-- <span class="text-gray-500">{{ form.downloads }}</span>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ArrowLeft,View, Menu, Search,Compass, Cpu,Monitor, Download, Platform, Avatar } from '@element-plus/icons-vue'
|
||||
import type {CmsWebsite} from "~/api/cms/cmsWebsite/model";
|
||||
|
||||
const i18n = useI18n();
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
title?: string;
|
||||
desc?: string;
|
||||
buyUrl?: string;
|
||||
form?: CmsWebsite;
|
||||
value?: number;
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done', where: any): void
|
||||
}>()
|
||||
|
||||
// 搜索表单
|
||||
const where = reactive<any>({
|
||||
keywords: '',
|
||||
page: 1,
|
||||
limit: 20,
|
||||
status: 0,
|
||||
parentId: undefined,
|
||||
categoryId: undefined,
|
||||
lang: i18n.locale.value
|
||||
});
|
||||
|
||||
const reload = () => {
|
||||
|
||||
}
|
||||
reload();
|
||||
</script>
|
||||
195
pages/case/components/Comments.vue
Normal file
195
pages/case/components/Comments.vue
Normal file
@@ -0,0 +1,195 @@
|
||||
<template>
|
||||
<el-descriptions title="评分及评价">
|
||||
<template #extra>
|
||||
<el-button type="text" @click="onComplaint">投诉</el-button>
|
||||
<el-button type="text" @click="onComments">发表评论</el-button>
|
||||
</template>
|
||||
</el-descriptions>
|
||||
<form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-position="top"
|
||||
class="w-full sm:py-2"
|
||||
size="large"
|
||||
status-icon
|
||||
>
|
||||
<template v-if="comments && comments.length > 0">
|
||||
<div class="w-full p-4 bg-white">
|
||||
<div v-for="(item,index) in comments" :key="index"
|
||||
class="flex flex-col border-b-2 border-gray-200 pb-2 mb-3"
|
||||
style="border-bottom:1px solid #f3f3f3">
|
||||
<el-space class="user-info flex items-start" style="align-items:normal">
|
||||
<div class="avatar">
|
||||
<el-avatar :src="item.logo"/>
|
||||
</div>
|
||||
<div class="nickname flex flex-col">
|
||||
<el-space class="text-sm text-gray-900">
|
||||
<span class="font-bold">{{ item.tenantName }}</span>
|
||||
<el-rate v-model="item.rate" disabled size="small"/>
|
||||
</el-space>
|
||||
<span class="text-xs text-gray-400">{{ item.createTime }}</span>
|
||||
<div class="comments py-2" v-html="item.comments"></div>
|
||||
<template v-if="item.children" v-for="(sub,index2) in item.children" :key="index2">
|
||||
<el-space class="text-sm text-gray-900">
|
||||
<el-avatar :src="sub.logo" size="small"/>
|
||||
<span class="font-bold">{{ sub.tenantName }}</span>
|
||||
<span class="text-xs text-gray-400">{{ sub.createTime }}</span>
|
||||
</el-space>
|
||||
<div class="comments py-2" v-html="sub.comments"></div>
|
||||
</template>
|
||||
</div>
|
||||
</el-space>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pagination flex justify-center">
|
||||
<el-pagination background layout="prev, pager, next" size="small" :total="count" @change="onPageChange"/>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
暂无用户评论
|
||||
</template>
|
||||
|
||||
<!-- 发表评论 -->
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
title="发表评论"
|
||||
align-center
|
||||
width="500"
|
||||
:before-close="() => visible = false"
|
||||
>
|
||||
<el-form-item prop="rate">
|
||||
<el-rate v-model="form.rate" size="large" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="comments">
|
||||
<el-input v-model="form.comments" :rows="5" type="textarea"
|
||||
placeholder="最多300字,支持 markdown 语法。请认真填写评论内容,以便于帮助作者更好完善插件,如需反馈问题,请到下方插件提问进行提交。"/>
|
||||
</el-form-item>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitForm(formRef)">
|
||||
提交
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 发起投诉 -->
|
||||
<el-dialog
|
||||
v-model="visible2"
|
||||
title="为什么举报此内容?"
|
||||
align-center
|
||||
width="500"
|
||||
:before-close="() => visible2 = false"
|
||||
>
|
||||
<el-checkbox-group v-model="checkList">
|
||||
<el-checkbox label="与我无关" value="与我无关"/>
|
||||
<el-checkbox label="文章过时" value="文章过时"/>
|
||||
<el-checkbox label="标题有误" value="标题有误"/>
|
||||
<el-checkbox label="图像质量差或视觉缺陷" value="图像质量差或视觉缺陷"/>
|
||||
<el-checkbox label="垃圾邮件" value="垃圾邮件"/>
|
||||
<el-checkbox label="成人或违法违规内容" value="成人或违法违规内容"/>
|
||||
<el-checkbox label="侵犯知识产权" value="侵犯知识产权"/>
|
||||
</el-checkbox-group>
|
||||
<div class="py-3">
|
||||
<el-input v-model="form.comments" :rows="5" type="textarea"
|
||||
placeholder="在此处输入反馈。请记住不要包含个人信息,如电话号码。"/>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="visible2 = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitForm(formRef)">
|
||||
提交
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {FullScreen} from '@element-plus/icons-vue'
|
||||
import type {ApiResult} from "~/api";
|
||||
import type {FormInstance, FormRules} from "element-plus";
|
||||
import {useClientRequest} from "~/composables/useClientRequest";
|
||||
import {reactive, ref} from "vue";
|
||||
import useFormData from "~/utils/use-form-data";
|
||||
import type {CompanyComment} from "~/api/system/companyComment/model";
|
||||
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
title?: string;
|
||||
companyId?: number;
|
||||
comments?: CompanyComment[];
|
||||
count?: number;
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
const visible = ref<boolean>(false);
|
||||
const visible2 = ref<boolean>(false);
|
||||
const checkList = ref<string[]>([]);
|
||||
const loading = ref<boolean>(true)
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done', page: number): void
|
||||
}>()
|
||||
|
||||
// 配置信息
|
||||
const {form, resetFields} = useFormData<CompanyComment>({
|
||||
id: undefined,
|
||||
parentId: undefined,
|
||||
userId: undefined,
|
||||
companyId: undefined,
|
||||
rate: undefined,
|
||||
sortNumber: undefined,
|
||||
comments: undefined,
|
||||
status: undefined,
|
||||
});
|
||||
|
||||
const rules = reactive<FormRules<any>>({
|
||||
rate: [
|
||||
{required: true, message: '请输入评分', trigger: 'blur'},
|
||||
],
|
||||
comments: [
|
||||
{required: true, message: '请输入手机号码', trigger: 'blur'},
|
||||
{pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur'},
|
||||
],
|
||||
})
|
||||
|
||||
const onComments = () => {
|
||||
visible.value = true;
|
||||
}
|
||||
|
||||
const onComplaint = () => {
|
||||
visible2.value = true;
|
||||
}
|
||||
|
||||
const onPageChange = (page: number) => {
|
||||
emit('done', page)
|
||||
}
|
||||
|
||||
const submitForm = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
if (form.rate === 0) {
|
||||
ElMessage.error('还没有评分哦!')
|
||||
return false;
|
||||
}
|
||||
form.companyId = Number(getIdBySpm(5));
|
||||
useClientRequest<ApiResult<any>>(`/system/company-comment`, {
|
||||
method: 'POST',
|
||||
body: form
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
ElMessage.success(res.message)
|
||||
visible.value = false
|
||||
resetFields();
|
||||
emit('done',0)
|
||||
} else {
|
||||
return ElMessage.error(res.message)
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
102
pages/case/components/PageBanner.vue
Normal file
102
pages/case/components/PageBanner.vue
Normal file
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<div class="banner m-auto relative sm:flex">
|
||||
<div class="md:w-screen-xl m-auto py-10">
|
||||
<div class="gap-8 sm:gap-y-16 lg:items-center" v-if="form">
|
||||
<div class="w-full sm:px-0 px-4">
|
||||
<div class="flex flex-1">
|
||||
<template v-if="form.websiteLogo">
|
||||
<el-image :src="form.websiteLogo" shape="square"
|
||||
class="hidden-sm-and-down bg-white w-[128px] h-[128px] cursor-pointer rounded-avatar shadow-sm hover:shadow mr-6"/>
|
||||
</template>
|
||||
<div class="title flex flex-col">
|
||||
<h1
|
||||
class="text-2xl font-bold tracking-tight text-gray-900 dark:text-white sm:text-3xl lg:text-3xl">
|
||||
<el-space>
|
||||
<span>{{ form.websiteName }}</span>
|
||||
</el-space>
|
||||
</h1>
|
||||
<div class="my-1 text-sm text-gray-500 w-auto sm:max-w-3xl max-w-xs flex-1 dark:text-gray-400">
|
||||
{{ form?.comments || desc }}
|
||||
</div>
|
||||
<el-space class="btn">
|
||||
<nuxt-link target="_blank"><el-button type="primary" round>获取</el-button></nuxt-link>
|
||||
</el-space>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type {ApiResult} from "~/api";
|
||||
import type {Company} from "~/api/system/company/model";
|
||||
import type {CmsWebsite} from "~/api/cms/cmsWebsite/model";
|
||||
|
||||
const token = useToken();
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
title?: string;
|
||||
desc?: string;
|
||||
buyUrl?: string;
|
||||
form?: CmsWebsite;
|
||||
value?: number;
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done'): void
|
||||
}>()
|
||||
|
||||
const onBuy = (item: Company) => {
|
||||
// if(item.type === 1){
|
||||
// // 插件
|
||||
// openSpmUrl(`/product/checkout`,item,item.productId)
|
||||
// }else {
|
||||
// // 产品
|
||||
// openSpmUrl(`/product/create`,item,item.productId)
|
||||
// }
|
||||
if (!token.value || token.value == '') {
|
||||
ElMessage.error('请先登录');
|
||||
setTimeout(() => {
|
||||
navigateTo(`/product/create`)
|
||||
}, 500)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 安装插件
|
||||
const installPlug = () => {
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '安装中...'
|
||||
})
|
||||
useClientRequest<ApiResult<any>>(`/system/menu/install`, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
companyId: getIdBySpm(5)
|
||||
}
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
setTimeout(() => {
|
||||
ElMessage.success(res.message);
|
||||
loading.close()
|
||||
emit('done')
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.rounded-avatar {
|
||||
border-radius: 30px;
|
||||
}
|
||||
|
||||
.rounded-avatar-xs {
|
||||
border-radius: 20px;
|
||||
}
|
||||
</style>
|
||||
45
pages/case/components/SearchBar.vue
Normal file
45
pages/case/components/SearchBar.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<el-space class="flex items-center">
|
||||
<el-input v-model="where.keywords" :placeholder="`${$t('searchKeywords')}...`" :suffix-icon="Search" @change="reload"/>
|
||||
</el-space>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Search } from '@element-plus/icons-vue'
|
||||
import type {CmsArticle} from "~/api/cms/cmsArticle/model";
|
||||
|
||||
const i18n = useI18n();
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
title?: string;
|
||||
desc?: string;
|
||||
buyUrl?: string;
|
||||
form?: CmsArticle;
|
||||
value?: number;
|
||||
}>(),
|
||||
{}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done', where: any): void
|
||||
}>()
|
||||
|
||||
// 搜索表单
|
||||
const where = reactive<any>({
|
||||
keywords: '',
|
||||
page: 1,
|
||||
limit: 20,
|
||||
status: 0,
|
||||
parentId: undefined,
|
||||
categoryId: undefined,
|
||||
lang: i18n.locale.value
|
||||
});
|
||||
|
||||
const reload = () => {
|
||||
navigateTo(`/search/${where.keywords}`)
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
</style>
|
||||
154
pages/case/index.vue
Normal file
154
pages/case/index.vue
Normal file
@@ -0,0 +1,154 @@
|
||||
<template>
|
||||
|
||||
<!-- 主体部分 -->
|
||||
<div class="xl:w-screen-xl m-auto py-4 mt-12 px-4 sm:px-0 sm:mt-2">
|
||||
<el-page-header :icon="ArrowLeft" @back="goBack">
|
||||
<template #content>
|
||||
<span class="text-large font-600 line-clamp-1"> 客户案例 </span>
|
||||
</template>
|
||||
<template #extra>
|
||||
<el-space class="flex items-center">
|
||||
<el-input
|
||||
v-model="where.keywords"
|
||||
:placeholder="`搜索关键词`"
|
||||
class="hidden-sm-and-down"
|
||||
:suffix-icon="Search"
|
||||
:style="{ width: inputWidth }"
|
||||
@focus="handleFocus"
|
||||
@blur="handleBlur"
|
||||
@change="reload"
|
||||
/>
|
||||
<el-button class="hidden-sm-and-up" :icon="Search" @click="showSearch = true"></el-button>
|
||||
</el-space>
|
||||
<el-dialog
|
||||
v-model="showSearch"
|
||||
fullscreen
|
||||
>
|
||||
<el-input
|
||||
v-model="where.keywords"
|
||||
:placeholder="`搜索关键词`"
|
||||
size="large"
|
||||
class="w-full my-5"
|
||||
:suffix-icon="Search"
|
||||
@change="reload"
|
||||
/>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<el-row :gutter="24" id="container" class="clearfix">
|
||||
<el-col v-for="(item,index) in list" :key="index" :span="6" :xs="24" class="left mb-8">
|
||||
<el-card shadow="hover" :body-style="{ padding: '0px' }" class="cursor-pointer" @mouseover="showDomain(item)"
|
||||
@mouseleave="hideDomain">
|
||||
<nuxt-link :to="`/market/${item.websiteId}`">
|
||||
<div class="flex-1 px-4 py-5 sm:p-4 !p-4">
|
||||
<div class="text-gray-700 dark:text-white text-base font-semibold flex gap-1.5">
|
||||
<el-avatar
|
||||
:src="item.websiteLogo" shape="square" :size="55" style="background-color: white;"/>
|
||||
<div class="flex-1 text-lg cursor-pointer flex flex-col">
|
||||
{{ item.websiteName }}
|
||||
<div class="flex justify-between items-center">
|
||||
<sapn class="text-xs text-gray-400 font-normal line-clamp-1">
|
||||
{{ id == item.websiteId ? item.domain : item.comments || '暂无描述' }}
|
||||
</sapn>
|
||||
<el-button size="small" round>获取</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-image pt-3 overflow-hidden">
|
||||
<el-image v-if="item.files" :src="`${JSON.parse(item.files)[0]}`" class="w-full h-1/2 max-h-[220px] transition-transform duration-300 ease-in-out hover:scale-110"/>
|
||||
<el-image v-else class="w-full h-[220px]"/>
|
||||
</div>
|
||||
</div>
|
||||
</nuxt-link>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-page-header>
|
||||
|
||||
<Pagination :total="total" @done="search"/>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import {ArrowLeft, Search} from '@element-plus/icons-vue'
|
||||
import type {CmsArticleParam} from "~/api/cms/cmsArticle/model";
|
||||
import {pageCmsWebsiteAll} from "~/api/cms/cmsWebsite";
|
||||
import type {CmsWebsite, CmsWebsiteParam} from "~/api/cms/cmsWebsite/model";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
// 页面信息
|
||||
const list = ref<CmsWebsite[]>([]);
|
||||
const total = ref(0);
|
||||
const id = ref<number>();
|
||||
const inputWidth = ref<string>('180px');
|
||||
const showSearch = ref<boolean>(false);
|
||||
|
||||
// 搜索表单
|
||||
const where = reactive<CmsWebsiteParam>({
|
||||
keywords: '',
|
||||
page: 1,
|
||||
limit: 12,
|
||||
status: undefined,
|
||||
recommend: undefined,
|
||||
search: true,
|
||||
websiteType: undefined,
|
||||
categoryId: undefined,
|
||||
lang: undefined
|
||||
});
|
||||
|
||||
const goBack = () => {
|
||||
router.back();
|
||||
}
|
||||
const handleFocus = () => {
|
||||
inputWidth.value = '400px'; // 聚焦时宽度
|
||||
}
|
||||
const handleBlur = () => {
|
||||
inputWidth.value = '180px'; // 聚焦时宽度
|
||||
}
|
||||
|
||||
const showDomain = (item: CmsWebsite) => {
|
||||
id.value = Number(item.websiteId);
|
||||
};
|
||||
|
||||
const hideDomain = () => {
|
||||
id.value = 0;
|
||||
};
|
||||
|
||||
// 加载页面数据
|
||||
const reload = async () => {
|
||||
await pageCmsWebsiteAll({
|
||||
...where,
|
||||
plugin: false
|
||||
}).then(response => {
|
||||
if (response?.list) {
|
||||
list.value = response?.list;
|
||||
total.value = response.count;
|
||||
}
|
||||
}).catch(() => {
|
||||
}).finally(() => showSearch.value = false)
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
* @param data
|
||||
*/
|
||||
const search = (data: CmsArticleParam) => {
|
||||
where.page = data.page;
|
||||
reload();
|
||||
}
|
||||
|
||||
watch(
|
||||
() => route.params.id,
|
||||
() => {
|
||||
reload();
|
||||
},
|
||||
{immediate: true}
|
||||
);
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.el-input {
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user