Browse Source

疫苗预约系统

master
科技小王子 7 months ago
parent
commit
8be7d3d371
  1. 2
      components/AppHeader.vue
  2. 63
      pages/case/components/CardList.vue
  3. 113
      pages/case/components/PageBanner.vue
  4. 92
      pages/case/index.vue
  5. 47
      pages/developer/components/CardList.vue
  6. 157
      pages/developer/index.vue
  7. 149
      pages/developer/join-in.vue
  8. 47
      pages/docs/components/CardList.vue
  9. 103
      pages/docs/index.vue
  10. 52
      pages/down/components/CardList.vue
  11. 96
      pages/down/index.vue
  12. 26
      pages/form/components/Comments.vue
  13. 14
      pages/form/components/PageBanner.vue
  14. 107
      pages/item/components/PageBanner.vue
  15. 169
      pages/item/index.vue
  16. 358
      pages/manage/cms/index.vue
  17. 373
      pages/manage/index.vue
  18. 358
      pages/manage/shop/index.vue
  19. 56
      pages/market/components/CardList.vue
  20. 115
      pages/market/components/PageBanner.vue
  21. 114
      pages/market/detail/[plugId].vue
  22. 99
      pages/market/detail/components/Header.vue
  23. 103
      pages/market/index.vue
  24. 82
      pages/merchant/index.vue
  25. 174
      pages/merchant/join-in.vue
  26. 105
      pages/product/[id].vue
  27. 219
      pages/product/checkout/index.vue
  28. 53
      pages/product/components/CardList.vue
  29. 93
      pages/product/create/components/PageBanner.vue
  30. 245
      pages/product/create/index.vue
  31. 25
      pages/product/createWebsite/index.vue
  32. 25
      pages/product/createWebsite/index2.vue
  33. 168
      pages/product/detail/[id].vue
  34. 85
      pages/product/index.vue
  35. 77
      pages/product/website.vue
  36. 87
      pages/templates/index.vue

2
components/AppHeader.vue

@ -12,7 +12,7 @@
:src="config.siteLogo"
shape="square"
fit="fill"
class="lg:h-7 lg:w-auto h-5 sm:w-[120px] h-[35px]"
class="lg:h-7 lg:w-auto h-6 w-6 sm:w-[120px] h-[35px]"
:alt="config.siteName"
:title="config.siteName"
/>

63
pages/case/components/CardList.vue

@ -1,63 +0,0 @@
<template>
<div class="xl:w-screen-xl sm:flex xl:p-0 p-4 m-auto relative" v-infinite-scroll="load">
<el-row :gutter="24" class="flex">
<template v-for="(item,index) in list" :key="index">
<el-col :span="8" class="mb-5 min-w-xs">
<el-card shadow="hover" :body-style="{ padding: '0px' }" class="hover:bg-gray-50 cursor-pointer" @click="openSpmUrl(`/item`,item,item.appId,true)">
<div class="flex-1 px-4 py-5 sm:p-6 !p-4">
<div class="text-gray-700 dark:text-white flex items-center gap-2">
<div class="avatar">
<el-avatar :src="item.appIcon" shape="square" :lazy="true" :size="48" />
</div>
<div class="app-name flex flex-col pb-2">
<span class="flex-1 text-xl font-bold">{{ item.appName }}</span>
<span class="text-gray-400 text-xs">{{ item.appUrl || item.appCode }}</span>
</div>
</div>
<div class="flex items-center gap-1.5 py-2 text-gray-500 justify-between">
<span class="text-gray-400 min-h-[50px] overflow-hidden">{{ item.comments }} </span>
</div>
<div class="button-group flex justify-center mt-3">
<el-button class="w-full" @click.stop="addFavorite(item)">加入收藏</el-button>
<el-button class="w-full" @click.stop="openSpmUrl(`/item`,item,item.appId,true)">查看详情</el-button>
<el-button v-if="item.appUrl" class="w-full" @click="openSpmUrl(`https://${item.tenantCode}.websoft.top`,item,item.appId,true)">产品控制台</el-button>
<el-button v-else class="w-full" @click="openSpmUrl(`https://${item.tenantCode}.websoft.top`,item,item.appId,true)">产品控制台</el-button>
</div>
</div>
</el-card>
</el-col>
</template>
</el-row>
</div>
<div v-if="disabled" class="px-1 text-center text-gray-500 min-h-xs">
没有更多了
</div>
</template>
<script setup lang="ts">
import {openSpmUrl} from "~/utils/common";
import dayjs from "dayjs";
import type {App} from "~/api/oa/app/model";
const props = withDefaults(
defineProps<{
list?: App[];
disabled?: boolean;
}>(),
{}
);
const emit = defineEmits<{
(e: 'done'): void;
}>();
const addFavorite = () => {
}
const load = () => {
if(!props.disabled){
emit('done')
}
}
</script>

113
pages/case/components/PageBanner.vue

@ -1,113 +0,0 @@
<template>
<div class="banner m-auto relative sm:flex">
<svg viewBox="0 0 1440 181" fill="none" xmlns="http://www.w3.org/2000/svg"
class="pointer-events-none absolute w-full top-[-2px] transition-all text-green-5 flex-shrink-0 opacity-100 duration-[400ms] opacity-80 -z-10">
<mask id="path-1-inside-1_414_5526" fill="white">
<path d="M0 0H1440V181H0V0Z"></path>
</mask>
<path d="M0 0H1440V181H0V0Z" fill="url(#paint0_linear_414_5526)" fill-opacity="0.22"></path>
<path d="M0 2H1440V-2H0V2Z" fill="url(#paint1_linear_414_5526)" mask="url(#path-1-inside-1_414_5526)"></path>
<defs>
<linearGradient id="paint0_linear_414_5526" x1="720" y1="0" x2="720" y2="181" gradientUnits="userSpaceOnUse">
<stop stop-color="currentColor"></stop>
<stop offset="1" stop-color="currentColor" stop-opacity="0"></stop>
</linearGradient>
<linearGradient id="paint1_linear_414_5526" x1="0" y1="90.5" x2="1440" y2="90.5" gradientUnits="userSpaceOnUse">
<stop stop-color="currentColor" stop-opacity="0"></stop>
<stop offset="0.395" stop-color="currentColor"></stop>
<stop offset="1" stop-color="currentColor" stop-opacity="0"></stop>
</linearGradient>
</defs>
</svg>
<div class="md:w-screen-xl m-auto md:p-0 px-4">
<div class="py-8 sm:py-16" _path="/templates" _dir="" _draft="false" _partial="false" _locale=""
_id="content:4.templates.yml" _type="yaml" _source="content" _file="4.templates.yml" _stem="4.templates"
_extension="yml">
<div v-if="layout">
<div class="banner w-full">
<h1
class="text-3xl font-bold tracking-tight text-gray-900 dark:text-white sm:text-4xl lg:text-5xl">
<span v-if="layout.title">{{ layout.title }}</span>
<span v-if="layout.name">{{ layout.name }}</span>
</h1>
<div class="mt-4 text-lg text-gray-500 dark:text-gray-400 gap-8 sm:gap-y-16 grid lg:grid-cols-2 lg:items-center">
{{ layout.description }}
</div>
<div class="flex justify-between w-full items-center mt-4">
<el-space>
<div class="w-[500px] pr-10">
<el-input
v-model="where.keywords"
placeholder="搜索"
:prefix-icon="Search"
@keydown.enter="handleClick"
>
<template #append>
<el-button size="large" type="primary" @click="handleClick">搜索</el-button>
</template>
</el-input>
</div>
</el-space>
<el-space>
<el-button size="large">我的收藏</el-button>
<el-button size="large">热门推荐</el-button>
</el-space>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { Search } from '@element-plus/icons-vue'
import {useConfigInfo} from "~/composables/configState";
import {openSpmUrl} from "~/utils/common";
import type {CompanyParam} from "~/api/system/company/model";
const token = useToken();
const sysDomain = useSysDomain();
withDefaults(
defineProps<{
layout?: any;
title?: string;
desc?: string;
buyUrl?: string;
}>(),
{
title: 'Templates',
desc: 'Explore community templates to get up and running in a few seconds.',
demoUrl: '/product/website',
buyUrl: 'https://github.com/websoft9/ansible-templates'
}
);
//
const where = reactive<CompanyParam>({
keywords: ''
});
const config = useConfigInfo();
//
const handleClick = async () => {
if (where.keywords == '') {
return false;
}
if(activeName.value == 'web'){
const {data: response} = await useServerRequest<ApiResult<PageResult<Website>>>('/cms/cms-website/page',{baseURL: runtimeConfig.public.apiServer, params: {
page: page.value, keywords: where.keywords
}})
if(response.value?.data){
if (response.value?.data.list) {
websites.value = response.value?.data.list;
}
if(response.value.data.count == 0){
resultText.value = '暂无相关结果'
}
}
}
}
</script>

92
pages/case/index.vue

@ -1,92 +0,0 @@
<template>
<PageBanner :layout="layout" title="案例" desc="客户案例推荐,或许更快找到灵感" />
<CardList :list="list" :disabled="disabled" @done="onSearch" />
</template>
<script setup lang="ts">
import type {ApiResult, PageResult} from "~/api";
import {useServerRequest} from "~/composables/useServerRequest";
import {useWebsite} from "~/composables/configState";
import type {Navigation} from "~/api/cms/navigation/model";
import type {CompanyParam} from "~/api/system/company/model";
import CardList from './components/CardList.vue';
import PageBanner from "./components/PageBanner.vue";
import type {App} from "~/api/oa/app/model";
const route = useRoute();
//
const runtimeConfig = useRuntimeConfig();
const list = ref<App[]>([]);
const page = ref<number>(1);
const resultText = ref('');
const layout = ref<any>();
const disabled = ref<boolean>(false);
const activeName = ref(undefined)
//
const form = ref<Navigation>();
const website = useWebsite();
//
const where = reactive<CompanyParam>({
keywords: ''
});
const handleClick = (e:any) => {
console.log(e.index)
}
const onSearch = () => {
if(!disabled.value){
page.value++;
reload(route.path);
}
}
//
const reload = async (path: string) => {
const {data: response} = await useServerRequest<ApiResult<PageResult<App>>>('/oa/oa-app/page',{baseURL: runtimeConfig.public.apiServer, params: {
page: page.value,
limit: 8,
showCase: 1,
keywords: where.keywords
}})
if(response.value?.data){
if (list.value.length < response.value?.data.count) {
disabled.value = false;
if (response.value?.data.list) {
list.value = list.value.concat(response.value?.data.list);
}
}else {
disabled.value = true;
}
if(response.value.data.count == 0){
resultText.value = '暂无相关结果'
}
}
}
const { data: nav } = await useServerRequest<ApiResult<Navigation>>('/cms/cms-navigation/getNavigationByPath',{query: {path: route.path}})
if(nav.value?.data){
form.value = nav.value?.data;
}
//
if(form.value?.layout){
layout.value = JSON.parse(form.value?.layout)
}
useHead({
title: `案例 - ${website.value.websiteName}`,
bodyAttrs: {
class: "page-container",
}
});
watch(
() => route.path,
(path) => {
reload(path);
},
{ immediate: true }
);
</script>

47
pages/developer/components/CardList.vue

@ -1,47 +0,0 @@
<template>
<div class="xl:w-screen-xl sm:flex xl:p-0 p-4 m-auto relative" v-infinite-scroll="load">
<el-row :gutter="24" class="flex">
<template v-for="(item,index) in list" :key="index">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb-5 min-w-xs">
<el-card shadow="hover" :body-style="{ padding: '0px' }" class="hover:bg-gray-50 cursor-pointer" @click="openSpmUrl(`/detail`,item,item.articleId)">
<el-image :src="item.image" fit="fill" :lazy="true" class="w-full h-[150px] cursor-pointer" />
<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="flex-1 text-xl cursor-pointer">{{ item.title }}</div>
</div>
<div class="flex items-center gap-1.5 py-2 text-gray-500 justify-between">
<div class="text-gray-500">{{ item.comments }}</div>
</div>
</div>
</el-card>
</el-col>
</template>
</el-row>
</div>
<div v-if="disabled" class="px-1 text-center text-gray-500 min-h-xs">
没有更多了
</div>
</template>
<script setup lang="ts">
import {openSpmUrl} from "~/utils/common";
import dayjs from "dayjs";
const props = withDefaults(
defineProps<{
list?: any[];
disabled?: boolean;
}>(),
{}
);
const emit = defineEmits<{
(e: 'done'): void;
}>();
const load = () => {
if(!props.disabled){
emit('done')
}
}
</script>

157
pages/developer/index.vue

@ -1,157 +0,0 @@
<template>
<PageBanner :layout="layout" title="入驻成为开发者" @done="onDone" />
<div v-if="showContent" class="md:w-screen-xl md:px-0 px-4 m-auto relative sm:flex bg-white rounded-lg py-4 ">
1231232
<el-tabs class="px-4 bg-white" v-if="form">
<el-tab-pane label="个人开发者认证">
<el-form :model="form" label-width="auto" size="large" label-position="top" class="sm:w-screen-md w-full sm:py-2">
<el-form-item label="真实姓名">
<el-input v-model="form.realName" placeholder="请输入真实姓名" />
</el-form-item>
<el-form-item label="证件号码">
<el-input v-model="form.idCard" placeholder="请输入证件号码" />
</el-form-item>
<el-form-item label="身份证(正面)">
<Upload />
</el-form-item>
<el-form-item label="身份证(反面)">
<Upload />
</el-form-item>
<el-form-item>
<el-button type="primary" size="large" @click="onSubmit">提交</el-button>
</el-form-item>
</el-form>
<el-result
icon="success"
title="个人认证成功"
sub-title="认证完成时间 2024-09-30"
>
<template #extra>
<el-button type="text">修改认证信息</el-button>
</template>
</el-result>
</el-tab-pane>
<el-tab-pane label="企业开发者认证">
<el-form :model="form" label-width="auto" size="large" label-position="top" class="sm:w-screen-md w-full sm:py-2">
<el-form-item label="企业名称">
<el-input v-model="form.companyName" placeholder="请输入企业名称" />
</el-form-item>
<el-form-item label="社会信用代码">
<el-input v-model="form.idCard" placeholder="请输入社会信用代码" />
</el-form-item>
<el-form-item label="营业执照">
<Upload />
</el-form-item>
<el-form-item label="所属行业">
<el-select v-model="form.city" placeholder="请选择所属行业">
</el-select>
</el-form-item>
<el-form-item label="网站信息">
<el-input v-model="form.idCard" placeholder="请输入网站信息" />
</el-form-item>
<el-form-item label="您的身份">
<el-radio-group v-model="form.sex">
<el-radio value="1">法定代表人</el-radio>
<el-radio value="2">被授权人</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="用户协议">
<el-checkbox v-model="form.status">请务必提供真实信息我司有权自行或委托第三方审查您提供的身份信息是否属真实有效若提供虚假信息由此的全部后果由您承担</el-checkbox>
</el-form-item>
<el-form-item>
<el-button type="primary" size="large" @click="onSubmit">提交</el-button>
</el-form-item>
</el-form>
<el-result
icon="success"
title="企业认证成功"
sub-title="认证完成时间 2024-09-30"
>
<template #extra>
<el-button type="text">修改认证信息</el-button>
</template>
</el-result>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup lang="ts">
import type {ApiResult, PageResult} from "~/api";
import {useServerRequest} from "~/composables/useServerRequest";
import {useWebsite} from "~/composables/configState";
import type {Navigation} from "~/api/cms/navigation/model";
import type {CompanyParam} from "~/api/system/company/model";
import type {Article} from "~/api/cms/article/model";
const route = useRoute();
//
const runtimeConfig = useRuntimeConfig();
const list = ref<Article[]>([]);
const page = ref<number>(1);
const resultText = ref('');
const layout = ref<any>();
const disabled = ref<boolean>(false);
//
const form = ref<Navigation>();
const showContent = ref<boolean>(false);
const website = useWebsite();
//
const where = reactive<CompanyParam>({
keywords: ''
});
const onDone = (index: boolean) => {
showContent.value = index;
}
//
const reload = async (path: string) => {
const {data: response} = await useServerRequest<ApiResult<PageResult<Article>>>('/cms/cms-article/page',{baseURL: runtimeConfig.public.apiServer, params: {
page: page.value,
limit: 8,
userId: 0,
keywords: where.keywords
}})
if(response.value?.data){
if (list.value.length < response.value?.data.count) {
disabled.value = false;
if (response.value?.data.list) {
list.value = list.value.concat(response.value?.data.list);
}
}else {
disabled.value = true;
}
if(response.value.data.count == 0){
resultText.value = '暂无相关结果'
}
}
}
// const { data: nav } = await useServerRequest<ApiResult<Navigation>>('/cms/cms-navigation/getNavigationByPath',{query: {path: route.path}})
// console.log(nav.value?.data)
// if(nav.value?.data){
// form.value = nav.value?.data;
// console.log(form.value,'form...')
// }
// //
// if(form.value?.layout){
// layout.value = JSON.parse(form.value?.layout)
// }
useHead({
title: `开发者中心 - ${website.value?.websiteName}`,
bodyAttrs: {
class: "page-container",
}
});
watch(
() => route.path,
(path) => {
reload(path);
},
{ immediate: true }
);
</script>

