Browse Source

新增:manger页面及产品与服务下拉菜单

master
科技小王子 9 months ago
parent
commit
4ce0d9fb08
  1. 2
      api/cms/website/model/index.ts
  2. 20
      components/AppHeader.vue
  3. 2
      components/Banner.vue
  4. 29
      components/UserMenu.vue
  5. 14
      composables/useServerRequest.ts
  6. 94
      layouts/default.vue
  7. 11
      nuxt.config.ts
  8. 359
      pages/manage/cms/index.vue
  9. 305
      pages/manage/index.vue
  10. 359
      pages/manage/shop/index.vue
  11. 76
      pages/market/[custom].vue
  12. 19
      pages/passport/login.vue
  13. 3
      pages/product/[id].vue
  14. 236
      pages/search/index.vue
  15. 169
      pages/user/auth.vue
  16. 25
      pages/user/index.vue
  17. 33
      pages/user/order.vue
  18. 64
      pages/user/password.vue
  19. 1
      types/global.d.ts
  20. BIN
      归档.zip

2
api/cms/website/model/index.ts

@ -61,6 +61,8 @@ export interface Website {
links?: Link[]; links?: Link[];
// 配置信息 // 配置信息
config?: any; config?: any;
topNavs?: Navigation[];
bottomNavs?: Navigation[];
} }
/** /**

20
components/AppHeader.vue

@ -17,14 +17,14 @@
<text>{{ config?.siteName }}</text> <text>{{ config?.siteName }}</text>
</nuxt-link> </nuxt-link>
</div> </div>
<nav class="hidden-sm-and-down">
<el-menu <el-menu
:default-active="currentIndex" :default-active="currentIndex"
mode="horizontal" mode="horizontal"
text-color="#000000" text-color="#000000"
active-text-color="#000000" active-text-color="#000000"
:collapse="true" :collapse="true"
:ellipsis="true"
:ellipsis="false"
style="border: none" style="border: none"
@select="handleSelect" @select="handleSelect"
> >
@ -55,19 +55,12 @@
<!-- </template>--> <!-- </template>-->
<!-- </el-sub-menu>--> <!-- </el-sub-menu>-->
</el-menu> </el-menu>
</nav>
</div> </div>
<div class="header__right items-center"> <div class="header__right items-center">
<el-space class="sm:flex hidden" v-if="config.showSearchTools">
<el-input
class="w-20"
placeholder="站内搜索"
:suffix-icon="ElIconSearch"
v-model="searchValue"
@keyup.enter.native="handleSearch"
/>
<el-button v-if="token" @click="navigateTo(`/manage`)">控制台</el-button>
<!-- <el-button v-if="token" @click="openSpmUrl(`https://${TID_ADMIN}.websoft.top/token-login`,website,Number(TID_ADMIN))">控制台</el-button>-->
<el-space class="sm:flex hidden" size="large" v-if="config.showSearchTools">
<!-- <el-button v-if="token" @click="navigateTo(`/manage`)">控制台</el-button>-->
<el-button v-if="config.showSearchIcon" circle :icon="ElIconSearch" @click="navigateTo('/search')"></el-button>
<el-button v-if="token" @click="openSpmUrl(`https://${TID_ADMIN}.websoft.top/token-login`,website,Number(TID_ADMIN))">控制台</el-button>
<ClientOnly> <ClientOnly>
<template v-if="token"> <template v-if="token">
<el-dropdown @command="handleCommand"> <el-dropdown @command="handleCommand">
@ -82,7 +75,6 @@
</el-dropdown> </el-dropdown>
</template> </template>
<template v-else> <template v-else>
<!-- <el-button v-if="config.showSearchIcon" circle :icon="ElIconSearch" @click="navigateTo('/search')"></el-button>-->
<el-button v-if="config.showLoginButton" circle :icon="ElIconUserFilled" @click="goLogin"></el-button> <el-button v-if="config.showLoginButton" circle :icon="ElIconUserFilled" @click="goLogin"></el-button>
</template> </template>
</ClientOnly> </ClientOnly>

2
components/Banner.vue

@ -8,7 +8,7 @@
<div class="description mb-4 mt-1 text-xl max-w-3xl text-gray-600">{{ layout?.description }}</div> <div class="description mb-4 mt-1 text-xl max-w-3xl text-gray-600">{{ layout?.description }}</div>
<div class="buy-btn"> <div class="buy-btn">
<el-button v-if="layout.demoUrl" @click="openSpmUrl(layout.demoUrl)" type="primary">演示地址</el-button> <el-button v-if="layout.demoUrl" @click="openSpmUrl(layout.demoUrl)" type="primary">演示地址</el-button>
<el-button v-if="layout.buyUrl" type="warning" @click="openSpmUrl(layout.buyUrl)">立即购买</el-button>
<el-button v-if="layout.buyUrl" type="warning" @click="openSpmUrl(`https://5.websoft.top`)">立即开通</el-button>
<el-button v-if="layout.docUrl" @click="openSpmUrl(layout.docUrl)">产品文档</el-button> <el-button v-if="layout.docUrl" @click="openSpmUrl(layout.docUrl)">产品文档</el-button>
</div> </div>
<div class="demo-account mt-3 text-gray-400" v-if="layout?.account">账号密码{{ layout.account }}</div> <div class="demo-account mt-3 text-gray-400" v-if="layout?.account">账号密码{{ layout.account }}</div>

29
components/UserMenu.vue

@ -1,14 +1,18 @@
<template> <template>
<el-menu
class="full-width-menu"
style="border: none; width: 100%"
:default-active="activeIndex"
@select="handleSelect"
>
<el-menu-item v-for="(item,index) in activities" :index="`${item.path}`" :key="index" class="sm:w-[170px] w-full" style="border-bottom: 1px solid #f3f3f3;">
<span class="text-center w-full" @click="navigateTo(item.path)">{{ item.name }}</span>
</el-menu-item>
</el-menu>
<div class="sm:w-[170px] sm:flex sm:mb-0 mb-5 justify-center w-full rounded-lg">
<el-menu
class="full-width-menu rounded-lg"
background-color="transparent"
text-color="#606266"
style="border: none; width: 100%"
:default-active="activeIndex"
@select="handleSelect"
>
<el-menu-item v-for="(item,index) in activities" :index="`${item.path}`" :key="index" class="custom-menu-item hover:rounded-lg sm:w-[170px] w-full">
<span class="text-center w-full" @click="navigateTo(item.path)">{{ item.name }}</span>
</el-menu-item>
</el-menu>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -56,3 +60,8 @@ const handleSelect = (index: string) => {
} }
</script> </script>
<style lang="scss">
.custom-menu-item:hover{
background-color: #dee3e8;
}
</style>

14
composables/useServerRequest.ts

@ -26,13 +26,13 @@ export const useServerRequest = <T>(url: string, opts?: UseFetchOptions<T, unkno
// 开发环境 // 开发环境
if(process.env.NODE_ENV === 'development'){ if(process.env.NODE_ENV === 'development'){
baseUrl.value = `${runtimeConfig.public.apiDev}`
baseUrl.value = `${runtimeConfig.public.apiBase}`
} }
const defaultOptions: UseFetchOptions<unknown> = { const defaultOptions: UseFetchOptions<unknown> = {
baseURL: baseUrl.value, baseURL: baseUrl.value,
onRequest({ options }) { onRequest({ options }) {
options.headers = (options.headers || {}) as { [key: string]: string }; options.headers = (options.headers || {}) as { [key: string]: string };
options.headers.tenantid = runtimeConfig.public.tenantId;
// options.headers.tenantid = runtimeConfig.public.tenantId;
if (token.value) { if (token.value) {
options.headers.Authorization = token.value; options.headers.Authorization = token.value;
} }
@ -41,13 +41,13 @@ export const useServerRequest = <T>(url: string, opts?: UseFetchOptions<T, unkno
const parts = domain.split('.'); const parts = domain.split('.');
const subDomain = parts[0]; const subDomain = parts[0];
if (isInteger(subDomain)) { if (isInteger(subDomain)) {
options.headers.tenantid = `${subDomain}`;
// options.headers.tenantid = `${subDomain}`;
} }
// TODO 2 从绑定域名解构的租户ID // TODO 2 从绑定域名解构的租户ID
options.headers.tenantid = `5`;
// if(localStorage.getItem('TID_DOMAIN')){
// options.headers.tenantid = `${localStorage.getItem('TID_DOMAIN')}`;
// }
// options.headers.tenantid = `5`;
if(localStorage.getItem('TID_DOMAIN')){
options.headers.tenantid = `${localStorage.getItem('TID_DOMAIN')}`;
}
}, },
onResponse({ response }) { onResponse({ response }) {
if (+response.status === 0 && +response._data.code !== 0) { if (+response.status === 0 && +response._data.code !== 0) {

94
layouts/default.vue

@ -1,5 +1,4 @@
<template> <template>
<!-- 加载应用 --> <!-- 加载应用 -->
<template v-if="!loading"> <template v-if="!loading">
<!-- 管理中心界面 --> <!-- 管理中心界面 -->
@ -28,8 +27,10 @@
import type {Config} from "~/types/global"; import type {Config} from "~/types/global";
import {getLoacl, getPath, setLocal} from "~/utils/common"; import {getLoacl, getPath, setLocal} from "~/utils/common";
import UnderMaintenance from "~/components/UnderMaintenance.vue"; import UnderMaintenance from "~/components/UnderMaintenance.vue";
import {navigateTo} from "#imports";
// //
const runtimeConfig = useRuntimeConfig();
const loading = ref<boolean>(false) const loading = ref<boolean>(false)
const website = useWebsite() const website = useWebsite()
const config = useConfigInfo() const config = useConfigInfo()
@ -54,73 +55,86 @@
// text: 'Loading' // text: 'Loading'
// }) // })
// TODO 1 ,ID
// TODO 1
const domain = window.location.hostname; const domain = window.location.hostname;
if(domain !== 'localhost'){ if(domain !== 'localhost'){
// //
const runtimeConfig = useRuntimeConfig(); const runtimeConfig = useRuntimeConfig();
const {data: domainInfo } = await useServerRequest<ApiResult<Domain>>('/cms/domain/getByDomain',{query: {
domain
const {data: domainInfo } = await useServerRequest<ApiResult<Domain>>('/cms/cms-domain/getTenantIdByDomain',{baseURL: runtimeConfig.public.apiServer,query: {
domain
}}); }});
const data = domainInfo.value?.data; const data = domainInfo.value?.data;
console.log(data,'查询当前域名是否有绑定域名,绑定则解构出租户ID放入缓存')
if (data) { if (data) {
// localStorage.setItem('TID_DOMAIN',`${data?.tenantId}`)
console.log('TID_DOMAIN',data.tenantId)
localStorage.setItem('TID_DOMAIN',`${data?.tenantId}`)
}else { }else {
// website.value.statusIcon = 'error';
// website.value.statusName = '';
// website.value.statusUrl = 'https://websoft.top'
// website.value.statusBtnText = '';
// website.value.statusText = '';
// loading.value = true;
// return ;
token.value = '';
navigateTo('/passport/login')
} }
} }
// TODO 2 // TODO 2
const {data: websiteInfo } = await useServerRequest<ApiResult<Website>>('/cms/website/getSiteInfo');
const {data: websiteInfo } = await useServerRequest<ApiResult<Website>>('/cms/cms-website/getSiteInfo',{baseURL: runtimeConfig.public.apiServer,headers: {
tenantid: 5
}});
if(!websiteInfo.value){ if(!websiteInfo.value){
ElMessage.error('require is not defined.') ElMessage.error('require is not defined.')
return false; return false;
} }
if(websiteInfo.value?.data){ if(websiteInfo.value?.data){
website.value = websiteInfo.value?.data; website.value = websiteInfo.value?.data;
config.value = website.value.config;
if(website.value.topNavs){
menu.value = website.value?.topNavs;
}
if(website.value.bottomNavs){
subMenu.value = website.value?.bottomNavs;
}
//
if(domain !== 'localhost') {
console.log(domain,'domain')
console.log(website.value.websiteCode)
console.log(`${website.value?.websiteCode}.wsdns.cn`,'二级域名')
}
} }
// TODO 4 // TODO 4
const {data: websiteRealTime } = await useServerRequest<ApiResult<Website>>('/cms/website/' + website.value.websiteId);
website.value = Object.assign({},website.value,websiteRealTime.value?.data)
if (website.value?.status != 1) {
useHead({title: ''})
loading.value = true;
return false;
}
// const {data: websiteRealTime } = await useServerRequest<ApiResult<Website>>('/cms/cms-website/' + website.value.websiteId,{baseURL: runtimeConfig.public.apiServer});
// website.value = Object.assign({},website.value,websiteRealTime.value?.data)
// if (website.value?.status != 1) {
// useHead({title: ''})
// // loading.value = true;
// return false;
// }
// TODO 5 // TODO 5
const { data: fields } = await useServerRequest<ApiResult<Config>>('/cms/website-field/config', {});
if (fields.value?.data) {
config.value = fields.value?.data;
}
// const { data: fields } = await useServerRequest<ApiResult<Config>>('/cms/cms-website-field/config', {baseURL: runtimeConfig.public.apiServer});
// if (fields.value?.data) {
// config.value = fields.value?.data;
// }
// TODO 6 // TODO 6
const { data: menuInfo } = await useServerRequest<ApiResult<Navigation[]>>('/cms/navigation/tree', {
query: {
top: 0
}
});
if(menuInfo.value?.data){
menu.value = menuInfo.value?.data
}
// const { data: menuInfo } = await useServerRequest<ApiResult<Navigation[]>>('/cms/cms-navigation/tree', {baseURL: runtimeConfig.public.apiServer,
// query: {
// top: 0
// }
// });
// if(menuInfo.value?.data){
// console.log(menuInfo.value.data,'')
// menu.value = menuInfo.value?.data
// }
// TODO 7 // TODO 7
const { data: subMenuInfo } = await useServerRequest<ApiResult<Navigation[]>>('/cms/navigation/tree', {
query: {
bottom: 0
}
});
if(subMenuInfo.value?.data){
subMenu.value = subMenuInfo.value?.data
}
// const { data: subMenuInfo } = await useServerRequest<ApiResult<Navigation[]>>('/cms/cms-navigation/tree', {baseURL: runtimeConfig.public.apiServer,
// query: {
// bottom: 0
// }
// });
// if(subMenuInfo.value?.data){
// subMenu.value = subMenuInfo.value?.data
// }
// TODO 8 // TODO 8
// const { data: navInfo } = await useServerRequest<ApiResult<Navigation>>('/cms/navigation/getNavigationByPath', { // const { data: navInfo } = await useServerRequest<ApiResult<Navigation>>('/cms/navigation/getNavigationByPath', {

11
nuxt.config.ts

@ -33,13 +33,12 @@ export default defineNuxtConfig({
public: { public: {
// 开发环境配置 // 开发环境配置
tenantId: '5', tenantId: '5',
// apiDev: 'http://127.0.0.1:9001/api',
apiDev: 'https://modules.gxwebsoft.com/api',
apiServerDev: 'http://127.0.0.1:9090/api',
apiBase: 'http://127.0.0.1:9001/api',
apiServer: 'http://127.0.0.1:9090/api',
// 以下一般不需要修改
apiBase: 'https://modules.gxwebsoft.com/api',
apiServer: 'https://server.gxwebsoft.com/api',
// 生产环境
// apiBase: 'https://modules.gxwebsoft.com/api',
// apiServer: 'https://server.gxwebsoft.com/api',
globalTitle: '网宿软件', globalTitle: '网宿软件',
domain: 'websoft.top' domain: 'websoft.top'
}, },

359
pages/manage/cms/index.vue

@ -0,0 +1,359 @@
<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,
isAdmin: 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>

305
pages/manage/index.vue

@ -1,11 +1,11 @@
<template> <template>
<div class="common-layout"> <div class="common-layout">
<el-container> <el-container>
<!-- 顶部菜单 -->
<el-header class="bg-black flex items-center justify-between" height="50px"> <el-header class="bg-black flex items-center justify-between" height="50px">
<el-space class="flex items-center" @click="navigateTo('/manage', { replace: false })">
<div class="expand flex items-center justify-center block bg-gray-800 hover:bg-gray-700 h-[32px] w-[32px] cursor-pointer" @mouseover="visible = true"><el-icon color="white" class="block" size="20"><Expand /></el-icon></div>
<el-avatar src="https://oss.wsdns.cn/20240331/7f7f7f57e12c45338beb7bfc7ecccfe9.png" class="cursor-pointer" shape="square" :size="32" />
<div class="user-center text-white text-lg cursor-pointer">控制台</div>
<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> </el-space>
<template v-if="token"> <template v-if="token">
<el-dropdown @command="handleCommand"> <el-dropdown @command="handleCommand">
@ -19,12 +19,11 @@
</template> </template>
</el-dropdown> </el-dropdown>
</template> </template>
<template v-else>
<el-button v-if="config.showLoginButton" circle :icon="ElIconUserFilled" @click="goLogin"></el-button>
</template>
</el-header> </el-header>
<!-- 主体 -->
<el-container> <el-container>
<el-aside width="200px" class="bg-white" :style="{ minHeight: 'calc(100vh - 60px)' }">
<!-- 左侧菜单区域 -->
<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"> <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 企业官网 WDS
<el-icon><Memo /></el-icon> <el-icon><Memo /></el-icon>
@ -36,147 +35,155 @@
@open="handleOpen" @open="handleOpen"
@close="handleClose" @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 v-for="(item,index) in menus" :key="item.menuId" :index="`${item.menuId}`">
<span>{{ item.title }}</span>
</el-menu-item> </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-menu>
</el-aside> </el-aside>
<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>
<!-- 左侧内容区域 -->
<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>
<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 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> </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 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> </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>
</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> </div>
</div>
</el-col>
</template>
</el-row>
</el-card>
</el-main>
</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>
</el-container> </el-container>
</div> </div>
@ -202,6 +209,7 @@ const visible = ref(false);
const showIcon = ref(false); const showIcon = ref(false);
const activeIndex = ref('mp-weixin'); const activeIndex = ref('mp-weixin');
const list = ref<Tenant[]>(); const list = ref<Tenant[]>();
const menus = ref<Menu[]>();
const avatar = ref(localStorage.getItem('avatar')) const avatar = ref(localStorage.getItem('avatar'))
@ -210,12 +218,15 @@ import {
Menu as IconMenu, Menu as IconMenu,
Location, Location,
Expand, Expand,
MoreFilled,
Grid,
Memo, Memo,
Close, Close,
Star, Star,
Setting, Setting,
} from '@element-plus/icons-vue' } from '@element-plus/icons-vue'
import {navigateTo} from "#imports"; import {navigateTo} from "#imports";
import type {Menu} from "~/api/system/menu/model";
const handleOpen = (key: string, keyPath: string[]) => { const handleOpen = (key: string, keyPath: string[]) => {
console.log(key, keyPath) console.log(key, keyPath)
} }
@ -315,7 +326,7 @@ const getUserInfo = async () => {
const reload = async () => { const reload = async () => {
const {data: response} = await useServerRequest<ApiResult<PageResult<Tenant>>>('/system/tenant/page',{baseURL: runtimeConfig.public.apiServerDev, params: {
const {data: response} = await useServerRequest<ApiResult<PageResult<Tenant>>>('/system/tenant/page',{baseURL: runtimeConfig.public.apiServer, params: {
userId: localStorage.getItem('UserId') userId: localStorage.getItem('UserId')
}}) }})
if(response.value?.data){ if(response.value?.data){
@ -324,6 +335,16 @@ const reload = async () => {
list.value = 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( watch(

359
pages/manage/shop/index.vue

@ -0,0 +1,359 @@
<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,
isAdmin: 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>

76
pages/market/[custom].vue

@ -0,0 +1,76 @@
<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 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 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/navigation/' + getIdBySpm(5))
if (nav.value?.data) {
form.value = nav.value.data
}else{
const { data: nav } = await useServerRequest<ApiResult<Navigation>>('/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>

19
pages/passport/login.vue

@ -17,10 +17,10 @@
<div class="custom-style my-4"> <div class="custom-style my-4">
<el-form :model="form" label-width="auto" class="w-[330px]"> <el-form :model="form" label-width="auto" class="w-[330px]">
<el-form-item> <el-form-item>
<el-input class="w-full" size="large" maxlength="30" placeholder="登录账号" :prefix-icon="Avatar" v-model="form.username" />
<el-input class="w-full" size="large" maxlength="11" placeholder="手机号码" :prefix-icon="Avatar" v-model="form.username" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-input type="password" size="large" maxlength="30" placeholder="登录密码" :prefix-icon="Briefcase" v-model="form.password" />
<el-input type="password" size="large" maxlength="100" placeholder="登录密码" :prefix-icon="Briefcase" v-model="form.password" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-space class="flex justify-between w-full"> <el-space class="flex justify-between w-full">
@ -185,6 +185,7 @@ let countdownTimer: number | null = null;
// //
const { form } = useFormData<User>({ const { form } = useFormData<User>({
userId: undefined,
username: '', username: '',
phone: '', phone: '',
password: '', password: '',
@ -205,7 +206,7 @@ const openImgCodeModal = () => {
}; };
const checkUser = async () => { const checkUser = async () => {
const {data: hasUser } = await useServerRequest<ApiResult<CaptchaResult>>('/existence',{baseURL: runtimeConfig.public.apiServerDev,method: "get",params: {
const {data: hasUser } = await useServerRequest<ApiResult<CaptchaResult>>('/existence',{baseURL: runtimeConfig.public.apiServer,method: "get",params: {
field: 'phone', value: form.phone field: 'phone', value: form.phone
}}); }});
if(hasUser.value?.code == 0){ if(hasUser.value?.code == 0){
@ -257,7 +258,7 @@ const onLoginBar = () => {
/* 获取图形验证码 */ /* 获取图形验证码 */
const changeCaptcha = async () => { const changeCaptcha = async () => {
const {data: captchaInfo } = await useServerRequest<ApiResult<CaptchaResult>>('/captcha',{baseURL: runtimeConfig.public.apiServerDev});
const {data: captchaInfo } = await useServerRequest<ApiResult<CaptchaResult>>('/captcha',{baseURL: runtimeConfig.public.apiServer});
const captchaData = captchaInfo.value?.data const captchaData = captchaInfo.value?.data
if(captchaData){ if(captchaData){
captcha.value = captchaData.base64; captcha.value = captchaData.base64;
@ -281,7 +282,7 @@ useHead({
* 执行登录 * 执行登录
*/ */
const onSubmit = async () => { const onSubmit = async () => {
const {data: response} = await useServerRequest<ApiResult<LoginResult>>('/login',{baseURL: runtimeConfig.public.apiServerDev,method: "post",body: form})
const {data: response} = await useServerRequest<ApiResult<LoginResult>>('/login',{baseURL: runtimeConfig.public.apiServer,method: "post",body: form})
// //
if(response.value?.code == 0){ if(response.value?.code == 0){
ElMessage.success(response.value?.message) ElMessage.success(response.value?.message)
@ -297,7 +298,7 @@ const onSubmit = async () => {
* 短信验证码登录 * 短信验证码登录
*/ */
const onSubmitBySms = async () => { const onSubmitBySms = async () => {
const {data: response} = await useServerRequest<ApiResult<LoginResult>>('/loginBySms',{baseURL: runtimeConfig.public.apiServerDev,method: "post",body: {
const {data: response} = await useServerRequest<ApiResult<LoginResult>>('/loginBySms',{baseURL: runtimeConfig.public.apiServer,method: "post",body: {
phone: form.phone, phone: form.phone,
code: form.code, code: form.code,
isAdmin: true isAdmin: true
@ -317,7 +318,7 @@ const onSubmitBySms = async () => {
* 账号密码注册 * 账号密码注册
*/ */
const onRegister = async () => { const onRegister = async () => {
const {data: response} = await useServerRequest<ApiResult<LoginResult>>('/register',{baseURL: runtimeConfig.public.apiServerDev,method: "post",body: {
const {data: response} = await useServerRequest<ApiResult<LoginResult>>('/register',{baseURL: runtimeConfig.public.apiServer,method: "post",body: {
companyName: '应用名称', companyName: '应用名称',
username: form.phone, username: form.phone,
phone: form.phone, phone: form.phone,
@ -344,7 +345,9 @@ const onRegister = async () => {
const doLogin = async (data: any) => { const doLogin = async (data: any) => {
const access_token = data?.access_token const access_token = data?.access_token
if(access_token){ if(access_token){
localStorage.setItem('token',access_token);
token.value = access_token; token.value = access_token;
console.log(access_token,'access_token')
} }
if(data.user){ if(data.user){
user.value.userId = data.user.userId; user.value.userId = data.user.userId;
@ -357,7 +360,7 @@ const doLogin = async (data: any) => {
// localStorage.setItem('TID_DOMAIN',data.user.tenantId); // localStorage.setItem('TID_DOMAIN',data.user.tenantId);
} }
setTimeout(() => { setTimeout(() => {
navigateTo('/user')
navigateTo('/')
return; return;
},500) },500)
} }

3
pages/product/[id].vue

@ -88,6 +88,7 @@ import type {Goods} from "~/api/shop/goods/model";
const route = useRoute(); const route = useRoute();
// //
const runtimeConfig = useRuntimeConfig();
const list = ref<Goods[]>([]); const list = ref<Goods[]>([]);
const title = ref(); const title = ref();
const categoryName = ref(); const categoryName = ref();
@ -110,7 +111,7 @@ const load = () => {
// //
const reload = async () => { const reload = async () => {
const { data: nav } = await useServerRequest<ApiResult<Navigation>>('/cms/navigation/getNavigationByPath',{query: {path: getPath()}})
const { data: nav } = await useServerRequest<ApiResult<Navigation>>('/cms/navigation/getNavigationByPath',{baseURL: runtimeConfig.public.apiServer, query: {path: getPath()}})
if(nav.value?.data){ if(nav.value?.data){
form.value = nav.value?.data; form.value = nav.value?.data;
} }

236
pages/search/index.vue

@ -1,159 +1,91 @@
<template> <template>
<!-- Banner -->
<Banner :layout="layout" />
<div class="container flex flex-col w-full md:w-screen-xl m-auto my-3">
<Breadcrumb :data="form" :title="`搜索结果`" />
<el-main class="overflow-y-hidden">
<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-0.5 bg-white mb-4 p-3 flex flex-row items-center hover:bg-gray-50 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>
<div class="login-layout mt-[100px] min-h-2xl m-auto sm:w-screen-sm w-full">
<div class="title text-xl text-gray-700 px-4 py-2 font-500 text-center">
<div class="sm:w-screen-sm w-full">
<el-input
v-model="where.keywords"
class="w-full"
size="large"
placeholder="搜索"
:prefix-icon="Search"
@keydown.enter="handleClick"
>
<template #append>
<el-button size="large" type="primary" @click="handleClick">搜索</el-button>
</template> </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-5 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>
</el-input>
<el-tabs v-model="activeName" class="my-3" @tab-click="handleClick">
<el-tab-pane label="应用" name="web"></el-tab-pane>
<el-tab-pane label="公众号" name="mp-official"></el-tab-pane>
<el-tab-pane label="小程序" name="mp-weixin"></el-tab-pane>
<el-tab-pane label="移动应用" name="app"></el-tab-pane>
<el-tab-pane label="小商店" name="mp-shop"></el-tab-pane>
<el-tab-pane label="其他" name="other"></el-tab-pane>
</el-tabs>
</div>
</div>
<template v-if="activeName === 'web'">
<div class="search bg-white rounded-lg p-3 w-full" v-if="websites.length > 0">
<div class="title text-gray-400 px-4 py-2 mb-4">网站应用</div>
<div class="result px-3">
<div v-for="(item,index) in websites" :key="index" 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-2 cursor-pointer">
<el-space @click="navTo(item)">
<div class="avatar">
<el-avatar :src="item.websiteLogo" style="background-color: #f3f3f3" size="large" />
</div> </div>
</el-col>
</template>
</el-row>
</el-card>
</el-main>
<!-- 左右结构 -->
<div class="news-box sm:mt-0 mt-2 flex sm:flex-row flex-col justify-between sm:space-x-4">
<div class="left sm:w-18/24">
<!-- 文章列表 -->
<div class="news-list">
<ul class="infinite-list px-3" v-infinite-scroll="load" :infinite-scroll-disabled="disabled">
<li v-for="item in list">
<div class="item flex justify-between py-3 px-4 gap-xl mb-5 rounded-lg mb-3 bg-white hover:shadow">
<div class="item-info py-2 flex flex-col justify-between">
<div class="title line-clamp-2 overflow-hidden text-ellipsis group-hover:group-hover:text-ellipsis">
<a :href="`/article/detail/${item.articleId}`" target="_blank" class="text-xl">{{ item.title }}</a>
</div>
<div class="desc max-w-22/24 text-gray-5 sm:block hidden" v-html="item.comments"></div>
<div class="actions text-gray-4 text-sm flex gap-2xl">
<span href="#">{{ item.updateTime }}</span>
<span href="#">浏览{{ item.actualViews }}</span>
</div>
</div>
<div class="item-image flex items-center" @click="navigateTo(`/article/detail/${item.articleId}`)">
<el-image :src="item.image" lazy class="sm:w-[140px] sm:h-[140px] w-[110px] h-[110px] bg-gray-50 cursor-pointer transition rounded-lg sm:rounded-lg ease-in-out delay-150 hover:-translate-y-1 hover:scale-110 duration-300" fit="contain" />
</div>
<div class="app-info flex flex-col">
<div class="text-lg">{{ item.websiteName }}</div>
<div class="text-gray-400">{{ item.comments }}</div>
<div class="text-gray-300 text-xs-1">{{ item.websiteType }}</div>
</div> </div>
</li>
</ul>
<div class="text-center text-gray-4">
<text v-if="disabled">没有更多了</text>
<text @click="load" v-else>加载更多</text>
</div>
</div>
</div>
<div class="right sm:mt-0 mt-4 sm:w-6/24">
<!-- 推荐文章 -->
<div class="category-item bg-white rounded-lg p-3 hover:shadow">
<div class="category-name text-lg text-gray-600 border-b border-gray-200 border-b-solid pb-2 mx-2">
<el-icon>
<ElIconLink/>
</el-icon>
<text class="ml-2">推荐文章</text>
</div>
<div class="flex flex-wrap px-2 py-4">
<div v-for="(item,index) in links" class="flex items-center">
<a :href="item.url" target="_blank">{{ item.name }}</a>
<el-divider v-if="index + 1 != links.length" direction="vertical" />
</div>
</div>
</div>
<div class="category-item mt-4 bg-white rounded-lg p-3 hover:shadow">
<div class="category-name text-lg text-gray-600 border-b border-gray-200 border-b-solid pb-2 mx-2">
<el-icon>
<ElIconLink/>
</el-icon>
<text class="ml-2">点击排行</text>
</div>
<div class="flex flex-wrap px-2 py-4">
<div v-for="(item,index) in links" class="flex items-center">
<a :href="item.url" target="_blank">{{ item.name }}</a>
<el-divider v-if="index + 1 != links.length" direction="vertical" />
</div>
</el-space>
</div> </div>
</div> </div>
</div> </div>
</template>
<div v-else class="px-1 text-center text-gray-500 min-h-xs">
{{ resultText }}
</div> </div>
</div> </div>
<!-- <el-divider />-->
<!-- <div v-if="!list">-->
<!-- <el-empty description="404 页面不存在"></el-empty>-->
<!-- </div>-->
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Search } from '@element-plus/icons-vue'
import type {ApiResult, PageResult} from "~/api"; import type {ApiResult, PageResult} from "~/api";
import type {Article} from "~/api/cms/article/model";
import {useServerRequest} from "~/composables/useServerRequest"; import {useServerRequest} from "~/composables/useServerRequest";
import Breadcrumb from "~/components/Breadcrumb.vue";
import {useForm, useWebsite} from "~/composables/configState";
import {useWebsite} from "~/composables/configState";
import type {Navigation} from "~/api/cms/navigation/model"; import type {Navigation} from "~/api/cms/navigation/model";
import {getIdByParam, getIdBySpm, getPath} from "~/utils/common";
import {getPath} from "~/utils/common";
import type {CompanyParam} from "~/api/system/company/model";
import type {Tenant} from "~/api/system/tenant/model";
import {navigateTo} from "#imports";
import type {Website} from "~/api/cms/website/model";
const route = useRoute(); const route = useRoute();
// //
const list = ref<Article[]>([]);
const title = ref();
const categoryName = ref();
const count = ref()
const links = ref<any[]>();
const runtimeConfig = useRuntimeConfig();
const list = ref<Tenant[]>([]);
const websites = ref<Website[]>([]);
const activeName = ref('web');
const page = ref<number>(0); const page = ref<number>(0);
const disabled = ref<boolean>(false);
const newList = ref<Article[]>();
const resultText = ref('');
const layout = ref<any>(); const layout = ref<any>();
// //
const form = ref<Navigation>(); const form = ref<Navigation>();
const website = useWebsite(); const website = useWebsite();
const load = () => {
if(!disabled.value){
page.value++;
// reload();
//
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)
} }
// //
@ -167,35 +99,33 @@ const reload = async () => {
if(form.value?.layout){ if(form.value?.layout){
layout.value = JSON.parse(form.value?.layout) layout.value = JSON.parse(form.value?.layout)
} }
console.log(layout.value)
//
const { data: articleList } = await useServerRequest<ApiResult<PageResult<Article>>>('/cms/article/page',{
params: {
page: page.value,
categoryId: getIdByParam()
}
})
if(articleList.value?.data){
list.value = articleList.value.data.list
}
console.log(list.value)
useHead({ useHead({
title: `${form.value.title} - ${website.value.websiteName}`,
meta: [{ name: form.value.design?.keywords, content: form.value.design?.description }],
title: `搜索结果 - ${website.value.websiteName}`,
bodyAttrs: { bodyAttrs: {
class: "page-container", class: "page-container",
},
script: [
{
children: "console.log('Hello World')",
},
],
}
}); });
} }
//
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 = '暂无相关结果'
}
}
}
}
watch( watch(
() => route, () => route,

169
pages/user/auth.vue

@ -1,89 +1,86 @@
<template> <template>
<div class="login-layout mt-[100px] m-auto sm:w-screen-xl w-full"> <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="mt-[100px] m-auto flex sm:flex-row flex-col sm:p-0 p-3">
<el-card shadow="hover" class="sm:w-[250px] sm:flex sm:mb-0 mb-5 justify-center w-full">
<div class="flex justify-center pb-4 flex-col justify-center items-center">
<el-avatar :src="userInfo?.avatar" :size="70" />
<text class="text-gray-400 py-1 text-sm">更换头像</text>
</div>
<!-- 用户菜单 -->
<UserMenu :activeIndex="activeIndex" />
</el-card>
<el-tabs type="border-card" class="flash bg-white hover:shadow w-full sm:ml-6 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:px-6 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:px-6 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>
<!-- 用户菜单 -->
<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>
</div> </div>
</template> </template>
@ -176,9 +173,3 @@ watch(
{ immediate: true } { immediate: true }
); );
</script> </script>
<style lang="less">
body{
background: url("https://oss.wsdns.cn/20240328/797a8e323bba4fc6827abf9d8b98ba45.png");
background-size: 100%;
}
</style>

25
pages/user/index.vue

@ -1,17 +1,11 @@
<template> <template>
<div class="login-layout mt-[100px] m-auto sm:w-screen-xl w-full"> <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="mt-[100px] m-auto flex sm:flex-row flex-col sm:p-0 p-3">
<el-card shadow="hover" class="sm:w-[250px] sm:flex sm:mb-0 mb-5 justify-center w-full">
<div class="flex justify-center pb-4 flex-col justify-center items-center">
<el-avatar :src="userInfo?.avatar" :size="70" />
<text class="text-gray-400 py-1 text-sm">更换头像</text>
</div>
<!-- 用户菜单 -->
<UserMenu :activeIndex="activeIndex" @done="onDone" />
</el-card>
<el-card shadow="hover" class="flash bg-white hover:shadow w-full sm:ml-6 ml-0">
<template #header>账号信息</template>
<el-form :model="form" label-width="auto" size="large" label-position="top" class="sm:w-screen-md w-full sm:px-6 sm:py-2">
<!-- 用户菜单 -->
<UserMenu :activeIndex="activeIndex" @done="onDone" />
<div class="flash ml-8 bg-white rounded-lg p-3 w-full">
<div class="title text-xl text-gray-700 px-4 py-2 mb-4 font-500">账号信息</div>
<el-form :model="form" label-width="auto" size="large" label-position="top" class="sm:w-screen-md w-full sm:px-4 sm:py-2">
<el-form-item label="手机号码"> <el-form-item label="手机号码">
<el-input disabled v-model="form.mobile" /> <el-input disabled v-model="form.mobile" />
</el-form-item> </el-form-item>
@ -34,7 +28,7 @@
<el-button type="primary" size="large" @click="onSubmit">保存</el-button> <el-button type="primary" size="large" @click="onSubmit">保存</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-card>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -52,6 +46,7 @@ const runtimeConfig = useRuntimeConfig();
const route = useRoute(); const route = useRoute();
const website = useWebsite() const website = useWebsite()
const config = useConfigInfo(); const config = useConfigInfo();
const token = useToken();
const userInfo = ref<User>(); const userInfo = ref<User>();
const activeIndex = ref(''); const activeIndex = ref('');
@ -112,9 +107,3 @@ watch(
{ immediate: true } { immediate: true }
); );
</script> </script>
<style lang="less">
body{
background: url("https://oss.wsdns.cn/20240328/797a8e323bba4fc6827abf9d8b98ba45.png");
background-size: 100%;
}
</style>

33
pages/user/order.vue

@ -1,22 +1,19 @@
<template> <template>
<div class="login-layout mt-[100px] m-auto sm:w-screen-xl w-full"> <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="mt-[100px] m-auto flex sm:flex-row flex-col sm:p-0 p-3">
<el-card shadow="hover" class="sm:w-[250px] sm:flex sm:mb-0 mb-5 justify-center w-full">
<div class="flex justify-center pb-4 flex-col justify-center items-center">
<el-avatar :src="userInfo?.avatar" :size="70" />
<text class="text-gray-400 py-1 text-sm">更换头像</text>
<!-- 用户菜单 -->
<UserMenu :activeIndex="activeIndex" @done="onDone" />
<div class="flash ml-8 bg-white rounded-lg p-3 w-full">
<div class="title text-xl text-gray-700 px-4 py-2 mb-4 font-500">订单列表</div>
<div class="px-3">
<el-table :data="tableData" class="sm:py-2 w-full">
<el-table-column prop="date" label="下单日期" width="180" />
<el-table-column prop="name" label="产品名称" width="180" />
<el-table-column prop="address" label="订单信息" />
</el-table>
</div> </div>
<!-- 用户菜单 -->
<UserMenu :activeIndex="activeIndex" />
</el-card>
<el-card shadow="hover" class="flash bg-white hover:shadow w-full sm:ml-6 ml-0">
<template #header>订单列表</template>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="date" label="下单日期" width="180" />
<el-table-column prop="name" label="产品名称" width="180" />
<el-table-column prop="address" label="订单信息" />
</el-table>
</el-card>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -96,9 +93,3 @@ watch(
{ immediate: true } { immediate: true }
); );
</script> </script>
<style lang="less">
body{
background: url("https://oss.wsdns.cn/20240328/797a8e323bba4fc6827abf9d8b98ba45.png");
background-size: 100%;
}
</style>

64
pages/user/password.vue

@ -1,43 +1,29 @@
<template> <template>
<div class="login-layout mt-[100px] m-auto sm:w-screen-xl w-full"> <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="mt-[100px] m-auto flex sm:flex-row flex-col sm:p-0 p-3">
<el-card shadow="hover" class="sm:w-[250px] sm:flex sm:mb-0 mb-5 justify-center w-full">
<div class="flex justify-center pb-4 flex-col justify-center items-center">
<el-avatar :src="userInfo?.avatar" :size="70" />
<text class="text-gray-400 py-1 text-sm">更换头像</text>
<!-- 用户菜单 -->
<UserMenu :activeIndex="activeIndex" @done="onDone" />
<div class="flash ml-8 bg-white rounded-lg p-3 w-full">
<div class="title text-xl text-gray-700 px-4 py-2 mb-4 font-500">修改密码</div>
<div class="sm:px-4">
<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.oldPassword" placeholder="请输入旧密码" />
</el-form-item>
<el-form-item label="新密码">
<el-input v-model="form.password" type="password" placeholder="请输入新密码" />
</el-form-item>
<el-form-item label="确认密码">
<el-input v-model="form.password2" type="password" placeholder="请确认新密码" />
</el-form-item>
<el-form-item>
<el-button type="primary" size="large" @click="onSubmit">保存</el-button>
</el-form-item>
</el-form>
</div> </div>
<!-- 用户菜单 -->
<UserMenu :activeIndex="activeIndex" />
</el-card>
<el-card shadow="hover" class="flash bg-white hover:shadow w-full sm:ml-6 ml-0">
<template #header>修改密码</template>
<el-form :model="form" label-width="auto" size="large" label-position="top" class="sm:w-screen-md w-full sm:px-6 sm:py-2">
<!-- <el-form-item label="手机号码">-->
<!-- <el-input disabled v-model="form.phone" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="短信验证码">-->
<!-- <el-space class="flex w-full">-->
<!-- <el-input size="large" placeholder="短信验证码" class="w-full" v-model="form.code" />-->
<!-- <el-button size="large" class="w-full" :disabled="!!countdownTime" @click="sendCode">-->
<!-- <span v-if="!countdownTime">发送验证码</span>-->
<!-- <span v-else>已发送 {{ countdownTime }} s</span>-->
<!-- </el-button>-->
<!-- </el-space>-->
<!-- </el-form-item>-->
<el-form-item label="旧密码">
<el-input v-model="form.oldPassword" placeholder="请输入旧密码" />
</el-form-item>
<el-form-item label="新密码">
<el-input v-model="form.password" type="password" placeholder="请输入新密码" />
</el-form-item>
<el-form-item label="确认密码">
<el-input v-model="form.password2" type="password" placeholder="请确认新密码" />
</el-form-item>
<el-form-item>
<el-button type="primary" size="large" @click="onSubmit">保存</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -153,9 +139,3 @@ watch(
{ immediate: true } { immediate: true }
); );
</script> </script>
<style lang="less">
body{
background: url("https://oss.wsdns.cn/20240328/797a8e323bba4fc6827abf9d8b98ba45.png");
background-size: 100%;
}
</style>

1
types/global.d.ts

@ -16,6 +16,7 @@ export interface Config {
showLoginButton?: string; showLoginButton?: string;
showAdminIcon?: string; showAdminIcon?: string;
loginBgImg?: string; loginBgImg?: string;
yyyy_bg?: string;
wxQrcode?: string; wxQrcode?: string;
wxQrcodeText?: string; wxQrcodeText?: string;
copyrightForDemoData?: string; copyrightForDemoData?: string;

BIN
归档.zip

Binary file not shown.
Loading…
Cancel
Save