refactor(layout): 重构布局相关 API
- 移除了对 MODULES_API_URL 的引用,仅使用
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
VITE_APP_NAME=后台管理(开发环境)
|
VITE_APP_NAME=后台管理(开发环境)
|
||||||
VITE_API_URL=http://127.0.0.1:9200/api
|
#VITE_API_URL=http://127.0.0.1:9200/api
|
||||||
#VITE_SERVER_API_URL=http://127.0.0.1:8000/api
|
#VITE_SERVER_API_URL=http://127.0.0.1:8000/api
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import request from '@/utils/request';
|
|||||||
import type { ApiResult } from '@/api';
|
import type { ApiResult } from '@/api';
|
||||||
import type { User } from '@/api/system/user/model';
|
import type { User } from '@/api/system/user/model';
|
||||||
import type { UpdatePasswordParam, NoticeResult } from './model';
|
import type { UpdatePasswordParam, NoticeResult } from './model';
|
||||||
import {MODULES_API_URL, SERVER_API_URL} from '@/config/setting';
|
import {SERVER_API_URL} from '@/config/setting';
|
||||||
import { Company } from '@/api/system/company/model';
|
import { Company } from '@/api/system/company/model';
|
||||||
import { CmsWebsite } from '@/api/cms/cmsWebsite/model';
|
import { CmsWebsite } from '@/api/cms/cmsWebsite/model';
|
||||||
import {Menu} from "@/api/system/menu/model";
|
import {Menu} from "@/api/system/menu/model";
|
||||||
@@ -26,7 +26,7 @@ export async function getTenantInfo(): Promise<Company> {
|
|||||||
*/
|
*/
|
||||||
export async function getSiteInfo() {
|
export async function getSiteInfo() {
|
||||||
const res = await request.get<ApiResult<CmsWebsite>>(
|
const res = await request.get<ApiResult<CmsWebsite>>(
|
||||||
MODULES_API_URL + '/cms/getSiteInfo',
|
'/shop/getShopInfo',
|
||||||
{
|
{
|
||||||
params: {
|
params: {
|
||||||
lang: getLang()
|
lang: getLang()
|
||||||
@@ -70,7 +70,7 @@ export async function updateLoginUser(data: User) {
|
|||||||
*/
|
*/
|
||||||
export async function getServerTime() {
|
export async function getServerTime() {
|
||||||
const res = await request.get<ApiResult<any>>(
|
const res = await request.get<ApiResult<any>>(
|
||||||
MODULES_API_URL + '/cms/website/getServerTime'
|
'/cms/website/getServerTime'
|
||||||
);
|
);
|
||||||
if (res.data.code === 0 && res.data.data) {
|
if (res.data.code === 0 && res.data.data) {
|
||||||
return res.data.data;
|
return res.data.data;
|
||||||
@@ -84,7 +84,7 @@ export async function getServerTime() {
|
|||||||
*/
|
*/
|
||||||
export async function getNext7day() {
|
export async function getNext7day() {
|
||||||
const res = await request.get<ApiResult<any>>(
|
const res = await request.get<ApiResult<any>>(
|
||||||
MODULES_API_URL + '/cms/website/getNext7day'
|
'/cms/website/getNext7day'
|
||||||
);
|
);
|
||||||
console.log('res.data.code: ', res.data.code);
|
console.log('res.data.code: ', res.data.code);
|
||||||
if (res.data.code === 0 && res.data.data) {
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ const columns = ref<ColumnItem[]>([
|
|||||||
key: 'createTime',
|
key: 'createTime',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 180,
|
width: 180,
|
||||||
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd HH:mm:ss'),
|
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd'),
|
||||||
sorter: true
|
sorter: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ const columns = ref<ColumnItem[]>([
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ const columns = ref<ColumnItem[]>([
|
|||||||
sorter: true,
|
sorter: true,
|
||||||
hideInTable: true,
|
hideInTable: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ const columns = ref<ColumnItem[]>([
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ const columns = ref<ColumnItem[]>([
|
|||||||
width: 170,
|
width: 170,
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd HH:mm:ss')
|
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
|
|||||||
@@ -11,20 +11,20 @@
|
|||||||
:height="80"
|
:height="80"
|
||||||
:preview="false"
|
:preview="false"
|
||||||
style="border-radius: 8px"
|
style="border-radius: 8px"
|
||||||
:src="siteStore.logo"
|
:src="siteStore.websiteLogo"
|
||||||
fallback="/logo.png"
|
fallback="/logo.png"
|
||||||
/>
|
/>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="14">
|
<a-col :span="14">
|
||||||
<div class="system-info">
|
<div class="system-info">
|
||||||
<h2 class="ele-text-heading">{{ siteStore.appName }}</h2>
|
<h2 class="ele-text-heading">{{ siteStore.websiteName }}</h2>
|
||||||
<p class="ele-text-secondary">{{ siteStore.description }}</p>
|
<p class="ele-text-secondary">{{ siteStore.websiteComments }}</p>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-tag color="blue">{{ siteStore.version }}</a-tag>
|
<a-tag color="blue">版本 {{ systemInfo.version }}</a-tag>
|
||||||
<a-tag color="green">{{ siteStore.statusText }}</a-tag>
|
<a-tag color="green">{{ systemInfo.status }}</a-tag>
|
||||||
<a-popover title="小程序码">
|
<a-popover title="小程序码">
|
||||||
<template #content>
|
<template #content>
|
||||||
<p><img :src="siteStore.mpQrCode" alt="小程序码" width="300" height="300"></p>
|
<p><img :src="siteStore.websiteDarkLogo" alt="小程序码" width="300" height="300"></p>
|
||||||
</template>
|
</template>
|
||||||
<a-tag>
|
<a-tag>
|
||||||
<QrcodeOutlined/>
|
<QrcodeOutlined/>
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ const columns = ref<ColumnItem[]>([
|
|||||||
key: 'createTime',
|
key: 'createTime',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 180,
|
width: 180,
|
||||||
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd HH:mm:ss'),
|
customRender: ({text}) => toDateString(text, 'yyyy-MM-dd'),
|
||||||
sorter: true
|
sorter: true
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<a-form-item label="LOGO" name="avatar">
|
<a-form-item label="Logo" name="avatar">
|
||||||
<SelectFile
|
<SelectFile
|
||||||
:placeholder="`请选择图片`"
|
:placeholder="`请选择图片`"
|
||||||
:limit="1"
|
:limit="1"
|
||||||
@@ -29,6 +29,9 @@
|
|||||||
@del="onDeleteItem"
|
@del="onDeleteItem"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item label="账号类型" name="type">
|
||||||
|
{{ form.type }}
|
||||||
|
</a-form-item>
|
||||||
<a-form-item label="小程序名称" name="websiteName">
|
<a-form-item label="小程序名称" name="websiteName">
|
||||||
<a-input
|
<a-input
|
||||||
allow-clear
|
allow-clear
|
||||||
@@ -64,26 +67,14 @@
|
|||||||
v-model:value="form.comments"
|
v-model:value="form.comments"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="账号类型" name="type">
|
<a-form-item label="SEO关键词" name="keywords">
|
||||||
{{ form.websiteType }}
|
<a-textarea
|
||||||
</a-form-item>
|
:rows="4"
|
||||||
<a-form-item label="小程序码" name="avatar">
|
:maxlength="200"
|
||||||
<SelectFile
|
placeholder="请输入SEO关键词"
|
||||||
:placeholder="`请选择图片`"
|
v-model:value="form.keywords"
|
||||||
:limit="1"
|
|
||||||
:data="websiteQrcode"
|
|
||||||
@done="chooseQrcode"
|
|
||||||
@del="onDeleteQrcode"
|
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- <a-form-item label="SEO关键词" name="keywords">-->
|
|
||||||
<!-- <a-textarea-->
|
|
||||||
<!-- :rows="4"-->
|
|
||||||
<!-- :maxlength="200"-->
|
|
||||||
<!-- placeholder="请输入SEO关键词"-->
|
|
||||||
<!-- v-model:value="form.keywords"-->
|
|
||||||
<!-- />-->
|
|
||||||
<!-- </a-form-item>-->
|
|
||||||
<!-- <a-form-item label="全局样式" name="style">-->
|
<!-- <a-form-item label="全局样式" name="style">-->
|
||||||
<!-- <a-textarea-->
|
<!-- <a-textarea-->
|
||||||
<!-- :rows="4"-->
|
<!-- :rows="4"-->
|
||||||
@@ -123,6 +114,7 @@
|
|||||||
v-model:value="form.statusText"
|
v-model:value="form.statusText"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<!-- <a-divider style="margin-bottom: 24px" />-->
|
||||||
</a-form>
|
</a-form>
|
||||||
</ele-modal>
|
</ele-modal>
|
||||||
</template>
|
</template>
|
||||||
@@ -135,9 +127,10 @@ import {addCmsWebsite, updateCmsWebsite} from '@/api/cms/cmsWebsite';
|
|||||||
import {CmsWebsite} from '@/api/cms/cmsWebsite/model';
|
import {CmsWebsite} from '@/api/cms/cmsWebsite/model';
|
||||||
import {useThemeStore} from '@/store/modules/theme';
|
import {useThemeStore} from '@/store/modules/theme';
|
||||||
import {storeToRefs} from 'pinia';
|
import {storeToRefs} from 'pinia';
|
||||||
import {FormInstance} from 'ant-design-vue/es/form';
|
import {FormInstance, type Rule} from 'ant-design-vue/es/form';
|
||||||
import {ItemType} from 'ele-admin-pro/es/ele-image-upload/types';
|
import {ItemType} from 'ele-admin-pro/es/ele-image-upload/types';
|
||||||
import {FileRecord} from '@/api/system/file/model';
|
import {FileRecord} from '@/api/system/file/model';
|
||||||
|
import {checkExistence} from '@/api/cms/cmsDomain';
|
||||||
import {updateCmsDomain} from '@/api/cms/cmsDomain';
|
import {updateCmsDomain} from '@/api/cms/cmsDomain';
|
||||||
import {updateTenant} from "@/api/system/tenant";
|
import {updateTenant} from "@/api/system/tenant";
|
||||||
|
|
||||||
@@ -203,14 +196,14 @@ const updateVisible = (value: boolean) => {
|
|||||||
|
|
||||||
// 表单验证规则
|
// 表单验证规则
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
comments: [
|
// comments: [
|
||||||
{
|
// {
|
||||||
required: true,
|
// required: true,
|
||||||
type: 'string',
|
// type: 'string',
|
||||||
message: '请填写小程序描述',
|
// message: '请填写小程序描述',
|
||||||
trigger: 'blur'
|
// trigger: 'blur'
|
||||||
}
|
// }
|
||||||
],
|
// ],
|
||||||
keywords: [
|
keywords: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
@@ -243,6 +236,31 @@ const rules = reactive({
|
|||||||
trigger: 'blur'
|
trigger: 'blur'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
// websiteCode: [
|
||||||
|
// {
|
||||||
|
// required: true,
|
||||||
|
// type: 'string',
|
||||||
|
// message: '该域名已被使用',
|
||||||
|
// validator: (_rule: Rule, value: string) => {
|
||||||
|
// return new Promise<void>((resolve, reject) => {
|
||||||
|
// if (!value) {
|
||||||
|
// return reject('请输入二级域名');
|
||||||
|
// }
|
||||||
|
// checkExistence('domain', `${value}.wsdns.cn`)
|
||||||
|
// .then(() => {
|
||||||
|
// if (value === oldDomain.value) {
|
||||||
|
// return resolve();
|
||||||
|
// }
|
||||||
|
// reject('已存在');
|
||||||
|
// })
|
||||||
|
// .catch(() => {
|
||||||
|
// resolve();
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// trigger: 'blur'
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
adminUrl: [
|
adminUrl: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
@@ -286,26 +304,28 @@ const chooseImage = (data: FileRecord) => {
|
|||||||
form.websiteLogo = data.downloadUrl;
|
form.websiteLogo = data.downloadUrl;
|
||||||
};
|
};
|
||||||
|
|
||||||
const chooseQrcode = (data: FileRecord) => {
|
|
||||||
websiteQrcode.value.push({
|
|
||||||
uid: data.id,
|
|
||||||
url: data.path,
|
|
||||||
status: 'done'
|
|
||||||
});
|
|
||||||
form.websiteDarkLogo = data.downloadUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const onDeleteItem = (index: number) => {
|
const onDeleteItem = (index: number) => {
|
||||||
images.value.splice(index, 1);
|
images.value.splice(index, 1);
|
||||||
form.websiteLogo = '';
|
form.websiteLogo = '';
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDeleteQrcode = (index: number) => {
|
const chooseFile = (data: FileRecord) => {
|
||||||
websiteQrcode.value.splice(index, 1);
|
form.websiteCode = data.url;
|
||||||
form.websiteDarkLogo = '';
|
files.value.push({
|
||||||
|
uid: data.id,
|
||||||
|
url: data.url,
|
||||||
|
status: 'done'
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onDeleteFile = (index: number) => {
|
||||||
|
files.value.splice(index, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
// const onWebsiteType = (text: string) => {
|
||||||
|
// form.websiteType = text;
|
||||||
|
// };
|
||||||
|
|
||||||
const {resetFields} = useForm(form, rules);
|
const {resetFields} = useForm(form, rules);
|
||||||
|
|
||||||
/* 保存编辑 */
|
/* 保存编辑 */
|
||||||
@@ -374,13 +394,6 @@ watch(
|
|||||||
status: 'done'
|
status: 'done'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (props.data.websiteDarkLogo) {
|
|
||||||
websiteQrcode.value.push({
|
|
||||||
uid: uuid(),
|
|
||||||
url: props.data.websiteDarkLogo,
|
|
||||||
status: 'done'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (props.data.files) {
|
if (props.data.files) {
|
||||||
files.value = JSON.parse(props.data.files);
|
files.value = JSON.parse(props.data.files);
|
||||||
}
|
}
|
||||||
258
src/views/shop/dashboard/index.vue
Normal file
258
src/views/shop/dashboard/index.vue
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
<template>
|
||||||
|
<a-page-header :show-back="false">
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<!-- 应用基本信息卡片 -->
|
||||||
|
<a-col :span="24" style="margin-bottom: 16px">
|
||||||
|
<a-card title="概况" :bordered="false">
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-image
|
||||||
|
:width="80"
|
||||||
|
:height="80"
|
||||||
|
:preview="false"
|
||||||
|
style="border-radius: 8px"
|
||||||
|
:src="siteStore.logo"
|
||||||
|
fallback="/logo.png"
|
||||||
|
/>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="14">
|
||||||
|
<div class="system-info">
|
||||||
|
<h2 class="ele-text-heading">{{ siteStore.appName }}</h2>
|
||||||
|
<p class="ele-text-secondary">{{ siteStore.description }}</p>
|
||||||
|
<a-space>
|
||||||
|
<a-tag color="blue">{{ siteStore.version }}</a-tag>
|
||||||
|
<a-tag color="green">{{ siteStore.statusText }}</a-tag>
|
||||||
|
<a-popover title="小程序码">
|
||||||
|
<template #content>
|
||||||
|
<p><img :src="siteStore.mpQrCode" alt="小程序码" width="300" height="300"></p>
|
||||||
|
</template>
|
||||||
|
<a-tag>
|
||||||
|
<QrcodeOutlined/>
|
||||||
|
</a-tag>
|
||||||
|
</a-popover>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="3">
|
||||||
|
<div class="flex justify-center items-center h-full w-full">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<!-- 统计数据卡片 -->
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-card :bordered="false" class="stat-card">
|
||||||
|
<a-statistic
|
||||||
|
title="用户总数"
|
||||||
|
:value="userCount"
|
||||||
|
:value-style="{ color: '#3f8600' }"
|
||||||
|
:loading="loading"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<UserOutlined/>
|
||||||
|
</template>
|
||||||
|
</a-statistic>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-card :bordered="false" class="stat-card">
|
||||||
|
<a-statistic
|
||||||
|
title="订单总数"
|
||||||
|
:value="orderCount"
|
||||||
|
:value-style="{ color: '#1890ff' }"
|
||||||
|
:loading="loading"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<AccountBookOutlined/>
|
||||||
|
</template>
|
||||||
|
</a-statistic>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-card :bordered="false" class="stat-card">
|
||||||
|
<a-statistic
|
||||||
|
title="总营业额"
|
||||||
|
:value="totalSales"
|
||||||
|
:value-style="{ color: '#cf1322' }"
|
||||||
|
:loading="loading"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<MoneyCollectOutlined/>
|
||||||
|
</template>
|
||||||
|
</a-statistic>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-card :bordered="false" class="stat-card">
|
||||||
|
<a-statistic
|
||||||
|
title="系统运行天数"
|
||||||
|
:value="runDays"
|
||||||
|
suffix="天"
|
||||||
|
:value-style="{ color: '#722ed1' }"
|
||||||
|
:loading="loading"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<ClockCircleOutlined/>
|
||||||
|
</template>
|
||||||
|
</a-statistic>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<!-- 系统基本信息 -->
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-card title="基本信息" :bordered="false">
|
||||||
|
<a-descriptions :column="1" size="small">
|
||||||
|
<a-descriptions-item label="系统名称">
|
||||||
|
{{ systemInfo.name }}
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="版本号">
|
||||||
|
{{ systemInfo.version }}
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="部署环境">
|
||||||
|
{{ systemInfo.environment }}
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="数据库">
|
||||||
|
{{ systemInfo.database }}
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="服务器">
|
||||||
|
{{ systemInfo.server }}
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="创建时间">
|
||||||
|
{{ siteInfo?.createTime }}
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="到期时间">
|
||||||
|
{{ siteInfo?.expirationTime }}
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="技术支持">
|
||||||
|
<span class="cursor-pointer" @click="openNew(`https://websoft.top/order/3429.html`)">网宿软件</span>
|
||||||
|
</a-descriptions-item>
|
||||||
|
</a-descriptions>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<!-- 快捷操作 -->
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-card title="快捷操作" :bordered="false">
|
||||||
|
<a-space direction="vertical" style="width: 100%">
|
||||||
|
<a-button type="primary" block @click="$router.push('/website/index')">
|
||||||
|
<ShopOutlined/>
|
||||||
|
站点管理
|
||||||
|
</a-button>
|
||||||
|
<a-button block @click="$router.push('/website/order')">
|
||||||
|
<CalendarOutlined/>
|
||||||
|
订单管理
|
||||||
|
</a-button>
|
||||||
|
<a-button block @click="$router.push('/system/user')">
|
||||||
|
<UserOutlined/>
|
||||||
|
用户管理
|
||||||
|
</a-button>
|
||||||
|
<a-button block @click="$router.push('/system/login-record')">
|
||||||
|
<FileTextOutlined/>
|
||||||
|
系统日志
|
||||||
|
</a-button>
|
||||||
|
<a-button block @click="$router.push('/system/setting')">
|
||||||
|
<SettingOutlined/>
|
||||||
|
系统设置
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-page-header>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {ref, onMounted, onUnmounted, computed} from 'vue';
|
||||||
|
import {
|
||||||
|
UserOutlined,
|
||||||
|
CalendarOutlined,
|
||||||
|
QrcodeOutlined,
|
||||||
|
ShopOutlined,
|
||||||
|
ClockCircleOutlined,
|
||||||
|
SettingOutlined,
|
||||||
|
AccountBookOutlined,
|
||||||
|
FileTextOutlined,
|
||||||
|
MoneyCollectOutlined
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
|
import {openNew} from "@/utils/common";
|
||||||
|
import { useSiteStore } from '@/store/modules/site';
|
||||||
|
import { useStatisticsStore } from '@/store/modules/statistics';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
||||||
|
// 使用状态管理
|
||||||
|
const siteStore = useSiteStore();
|
||||||
|
const statisticsStore = useStatisticsStore();
|
||||||
|
|
||||||
|
// 从 store 中获取响应式数据
|
||||||
|
const { siteInfo, loading: siteLoading } = storeToRefs(siteStore);
|
||||||
|
const { loading: statisticsLoading } = storeToRefs(statisticsStore);
|
||||||
|
|
||||||
|
// 系统信息
|
||||||
|
const systemInfo = ref({
|
||||||
|
name: '小程序开发',
|
||||||
|
description: '基于Spring、SpringBoot、SpringMVC等技术栈构建的前后端分离开发平台',
|
||||||
|
version: '2.0.0',
|
||||||
|
status: '运行中',
|
||||||
|
logo: '/logo.png',
|
||||||
|
environment: '生产环境',
|
||||||
|
database: 'MySQL 8.0',
|
||||||
|
server: 'Linux CentOS 7.9',
|
||||||
|
expirationTime: '2024-01-01 09:00:00'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 计算属性
|
||||||
|
const runDays = computed(() => siteStore.runDays);
|
||||||
|
const userCount = computed(() => statisticsStore.userCount);
|
||||||
|
const orderCount = computed(() => statisticsStore.orderCount);
|
||||||
|
const totalSales = computed(() => statisticsStore.totalSales);
|
||||||
|
|
||||||
|
// 加载状态
|
||||||
|
const loading = computed(() => siteLoading.value || statisticsLoading.value);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
// 加载网站信息和统计数据
|
||||||
|
try {
|
||||||
|
await Promise.all([
|
||||||
|
siteStore.fetchSiteInfo(),
|
||||||
|
statisticsStore.fetchStatistics()
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 开始自动刷新统计数据(每5分钟)
|
||||||
|
statisticsStore.startAutoRefresh();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载数据失败:', error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
// 组件卸载时停止自动刷新
|
||||||
|
statisticsStore.stopAutoRefresh();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.system-info h2 {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card :deep(.ant-statistic-title) {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card :deep(.ant-statistic-content) {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,430 +0,0 @@
|
|||||||
<template>
|
|
||||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
|
||||||
<a-spin :spinning="loading" class="page">
|
|
||||||
<a-card>
|
|
||||||
<a-form
|
|
||||||
ref="formRef"
|
|
||||||
:model="form"
|
|
||||||
:rules="rules"
|
|
||||||
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
|
||||||
:wrapper-col="
|
|
||||||
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<a-form-item label="LOGO" name="avatar">
|
|
||||||
<SelectFile
|
|
||||||
:placeholder="`请选择图片`"
|
|
||||||
:limit="1"
|
|
||||||
:data="images"
|
|
||||||
@done="chooseImage"
|
|
||||||
@del="onDeleteItem"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="小程序名称" name="websiteName">
|
|
||||||
<a-input
|
|
||||||
allow-clear
|
|
||||||
placeholder="请输入小程序名称"
|
|
||||||
v-model:value="form.websiteName"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="网站域名" name="domain" v-if="form.type == 10">
|
|
||||||
<a-input
|
|
||||||
v-model:value="form.domain"
|
|
||||||
placeholder="huawei.com"
|
|
||||||
>
|
|
||||||
<template #addonBefore>
|
|
||||||
<a-select v-model:value="form.prefix" style="width: 90px">
|
|
||||||
<a-select-option value="http://">http://</a-select-option>
|
|
||||||
<a-select-option value="https://">https://</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</template>
|
|
||||||
</a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="AppId" name="websiteCode" v-if="form.type == 20">
|
|
||||||
<a-input
|
|
||||||
allow-clear
|
|
||||||
placeholder="请输入AppId"
|
|
||||||
v-model:value="form.websiteCode"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="小程序描述" name="comments">
|
|
||||||
<a-textarea
|
|
||||||
:rows="4"
|
|
||||||
:maxlength="200"
|
|
||||||
placeholder="请输入小程序描述"
|
|
||||||
v-model:value="form.comments"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="账号类型" name="type">
|
|
||||||
{{ form.websiteType }}
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="小程序码" name="avatar">
|
|
||||||
<SelectFile
|
|
||||||
:placeholder="`请选择图片`"
|
|
||||||
:limit="1"
|
|
||||||
:data="websiteQrcode"
|
|
||||||
@done="chooseQrcode"
|
|
||||||
@del="onDeleteQrcode"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<!-- <a-form-item label="SEO关键词" name="keywords">-->
|
|
||||||
<!-- <a-textarea-->
|
|
||||||
<!-- :rows="4"-->
|
|
||||||
<!-- :maxlength="200"-->
|
|
||||||
<!-- placeholder="请输入SEO关键词"-->
|
|
||||||
<!-- v-model:value="form.keywords"-->
|
|
||||||
<!-- />-->
|
|
||||||
<!-- </a-form-item>-->
|
|
||||||
<!-- <a-form-item label="全局样式" name="style">-->
|
|
||||||
<!-- <a-textarea-->
|
|
||||||
<!-- :rows="4"-->
|
|
||||||
<!-- :maxlength="200"-->
|
|
||||||
<!-- placeholder="全局样式"-->
|
|
||||||
<!-- v-model:value="form.style"-->
|
|
||||||
<!-- />-->
|
|
||||||
<!-- </a-form-item>-->
|
|
||||||
<!-- <a-form-item label="小程序类型" name="websiteType">-->
|
|
||||||
<!-- <a-select-->
|
|
||||||
<!-- :options="websiteType"-->
|
|
||||||
<!-- :value="form.websiteType"-->
|
|
||||||
<!-- placeholder="请选择主体类型"-->
|
|
||||||
<!-- @change="onCmsWebsiteType"-->
|
|
||||||
<!-- />-->
|
|
||||||
<!-- </a-form-item>-->
|
|
||||||
<!-- <a-form-item label="当前版本" name="version">-->
|
|
||||||
<!-- <a-tag color="red" v-if="form.version === 10">标准版</a-tag>-->
|
|
||||||
<!-- <a-tag color="green" v-if="form.version === 20">专业版</a-tag>-->
|
|
||||||
<!-- <a-tag color="cyan" v-if="form.version === 30">永久授权</a-tag>-->
|
|
||||||
<!-- </a-form-item>-->
|
|
||||||
<a-form-item label="状态" name="running">
|
|
||||||
<a-radio-group
|
|
||||||
v-model:value="form.running"
|
|
||||||
:disabled="form.running == 4 || form.running == 5"
|
|
||||||
>
|
|
||||||
<a-radio :value="1">运行中</a-radio>
|
|
||||||
<a-radio :value="2">维护中</a-radio>
|
|
||||||
<a-radio :value="3">已关闭</a-radio>
|
|
||||||
</a-radio-group>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item v-if="form.running == 2" label="维护说明" name="statusText">
|
|
||||||
<a-textarea
|
|
||||||
:rows="4"
|
|
||||||
:maxlength="200"
|
|
||||||
placeholder="状态说明"
|
|
||||||
v-model:value="form.statusText"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
|
|
||||||
</a-card>
|
|
||||||
</a-spin>
|
|
||||||
</a-page-header>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import {ref, reactive, watch} from 'vue';
|
|
||||||
import {Form, message} from 'ant-design-vue';
|
|
||||||
import {assignObject, uuid} from 'ele-admin-pro';
|
|
||||||
import {addCmsWebsite, updateCmsWebsite} from '@/api/cms/cmsWebsite';
|
|
||||||
import {CmsWebsite} from '@/api/cms/cmsWebsite/model';
|
|
||||||
import {useThemeStore} from '@/store/modules/theme';
|
|
||||||
import {storeToRefs} from 'pinia';
|
|
||||||
import {FormInstance} from 'ant-design-vue/es/form';
|
|
||||||
import {ItemType} from 'ele-admin-pro/es/ele-image-upload/types';
|
|
||||||
import {FileRecord} from '@/api/system/file/model';
|
|
||||||
import {updateCmsDomain} from '@/api/cms/cmsDomain';
|
|
||||||
import {updateTenant} from "@/api/system/tenant";
|
|
||||||
import {getPageTitle, push} from "@/utils/common";
|
|
||||||
import router from "@/router";
|
|
||||||
import { useSiteStore } from '@/store/modules/site';
|
|
||||||
import useFormData from "@/utils/use-form-data";
|
|
||||||
import type {User} from "@/api/system/user/model";
|
|
||||||
|
|
||||||
// 是否是修改
|
|
||||||
const isUpdate = ref(false);
|
|
||||||
const useForm = Form.useForm;
|
|
||||||
// 是否开启响应式布局
|
|
||||||
const themeStore = useThemeStore();
|
|
||||||
const {styleResponsive} = storeToRefs(themeStore);
|
|
||||||
const siteStore = useSiteStore();
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'done'): void;
|
|
||||||
(e: 'update:visible', visible: boolean): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
// 提交状态
|
|
||||||
const loading = ref(false);
|
|
||||||
const siteInfo = ref<CmsWebsite>({})
|
|
||||||
// 表格选中数据
|
|
||||||
const formRef = ref<FormInstance | null>(null);
|
|
||||||
const images = ref<ItemType[]>([]);
|
|
||||||
const websiteQrcode = ref<ItemType[]>([]);
|
|
||||||
const files = ref<ItemType[]>([]);
|
|
||||||
|
|
||||||
// 用户信息
|
|
||||||
const {form, assignFields} = useFormData<CmsWebsite>({
|
|
||||||
websiteId: undefined,
|
|
||||||
websiteLogo: undefined,
|
|
||||||
websiteName: undefined,
|
|
||||||
websiteCode: undefined,
|
|
||||||
type: 20,
|
|
||||||
files: undefined,
|
|
||||||
keywords: '',
|
|
||||||
prefix: '',
|
|
||||||
domain: '',
|
|
||||||
adminUrl: '',
|
|
||||||
style: '',
|
|
||||||
icpNo: undefined,
|
|
||||||
email: undefined,
|
|
||||||
version: undefined,
|
|
||||||
websiteType: '',
|
|
||||||
running: 1,
|
|
||||||
expirationTime: undefined,
|
|
||||||
sortNumber: undefined,
|
|
||||||
comments: undefined,
|
|
||||||
status: undefined,
|
|
||||||
statusText: undefined
|
|
||||||
});
|
|
||||||
|
|
||||||
/* 更新visible */
|
|
||||||
const updateVisible = (value: boolean) => {
|
|
||||||
emit('update:visible', value);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 表单验证规则
|
|
||||||
const rules = reactive({
|
|
||||||
comments: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
type: 'string',
|
|
||||||
message: '请填写小程序描述',
|
|
||||||
trigger: 'blur'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
keywords: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
type: 'string',
|
|
||||||
message: '请填写SEO关键词',
|
|
||||||
trigger: 'blur'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
running: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
type: 'number',
|
|
||||||
message: '请选择小程序状态',
|
|
||||||
trigger: 'change'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
domain: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
type: 'string',
|
|
||||||
message: '请填写小程序域名',
|
|
||||||
trigger: 'blur'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
websiteCode: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
type: 'string',
|
|
||||||
message: '请填写小程序码',
|
|
||||||
trigger: 'blur'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
adminUrl: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
type: 'string',
|
|
||||||
message: '请填写小程序后台管理地址',
|
|
||||||
trigger: 'blur'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
icpNo: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
type: 'string',
|
|
||||||
message: '请填写ICP备案号',
|
|
||||||
trigger: 'blur'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
appSecret: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
type: 'string',
|
|
||||||
message: '请填写小程序秘钥',
|
|
||||||
trigger: 'blur'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
websiteName: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
type: 'string',
|
|
||||||
message: '请填写小程序信息名称',
|
|
||||||
trigger: 'blur'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
const chooseImage = (data: FileRecord) => {
|
|
||||||
images.value.push({
|
|
||||||
uid: data.id,
|
|
||||||
url: data.path,
|
|
||||||
status: 'done'
|
|
||||||
});
|
|
||||||
form.websiteLogo = data.downloadUrl;
|
|
||||||
};
|
|
||||||
|
|
||||||
const chooseQrcode = (data: FileRecord) => {
|
|
||||||
websiteQrcode.value.push({
|
|
||||||
uid: data.id,
|
|
||||||
url: data.path,
|
|
||||||
status: 'done'
|
|
||||||
});
|
|
||||||
form.websiteDarkLogo = data.downloadUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const onDeleteItem = (index: number) => {
|
|
||||||
images.value.splice(index, 1);
|
|
||||||
form.websiteLogo = '';
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDeleteQrcode = (index: number) => {
|
|
||||||
websiteQrcode.value.splice(index, 1);
|
|
||||||
form.websiteDarkLogo = '';
|
|
||||||
};
|
|
||||||
|
|
||||||
const {resetFields} = useForm(form, rules);
|
|
||||||
|
|
||||||
/* 保存编辑 */
|
|
||||||
const save = () => {
|
|
||||||
if (!formRef.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
formRef.value
|
|
||||||
.validate()
|
|
||||||
.then(() => {
|
|
||||||
loading.value = true;
|
|
||||||
const saveOrUpdate = isUpdate.value ? updateCmsWebsite : addCmsWebsite;
|
|
||||||
if (!isUpdate.value) {
|
|
||||||
updateVisible(false);
|
|
||||||
message.loading('创建过程中请勿刷新页面!', 0)
|
|
||||||
}
|
|
||||||
const formData = {
|
|
||||||
...form,
|
|
||||||
type: 20,
|
|
||||||
adminUrl: `mp.websoft.top`,
|
|
||||||
files: JSON.stringify(files.value),
|
|
||||||
};
|
|
||||||
saveOrUpdate(formData)
|
|
||||||
.then((msg) => {
|
|
||||||
loading.value = false;
|
|
||||||
updateVisible(false);
|
|
||||||
updateCmsDomain({
|
|
||||||
websiteId: form.websiteId,
|
|
||||||
domain: `${localStorage.getItem('TenantId')}.shoplnk.cn`
|
|
||||||
});
|
|
||||||
updateTenant({
|
|
||||||
tenantName: `${form.websiteName}`
|
|
||||||
}).then(() => {
|
|
||||||
})
|
|
||||||
localStorage.setItem('Domain', `${form.websiteCode}.shoplnk.cn`);
|
|
||||||
localStorage.setItem('WebsiteId', `${form.websiteId}`);
|
|
||||||
localStorage.setItem('WebsiteName', `${form.websiteName}`);
|
|
||||||
message.destroy();
|
|
||||||
message.success(msg);
|
|
||||||
// window.location.reload();
|
|
||||||
emit('done');
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
loading.value = false;
|
|
||||||
message.destroy();
|
|
||||||
message.error(e.message);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const reload = async () => {
|
|
||||||
try {
|
|
||||||
const data = await siteStore.fetchSiteInfo();
|
|
||||||
if (data) {
|
|
||||||
console.log(data);
|
|
||||||
assignFields({
|
|
||||||
...data
|
|
||||||
});
|
|
||||||
if (data.websiteLogo) {
|
|
||||||
images.value.push({
|
|
||||||
uid: uuid(),
|
|
||||||
url: data.websiteLogo,
|
|
||||||
status: 'done'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取网站信息失败:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => router.currentRoute.value.query,
|
|
||||||
(query) => {
|
|
||||||
if (query) {
|
|
||||||
reload();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{immediate: true}
|
|
||||||
);
|
|
||||||
// watch(
|
|
||||||
// () => props.visible,
|
|
||||||
// (visible) => {
|
|
||||||
// if (visible) {
|
|
||||||
// images.value = [];
|
|
||||||
// files.value = [];
|
|
||||||
// websiteQrcode.value = [];
|
|
||||||
// if (props.data?.websiteId) {
|
|
||||||
// assignObject(form, props.data);
|
|
||||||
// if (props.data.websiteLogo) {
|
|
||||||
// images.value.push({
|
|
||||||
// uid: uuid(),
|
|
||||||
// url: props.data.websiteLogo,
|
|
||||||
// status: 'done'
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// if (props.data.websiteDarkLogo) {
|
|
||||||
// websiteQrcode.value.push({
|
|
||||||
// uid: uuid(),
|
|
||||||
// url: props.data.websiteDarkLogo,
|
|
||||||
// status: 'done'
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// if (props.data.files) {
|
|
||||||
// files.value = JSON.parse(props.data.files);
|
|
||||||
// }
|
|
||||||
// if (props.data.websiteCode) {
|
|
||||||
// oldDomain.value = props.data.websiteCode;
|
|
||||||
// }
|
|
||||||
// isUpdate.value = true;
|
|
||||||
// } else {
|
|
||||||
// isUpdate.value = false;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// resetFields();
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// {immediate: true}
|
|
||||||
// );
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
export default {
|
|
||||||
name: 'CmsWebsite'
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
|
||||||
Reference in New Issue
Block a user