149
pages/developer/join-in.vue

@ -1,149 +0,0 @@
<template>
<PageBanner :layout="layout" />
<div class="login-layout mt-[100px] m-auto sm:w-screen-xl w-full">
<div class="mt-[100px] m-auto flex sm:flex-row flex-col sm:p-0 p-3">
<div class="flash ml-8 bg-white rounded-lg px-7 py-4 w-full">
<el-tabs class="flash bg-white ml-0">
<el-tab-pane label="个人开发者">
<el-form :model="form" label-width="auto" size="large" label-position="top" class="sm:w-screen-md w-full sm:py-2">
<el-form-item label="真实姓名">
<el-input v-model="form.realName" placeholder="请输入真实姓名" />
</el-form-item>
<el-form-item label="证件号码">
<el-input v-model="form.idCard" placeholder="请输入证件号码" />
</el-form-item>
<el-form-item label="身份证(正面)">
<Upload />
</el-form-item>
<el-form-item label="身份证(反面)">
<Upload />
</el-form-item>
<el-form-item>
<el-button type="primary" size="large" @click="onSubmit">提交</el-button>
</el-form-item>
</el-form>
<el-result
icon="success"
title="个人认证成功"
sub-title="认证完成时间 2024-09-30"
>
<template #extra>
<el-button type="text">修改认证信息</el-button>
</template>
</el-result>
</el-tab-pane>
<el-tab-pane label="企业开发者">
<el-form :model="form" label-width="auto" size="large" label-position="top" class="sm:w-screen-md w-full sm:py-2">
<el-form-item label="企业名称">
<el-input v-model="form.companyName" placeholder="请输入企业名称" />
</el-form-item>
<el-form-item label="社会信用代码">
<el-input v-model="form.idCard" placeholder="请输入社会信用代码" />
</el-form-item>
<el-form-item label="营业执照">
<Upload />
</el-form-item>
<el-form-item label="所属行业">
<el-select v-model="form.city" placeholder="请选择所属行业">
</el-select>
</el-form-item>
<el-form-item label="网站信息">
<el-input v-model="form.idCard" placeholder="请输入网站信息" />
</el-form-item>
<el-form-item label="您的身份">
<el-radio-group v-model="form.sex">
<el-radio value="1">法定代表人</el-radio>
<el-radio value="2">被授权人</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="用户协议">
<el-checkbox v-model="form.status">请务必提供真实信息我司有权自行或委托第三方审查您提供的身份信息是否属真实有效若提供虚假信息由此的全部后果由您承担</el-checkbox>
</el-form-item>
<el-form-item>
<el-button type="primary" size="large" @click="onSubmit">提交</el-button>
</el-form-item>
</el-form>
<el-result
icon="success"
title="企业认证成功"
sub-title="认证完成时间 2024-09-30"
>
<template #extra>
<el-button type="text">修改认证信息</el-button>
</template>
</el-result>
</el-tab-pane>
</el-tabs>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import {useConfigInfo, useToken, useWebsite} from "~/composables/configState";
import useFormData from '@/utils/use-form-data';
import type { User } from '@/api/system/user/model';
import { ref } from 'vue'
import {useServerRequest} from "~/composables/useServerRequest";
import type {ApiResult} from "~/api";
//
const runtimeConfig = useRuntimeConfig();
const route = useRoute();
const activeIndex = ref('');
const website = useWebsite()
const config = useConfigInfo();
const token = useToken();
const userInfo = ref<User>();
//
const { form, assignFields } = useFormData<User>({
userId: undefined,
nickname: '',
username: '',
phone: '',
mobile: '',
sex: '',
sexName: '',
email: '',
password: '',
code: '',
smsCode: '',
comments: '',
remember: true
});
useHead({
title: `用户中心 - ${config.value?.siteName}`,
meta: [{ name: website.value.keywords, content: website.value.comments }]
});
const onSubmit = async () => {
const {data: modify } = await useServerRequest<ApiResult<User>>('/auth/user',{
baseURL: runtimeConfig.public.apiServer,
method: 'put',
body: form
})
if(modify.value?.code == 0){
ElMessage.success('修改成功')
}
}
const reload = async () => {
const {data: response} = await useServerRequest<ApiResult<User>>('/auth/user',{baseURL: runtimeConfig.public.apiServer})
if(response.value?.data){
userInfo.value = response.value?.data;
assignFields(response.value?.data);
}
}
watch(
() => route.path,
(path) => {
activeIndex.value = path;
console.log(path,'=>Path')
reload();
},
{ immediate: true }
);
</script>

47
pages/docs/components/CardList.vue

@ -1,47 +0,0 @@
<template>
<div class="xl:w-screen-xl sm:flex xl:p-0 p-4 m-auto relative" v-infinite-scroll="load">
<el-row :gutter="24" class="flex">
<template v-for="(item,index) in list" :key="index">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb-5 min-w-xs">
<el-card shadow="hover" :body-style="{ padding: '0px' }" class="hover:bg-gray-50 cursor-pointer" @click="openSpmUrl(`/detail`,item,item.articleId)">
<el-image :src="item.image" fit="fill" :lazy="true" class="w-full h-[150px] cursor-pointer" />
<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="flex-1 text-xl cursor-pointer">{{ item.title }}</div>
</div>
<div class="flex items-center gap-1.5 py-2 text-gray-500 justify-between">
<div class="text-gray-500">{{ item.comments }}</div>
</div>
</div>
</el-card>
</el-col>
</template>
</el-row>
</div>
<div v-if="disabled" class="px-1 text-center text-gray-500 min-h-xs">
没有更多了
</div>
</template>
<script setup lang="ts">
import {openSpmUrl} from "~/utils/common";
import dayjs from "dayjs";
const props = withDefaults(
defineProps<{
list?: any[];
disabled?: boolean;
}>(),
{}
);
const emit = defineEmits<{
(e: 'done'): void;
}>();
const load = () => {
if(!props.disabled){
emit('done')
}
}
</script>

103
pages/docs/index.vue

@ -1,103 +0,0 @@
<template>
<PageBanner :layout="layout" title="文档" />
<el-tabs v-model="activeName" class="md:w-screen-xl m-auto relative sm:flex pb-2" @tab-click="handleClick">
<el-tab-pane label="企业官网" name="website"></el-tab-pane>
<el-tab-pane label="企业商城" name="weShop"></el-tab-pane>
<el-tab-pane label="内容管理" name="cms"></el-tab-pane>
<el-tab-pane label="点餐外卖" name="food"></el-tab-pane>
<el-tab-pane label="派单系统" name="task"></el-tab-pane>
<el-tab-pane label="办公OA" name="oa"></el-tab-pane>
<el-tab-pane label="常见问题" name="ask"></el-tab-pane>
</el-tabs>
<CardList :list="list" :disabled="disabled" @done="onSearch" />
</template>
<script setup lang="ts">
import type {ApiResult, PageResult} from "~/api";
import {useServerRequest} from "~/composables/useServerRequest";
import {useWebsite} from "~/composables/configState";
import type {Navigation} from "~/api/cms/navigation/model";
import type {CompanyParam} from "~/api/system/company/model";
import type {Article} from "~/api/cms/article/model";
import CardList from './components/CardList.vue';
const route = useRoute();
//
const runtimeConfig = useRuntimeConfig();
const list = ref<Article[]>([]);
const page = ref<number>(1);
const resultText = ref('');
const layout = ref<any>();
const disabled = ref<boolean>(false);
const activeName = ref(undefined)
//
const form = ref<Navigation>();
const website = useWebsite();
//
const where = reactive<CompanyParam>({
keywords: ''
});
const handleClick = (e:any) => {
console.log(e.index)
}
const onSearch = () => {
if(!disabled.value){
page.value++;
reload(route.path);
}
}
//
const reload = async (path: string) => {
const {data: response} = await useServerRequest<ApiResult<PageResult<Article>>>('/cms/cms-article/page',{baseURL: runtimeConfig.public.apiServer, params: {
page: page.value,
limit: 8,
userId: 0,
keywords: where.keywords
}})
if(response.value?.data){
if (list.value.length < response.value?.data.count) {
disabled.value = false;
if (response.value?.data.list) {
list.value = list.value.concat(response.value?.data.list);
}
}else {
disabled.value = true;
}
if(response.value.data.count == 0){
resultText.value = '暂无相关结果'
}
}
}
const { data: nav } = await useServerRequest<ApiResult<Navigation>>('/cms/cms-navigation/getNavigationByPath',{query: {path: route.path}})
console.log(nav.value?.data)
if(nav.value?.data){
form.value = nav.value?.data;
console.log(form.value,'form...')
}
//
if(form.value?.layout){
layout.value = JSON.parse(form.value?.layout)
}
useHead({
title: `文档 - ${website.value.websiteName}`,
bodyAttrs: {
class: "page-container",
}
});
watch(
() => route.path,
(path) => {
reload(path);
},
{ immediate: true }
);
</script>

52
pages/down/components/CardList.vue

@ -1,52 +0,0 @@
<template>
<div class="xl:w-screen-xl sm:flex xl:p-0 p-4 m-auto relative" v-infinite-scroll="load">
<el-row :gutter="24" class="flex">
<template v-for="(item,index) in list" :key="index">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb-5 min-w-xs">
<el-card shadow="hover" :body-style="{ padding: '0px' }" class="hover:bg-gray-50 cursor-pointer">
<el-image :src="`${item.image}`" fit="contain" :lazy="true" class="w-full md:h-[150px] h-[199px] cursor-pointer" />
<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="flex-1 text-xl cursor-pointer">{{ item.title }}</div>
</div>
<div class="flex items-center gap-1.5 py-2 text-gray-500 justify-between">
<div class="text-gray-500">{{ item.comments }}</div>
</div>
<div class="button-group flex justify-center mt-3">
<el-button class="w-full" size="large" :icon="ElIconView" @click="openSpmUrl(`/item`, item, item.productId,true)">在线体验</el-button>
<el-button type="primary" size="large" class="w-full" :icon="ElIconShoppingCart">下载源码</el-button>
</div>
</div>
</el-card>
</el-col>
</template>
</el-row>
</div>
<div v-if="disabled" class="px-1 text-center text-gray-500 min-h-xs">
没有更多了
</div>
</template>
<script setup lang="ts">
import {openSpmUrl} from "~/utils/common";
import dayjs from "dayjs";
import type {CmsProduct} from "~/api/cms/cmsProduct/model";
const props = withDefaults(
defineProps<{
list?: CmsProduct[];
disabled?: boolean;
}>(),
{}
);
const emit = defineEmits<{
(e: 'done'): void;
}>();
const load = () => {
if(!props.disabled){
emit('done')
}
}
</script>

96
pages/down/index.vue

@ -1,96 +0,0 @@
<template>
<PageBanner :layout="layout" :title="`开源版免费下载`"
:desc="`拥抱开源、坚守品质;致力于打造安全稳定高可用的WEB应用!`"/>
<div class="text-3xl py-5">{{ count }}</div>
<el-button @click="increment">点击</el-button>
<CardList :list="list" :disabled="disabled" @done="onSearch"/>
</template>
<script setup lang="ts">
import type {ApiResult, PageResult} from "~/api";
import {useServerRequest} from "~/composables/useServerRequest";
import {useWebsite} from "~/composables/configState";
import type {Navigation} from "~/api/cms/navigation/model";
import type {CompanyParam} from "~/api/system/company/model";
import CardList from './components/CardList.vue';
import type {CmsProduct} from "~/api/cms/cmsProduct/model";
import { v4 as uuidv4 } from 'uuid';
const route = useRoute();
//
const runtimeConfig = useRuntimeConfig();
const list = ref<CmsProduct[]>([]);
const page = ref<number>(1);
const resultText = ref('');
const layout = ref<any>();
const disabled = ref<boolean>(false);
//
const form = ref<Navigation>();
const website = useWebsite();
//
const where = reactive<CompanyParam>({
keywords: ''
});
const onSearch = () => {
if (!disabled.value) {
page.value++;
reload(route.path);
}
}
const count = useToken()
function increment() {
count.value = uuidv4()
}
//
const reload = async (path: string) => {
const {data: response} = await useServerRequest<ApiResult<PageResult<CmsProduct>>>('/cms/cms-product/page', {
baseURL: runtimeConfig.public.apiServer, params: {
page: page.value,
limit: 8,
price: 0,
keywords: where.keywords
}
})
if (response.value?.data) {
if (list.value.length < response.value?.data.count) {
disabled.value = false;
if (response.value?.data.list) {
list.value = list.value.concat(response.value?.data.list);
}
} else {
disabled.value = true;
}
if (response.value.data.count == 0) {
resultText.value = '暂无相关结果'
}
}
}
const {data: nav} = await useServerRequest<ApiResult<Navigation>>('/cms/cms-navigation/getNavigationByPath', {query: {path: route.path}})
if (nav.value?.data) {
form.value = nav.value?.data;
}
//
if (form.value?.layout) {
layout.value = JSON.parse(form.value?.layout)
}
useHead({
title: `产品 - ${website.value.websiteName}`,
bodyAttrs: {
class: "page-container",
}
});
watch(
() => route.path,
(path) => {
reload(path);
},
{immediate: true}
);
</script>

26
pages/form/components/Comments.vue

@ -38,19 +38,19 @@
placeholder="13800138000"
/>
</el-form-item>
<el-form-item label="您预约的疫苗" prop="age">
<el-radio-group v-model="form.type">
<el-radio value="九阶" size="large" border>九阶</el-radio>
<el-radio value="四阶" size="large" border>四阶</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="本次接种的剂次" prop="number">
<el-checkbox-group v-model="checkList">
<el-checkbox label="第一剂" value="第一剂" />
<el-checkbox label="第二剂" value="第二剂" />
<el-checkbox label="第三剂" value="第三剂" />
</el-checkbox-group>
</el-form-item>
<!-- <el-form-item label="您预约的疫苗" prop="age">-->
<!-- <el-radio-group v-model="form.type">-->
<!-- <el-radio value="九阶" size="large" border>九阶</el-radio>-->
<!-- <el-radio value="四阶" size="large" border>四阶</el-radio>-->
<!-- </el-radio-group>-->
<!-- </el-form-item>-->
<!-- <el-form-item label="本次接种的剂次" prop="number">-->
<!-- <el-checkbox-group v-model="checkList">-->
<!-- <el-checkbox label="第一剂" value="第一剂" />-->
<!-- <el-checkbox label="第二剂" value="第二剂" />-->
<!-- <el-checkbox label="第三剂" value="第三剂" />-->
<!-- </el-checkbox-group>-->
<!-- </el-form-item>-->
<el-form-item label="备注信息" prop="comments">
<el-input
v-model="form.comments"

14
pages/form/components/PageBanner.vue

@ -64,7 +64,7 @@ const props = withDefaults(
const url = ref<string>('');
const poster = ref<string>('');
onMounted(() => {
const reload = () => {
new Player({
id: "mse", //id
lang: "zh", //
@ -72,20 +72,22 @@ onMounted(() => {
autoplay: false, //
screenShot: false, //
//
url: url.value,
url: props.form.video,
//
poster: poster.value,
fluid: true, //
playbackRate: [0.5, 1, 2] //
});
});
};
watch(
() => props.form.video,
(video) => {
console.log(video,'=>video')
url.value = 'https://oss.wsdns.cn/20240417/9339681f3bc14999bfb2d26491f1c96e.mp4';
poster.value = props.form.photo;
if(video){
url.value = video;
// poster.value = props.form.photo;
reload();
}
},
{ immediate: true }
);

107
pages/item/components/PageBanner.vue

@ -1,107 +0,0 @@
<template>
<div class="banner m-auto relative sm:flex">
<svg viewBox="0 0 1440 181" fill="none" xmlns="http://www.w3.org/2000/svg"
class="pointer-events-none absolute w-full top-[-2px] transition-all text-green-5 flex-shrink-0 opacity-100 duration-[400ms] opacity-80 -z-10">
<mask id="path-1-inside-1_414_5526" fill="white">
<path d="M0 0H1440V181H0V0Z"></path>
</mask>
<path d="M0 0H1440V181H0V0Z" fill="url(#paint0_linear_414_5526)" fill-opacity="0.22"></path>
<path d="M0 2H1440V-2H0V2Z" fill="url(#paint1_linear_414_5526)" mask="url(#path-1-inside-1_414_5526)"></path>
<defs>
<linearGradient id="paint0_linear_414_5526" x1="720" y1="0" x2="720" y2="181" gradientUnits="userSpaceOnUse">
<stop stop-color="currentColor"></stop>
<stop offset="1" stop-color="currentColor" stop-opacity="0"></stop>
</linearGradient>
<linearGradient id="paint1_linear_414_5526" x1="0" y1="90.5" x2="1440" y2="90.5" gradientUnits="userSpaceOnUse">
<stop stop-color="currentColor" stop-opacity="0"></stop>
<stop offset="0.395" stop-color="currentColor"></stop>
<stop offset="1" stop-color="currentColor" stop-opacity="0"></stop>
</linearGradient>
</defs>
</svg>
<div class="md:w-screen-xl m-auto">
<Breadcrumb :data="form" />
<div class="py-8 sm:py-16" _path="/templates" _dir="" _draft="false" _partial="false" _locale=""
_id="content:4.templates.yml" _type="yaml" _source="content" _file="4.templates.yml" _stem="4.templates"
_extension="yml">
<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">
<el-avatar :src="form.image" shape="square" :size="180" class="hidden-sm-and-down rounded-avatar shadow-sm hover:shadow mr-4" />
<el-avatar :src="form.image" shape="square" :size="80" class="hidden-sm-and-up rounded-avatar-xs shadow-sm hover:shadow mr-4" />
<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-4xl">
<span v-if="form.title">{{ form.title }}</span>
</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>
<a class="company-name text-sm my-1">
{{ form.companyName || 'WebSoft Inc.' }}
</a>
<el-rate v-model="form.rate" />
<div class="btn">
<el-space class="mt-4">
<el-button
:icon="ElIconBottom"
size="large"
@click="openSpmUrl(`/product/create`,form,form.productId)"
>
立即开通
</el-button>
<el-button
:icon="ElIconView"
size="large"
class="hidden-sm-and-down"
@click="openSpmUrl(form.demoUrl)"
>
演示地址
</el-button>
<el-button
:icon="ElIconHomeFilled"
size="large"
@click="navigateTo(`/ask/${form.userId}`)"
>
个人主页
</el-button>
</el-space>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import Breadcrumb from "~/components/Breadcrumb.vue";
withDefaults(
defineProps<{
title?: string;
desc?: string;
buyUrl?: string;
form?: any;
value?: number;
}>(),
{
title: 'Templates',
desc: 'Explore community templates to get up and running in a few seconds.',
demoUrl: '/product/website',
buyUrl: 'https://github.com/websoft9/ansible-templates',
value: 4.2
}
);
</script>
<style scoped lang="less">
.rounded-avatar{
border-radius: 30px;
}
.rounded-avatar-xs{
border-radius: 20px;
}
</style>

169
pages/item/index.vue

@ -1,169 +0,0 @@
<!-- 文章详情 -->
<template>
<PageBanner :form="form" />
<div class="page-main md:w-screen-xl m-auto p-3">
<el-row :gutter="24">
<el-col :span="18" :xs="24">
<el-card shadow="hover" class="hover:border-green-50 hover:border-2 mb-5">
<template #header>
<div class="card-header font-bold text-xl">
<span>应用截图</span>
</div>
</template>
<div class="flex gap-xl">
<template v-for="(item,index) in form.files" :key="index" class="text item">
<el-image
:src="item.url"
:zoom-rate="1.2"
:max-scale="7"
:min-scale="0.2"
:preview-src-list="srcList"
:initial-index="4"
fit="contain"
/>
</template>
</div>
</el-card>
<el-card shadow="hover" class="hover:border-green-50 hover:border-2 mb-5">
<template #header>
<div class="card-header font-bold text-xl">
<span>说明</span>
</div>
</template>
<p v-html="form.content"></p>
</el-card>
<el-card shadow="hover" class="hover:border-green-50 hover:border-2 mb-5">
<template #header>
<div class="card-header font-bold text-xl">
<span>评分和评价</span>
</div>
</template>
</el-card>
<el-card shadow="hover" class="hover:border-green-50 hover:border-2 mb-5">
<template #header>
<div class="card-header font-bold text-xl">
<span>其他信息</span>
</div>
</template>
</el-card>
</el-col>
<el-col :span="6" :xs="24">
<el-card shadow="hover" class="hover:border-green-50 hover:border-2 mb-5">
<template #header>
<div class="card-header font-bold text-xl">
<span>其他信息</span>
</div>
</template>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts">
import type {ApiResult} from "~/api";
import {useServerRequest} from "~/composables/useServerRequest";
import {useWebsite} from "~/composables/configState";
import type {BreadcrumbItem} from "~/types/global";
import {getIdBySpm} from "~/utils/common";
import useFormData from "~/utils/use-form-data";
import type {CmsProduct} from "~/api/cms/cmsProduct/model";
import PageBanner from './components/PageBanner.vue';
//
const route = useRoute();
const website = useWebsite();
const breadcrumb = ref<BreadcrumbItem>();
const activeName = ref();
const url =
'https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg'
const srcList = ref<any[]>([]);
//
const { form, assignFields } = useFormData<CmsProduct>({
productId: undefined,
type: undefined,
code: undefined,
title: undefined,
image: undefined,
content: undefined,
parentId: undefined,
categoryId: undefined,
specs: undefined,
position: undefined,
unitName: undefined,
price: undefined,
salePrice: undefined,
deductStockType: undefined,
files: undefined,
sales: undefined,
stock: undefined,
gainIntegral: undefined,
recommend: undefined,
merchantId: undefined,
isShow: undefined,
status: undefined,
userId: undefined,
deleted: undefined,
tenantId: undefined,
createTime: undefined,
updateTime: undefined,
comments: '',
sortNumber: 100,
parentName: undefined,
parentPath: undefined,
categoryName: undefined,
rate: 0,
});
//
const reload = async () => {
// spm()
const { data: item } = await useServerRequest<ApiResult<CmsProduct>>('/cms/cms-product/' + getIdBySpm(5))
if (item.value?.data) {
assignFields(item.value.data)
form.title = item.value?.data?.title;
form.parentName = '产品';
form.parentPath = '/product';
form.categoryName = '产品详情';
form.rate = item.value.data.tenantId;
if(item.value.data.files){
form.files = JSON.parse(item.value?.data?.files)
srcList.value = form.files?.map(d => d.url)
}
form.comments = item.value?.data?.comments;
}
// seo
useHead({
title: `${form.title} - ${website.value.websiteName}`,
bodyAttrs: {
class: "page-container",
}
});
//
breadcrumb.value = form
}
watch(
() => route.path,
(path) => {
console.log(path,'=>Path')
reload();
},
{ immediate: true }
);
</script>
<style lang="less">
.content {
img {
max-width: 100%;
}
}
</style>

358
pages/manage/cms/index.vue

@ -1,358 +0,0 @@
<template>
<div class="common-layout">
<el-container>
<!-- 顶部菜单 -->
<el-header class="bg-black flex items-center justify-between" height="50px">
<el-space class="flex items-center">
<el-avatar src="https://oss.wsdns.cn/20240331/7f7f7f57e12c45338beb7bfc7ecccfe9.png" class="cursor-pointer" shape="square" :size="32" @click="navigateTo('/manage', { replace: false })" />
<div class="expand flex items-center justify-center block hover:bg-gray-700 h-[32px] w-[32px] cursor-pointer" @click="visible = !visible"><el-icon color="white" class="block" size="20"><Grid /></el-icon></div>
</el-space>
<template v-if="token">
<el-dropdown @command="handleCommand">
<el-avatar class="cursor-pointer" :src="userInfo?.avatar" :size="30" />
<el-button circle :icon="ElIconUserFilled" color="#155FAA"></el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="user">个人中心</el-dropdown-item>
<el-dropdown-item divided command="logOut" @click="navigateTo('/user/logout')">退出</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
</el-header>
<!-- 主体 -->
<el-container>
<!-- 左侧菜单区域 -->
<el-aside width="200px" class="bg-white" :style="{ minHeight: 'calc(100vh - 50px)' }">
<div class="flex items-center justify-between py-4 px-5 text-lg font-bold text-center bg-white border-b-1 border-b-gray-100 border-b-solid">
企业官网 WDS
<el-icon><Memo /></el-icon>
</div>
<el-menu
default-active="2"
class="el-menu-vertical-demo"
style="border: none"
@open="handleOpen"
@close="handleClose"
>
<el-menu-item index="1">
<span>概况</span>
</el-menu-item>
<el-menu-item index="2">
<span>栏目管理</span>
</el-menu-item>
<el-menu-item index="3">
<span>文章列表</span>
</el-menu-item>
<el-menu-item index="4">
<span>素材管理</span>
</el-menu-item>
<el-menu-item index="5">
<span>广告管理</span>
</el-menu-item>
<el-menu-item index="6">
<span>订单管理</span>
</el-menu-item>
<el-menu-item index="7">
<span>用户管理</span>
</el-menu-item>
<el-menu-item index="8">
<span>系统设置</span>
</el-menu-item>
</el-menu>
</el-aside>
<!-- 左侧内容区域 -->
<el-container>
<el-main class="overflow-y-hidden relative">
<div class="absolute inset-0 bg-black opacity-10 z-1" v-if="visible" @click="visible = false"></div>
<div v-if="visible" class="drawer w-screen-lg h-full bg-white left-0 top-[50px] fixed z-2 shadow-lg">
<div class="flex items-center justify-between p-3 border-b border-b-solid border-b-gray-200">
<div class="text-lg font-bold">产品与服务</div>
<el-space class="flex items-center">
<el-input
class="w-20"
placeholder="站内搜索"
:suffix-icon="ElIconSearch"
v-model="form.comments"
@keyup.enter.native="handleSearch"
/>
<!-- <el-input v-model="search" placeholder="搜索应用" class="w-[200px]" />-->
<div class="cursor-pointer mt-1 ml-5" @click="visible = false"><el-icon size="24" color="gray"><Close /></el-icon></div>
</el-space>
</div>
<div class="menu-content flex">
<div class="w-[200px] bg-gray-50">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
style="border-right: 1px solid #f9fafb"
@open="handleOpen"
@close="handleClose"
>
<el-menu-item index="2">
<span>精选</span>
</el-menu-item>
<el-menu-item index="3">
<span>网页</span>
</el-menu-item>
<el-menu-item index="4">
<span>移动</span>
</el-menu-item>
<el-menu-item index="5">
<span>办公</span>
</el-menu-item>
<el-menu-item index="6">
<span>其他</span>
</el-menu-item>
</el-menu>
</div>
<div class="w-full p-3">
<el-scrollbar class="w-full" height="calc(100vh - 108px)">
<el-row :gutter="16">
<template v-for="item in 20" :key="item">
<el-col :span="8">
<div class="px-3 py-1 mb-2 text-sm text-gray-700 font-bold flex justify-between items-center">API 与工具</div>
<p class="scrollbar-demo-item hover:bg-gray-100 px-3 py-1 mb-2 cursor-pointer text-sm text-gray-500 flex justify-between items-center">
<span class="product-name">{{ item }} 云服务器 ECS</span>
<span class="icon flex items-center hover:flex">
<el-icon color="gray"><Star /></el-icon>
</span>
</p>
</el-col>
</template>
</el-row>
</el-scrollbar>
</div>
</div>
</div>
<div class="my-3">
<el-alert type="warning">
<template #title>
<text type="text" class="cursor-pointer">关于小程序技术平台服务协议更新公告</text>
</template>
</el-alert>
</div>
<el-card shadow="hover" class="flash mt-4 bg-white hover:shadow rounded-lg">
<template #header>我的应用</template>
<el-row :gutter="16">
<template v-for="(item,index) in list" :key="index">
<el-col :span="6" @click="openSpmUrl(`https://${item.tenantId}.websoft.top/token-login`,item,item.tenantId)">
<div class="app-item block border-solid rounded-lg border-gray-300 border-1 bg-white mb-4 p-3 flex flex-row items-center hover:border-blue-4 hover:border-1.5 cursor-pointer">
<el-avatar :src="item?.logo" shape="square" />
<div class="info ml-2">
<div class="app-item-title font-bold flex items-center">{{ item.tenantName }}<el-tag type="warning" class="ml-2" size="small">网页</el-tag></div>
<div class="app-item-desc text-gray-400">{{ item.comments }}</div>
</div>
</div>
</el-col>
</template>
</el-row>
</el-card>
<!-- <el-card shadow="hover" class="mt-4">-->
<!-- <el-tabs v-model="activeIndex" type="">-->
<!-- <el-tab-pane label="微信小程序" name="mp-weixin">-->
<!-- <el-table :data="tableData" stripe style="width: 100%">-->
<!-- <el-table-column prop="date" label="Date" width="180" />-->
<!-- <el-table-column prop="name" label="Name" width="180" />-->
<!-- <el-table-column prop="address" label="Address" />-->
<!-- </el-table>-->
<!-- </el-tab-pane>-->
<!-- <el-tab-pane label="网页/移动应用" name="web">-->
<!-- </el-tab-pane>-->
<!-- </el-tabs>-->
<!-- </el-card>-->
<el-card shadow="hover" class="flash mt-4 bg-white hover:shadow ">
<template #header>开发工具推荐</template>
<el-row :gutter="16">
<template v-for="(item,index) in list" :key="index">
<el-col :span="6" @click="openSpmUrl(`https://${item.tenantId}.websoft.top/token-login`,item,item.tenantId)">
<div class="app-item block border-solid rounded-lg border-gray-300 border-1 mb-4 p-3 flex flex-row items-center hover:border-blue-4 hover:border-1.5 cursor-pointer">
<div class="info ml-2">
<div class="app-item-title">{{ item.tenantName }}</div>
<div class="app-item-desc text-gray-400">{{ item.comments }}</div>
</div>
</div>
</el-col>
</template>
</el-row>
</el-card>
</el-main>
<el-footer class="fixed bottom-0 items-center flex justify-center text-gray-400" :style="{ width: 'calc(100vw - 200px)' }">
<span>Copyright © {{ new Date().getFullYear() }} {{ config?.copyright }}</span>
</el-footer>
</el-container>
</el-container>
</el-container>
</div>
</template>
<script setup lang="ts">
import {useConfigInfo, useToken, useWebsite} from "~/composables/configState";
import useFormData from '@/utils/use-form-data';
import type { User } from '@/api/system/user/model';
import { ref } from 'vue'
import {useServerRequest} from "~/composables/useServerRequest";
import type {ApiResult, PageResult} from "~/api";
import type {Company} from "~/api/system/company/model";
import type {Tenant} from "~/api/system/tenant/model";
//
const runtimeConfig = useRuntimeConfig();
const route = useRoute();
const website = useWebsite()
const config = useConfigInfo();
const token = useToken();
const userInfo = ref<User>();
const visible = ref(false);
const showIcon = ref(false);
const activeIndex = ref('mp-weixin');
const list = ref<Tenant[]>();
const avatar = ref(localStorage.getItem('avatar'))
import {
Document,
Menu as IconMenu,
Location,
Expand,
MoreFilled,
Grid,
Memo,
Close,
Star,
Setting,
} from '@element-plus/icons-vue'
import {navigateTo} from "#imports";
const handleOpen = (key: string, keyPath: string[]) => {
console.log(key, keyPath)
}
const handleClose = (key: string, keyPath: string[]) => {
console.log(key, keyPath)
}
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
]
//
const { form, assignFields } = useFormData<User>({
userId: undefined,
nickname: '',
username: '',
phone: '',
mobile: '',
sex: '',
sexName: '',
email: '',
password: '',
code: '',
smsCode: '',
comments: '',
remember: true
});
useHead({
title: `用户中心 - ${config.value?.siteName}`,
meta: [{ name: website.value.keywords, content: website.value.comments }]
});
function handleCommand(command: string) {
switch (command) {
case 'logOut':
logOut();
break;
default:
navigateTo('/user');
break;
}
}
function logOut() {
token.value = ''
navigateTo('/passport/login')
}
const onDone = (index: string) => {
activeIndex.value = index;
}
const onSubmit = async () => {
const {data: modify } = await useServerRequest<ApiResult<User>>('/auth/user',{
baseURL: runtimeConfig.public.apiServer,
method: 'put',
body: form
})
if(modify.value?.code == 0){
ElMessage.success('修改成功')
}
}
const handleSearch = () => {
console.log('搜索')
}
const getUserInfo = async () => {
const {data: response} = await useServerRequest<ApiResult<User>>('/auth/user',{baseURL: runtimeConfig.public.apiServer})
if(response.value?.data){
userInfo.value = response.value?.data;
}
}
const reload = async () => {
const {data: response} = await useServerRequest<ApiResult<PageResult<Tenant>>>('/system/tenant/page',{baseURL: runtimeConfig.public.apiServer, params: {
userId: localStorage.getItem('UserId')
}})
if(response.value?.data){
console.log(response.value,'tenantList')
if (response.value?.data.list) {
list.value = response.value?.data.list;
}
}
}
watch(
() => route.path,
() => {
reload();
getUserInfo();
},
{ immediate: true }
);
</script>
<style lang="less">
.el-row {
margin-bottom: 20px;
}
.el-row:last-child {
margin-bottom: 0;
}
.el-col {
border-radius: 4px;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
</style>

373
pages/manage/index.vue

@ -1,373 +0,0 @@
<template>
<div class="common-layout">
<el-container>
<!-- 顶部菜单 -->
<el-header class="bg-black flex items-center justify-between" height="50px">
<el-space class="flex items-center">
<el-avatar src="https://oss.wsdns.cn/20240331/7f7f7f57e12c45338beb7bfc7ecccfe9.png" class="cursor-pointer" shape="square" :size="32" @click="navigateTo('/manage', { replace: false })" />
<div class="expand flex items-center justify-center block hover:bg-gray-700 h-[32px] w-[32px] cursor-pointer" @click="visible = !visible"><el-icon color="white" class="block" size="20"><Grid /></el-icon></div>
</el-space>
<template v-if="token">
<el-dropdown @command="handleCommand">
<el-avatar class="cursor-pointer" :src="userInfo?.avatar" :size="30" />
<el-button circle :icon="ElIconUserFilled" color="#155FAA"></el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="user">个人中心</el-dropdown-item>
<el-dropdown-item divided command="logOut" @click="navigateTo('/user/logout')">退出</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
</el-header>
<!-- 主体 -->
<el-container>
<!-- 左侧菜单区域 -->
<el-aside width="200px" class="bg-white" :style="{ minHeight: 'calc(100vh - 50px)' }">
<div class="flex items-center justify-between py-4 px-5 text-lg font-bold text-center bg-white border-b-1 border-b-gray-100 border-b-solid">
企业官网 WDS
<el-icon><Memo /></el-icon>
</div>
<el-menu
default-active="2"
class="el-menu-vertical-demo"
style="border: none"
@open="handleOpen"
@close="handleClose"
>
<el-menu-item v-for="(item,index) in menus" :key="item.menuId" :index="`${item.menuId}`">
<span>{{ item.title }}</span>
</el-menu-item>
<!-- <el-menu-item index="1">-->
<!-- <span>概况</span>-->
<!-- </el-menu-item>-->
<!-- <el-menu-item index="2">-->
<!-- <span>栏目管理</span>-->
<!-- </el-menu-item>-->
<!-- <el-menu-item index="3">-->
<!-- <span>文章列表</span>-->
<!-- </el-menu-item>-->
<!-- <el-menu-item index="4">-->
<!-- <span>素材管理</span>-->
<!-- </el-menu-item>-->
<!-- <el-menu-item index="5">-->
<!-- <span>广告管理</span>-->
<!-- </el-menu-item>-->
<!-- <el-menu-item index="6">-->
<!-- <span>订单管理</span>-->
<!-- </el-menu-item>-->
<!-- <el-menu-item index="7">-->
<!-- <span>用户管理</span>-->
<!-- </el-menu-item>-->
<!-- <el-menu-item index="8">-->
<!-- <span>系统设置</span>-->
<!-- </el-menu-item>-->
</el-menu>
</el-aside>
<!-- 左侧内容区域 -->
<el-container>
<el-main class="overflow-y-hidden relative">
<div class="absolute inset-0 bg-black opacity-10 z-1" v-if="visible" @click="visible = false"></div>
<div v-if="visible" class="drawer w-screen-lg h-full bg-white left-0 top-[50px] fixed z-2 shadow-lg">
<div class="flex items-center justify-between p-3 border-b border-b-solid border-b-gray-200">
<div class="text-lg font-bold">产品与服务</div>
<el-space class="flex items-center">
<el-input
class="w-20"
placeholder="站内搜索"
:suffix-icon="ElIconSearch"
v-model="form.comments"
@keyup.enter.native="handleSearch"
/>
<!-- <el-input v-model="search" placeholder="搜索应用" class="w-[200px]" />-->
<div class="cursor-pointer mt-1 ml-5" @click="visible = false"><el-icon size="24" color="gray"><Close /></el-icon></div>
</el-space>
</div>
<div class="menu-content flex">
<div class="w-[200px] bg-gray-50">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
style="border-right: 1px solid #f9fafb"
@open="handleOpen"
@close="handleClose"
>
<el-menu-item index="2">
<span>精选</span>
</el-menu-item>
<el-menu-item index="3">
<span>网页</span>
</el-menu-item>
<el-menu-item index="4">
<span>移动</span>
</el-menu-item>
<el-menu-item index="5">
<span>办公</span>
</el-menu-item>
<el-menu-item index="6">
<span>其他</span>
</el-menu-item>
</el-menu>
</div>
<div class="w-full p-3">
<el-scrollbar class="w-full" height="calc(100vh - 108px)">
<el-row :gutter="16">
<template v-for="item in 20" :key="item">
<el-col :span="8">
<div class="px-3 py-1 mb-2 text-sm text-gray-700 font-bold flex justify-between items-center">API 与工具</div>
<p class="scrollbar-demo-item hover:bg-gray-100 px-3 py-1 mb-2 cursor-pointer text-sm text-gray-500 flex justify-between items-center">
<span class="product-name">{{ item }} 云服务器 ECS</span>
<span class="icon flex items-center hover:flex">
<el-icon color="gray"><Star /></el-icon>
</span>
</p>
</el-col>
</template>
</el-row>
</el-scrollbar>
</div>
</div>
</div>
<div class="my-3">
<el-alert type="warning">
<template #title>
<text type="text" class="cursor-pointer">关于小程序技术平台服务协议更新公告</text>
</template>
</el-alert>
</div>
<el-card shadow="hover" class="flash mt-4 bg-white hover:shadow rounded-lg">
<template #header>我的应用</template>
<el-row :gutter="16">
<template v-for="(item,index) in list" :key="index">
<el-col :span="6" @click="openSpmUrl(`https://${item.tenantId}.websoft.top/token-login`,item,item.tenantId)">
<div class="app-item block border-solid rounded-lg border-gray-300 border-1 bg-white mb-4 p-3 flex flex-row items-center hover:border-blue-4 hover:border-1.5 cursor-pointer">
<el-avatar :src="item?.logo" shape="square" />
<div class="info ml-2">
<div class="app-item-title font-bold flex items-center">{{ item.tenantName }}<el-tag type="warning" class="ml-2" size="small">网页</el-tag></div>
<div class="app-item-desc text-gray-400">{{ item.comments }}</div>
</div>
</div>
</el-col>
</template>
</el-row>
</el-card>
<!-- <el-card shadow="hover" class="mt-4">-->
<!-- <el-tabs v-model="activeIndex" type="">-->
<!-- <el-tab-pane label="微信小程序" name="mp-weixin">-->
<!-- <el-table :data="tableData" stripe style="width: 100%">-->
<!-- <el-table-column prop="date" label="Date" width="180" />-->
<!-- <el-table-column prop="name" label="Name" width="180" />-->
<!-- <el-table-column prop="address" label="Address" />-->
<!-- </el-table>-->
<!-- </el-tab-pane>-->
<!-- <el-tab-pane label="网页/移动应用" name="web">-->
<!-- </el-tab-pane>-->
<!-- </el-tabs>-->
<!-- </el-card>-->
<el-card shadow="hover" class="flash mt-4 bg-white hover:shadow ">
<template #header>开发工具推荐</template>
<el-row :gutter="16">
<template v-for="(item,index) in list" :key="index">
<el-col :span="6" @click="openSpmUrl(`https://${item.tenantId}.websoft.top/token-login`,item,item.tenantId)">
<div class="app-item block border-solid rounded-lg border-gray-300 border-1 mb-4 p-3 flex flex-row items-center hover:border-blue-4 hover:border-1.5 cursor-pointer">
<div class="info ml-2">
<div class="app-item-title">{{ item.tenantName }}</div>
<div class="app-item-desc text-gray-400">{{ item.comments }}</div>
</div>
</div>
</el-col>
</template>
</el-row>
</el-card>
</el-main>
<el-footer class="fixed bottom-0 items-center flex justify-center text-gray-400" :style="{ width: 'calc(100vw - 200px)' }">
<span>Copyright © {{ new Date().getFullYear() }} {{ config?.copyright }}</span>
</el-footer>
</el-container>
</el-container>
</el-container>
</div>
</template>
<script setup lang="ts">
import {useConfigInfo, useToken, useWebsite} from "~/composables/configState";
import useFormData from '@/utils/use-form-data';
import type { User } from '@/api/system/user/model';
import { ref } from 'vue'
import {useServerRequest} from "~/composables/useServerRequest";
import type {ApiResult, PageResult} from "~/api";
import type {Company} from "~/api/system/company/model";
import type {Tenant} from "~/api/system/tenant/model";
//
const runtimeConfig = useRuntimeConfig();
const route = useRoute();
const website = useWebsite()
const config = useConfigInfo();
const token = useToken();
const userInfo = ref<User>();
const visible = ref(false);
const showIcon = ref(false);
const activeIndex = ref('mp-weixin');
const list = ref<Tenant[]>();
const menus = ref<Menu[]>();
const avatar = ref(localStorage.getItem('avatar'))
import {
Document,
Menu as IconMenu,
Location,
Expand,
MoreFilled,
Grid,
Memo,
Close,
Star,
Setting,
} from '@element-plus/icons-vue'
import {navigateTo} from "#imports";
import type {Menu} from "~/api/system/menu/model";
const handleOpen = (key: string, keyPath: string[]) => {
console.log(key, keyPath)
}
const handleClose = (key: string, keyPath: string[]) => {
console.log(key, keyPath)
}
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
]
//
const { form, assignFields } = useFormData<User>({
userId: undefined,
nickname: '',
username: '',
phone: '',
mobile: '',
sex: '',
sexName: '',
email: '',
password: '',
code: '',
smsCode: '',
comments: '',
remember: true
});
useHead({
title: `用户中心 - ${config.value?.siteName}`,
meta: [{ name: website.value.keywords, content: website.value.comments }]
});
function handleCommand(command: string) {
switch (command) {
case 'logOut':
logOut();
break;
default:
navigateTo('/user');
break;
}
}
function logOut() {
token.value = ''
navigateTo('/passport/login')
}
const onDone = (index: string) => {
activeIndex.value = index;
}
const onSubmit = async () => {
const {data: modify } = await useServerRequest<ApiResult<User>>('/auth/user',{
baseURL: runtimeConfig.public.apiServer,
method: 'put',
body: form
})
if(modify.value?.code == 0){
ElMessage.success('修改成功')
}
}
const handleSearch = () => {
console.log('搜索')
}
const getUserInfo = async () => {
const {data: response} = await useServerRequest<ApiResult<User>>('/auth/user',{baseURL: runtimeConfig.public.apiServer})
if(response.value?.data){
userInfo.value = response.value?.data;
}
}
const reload = async () => {
const {data: response} = await useServerRequest<ApiResult<PageResult<Tenant>>>('/system/tenant/page',{baseURL: runtimeConfig.public.apiServer, params: {
userId: localStorage.getItem('UserId')
}})
if(response.value?.data){
console.log(response.value,'tenantList')
if (response.value?.data.list) {
list.value = response.value?.data.list;
}
}
const {data: response2} = await useServerRequest<ApiResult<PageResult<Menu>>>('/system/menu',{baseURL: runtimeConfig.public.apiServer, params: {
parentId: 64688,
menuType: 0,
hide: 0
}})
if(response2.value?.data){
if (response2.value?.data) {
menus.value = response2.value.data
}
}
}
watch(
() => route.path,
() => {
reload();
getUserInfo();
},
{ immediate: true }
);
</script>
<style lang="less">
.el-row {
margin-bottom: 20px;
}
.el-row:last-child {
margin-bottom: 0;
}
.el-col {
border-radius: 4px;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
</style>

358
pages/manage/shop/index.vue

@ -1,358 +0,0 @@
<template>
<div class="common-layout">
<el-container>
<!-- 顶部菜单 -->
<el-header class="bg-black flex items-center justify-between" height="50px">
<el-space class="flex items-center">
<el-avatar src="https://oss.wsdns.cn/20240331/7f7f7f57e12c45338beb7bfc7ecccfe9.png" class="cursor-pointer" shape="square" :size="32" @click="navigateTo('/manage', { replace: false })" />
<div class="expand flex items-center justify-center block hover:bg-gray-700 h-[32px] w-[32px] cursor-pointer" @click="visible = !visible"><el-icon color="white" class="block" size="20"><Grid /></el-icon></div>
</el-space>
<template v-if="token">
<el-dropdown @command="handleCommand">
<el-avatar class="cursor-pointer" :src="userInfo?.avatar" :size="30" />
<el-button circle :icon="ElIconUserFilled" color="#155FAA"></el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="user">个人中心</el-dropdown-item>
<el-dropdown-item divided command="logOut" @click="navigateTo('/user/logout')">退出</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
</el-header>
<!-- 主体 -->
<el-container>
<!-- 左侧菜单区域 -->
<el-aside width="200px" class="bg-white" :style="{ minHeight: 'calc(100vh - 50px)' }">
<div class="flex items-center justify-between py-4 px-5 text-lg font-bold text-center bg-white border-b-1 border-b-gray-100 border-b-solid">
企业商城 EMall
<el-icon><Memo /></el-icon>
</div>
<el-menu
default-active="2"
class="el-menu-vertical-demo"
style="border: none"
@open="handleOpen"
@close="handleClose"
>
<el-menu-item index="1">
<span>概况</span>
</el-menu-item>
<el-menu-item index="2">
<span>栏目管理</span>
</el-menu-item>
<el-menu-item index="3">
<span>文章列表</span>
</el-menu-item>
<el-menu-item index="4">
<span>素材管理</span>
</el-menu-item>
<el-menu-item index="5">
<span>广告管理</span>
</el-menu-item>
<el-menu-item index="6">
<span>订单管理</span>
</el-menu-item>
<el-menu-item index="7">
<span>用户管理</span>
</el-menu-item>
<el-menu-item index="8">
<span>系统设置</span>
</el-menu-item>
</el-menu>
</el-aside>
<!-- 左侧内容区域 -->
<el-container>
<el-main class="overflow-y-hidden relative">
<div class="absolute inset-0 bg-black opacity-10 z-1" v-if="visible" @click="visible = false"></div>
<div v-if="visible" class="drawer w-screen-lg h-full bg-white left-0 top-[50px] fixed z-2 shadow-lg">
<div class="flex items-center justify-between p-3 border-b border-b-solid border-b-gray-200">
<div class="text-lg font-bold">产品与服务</div>
<el-space class="flex items-center">
<el-input
class="w-20"
placeholder="站内搜索"
:suffix-icon="ElIconSearch"
v-model="form.comments"
@keyup.enter.native="handleSearch"
/>
<!-- <el-input v-model="search" placeholder="搜索应用" class="w-[200px]" />-->
<div class="cursor-pointer mt-1 ml-5" @click="visible = false"><el-icon size="24" color="gray"><Close /></el-icon></div>
</el-space>
</div>
<div class="menu-content flex">
<div class="w-[200px] bg-gray-50">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
style="border-right: 1px solid #f9fafb"
@open="handleOpen"
@close="handleClose"
>
<el-menu-item index="2">
<span>精选</span>
</el-menu-item>
<el-menu-item index="3">
<span>网页</span>
</el-menu-item>
<el-menu-item index="4">
<span>移动</span>
</el-menu-item>
<el-menu-item index="5">
<span>办公</span>
</el-menu-item>
<el-menu-item index="6">
<span>其他</span>
</el-menu-item>
</el-menu>
</div>
<div class="w-full p-3">
<el-scrollbar class="w-full" height="calc(100vh - 108px)">
<el-row :gutter="16">
<template v-for="item in 20" :key="item">
<el-col :span="8">
<div class="px-3 py-1 mb-2 text-sm text-gray-700 font-bold flex justify-between items-center">API 与工具</div>
<p class="scrollbar-demo-item hover:bg-gray-100 px-3 py-1 mb-2 cursor-pointer text-sm text-gray-500 flex justify-between items-center">
<span class="product-name">{{ item }} 云服务器 ECS</span>
<span class="icon flex items-center hover:flex">
<el-icon color="gray"><Star /></el-icon>
</span>
</p>
</el-col>
</template>
</el-row>
</el-scrollbar>
</div>
</div>
</div>
<div class="my-3">
<el-alert type="warning">
<template #title>
<text type="text" class="cursor-pointer">关于小程序技术平台服务协议更新公告</text>
</template>
</el-alert>
</div>
<el-card shadow="hover" class="flash mt-4 bg-white hover:shadow rounded-lg">
<template #header>我的应用</template>
<el-row :gutter="16">
<template v-for="(item,index) in list" :key="index">
<el-col :span="6" @click="openSpmUrl(`https://${item.tenantId}.websoft.top/token-login`,item,item.tenantId)">
<div class="app-item block border-solid rounded-lg border-gray-300 border-1 bg-white mb-4 p-3 flex flex-row items-center hover:border-blue-4 hover:border-1.5 cursor-pointer">
<el-avatar :src="item?.logo" shape="square" />
<div class="info ml-2">
<div class="app-item-title font-bold flex items-center">{{ item.tenantName }}<el-tag type="warning" class="ml-2" size="small">网页</el-tag></div>
<div class="app-item-desc text-gray-400">{{ item.comments }}</div>
</div>
</div>
</el-col>
</template>
</el-row>
</el-card>
<!-- <el-card shadow="hover" class="mt-4">-->
<!-- <el-tabs v-model="activeIndex" type="">-->
<!-- <el-tab-pane label="微信小程序" name="mp-weixin">-->
<!-- <el-table :data="tableData" stripe style="width: 100%">-->
<!-- <el-table-column prop="date" label="Date" width="180" />-->
<!-- <el-table-column prop="name" label="Name" width="180" />-->
<!-- <el-table-column prop="address" label="Address" />-->
<!-- </el-table>-->
<!-- </el-tab-pane>-->
<!-- <el-tab-pane label="网页/移动应用" name="web">-->
<!-- </el-tab-pane>-->
<!-- </el-tabs>-->
<!-- </el-card>-->
<el-card shadow="hover" class="flash mt-4 bg-white hover:shadow ">
<template #header>开发工具推荐</template>
<el-row :gutter="16">
<template v-for="(item,index) in list" :key="index">
<el-col :span="6" @click="openSpmUrl(`https://${item.tenantId}.websoft.top/token-login`,item,item.tenantId)">
<div class="app-item block border-solid rounded-lg border-gray-300 border-1 mb-4 p-3 flex flex-row items-center hover:border-blue-4 hover:border-1.5 cursor-pointer">
<div class="info ml-2">
<div class="app-item-title">{{ item.tenantName }}</div>
<div class="app-item-desc text-gray-400">{{ item.comments }}</div>
</div>
</div>
</el-col>
</template>
</el-row>
</el-card>
</el-main>
<el-footer class="fixed bottom-0 items-center flex justify-center text-gray-400" :style="{ width: 'calc(100vw - 200px)' }">
<span>Copyright © {{ new Date().getFullYear() }} {{ config?.copyright }}</span>
</el-footer>
</el-container>
</el-container>
</el-container>
</div>
</template>
<script setup lang="ts">
import {useConfigInfo, useToken, useWebsite} from "~/composables/configState";
import useFormData from '@/utils/use-form-data';
import type { User } from '@/api/system/user/model';
import { ref } from 'vue'
import {useServerRequest} from "~/composables/useServerRequest";
import type {ApiResult, PageResult} from "~/api";
import type {Company} from "~/api/system/company/model";
import type {Tenant} from "~/api/system/tenant/model";
//
const runtimeConfig = useRuntimeConfig();
const route = useRoute();
const website = useWebsite()
const config = useConfigInfo();
const token = useToken();
const userInfo = ref<User>();
const visible = ref(false);
const showIcon = ref(false);
const activeIndex = ref('mp-weixin');
const list = ref<Tenant[]>();
const avatar = ref(localStorage.getItem('avatar'))
import {
Document,
Menu as IconMenu,
Location,
Expand,
MoreFilled,
Grid,
Memo,
Close,
Star,
Setting,
} from '@element-plus/icons-vue'
import {navigateTo} from "#imports";
const handleOpen = (key: string, keyPath: string[]) => {
console.log(key, keyPath)
}
const handleClose = (key: string, keyPath: string[]) => {
console.log(key, keyPath)
}
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
]
//
const { form, assignFields } = useFormData<User>({
userId: undefined,
nickname: '',
username: '',
phone: '',
mobile: '',
sex: '',
sexName: '',
email: '',
password: '',
code: '',
smsCode: '',
comments: '',
remember: true
});
useHead({
title: `用户中心 - ${config.value?.siteName}`,
meta: [{ name: website.value.keywords, content: website.value.comments }]
});
function handleCommand(command: string) {
switch (command) {
case 'logOut':
logOut();
break;
default:
navigateTo('/user');
break;
}
}
function logOut() {
token.value = ''
navigateTo('/passport/login')
}
const onDone = (index: string) => {
activeIndex.value = index;
}
const onSubmit = async () => {
const {data: modify } = await useServerRequest<ApiResult<User>>('/auth/user',{
baseURL: runtimeConfig.public.apiServer,
method: 'put',
body: form
})
if(modify.value?.code == 0){
ElMessage.success('修改成功')
}
}
const handleSearch = () => {
console.log('搜索')
}
const getUserInfo = async () => {
const {data: response} = await useServerRequest<ApiResult<User>>('/auth/user',{baseURL: runtimeConfig.public.apiServer})
if(response.value?.data){
userInfo.value = response.value?.data;
}
}
const reload = async () => {
const {data: response} = await useServerRequest<ApiResult<PageResult<Tenant>>>('/system/tenant/page',{baseURL: runtimeConfig.public.apiServer, params: {
userId: localStorage.getItem('UserId')
}})
if(response.value?.data){
console.log(response.value,'tenantList')
if (response.value?.data.list) {
list.value = response.value?.data.list;
}
}
}
watch(
() => route.path,
() => {
reload();
getUserInfo();
},
{ immediate: true }
);
</script>
<style lang="less">
.el-row {
margin-bottom: 20px;
}
.el-row:last-child {
margin-bottom: 0;
}
.el-col {
border-radius: 4px;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
</style>

56
pages/market/components/CardList.vue

@ -1,56 +0,0 @@
<template>
<div class="xl:w-screen-xl sm:flex xl:p-0 p-4 m-auto relative" v-infinite-scroll="load">
<el-row :gutter="24" class="flex">
<template v-for="(item,index) in list" :key="index">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb-5 min-w-xs">
<el-card shadow="hover" :body-style="{ padding: '0px' }" class="hover:bg-gray-50 cursor-pointer" @click="openSpmUrl(`/item`, item, item.productId,true)">
<el-image
:src="item.image"
fit="scale-down" :lazy="true" class="w-full md:h-[150px] h-[199px] cursor-pointer"/>
<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 items-center gap-1.5">
<span class="flex-1 text-xl cursor-pointer">{{ item.title }}</span>
<div class="text-red-500" v-if="item.price && item.price > 0">{{ item.price }}</div>
</div>
<div class="flex items-center gap-1.5 py-2 text-gray-500 justify-between">
<div class="text-gray-500">{{ item.comments }}</div>
</div>
<div class="button-group flex justify-center mt-3">
<el-button class="w-full" size="large" @click.stop="openSpmUrl(`/item`, item, item.productId,true)">查看详情</el-button>
<el-button type="primary" v-if="item.price && item.price > 0" size="large" class="w-full" :icon="ElIconShoppingCart" @click.stop="openSpmUrl(`/item`, item, item.productId,true)">购买
</el-button>
<el-button v-else class="w-full" size="large">下载插件</el-button>
</div>
</div>
</el-card>
</el-col>
</template>
</el-row>
</div>
<div v-if="disabled" class="px-1 text-center text-gray-500 min-h-xs">
没有更多了
</div>
</template>
<script setup lang="ts">
import {openSpmUrl} from "~/utils/common";
import dayjs from "dayjs";
const props = withDefaults(
defineProps<{
list?: any[];
disabled?: boolean;
}>(),
{}
);
const emit = defineEmits<{
(e: 'done'): void;
}>();
const load = () => {
if (!props.disabled) {
emit('done')
}
}
</script>

115
pages/market/components/PageBanner.vue

@ -1,115 +0,0 @@
<template>
<div class="banner m-auto relative sm:flex">
<svg viewBox="0 0 1440 181" fill="none" xmlns="http://www.w3.org/2000/svg"
class="pointer-events-none absolute w-full top-[-2px] transition-all text-green-5 flex-shrink-0 opacity-100 duration-[400ms] opacity-80 -z-10">
<mask id="path-1-inside-1_414_5526" fill="white">
<path d="M0 0H1440V181H0V0Z"></path>
</mask>
<path d="M0 0H1440V181H0V0Z" fill="url(#paint0_linear_414_5526)" fill-opacity="0.22"></path>
<path d="M0 2H1440V-2H0V2Z" fill="url(#paint1_linear_414_5526)" mask="url(#path-1-inside-1_414_5526)"></path>
<defs>
<linearGradient id="paint0_linear_414_5526" x1="720" y1="0" x2="720" y2="181" gradientUnits="userSpaceOnUse">
<stop stop-color="currentColor"></stop>
<stop offset="1" stop-color="currentColor" stop-opacity="0"></stop>
</linearGradient>
<linearGradient id="paint1_linear_414_5526" x1="0" y1="90.5" x2="1440" y2="90.5" gradientUnits="userSpaceOnUse">
<stop stop-color="currentColor" stop-opacity="0"></stop>
<stop offset="0.395" stop-color="currentColor"></stop>
<stop offset="1" stop-color="currentColor" stop-opacity="0"></stop>
</linearGradient>
</defs>
</svg>
<div class="md:w-screen-xl m-auto md:p-0 px-4">
<div class="py-8 sm:py-16" _path="/templates" _dir="" _draft="false" _partial="false" _locale=""
_id="content:4.templates.yml" _type="yaml" _source="content" _file="4.templates.yml" _stem="4.templates"
_extension="yml">
<div class="gap-8 sm:gap-y-16 grid lg:grid-cols-2 lg:items-center" v-if="layout">
<div class="">
<h1
class="text-3xl font-bold tracking-tight text-gray-900 dark:text-white sm:text-4xl lg:text-5xl">
<span v-if="layout.title">{{ layout.title }}</span>
<span v-if="layout.name">{{ layout.name }}</span>
</h1>
<div class="mt-4 text-lg text-gray-500 dark:text-gray-400">
{{ layout.description }}
</div>
<div class="flex justify-between w-full items-center mt-4">
<el-space>
<div class="w-[500px]">
<el-input
v-model="where.keywords"
placeholder="搜索"
:prefix-icon="Search"
@keydown.enter="handleClick"
>
<template #append>
<el-button size="large" type="primary" @click="handleClick">搜索</el-button>
</template>
</el-input>
</div>
<el-button
size="large"
@click="openSpmUrl(`https://${sysDomain}/token-login`)"
>
创建应用
</el-button>
</el-space>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { Search } from '@element-plus/icons-vue'
import {useConfigInfo} from "~/composables/configState";
import {openSpmUrl} from "~/utils/common";
import type {CompanyParam} from "~/api/system/company/model";
const token = useToken();
const sysDomain = useSysDomain();
withDefaults(
defineProps<{
layout?: any;
title?: string;
desc?: string;
buyUrl?: string;
}>(),
{
title: 'Templates',
desc: 'Explore community templates to get up and running in a few seconds.',
demoUrl: '/product/website',
buyUrl: 'https://github.com/websoft9/ansible-templates'
}
);
//
const where = reactive<CompanyParam>({
keywords: ''
});
const config = useConfigInfo();
//
const handleClick = async () => {
if (where.keywords == '') {
return false;
}
if(activeName.value == 'web'){
const {data: response} = await useServerRequest<ApiResult<PageResult<Website>>>('/cms/cms-website/page',{baseURL: runtimeConfig.public.apiServer, params: {
page: page.value, keywords: where.keywords
}})
if(response.value?.data){
if (response.value?.data.list) {
websites.value = response.value?.data.list;
}
if(response.value.data.count == 0){
resultText.value = '暂无相关结果'
}
}
}
}
</script>

114
pages/market/detail/[plugId].vue

@ -1,114 +0,0 @@
<!-- 文章详情 -->
<template>
<PageContainer :form="form" />
<div class="page-main md:w-screen-xl m-auto bg-white rounded-lg">
<div class="p-4 leading-7" v-html="form?.content">
</div>
</div>
</template>
<script setup lang="ts">
import type {ApiResult} from "~/api";
import {useServerRequest} from "~/composables/useServerRequest";
import {useWebsite} from "~/composables/configState";
import type {BreadcrumbItem} from "~/types/global";
import type {Navigation} from "~/api/cms/navigation/model";
import {getIdBySpm} from "~/utils/common";
import type {Article} from "~/api/cms/article/model";
import useFormData from "~/utils/use-form-data";
//
const route = useRoute();
const website = useWebsite();
const breadcrumb = ref<BreadcrumbItem>();
//
const { form, assignFields } = useFormData<Article>({
// id
articleId: undefined,
//
title: undefined,
//
type: undefined,
//
showType: undefined,
//
categoryId: undefined,
//
categoryName: undefined,
parentId: undefined,
parentName: undefined,
//
image: undefined,
//
files: undefined,
//
thumbnail: undefined,
//
video: undefined,
//
accept: undefined,
//
source: undefined,
//
content: undefined,
//
virtualViews: undefined,
//
actualViews: undefined,
// ID
userId: undefined,
//
nickname: undefined,
//
username: undefined,
//
userAvatar: undefined,
// ID
shopId: undefined,
//
likes: undefined,
//
sortNumber: undefined,
//
comments: undefined,
//
status: undefined,
//
createTime: undefined,
//
updateTime: undefined
});
//
const reload = async () => {
// spm()
const { data: nav } = await useServerRequest<ApiResult<Navigation>>('/cms/cms-article/' + getIdBySpm(5))
if (nav.value?.data) {
assignFields(nav.value.data)
}
// seo
useHead({
title: `${form.title} - ${website.value.websiteName}`,
bodyAttrs: {
class: "page-container",
}
});
//
breadcrumb.value = form
}
watch(
() => route.path,
(path) => {
console.log(path,'=>Path')
reload();
},
{ immediate: true }
);
</script>

99
pages/market/detail/components/Header.vue

@ -1,99 +0,0 @@
<template>
<div class="banner m-auto relative sm:flex">
<svg viewBox="0 0 1440 181" fill="none" xmlns="http://www.w3.org/2000/svg"
class="pointer-events-none absolute w-full top-[-2px] transition-all text-green-5 flex-shrink-0 opacity-100 duration-[400ms] opacity-80 -z-10">
<mask id="path-1-inside-1_414_5526" fill="white">
<path d="M0 0H1440V181H0V0Z"></path>
</mask>
<path d="M0 0H1440V181H0V0Z" fill="url(#paint0_linear_414_5526)" fill-opacity="0.22"></path>
<path d="M0 2H1440V-2H0V2Z" fill="url(#paint1_linear_414_5526)" mask="url(#path-1-inside-1_414_5526)"></path>
<defs>
<linearGradient id="paint0_linear_414_5526" x1="720" y1="0" x2="720" y2="181" gradientUnits="userSpaceOnUse">
<stop stop-color="currentColor"></stop>
<stop offset="1" stop-color="currentColor" stop-opacity="0"></stop>
</linearGradient>
<linearGradient id="paint1_linear_414_5526" x1="0" y1="90.5" x2="1440" y2="90.5" gradientUnits="userSpaceOnUse">
<stop stop-color="currentColor" stop-opacity="0"></stop>
<stop offset="0.395" stop-color="currentColor"></stop>
<stop offset="1" stop-color="currentColor" stop-opacity="0"></stop>
</linearGradient>
</defs>
</svg>
<div class="md:w-screen-xl m-auto">
<Breadcrumb :data="form" />
<div class="py-8 sm:py-16" _path="/templates" _dir="" _draft="false" _partial="false" _locale=""
_id="content:4.templates.yml" _type="yaml" _source="content" _file="4.templates.yml" _stem="4.templates"
_extension="yml">
<div class="gap-8 sm:gap-y-16 lg:items-center" v-if="form">
<div class="w-full">
<h1
class="text-2xl font-bold tracking-tight text-gray-900 dark:text-white sm:text-3xl lg:text-4xl">
<span v-if="form.title">{{ form.title }}</span>
</h1>
<div class="mt-4 text-gray-500 dark:text-gray-400">
<span>{{ form.nickname }}</span> · {{ form.createTime }}
</div>
<el-space class="mt-4">
<el-button
:icon="ElIconView"
size="large"
v-if="form.demoUrl"
@click="openSpmUrl(form.demoUrl)"
>
演示地址
</el-button>
<el-button
v-if="form.buyUrl"
:icon="ElIconBottom"
size="large"
@click="openSpmUrl(form.buyUrl)"
>
下载模版
</el-button>
<el-button
:icon="ElIconMemo"
size="large"
v-if="form.docUrl"
@click="openSpmUrl(form.docUrl)"
>
帮助文档
</el-button>
</el-space>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import {useConfigInfo} from "~/composables/configState";
import {openSpmUrl} from "~/utils/common";
import Breadcrumb from "~/components/Breadcrumb.vue";
import type {Article} from "~/api/cms/article/model";
const token = useToken();
const sysDomain = useSysDomain();
withDefaults(
defineProps<{
form?: Article;
title?: string;
desc?: string;
buyUrl?: string;
}>(),
{
title: 'Templates',
desc: 'Explore community templates to get up and running in a few seconds.',
demoUrl: '/product/website',
buyUrl: 'https://github.com/websoft9/ansible-templates'
}
);
const config = useConfigInfo();
</script>

103
pages/market/index.vue

@ -1,103 +0,0 @@
<template>
<PageBanner :layout="layout" />
<el-tabs v-model="activeName" class="md:w-screen-xl m-auto relative sm:flex pb-2" @tab-click="handleClick">
<el-tab-pane label="最新上架" name="happy"></el-tab-pane>
<el-tab-pane label="免费热榜" name="website"></el-tab-pane>
<el-tab-pane label="付费热榜" name="weShop"></el-tab-pane>
<el-tab-pane label="热门总榜" name="cms"></el-tab-pane>
<el-tab-pane label="我的收藏" name="food"></el-tab-pane>
</el-tabs>
<!-- <el-checkbox-group v-model="checkList" class="md:w-screen-xl m-auto relative sm:flex hidden pb-2">-->
<!-- <el-checkbox label="菜单" value="menu" />-->
<!-- <el-checkbox label="插件" value="plug" />-->
<!-- <el-checkbox label="应用" value="app" />-->
<!-- <el-checkbox label="前端" value="" />-->
<!-- </el-checkbox-group>-->
<CardList :list="list" :disabled="disabled" @done="onSearch" />
</template>
<script setup lang="ts">
import type {ApiResult, PageResult} from "~/api";
import {useServerRequest} from "~/composables/useServerRequest";
import {useWebsite} from "~/composables/configState";
import type {Navigation} from "~/api/cms/navigation/model";
import type {CompanyParam} from "~/api/system/company/model";
import CardList from './components/CardList.vue';
import PageBanner from './components/PageBanner.vue';
import type {CmsProduct} from "~/api/cms/cmsProduct/model";
const route = useRoute();
//
const runtimeConfig = useRuntimeConfig();
const list = ref<CmsProduct[]>([]);
const page = ref<number>(1);
const resultText = ref('');
const layout = ref<any>();
const disabled = ref<boolean>(false);
const activeName = ref(undefined)
const checkList = ref(['Value selected and disabled', 'Value A'])
//
const form = ref<Navigation>();
const website = useWebsite();
//
const where = reactive<CompanyParam>({
keywords: ''
});
const handleClick = (e:any) => {
console.log(e.index)
}
const onSearch = () => {
if(!disabled.value){
page.value++;
reload(route.path);
}
}
//
const reload = async (path: string) => {
const {data: response} = await useServerRequest<ApiResult<PageResult<CmsProduct>>>('/cms/cms-product/page',{baseURL: runtimeConfig.public.apiServer, params: {
page: page.value,limit: 8, keywords: where.keywords
}})
if(response.value?.data){
if (list.value.length < response.value?.data.count) {
disabled.value = false;
if (response.value?.data.list) {
list.value = list.value.concat(response.value?.data.list);
}
}else {
disabled.value = true;
}
if(response.value.data.count == 0){
resultText.value = '暂无相关结果'
}
}
}
const { data: nav } = await useServerRequest<ApiResult<Navigation>>('/cms/cms-navigation/getNavigationByPath',{query: {path: route.path}})
if(nav.value?.data){
form.value = nav.value?.data;
}
//
if(form.value?.layout){
layout.value = JSON.parse(form.value?.layout)
}
useHead({
title: `市场 - ${website.value.websiteName}`,
bodyAttrs: {
class: "page-container",
}
});
watch(
() => route.path,
(path) => {
reload(path);
},
{ immediate: true }
);
</script>

82
pages/merchant/index.vue

@ -1,82 +0,0 @@
<template>
</template>
<script setup lang="ts">
import type {ApiResult} from "~/api";
import {useServerRequest} from "~/composables/useServerRequest";
import {useConfigInfo, useForm, useToken, useWebsite} from "~/composables/configState";
import type {BreadcrumbItem} from "~/types/global";
import type {Navigation} from "~/api/cms/navigation/model";
import {getIdBySpm} from "~/utils/common";
//
const route = useRoute();
const user = useUser();
const layout = ref<any>();
const config = useConfigInfo();
const token = useToken();
const form = useForm();
const breadcrumb = ref<BreadcrumbItem>();
//
const reload = async () => {
// spm()
const {data: nav} = await useServerRequest<ApiResult<Navigation>>('/cms/cms-navigation/' + getIdBySpm(5))
if (nav.value?.data) {
form.value = nav.value.data
} else {
const {data: nav} = await useServerRequest<ApiResult<Navigation>>('/cms/cms-navigation/getNavigationByPath', {query: {path: route.path}})
if (nav.value?.data) {
form.value = nav.value?.data;
}
}
//
if (form.value?.layout) {
layout.value = JSON.parse(form.value?.layout)
}
// ()
if (!token.value || token.value == '') {
if (config.value.MustLogin) {
navigateTo('/passport/login');
return false;
}
}
//
if(!user.value?.merchantId){
navigateTo('/user/auth');
return false;
}
//
if(user.value.merchantId){
console.log('已认证未开发者>')
}
// seo
useHead({
title: `现代Web应用开发(Vue)框架 · WEBSOFT`,
meta: [{name: form.value.design?.keywords, content: form.value.design?.description}],
bodyAttrs: {
class: "page-container",
},
script: [
{
children: `console.log(${JSON.stringify(form.value)})`,
},
],
});
//
breadcrumb.value = form.value
}
watch(
() => route.path,
(path) => {
console.log(path, '=>Path')
reload();
},
{immediate: true}
);
</script>

174
pages/merchant/join-in.vue

@ -1,174 +0,0 @@
<template>
<div class="login-layout mt-[100px] m-auto sm:w-screen-xl w-full">
<div class="mt-[100px] m-auto flex sm:flex-row flex-col sm:p-0 p-3">
<!-- 用户菜单 -->
<UserMenu :activeIndex="activeIndex" @done="onDone" />
<div class="flash ml-8 bg-white rounded-lg px-7 py-4 w-full">
<el-tabs class="flash bg-white ml-0">
<el-tab-pane label="个人认证">
<el-form :model="form" label-width="auto" size="large" label-position="top" class="sm:w-screen-md w-full sm:py-2">
<el-form-item label="真实姓名">
<el-input v-model="form.realName" placeholder="请输入真实姓名" />
</el-form-item>
<el-form-item label="证件号码">
<el-input v-model="form.idCard" placeholder="请输入证件号码" />
</el-form-item>
<el-form-item label="身份证(正面)">
<Upload />
</el-form-item>
<el-form-item label="身份证(反面)">
<Upload />
</el-form-item>
<el-form-item>
<el-button type="primary" size="large" @click="onSubmit">提交</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="企业认证">
<el-form :model="form" label-width="auto" size="large" label-position="top" class="sm:w-screen-md w-full sm:py-2">
<el-form-item label="企业名称">
<el-input v-model="form.companyName" placeholder="请输入企业名称" />
</el-form-item>
<el-form-item label="社会信用代码">
<el-input v-model="form.idCard" placeholder="请输入社会信用代码" />
</el-form-item>
<el-form-item label="营业执照">
<Upload />
</el-form-item>
<el-form-item label="所属行业">
<el-select v-model="form.city" placeholder="请选择所属行业">
</el-select>
</el-form-item>
<el-form-item label="网站信息">
<el-input v-model="form.idCard" placeholder="请输入网站信息" />
</el-form-item>
<el-form-item label="您的身份">
<el-radio-group v-model="form.sex">
<el-radio value="1">法定代表人</el-radio>
<el-radio value="2">被授权人</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="用户协议">
<el-checkbox v-model="form.status">请务必提供真实信息我司有权自行或委托第三方审查您提供的身份信息是否属真实有效若提供虚假信息由此的全部后果由您承担</el-checkbox>
</el-form-item>
<el-form-item>
<el-button type="primary" size="large" @click="onSubmit">提交</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="个人认证成功">
<el-result
icon="success"
title="个人认证成功"
sub-title="认证完成时间 2024-09-30"
>
<template #extra>
<el-button type="text">修改认证信息</el-button>
</template>
</el-result>
</el-tab-pane>
<el-tab-pane label="企业认证成功">
<el-result
icon="success"
title="企业认证成功"
sub-title="认证完成时间 2024-09-30"
>
<template #extra>
<el-button type="text">修改认证信息</el-button>
</template>
</el-result>
</el-tab-pane>
</el-tabs>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import {useConfigInfo, useToken, useWebsite} from "~/composables/configState";
import useFormData from '@/utils/use-form-data';
import type { User } from '@/api/system/user/model';
import { ref } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import {useServerRequest} from "~/composables/useServerRequest";
import type {ApiResult} from "~/api";
import UserMenu from "~/components/UserMenu.vue";
//
const runtimeConfig = useRuntimeConfig();
const route = useRoute();
const activeIndex = ref('');
const website = useWebsite()
const config = useConfigInfo();
const token = useToken();
const userInfo = ref<User>();
//
const { form, assignFields } = useFormData<User>({
userId: undefined,
nickname: '',
username: '',
phone: '',
mobile: '',
sex: '',
sexName: '',
email: '',
password: '',
code: '',
smsCode: '',
comments: '',
remember: true
});
useHead({
title: `用户中心 - ${config.value?.siteName}`,
meta: [{ name: website.value.keywords, content: website.value.comments }]
});
const onSubmit = async () => {
const {data: modify } = await useServerRequest<ApiResult<User>>('/auth/user',{
baseURL: runtimeConfig.public.apiServer,
method: 'put',
body: form
})
if(modify.value?.code == 0){
ElMessage.success('修改成功')
}
}
const handleAvatarSuccess: UploadProps['onSuccess'] = (
response,
uploadFile
) => {
imageUrl.value = URL.createObjectURL(uploadFile.raw!)
}
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
if (rawFile.type !== 'image/jpeg') {
ElMessage.error('Avatar picture must be JPG format!')
return false
} else if (rawFile.size / 1024 / 1024 > 2) {
ElMessage.error('Avatar picture size can not exceed 2MB!')
return false
}
return true
}
const reload = async () => {
const {data: response} = await useServerRequest<ApiResult<User>>('/auth/user',{baseURL: runtimeConfig.public.apiServer})
if(response.value?.data){
userInfo.value = response.value?.data;
assignFields(response.value?.data);
}
}
watch(
() => route.path,
(path) => {
activeIndex.value = path;
console.log(path,'=>Path')
reload();
},
{ immediate: true }
);
</script>

105
pages/product/[id].vue

@ -1,105 +0,0 @@
<template>
<!-- Banner -->
<Banner :layout="layout" />
333
<div class="container md:w-screen-xl m-auto">
<div class="flex flex-col" v-if="app">
<Breadcrumb :data="form" :title="`应用详情`" />
<div class="page-main w-full bg-white rounded-lg">
<div class="p-4 leading-7">
<div class="goods-info flex">
<el-avatar :src="app.appIcon" class="mr-2" size="large" />
<div class="flex flex-col ml-2">
<div class="text-lg">{{ app.appName }}</div>
<div class="text-gray-400 w-screen-lg">{{ app.comments }}</div>
<div>应用ID: <span class="text-blue-500">{{ app.appId }}</span></div>
<div>后台演示: <span class="text-blue-500">{{ app.adminUrl }}</span></div>
<div>前端演示: <span class="text-blue-500">{{ app.appUrl }}</span></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 空白页 -->
<div class="mt-[60px]" v-if="!app">
<el-empty description="404 页面不存在"></el-empty>
</div>
</template>
<script setup lang="ts">
import { Search } from '@element-plus/icons-vue'
import type {ApiResult, PageResult} from "~/api";
import {useServerRequest} from "~/composables/useServerRequest";
import {useWebsite} from "~/composables/configState";
import type {Navigation} from "~/api/cms/navigation/model";
import {getIdByParam, getPath} from "~/utils/common";
import type {Company, CompanyParam} from "~/api/system/company/model";
import {navigateTo} from "#imports";
import Breadcrumb from "~/components/Breadcrumb.vue";
import type {App} from "~/api/oa/app/model";
const route = useRoute();
//
const runtimeConfig = useRuntimeConfig();
const resultText = ref('');
const layout = ref<any>();
//
const form = ref<Navigation>();
const website = useWebsite();
const app = ref<App>()
//
const where = reactive<CompanyParam>({
keywords: ''
});
const navTo = (item: Company) => {
navigateTo(`/market/${item.companyId}`)
}
//
const reload = async () => {
const { data: nav } = await useServerRequest<ApiResult<Navigation>>('/cms/cms-navigation/getNavigationByPath',{query: {path: getPath()}})
if(nav.value?.data){
form.value = nav.value?.data;
}
//
if(form.value?.layout){
layout.value = JSON.parse(form.value?.layout)
}
useHead({
title: `搜索结果 - ${website.value.websiteName}`,
bodyAttrs: {
class: "page-container",
}
});
await handleClick()
}
//
const handleClick = async () => {
const {data: response} = await useServerRequest<ApiResult<App>>(`/oa/oa-app/${getIdByParam()}`,{baseURL: runtimeConfig.public.apiServer})
if(response.value?.data){
if (response.value.data) {
app.value = response.value.data
}
if(!response.value){
resultText.value = '暂无相关结果'
}
}
}
watch(
() => route,
() => {
reload();
},
{ immediate: true }
);
</script>

219
pages/product/checkout/index.vue

@ -1,219 +0,0 @@
<template>
<div class="lg:w-screen-xl w-full m-auto">
<Breadcrumb title="订单确认"/>
</div>
<div class="page-main md:w-screen-xl m-auto p-3">
<el-row :gutter="24">
<el-col :span="16" :xs="24">
<el-card shadow="hover" class="mb-4">
<template #header>
<div class="card-header font-bold">
<span>订单确认</span>
</div>
</template>
<el-descriptions title="云·企业官网(SaaS交付)" :column="1" class="mb-4">
<el-descriptions-item label="套餐版本:">标准版需备案</el-descriptions-item>
<el-descriptions-item label="购买时长:">1</el-descriptions-item>
</el-descriptions>
<el-descriptions title="设计服务" :column="1" class="mb-4">
<el-descriptions-item label="是否需要设计:">需要</el-descriptions-item>
<el-descriptions-item label="套餐版本:">标准版</el-descriptions-item>
</el-descriptions>
<el-descriptions title="合计:" :column="1" class="mb-4">
<el-descriptions-item label="总价格:">3000.00</el-descriptions-item>
<el-descriptions-item label="优惠价格:">1280.00</el-descriptions-item>
</el-descriptions>
</el-card>
<el-card shadow="hover" class="mb-4">
<template #header>
<div class="card-header font-bold">
<span>服务协议</span>
</div>
</template>
<div class="flex items-center">
<el-checkbox v-model="isAgree"></el-checkbox>
<span class="ml-1">我已阅读并同意</span>
<span class="text-blue-400 hover:text-blue-500 cursor-pointer" @click="openSpmUrl(`/article/374`, {}, 0, true)">计算机软件著作权登记服务纸质登记专属条款</span>
</div>
</el-card>
</el-col>
<el-col :span="8" :xs="24">
<el-card shadow="hover" class="mb-4">
<template #header>
<div class="card-header font-bold">
<span>扫码支付</span>
</div>
</template>
<div class="flex justify-center">
<el-radio-group v-model="form.code">
<el-radio-button value="1" border>微信支付</el-radio-button>
<el-radio-button value="12" border>支付宝</el-radio-button>
<el-radio-button value="24" border>余额支付</el-radio-button>
</el-radio-group>
</div>
<div class="flex justify-center py-4">
<el-avatar :size="250" src="https://oss.wsdns.cn/20240409/247a492abda94b08ace33fa5405628ca.jpeg"
shape="square" />
</div>
<el-form-item>
<el-button type="danger" :disabled="!isAgree" class="w-full" size="large" @click="onSubmit">去支付</el-button>
</el-form-item>
</el-card>
</el-col>
</el-row>
</div>
<!-- <div class="login-layout mt-[100px] m-auto sm:w-screen-xl w-full">-->
<!-- <div class="mt-[100px] m-auto flex sm:flex-row flex-col sm:p-0 p-3">-->
<!-- <div class="flash bg-white rounded-lg px-7 py-4 w-full">-->
<!-- <el-tabs class="flash bg-white ml-0">-->
<!-- <el-tab-pane label="个人开发者">-->
<!-- <el-form :model="form" label-width="auto" size="large" label-position="top" class="sm:w-screen-md w-full sm:py-2">-->
<!-- <el-form-item label="商品类型">-->
<!-- <el-input v-model="form.title" placeholder="请输入真实姓名" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="资源包类型">-->
<!-- <el-input v-model="form.productId" placeholder="请输入证件号码" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="身份证(正面)">-->
<!-- <Upload />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="身份证(反面)">-->
<!-- <Upload />-->
<!-- </el-form-item>-->
<!-- <el-form-item>-->
<!-- <el-button type="primary" size="large" @click="onSubmit">提交</el-button>-->
<!-- </el-form-item>-->
<!-- </el-form>-->
<!-- </el-tab-pane>-->
<!-- </el-tabs>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
</template>
<script setup lang="ts">
import {useConfigInfo, useToken, useWebsite} from "~/composables/configState";
import useFormData from '@/utils/use-form-data';
import type {User} from '@/api/system/user/model';
import {ref} from 'vue'
import {useServerRequest} from "~/composables/useServerRequest";
import type {ApiResult} from "~/api";
import type {Product} from "~/api/oa/product/model";
import Breadcrumb from "~/components/Breadcrumb.vue";
//
const runtimeConfig = useRuntimeConfig();
const route = useRoute();
const activeIndex = ref('');
const website = useWebsite()
const isAgree = ref<boolean>(false);
const config = useConfigInfo();
const token = useToken();
const userInfo = ref<User>();
//
const {form, assignFields} = useFormData<Product>({
// ID
productId: undefined,
// 0 1 2
type: undefined,
//
code: undefined,
//
title: undefined,
//
image: undefined,
//
content: undefined,
// ID
parentId: undefined,
// ID
categoryId: undefined,
// 0 1
specs: undefined,
//
position: undefined,
// ()
unitName: undefined,
//
price: undefined,
//
salePrice: undefined,
// (10 20)
deductStockType: undefined,
//
files: undefined,
//
sales: undefined,
//
stock: undefined,
//
gainIntegral: undefined,
//
recommend: undefined,
// ID
merchantId: undefined,
// 01
isShow: undefined,
// , 0 1 2 3
status: undefined,
//
comments: undefined,
//
sortNumber: undefined,
// ID
userId: undefined,
// , 0, 1
deleted: undefined,
// id
tenantId: undefined,
//
createTime: undefined,
//
updateTime: undefined,
});
const handleChange = (e) => {
console.log(e)
}
const onSubmit = async () => {
const {data: modify} = await useServerRequest<ApiResult<User>>('/auth/user', {
baseURL: runtimeConfig.public.apiServer,
method: 'put',
body: form
})
if (modify.value?.code == 0) {
ElMessage.success('修改成功')
}
}
const reload = async () => {
const {data: response} = await useServerRequest<ApiResult<Product>>(`/cms/cms-product/${getIdBySpm(5)}`, {baseURL: runtimeConfig.public.apiServer})
if (response.value?.data) {
assignFields(response.value?.data);
form.categoryName = '立即开通'
useHead({
title: `${form.title}`,
meta: [{name: website.value.keywords, content: website.value.comments}]
});
}
}
watch(
() => route.path,
(path) => {
activeIndex.value = path;
console.log(path, '=>Path')
reload();
},
{immediate: true}
);
</script>
<style lang="scss">
.text-a123 {
color: #f0f2f5;
}
</style>

53
pages/product/components/CardList.vue

@ -1,53 +0,0 @@
<template>
<div class="xl:w-screen-xl sm:flex xl:p-0 p-4 m-auto relative" v-infinite-scroll="load">
<el-row :gutter="24" class="flex">
<template v-for="(item,index) in list" :key="index">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb-5 min-w-xs">
<el-card shadow="hover" :body-style="{ padding: '0px' }" class="hover:bg-gray-50 cursor-pointer" @click="openSpmUrl(`/item`, item, item.productId,true)">
<el-image :src="`${item.image}`" fit="contain" :lazy="true" class="w-full md:h-[150px] h-[199px] cursor-pointer" />
<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="flex-1 text-xl cursor-pointer">{{ item.title }}</div>
<div class="text-red-500">{{ item.price }} </div>
</div>
<div v-if="item.price && item.price > 0" class="flex items-center gap-1.5 py-2 text-gray-500 justify-between">
<div class="text-gray-500">{{ item.comments }}</div>
</div>
<div class="button-group flex justify-center mt-3">
<el-button type="primary" class="w-full" size="large" :icon="ElIconView" @click.stop="openSpmUrl(`/product/create`,item,item.productId,true)">立即开通</el-button>
<el-button size="large" class="w-full" @click.stop="openSpmUrl(`https://10241.websoft.top/system/user`,item, item.productId,true)">产品控制台</el-button>
</div>
</div>
</el-card>
</el-col>
</template>
</el-row>
</div>
<div v-if="disabled" class="px-1 text-center text-gray-500 min-h-xs">
没有更多了
</div>
</template>
<script setup lang="ts">
import {openSpmUrl} from "~/utils/common";
import dayjs from "dayjs";
import type {CmsProduct} from "~/api/cms/cmsProduct/model";
const props = withDefaults(
defineProps<{
list?: CmsProduct[];
disabled?: boolean;
}>(),
{}
);
const emit = defineEmits<{
(e: 'done'): void;
}>();
const load = () => {
if(!props.disabled){
emit('done')
}
}
</script>

93
pages/product/create/components/PageBanner.vue

@ -1,93 +0,0 @@
<template>
<div class="banner m-auto relative sm:flex">
<svg viewBox="0 0 1440 181" fill="none" xmlns="http://www.w3.org/2000/svg"
class="pointer-events-none absolute w-full top-[-2px] transition-all text-green-5 flex-shrink-0 opacity-100 duration-[400ms] opacity-80 -z-10">
<mask id="path-1-inside-1_414_5526" fill="white">
<path d="M0 0H1440V181H0V0Z"></path>
</mask>
<path d="M0 0H1440V181H0V0Z" fill="url(#paint0_linear_414_5526)" fill-opacity="0.22"></path>
<path d="M0 2H1440V-2H0V2Z" fill="url(#paint1_linear_414_5526)" mask="url(#path-1-inside-1_414_5526)"></path>
<defs>
<linearGradient id="paint0_linear_414_5526" x1="720" y1="0" x2="720" y2="181" gradientUnits="userSpaceOnUse">
<stop stop-color="currentColor"></stop>
<stop offset="1" stop-color="currentColor" stop-opacity="0"></stop>
</linearGradient>
<linearGradient id="paint1_linear_414_5526" x1="0" y1="90.5" x2="1440" y2="90.5" gradientUnits="userSpaceOnUse">
<stop stop-color="currentColor" stop-opacity="0"></stop>
<stop offset="0.395" stop-color="currentColor"></stop>
<stop offset="1" stop-color="currentColor" stop-opacity="0"></stop>
</linearGradient>
</defs>
</svg>
<div class="md:w-screen-xl m-auto px-3">
<Breadcrumb :data="form" />
<div class="md:py-8 sm:py-16 md:px-0 px-4 py-8" _path="/templates" _dir="" _draft="false" _partial="false"
_locale=""
_id="content:4.templates.yml" _type="yaml" _source="content" _file="4.templates.yml" _stem="4.templates"
_extension="yml">
<div class="gap-8 sm:gap-y-16 lg:items-center" v-if="form">
<div class="w-full">
<h1
class="text-2xl font-bold tracking-tight text-gray-900 dark:text-white sm:text-3xl lg:text-4xl">
<span v-if="form.title">{{ form.title }}</span>
</h1>
<div class="mt-4 text-lg text-gray-500 dark:text-gray-400">
{{ form?.comments }}
</div>
<el-space class="mt-4">
<el-button
:icon="ElIconView"
@click="openSpmUrl(``)"
>
产品介绍
</el-button>
<el-button
:icon="ElIconView"
@click="openSpmUrl(``)"
>
客户案例
</el-button>
<el-button
:icon="ElIconView"
@click="openSpmUrl(``)"
>
网站模版
</el-button>
<el-button
:icon="ElIconMemo"
@click="openSpmUrl(``)"
>
产品文档
</el-button>
</el-space>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import {openSpmUrl} from "~/utils/common";
import Breadcrumb from "~/components/Breadcrumb.vue";
import type {Article} from "~/api/cms/article/model";
withDefaults(
defineProps<{
title?: string;
desc?: string;
buyUrl?: string;
form?: Article;
}>(),
{
title: 'Templates',
desc: 'Explore community templates to get up and running in a few seconds.',
demoUrl: '/product/website',
buyUrl: 'https://github.com/websoft9/ansible-templates'
}
);
</script>

245
pages/product/create/index.vue

@ -1,245 +0,0 @@
<template>
<PageBanner :form="form" title="订单确认"/>
<div class="page-main md:w-screen-xl m-auto p-3">
<el-row :gutter="24">
<el-col :span="16" :xs="24">
<el-form :model="form" label-width="auto" label-position="left" class="w-full">
<el-card shadow="hover" class="mb-4">
<template #header>
<div class="card-header font-bold">
<span>·企业官网SaaS交付</span>
</div>
</template>
<div class="flex flex-col">
<el-form-item label="购买个数">
<el-input-number v-model="form.specs" :min="1" :max="10" @change="handleChange" />
</el-form-item>
<el-form-item label="购买时长">
<el-radio-group v-model="form.code">
<el-radio-button value="1" border>1个月</el-radio-button>
<el-radio-button value="12" border>1</el-radio-button>
<el-radio-button value="24" border>2</el-radio-button>
<el-radio-button value="36" border>3</el-radio-button>
<el-radio-button value="60" border>5</el-radio-button>
<el-radio-button value="120" border>10</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="套餐版本">
<el-radio-group v-model="form.image">
<el-radio-button value="1" border>标准版需备案</el-radio-button>
<el-radio-button value="2" border>标准版香港节点适合全球访问不支持备案</el-radio-button>
</el-radio-group>
</el-form-item>
</div>
</el-card>
<el-card shadow="hover" class="mb-4">
<template #header>
<div class="card-header font-bold">
<span>设计服务</span>
</div>
</template>
<div class="flex flex-col">
<el-form-item label="是否需要设计服务">
<el-radio-group v-model="form.code">
<el-radio-button value="1" border>需要</el-radio-button>
<el-radio-button value="12" border>不需要</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="套餐版本">
<el-radio-group v-model="form.image">
<el-radio-button value="1" border>需要备案</el-radio-button>
<el-radio-button value="2" border>不需要备案</el-radio-button>
</el-radio-group>
</el-form-item>
</div>
</el-card>
<!-- <el-form-item label="证件号码">-->
<!-- <el-input v-model="form.idCard" placeholder="请输入证件号码" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="身份证(正面)">-->
<!-- <Upload />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="身份证(反面)">-->
<!-- <Upload />-->
<!-- </el-form-item>-->
</el-form>
</el-col>
<el-col :span="8" :xs="24">
<el-card shadow="hover" class="mb-4">
<template #header>
<div class="card-header font-bold">
<span>配置清单</span>
</div>
</template>
<el-descriptions title="云·企业官网(SaaS交付)" :column="1" class="mb-4">
<el-descriptions-item label="套餐版本:">标准版需备案</el-descriptions-item>
<el-descriptions-item label="购买时长:">1</el-descriptions-item>
</el-descriptions>
<el-descriptions title="设计服务" :column="1" class="mb-4">
<el-descriptions-item label="是否需要设计:">需要</el-descriptions-item>
<el-descriptions-item label="套餐版本:">标准版</el-descriptions-item>
</el-descriptions>
<el-descriptions title="合计:" :column="1" class="mb-4">
<el-descriptions-item label="总价格:">3000.00</el-descriptions-item>
<el-descriptions-item label="优惠价格:">1280.00</el-descriptions-item>
</el-descriptions>
<el-form-item>
<el-button type="danger" class="w-full" size="large" @click="openSpmUrl(`/product/checkout`)">确认订单</el-button>
</el-form-item>
</el-card>
</el-col>
</el-row>
</div>
<!-- <div class="login-layout mt-[100px] m-auto sm:w-screen-xl w-full">-->
<!-- <div class="mt-[100px] m-auto flex sm:flex-row flex-col sm:p-0 p-3">-->
<!-- <div class="flash bg-white rounded-lg px-7 py-4 w-full">-->
<!-- <el-tabs class="flash bg-white ml-0">-->
<!-- <el-tab-pane label="个人开发者">-->
<!-- <el-form :model="form" label-width="auto" size="large" label-position="top" class="sm:w-screen-md w-full sm:py-2">-->
<!-- <el-form-item label="商品类型">-->
<!-- <el-input v-model="form.title" placeholder="请输入真实姓名" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="资源包类型">-->
<!-- <el-input v-model="form.productId" placeholder="请输入证件号码" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="身份证(正面)">-->
<!-- <Upload />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="身份证(反面)">-->
<!-- <Upload />-->
<!-- </el-form-item>-->
<!-- <el-form-item>-->
<!-- <el-button type="primary" size="large" @click="onSubmit">提交</el-button>-->
<!-- </el-form-item>-->
<!-- </el-form>-->
<!-- </el-tab-pane>-->
<!-- </el-tabs>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
</template>
<script setup lang="ts">
import {useConfigInfo, useToken, useWebsite} from "~/composables/configState";
import useFormData from '@/utils/use-form-data';
import type {User} from '@/api/system/user/model';
import {ref} from 'vue'
import {useServerRequest} from "~/composables/useServerRequest";
import type {ApiResult} from "~/api";
import type {Product} from "~/api/oa/product/model";
import PageBanner from './components/PageBanner.vue';
//
const runtimeConfig = useRuntimeConfig();
const route = useRoute();
const activeIndex = ref('');
const website = useWebsite()
const config = useConfigInfo();
const token = useToken();
const userInfo = ref<User>();
//
const {form, assignFields} = useFormData<Product>({
// ID
productId: undefined,
// 0 1 2
type: undefined,
//
code: undefined,
//
title: undefined,
//
image: undefined,
//
content: undefined,
// ID
parentId: undefined,
// ID
categoryId: undefined,
// 0 1
specs: undefined,
//
position: undefined,
// ()
unitName: undefined,
//
price: undefined,
//
salePrice: undefined,
// (10 20)
deductStockType: undefined,
//
files: undefined,
//
sales: undefined,
//
stock: undefined,
//
gainIntegral: undefined,
//
recommend: undefined,
// ID
merchantId: undefined,
// 01
isShow: undefined,
// , 0 1 2 3
status: undefined,
//
comments: undefined,
//
sortNumber: undefined,
// ID
userId: undefined,
// , 0, 1
deleted: undefined,
// id
tenantId: undefined,
//
createTime: undefined,
//
updateTime: undefined,
});
const handleChange = (e) => {
console.log(e)
}
const onSubmit = async () => {
const {data: modify} = await useServerRequest<ApiResult<User>>('/auth/user', {
baseURL: runtimeConfig.public.apiServer,
method: 'put',
body: form
})
if (modify.value?.code == 0) {
ElMessage.success('修改成功')
}
}
const reload = async () => {
const {data: response} = await useServerRequest<ApiResult<Product>>(`/cms/cms-product/${getIdBySpm(5)}`, {baseURL: runtimeConfig.public.apiServer})
if (response.value?.data) {
assignFields(response.value?.data);
form.categoryName = '立即开通'
useHead({
title: `${form.title}`,
meta: [{name: website.value.keywords, content: website.value.comments}]
});
}
}
watch(
() => route.path,
(path) => {
activeIndex.value = path;
console.log(path, '=>Path')
reload();
},
{immediate: true}
);
</script>
<style lang="scss">
.text-a123{
color: #f0f2f5;
}
</style>

25
pages/product/createWebsite/index.vue

@ -1,25 +0,0 @@
<template>
</template>
<script setup lang="ts">
//
import {useServerRequest} from "~/composables/useServerRequest";
import type {ApiResult} from "~/api";
import type {Company} from "~/api/system/company/model";
const {data: website} = await useServerRequest<ApiResult<Company>>('/cms/website/createWebsite', {
baseURL: 'http://127.0.0.1:9002/api',
method: 'post',
body: company.value?.data
})
if (website.value?.code == 401) {
console.log('网站不存在', website.value)
}
if (website.value?.code == 0) {
console.log('网站存在', website.value)
}
</script>
<style scoped lang="less">
</style>

25
pages/product/createWebsite/index2.vue

@ -1,25 +0,0 @@
<template>
</template>
<script setup lang="ts">
//
import {useServerRequest} from "~/composables/useServerRequest";
import type {ApiResult} from "~/api";
import type {Company} from "~/api/system/company/model";
const {data: website} = await useServerRequest<ApiResult<Company>>('/cms/website/createWebsite', {
baseURL: 'http://127.0.0.1:9002/api',
method: 'post',
body: company.value?.data
})
if (website.value?.code == 401) {
console.log('网站不存在', website.value)
}
if (website.value?.code == 0) {
console.log('网站存在', website.value)
}
</script>
<style scoped lang="less">
</style>

168
pages/product/detail/[id].vue

@ -1,168 +0,0 @@
<template>
<el-affix :offset="0" @change="onAffix">
<div class="affix justify-between p-2 opacity-90 border-b-solid border-gray-200 border-b-1" :class="affix ? 'bg-white w-full' : 'hidden'">
<div class="w-3/4 m-auto flex justify-between">
<a class="goods-name text-xl font-bold cursor-pointer hover:text-gray-900">{{ goods?.goodsName }}</a>
<div class="affix-bar">
<el-anchor :offset="100" direction="horizontal" :marker="false">
<el-anchor-link :href="`#basic`">
参数信息
</el-anchor-link>
<el-anchor-link :href="`#photo`">
图文详情
</el-anchor-link>
<el-anchor-link :href="`#comment`">
用户评价
</el-anchor-link>
<el-anchor-link :href="`#buynow`">
<el-button type="danger" size="small">立即购买</el-button>
</el-anchor-link>
</el-anchor>
</div>
</div>
</div>
</el-affix>
<div id="buynow" class="flex flex-col w-full md:w-screen-xl m-auto md:pt-[60px]" v-if="goods">
<Breadcrumb :data="goods" />
<div class="content bg-white rounded-xl">
<!-- <ProductShopInfo :data="goods?.merchant" />-->
<div id="buynow" class="bg-white p-4 mt-4 flex gap-xl rounded-xl">
<div class="goods-image flex gap-xl">
<div class="gap-xs flex flex-col" v-if="goods?.files">
<el-avatar v-for="item in JSON.parse(goods.files)" :src="item.url" size="large" shape="square" />
</div>
<el-image :src="goods?.image" fit="contain" class="w-2xl h-2xl bg-gray-100 border-radius:30px"></el-image>
</div>
<div class="goods-info flex flex-col gap-xs">
<div class="goods-name text-2xl">{{ goods.goodsName }}</div>
<div class="goods-price text-2xl red">{{ Number(goods?.salePrice) * Number(goods?.num) }}</div>
<div class="text-green-7">购买得积分</div>
<div class="text-gray-4">配送无需配送</div>
<div class="text-gray-4">保障假一赔四 退货包运费 极速退款</div>
<div class="text-gray-4">销量 {{ goods.sales }}</div>
<!-- <template v-for="spec in goods?.goodsSpecValue">-->
<!-- <div class="flex items-center">-->
<!-- <div class="text-gray-4">{{ spec.value }}</div>-->
<!-- <el-radio-group v-model="goods.radio">-->
<!-- <el-radio v-for="(specValue,specIndex) in spec.detail" :label="specIndex" border>{{ specValue }}</el-radio>-->
<!-- </el-radio-group>-->
<!-- </div>-->
<!-- </template>-->
<div class="text-gray-4">
已选中{{ goods.radio }}
</div>
<div class="text-gray-4">
数量
<el-input-number v-model="goods.num" :min="1" :max="10" label="描述文字"></el-input-number>
</div>
<div class="py-5">
<el-button-group size="large">
<el-button type="danger">立即购买</el-button>
<el-button type="warning">加入购物车</el-button>
</el-button-group>
<el-button size="large" class="ml-3">收藏</el-button>
</div>
</div>
</div>
</div>
<div id="basic" class="bg-white p-4 mt-4 flex gap-xl rounded-xl">
<el-descriptions class="margin-top" title="参数信息" :column="1" border>
<el-descriptions-item label="品牌">websoft</el-descriptions-item>
<el-descriptions-item label="版本">2.0</el-descriptions-item>
<el-descriptions-item label="开发语言">JavaVue3Nuxt</el-descriptions-item>
<el-descriptions-item label="版本">
<el-tag size="small">授权版</el-tag>
</el-descriptions-item>
<el-descriptions-item label="备注">江苏省苏州市吴中区吴中大道 1188 </el-descriptions-item>
</el-descriptions>
</div>
<div id="photo" class="bg-white p-4 mt-4 flex gap-xl rounded-xl flex-col">
<div class="font-bold">图文详情</div>
<div class="files flex flex-col w-3/4" v-if="goods?.files">
<el-image v-for="item in JSON.parse(goods.files)" :src="item.url" />
</div>
</div>
<div id="comment" class="bg-white p-4 mt-4 flex gap-xl rounded-xl">
<div class="font-bold">用户评价</div>
</div>
<div v-if="!goods">
<el-empty description="404 该商品找不到了222"></el-empty>
</div>
</div>
</template>
<script setup lang="ts">
import type {ApiResult} from "~/api";
import {useServerRequest} from "~/composables/useServerRequest";
import type {Goods} from "~/api/shop/goods/model";
import Breadcrumb from "~/components/Breadcrumb.vue";
import type {Navigation} from "~/api/cms/navigation/model";
import {useProductAffix} from "~/composables/configState";
import {getIdBySpm} from "~/utils/common";
const route = useRoute();
const affix = useProductAffix();
// ID
const goodsId = ref();
//
const form = ref<Navigation>();
//
const goods = ref<Goods>();
const onAffix = (index: boolean) => {
affix.value = index;
}
//
const reload = async () => {
// TODO
// const { data: nav } = await useServerRequest<ApiResult<Navigation>>('/cms/navigation/getNavigationByPath',{
// query: {
// path: goodsId.value
// }
// })
// if(nav.value?.data){
// form.value = nav.value.data;
// }
// TODO
console.log(goodsId.value,'sss')
const { data: info } = await useServerRequest<ApiResult<Goods>>('/shop/goods/' + getIdBySpm(5))
goods.value = info.value?.data;
console.log(goods.value)
}
watch(
() => route.query.spm,
(spm) => {
console.log(spm)
// TODO spmID
const spmValue = String(spm).split('.')
if(spmValue[5]){
goodsId.value = spmValue[5];
}
console.log(goodsId.value)
// TODO ()paramsID
const { detail } = route.params
const split = String(detail).split('.');
if(Number(split[0]) > 0){
goodsId.value = split[0];
}
reload();
},
{ immediate: true }
);
</script>

85
pages/product/index.vue

@ -1,85 +0,0 @@
<template>
<PageBanner :layout="layout" :title="`产品`" />
<CardList :list="list" :disabled="disabled" @done="onSearch" />
</template>
<script setup lang="ts">
import type {ApiResult, PageResult} from "~/api";
import {useServerRequest} from "~/composables/useServerRequest";
import {useWebsite} from "~/composables/configState";
import type {Navigation} from "~/api/cms/navigation/model";
import type {CompanyParam} from "~/api/system/company/model";
import CardList from './components/CardList.vue';
import type {CmsProduct} from "~/api/cms/cmsProduct/model";
const route = useRoute();
//
const runtimeConfig = useRuntimeConfig();
const list = ref<CmsProduct[]>([]);
const page = ref<number>(1);
const resultText = ref('');
const layout = ref<any>();
const disabled = ref<boolean>(false);
//
const form = ref<Navigation>();
const website = useWebsite();
//
const where = reactive<CompanyParam>({
keywords: ''
});
const onSearch = () => {
if(!disabled.value){
page.value++;
reload(route.path);
}
}
//
const reload = async (path: string) => {
const {data: response} = await useServerRequest<ApiResult<PageResult<CmsProduct>>>('/cms/cms-product/page',{baseURL: runtimeConfig.public.apiServer, params: {
page: page.value,
limit: 8,
keywords: where.keywords
}})
if(response.value?.data){
if (list.value.length < response.value?.data.count) {
disabled.value = false;
if (response.value?.data.list) {
list.value = list.value.concat(response.value?.data.list);
}
}else {
disabled.value = true;
}
if(response.value.data.count == 0){
resultText.value = '暂无相关结果'
}
}
}
const { data: nav } = await useServerRequest<ApiResult<Navigation>>('/cms/cms-navigation/getNavigationByPath',{query: {path: route.path}})
if(nav.value?.data){
form.value = nav.value?.data;
}
//
if(form.value?.layout){
layout.value = JSON.parse(form.value?.layout)
}
useHead({
title: `产品 - ${website.value.websiteName}`,
bodyAttrs: {
class: "page-container",
}
});
watch(
() => route.path,
(path) => {
reload(path);
},
{ immediate: true }
);
</script>

77
pages/product/website.vue

@ -1,77 +0,0 @@
<template>
<!-- Banner -->
<Banner :layout="layout" />
<!-- 简单模式 -->
<PageContainer :form="form" :layout="layout" />
<!-- 高级模式 -->
<div class="flex flex-col" v-if="layout?.showLayout">
{{ layout }}
</div>
</template>
<script setup lang="ts">
import type {ApiResult} from "~/api";
import {useServerRequest} from "~/composables/useServerRequest";
import {useConfigInfo, useForm, useToken, useWebsite} from "~/composables/configState";
import Breadcrumb from "~/components/Breadcrumb.vue";
import type {BreadcrumbItem} from "~/types/global";
import type {Navigation} from "~/api/cms/navigation/model";
import {getIdBySpm} from "~/utils/common";
import PageContainer from "~/components/PageContainer.vue";
//
const route = useRoute();
const website = useWebsite();
const config = useConfigInfo();
const token = useToken();
const form = useForm();
const breadcrumb = ref<BreadcrumbItem>();
const layout = ref<any>();
//
const reload = async () => {
// spm()
const { data: nav } = await useServerRequest<ApiResult<Navigation>>('/cms/cms-navigation/' + getIdBySpm(5))
if (nav.value?.data) {
form.value = nav.value.data
}else{
const { data: nav } = await useServerRequest<ApiResult<Navigation>>('/cms/cms-navigation/getNavigationByPath',{query: {path: route.path}})
if(nav.value?.data){
form.value = nav.value?.data;
}
}
//
if(form.value?.layout){
layout.value = JSON.parse(form.value?.layout)
}
// seo
useHead({
title: `${form.value.title} - ${website.value.websiteName}`,
meta: [{ name: form.value.design?.keywords, content: form.value.design?.description }],
bodyAttrs: {
class: "page-container",
},
script: [
{
children: `console.log(${JSON.stringify(form.value)})`,
},
],
});
//
breadcrumb.value = form.value
}
watch(
() => route.path,
(path) => {
console.log(path,'=>Path')
reload();
},
{ immediate: true }
);
</script>

87
pages/templates/index.vue

@ -1,87 +0,0 @@
<template>
<PageBanner :title="`模版资源`" :desc="`探索社区模板,几秒钟内即可启动并运行。`" />
<CardList :list="list" />
</template>
<script setup lang="ts">
import { Search } from '@element-plus/icons-vue'
import type {ApiResult, PageResult} from "~/api";
import {useServerRequest} from "~/composables/useServerRequest";
import {useWebsite} from "~/composables/configState";
import type {Navigation} from "~/api/cms/navigation/model";
import {getPath} from "~/utils/common";
import type {CompanyParam} from "~/api/system/company/model";
import type {Tenant} from "~/api/system/tenant/model";
import type {Website} from "~/api/cms/website/model";
import type {Article} from "~/api/cms/article/model";
const route = useRoute();
//
const runtimeConfig = useRuntimeConfig();
const list = ref<Tenant[]>([]);
const page = ref<number>(0);
const resultText = ref('');
const layout = ref<any>();
//
const form = ref<Navigation>();
const website = useWebsite();
//
const where = reactive<CompanyParam>({
keywords: ''
});
const navTo = (item: Website) => {
if(item.domain){
openSpmUrl(`https://${item.domain}`,item,item.tenantId)
return;
}
openSpmUrl(`https://${item.websiteCode}.wsdns.cn`,item,item.tenantId)
}
//
const reload = async () => {
const { data: nav } = await useServerRequest<ApiResult<Navigation>>('/cms/cms-navigation/getNavigationByPath',{query: {path: getPath()}})
if(nav.value?.data){
form.value = nav.value?.data;
}
//
if(form.value?.layout){
layout.value = JSON.parse(form.value?.layout)
}
useHead({
title: `搜索结果 - ${website.value.websiteName}`,
bodyAttrs: {
class: "page-container",
}
});
}
//
const handleClick = async () => {
const {data: response} = await useServerRequest<ApiResult<PageResult<Article>>>('/cms/cms-article/page',{baseURL: runtimeConfig.public.apiServer, params: {
page: page.value, keywords: where.keywords
}})
if(response.value?.data){
if (response.value?.data.list) {
list.value = response.value?.data.list;
}
if(response.value.data.count == 0){
resultText.value = '暂无相关结果'
}
}
}
watch(
() => route,
() => {
reload();
handleClick();
},
{ immediate: true }
);
</script>
Loading…
Cancel
Save