update admin

This commit is contained in:
全栈小学生 2023-06-08 18:17:58 +08:00
parent 45fc1fd1ca
commit 533cc3b53a
48 changed files with 888 additions and 499 deletions

View File

@ -41,16 +41,16 @@ export function getRechargeOrderStatusList() {
* 退
* @returns
*/
export function getRefund(params: Record<string, any>) {
return request.get(`refund/refund`, { params })
export function getRechargeRefund(params: Record<string, any>) {
return request.get(`order/recharge/refund`, { params })
}
/**
* 退
* @returns
*/
export function getRefundStatus() {
return request.get(`refund/status`)
export function getRechargeRefundStatus() {
return request.get(`order/recharge/refund/status`)
}
/**
@ -65,6 +65,6 @@ export function rechargeRefund(id: number) {
* 退
* @returns
*/
export function getRefundStat() {
return request.get(`refund/stat`);
export function getRechargeRefundStat() {
return request.get(`order/recharge/refund/stat`);
}

View File

@ -466,5 +466,20 @@ export function getAppMange() {
return request.get(`sys/applist`)
}
/***************************************************** 地图设置 ****************************************************/
/**
* key
*/
export function setMap(params: Record<string, any>) {
return request.put(`sys/config/map`, params, { showSuccessMessage: true })
}
/**
*
*/
export function getMap() {
return request.get(`sys/config/map`)
}

View File

@ -13,12 +13,22 @@
<div class="group-item px-[10px] text-xs rounded cursor-pointer flex" v-for="(item, index) in attachmentCategory.data" :key="index" :class="{ active: attachmentParam.cate_id == item.id }">
<div class="flex-1 leading-none truncate py-[10px]" @click="attachmentParam.cate_id = item.id">{{item.name }}</div>
<div class="leading-none operate py-[10px]" v-if="scene == 'attachment'">
<!-- 编辑分组 -->
<popover-input :placeholder="t('upload.attachmentCategoryPlaceholder')" @confirm="updateAttachmentCategory($event, index)" :value="item.name">
<span class="text-primary">{{ t('edit') }}</span>
</popover-input>
<!-- 删除分组 -->
<span class="text-danger ml-[5px]" @click="deleteAttachmentCategory(index)">{{ t('delete')}}</span>
<!-- 图片操作 -->
<el-dropdown :hide-on-click="false" v-if="scene == 'attachment'">
<icon name="element-MoreFilled" class="cursor-pointer ml-[10px]" size="14px" />{{item.name}}
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item class="text-center">
<popover-input :placeholder="t('upload.attachmentCategoryPlaceholder')" @confirm="updateAttachmentCategory($event, index)" :value="item.name">
<span>{{ t('edit') }}</span>
</popover-input>
</el-dropdown-item>
<el-dropdown-item @click="deleteAttachmentCategory(index)">
<div class="text-center w-full">{{ t('delete') }}</div>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</el-scrollbar>
@ -40,7 +50,6 @@
<el-button v-if="operate === false" class="ml-[10px]" type="primary" @click="operate = true">{{t('edit') }}</el-button>
<el-button v-else class="ml-[10px]" type="primary" @click="operate = false">{{ t('complete') }}</el-button>
</div>
</div>
</el-col>
<el-col :span="12" class="text-right">
@ -64,8 +73,8 @@
<div class="truncate my-[10px] cursor-pointer text-base flex-1 ">{{ item.real_name }}</div>
</el-tooltip>
<!-- 图片操作 -->
<el-dropdown :hide-on-click="false" v-if="scene == 'attachment'">
<icon name="element-MoreFilled" class="cursor-pointer ml-[10px]" size="14px" />
<el-dropdown :hide-on-click="false" v-if="scene == 'attachment'" class="attachment-action hidden ">
<icon name="element-MoreFilled" class="cursor-pointer ml-[8px]" size="14px" />
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item class="text-center" @click="previewImage(index)" v-if="item.att_type == 'image'">
@ -481,6 +490,11 @@ defineExpose({
}
}
}
.attachment-item:hover{
.attachment-action{
display: block;
}
}
.attachment-list-wrap {
.attachment-wrap {

View File

@ -72,7 +72,7 @@ const prop = defineProps({
}
})
const emit = defineEmits(['update:modelValue'])
const emit = defineEmits(['update:modelValue','change'])
const value = computed({
get() {
@ -121,6 +121,7 @@ const confirmSelect = (data: Record<string, any>) => {
})
}
setValue()
emit('change', value.value)
}
/**

View File

@ -7,7 +7,7 @@
"author":"作者",
"content":"文章内容",
"visit":"实际浏览量",
"visitVirtual":"虚拟浏览量",
"visitVirtual":"初始浏览量",
"isShow":"是否显示",
"sort":"排序",
"categoryIdPlaceholder":"请选择文章栏目",
@ -18,7 +18,7 @@
"authorPlaceholder":"请输入作者",
"contentPlaceholder":"请输入文章内容",
"visitPlaceholder":"请输入实际浏览量",
"visitVirtualPlaceholder":"请输入虚拟浏览量",
"visitVirtualPlaceholder":"请输入初始浏览量",
"isShowPlaceholder":"是否显示",
"sortPlaceholder":"请输入排序",
"addArticle":"添加文章",

View File

@ -8,7 +8,7 @@
"author":"作者",
"content":"文章内容",
"visit":"浏览量",
"visitVirtual":"虚拟浏览量",
"visitVirtual":"初始浏览量",
"isShow":"是否显示",
"sort":"排序",
"createTime":"创建时间",

View File

@ -103,5 +103,7 @@
"returnToPreviousPage": "返回",
"preview": "预览",
"emptyApp": "暂未安装任何应用",
"newInfo": "最新消息"
"newInfo": "最新消息",
"mapSetting": "地图设置",
"mapKey": "腾讯地图KEY"
}

View File

@ -1,4 +1,7 @@
{
"developTitle": "开发环境配置",
"wapDomain": "wap域名WAP_DOMAIN",
"wapDomainPlaceholder": "请输入wap域名",
"pageSet": "页面设置",
"tabEditContent": "内容",
"tabEditStyle": "样式",

View File

@ -6,5 +6,8 @@
"link": "链接",
"copy": "复制",
"copySuccess": "复制成功",
"weappNotSet": "小程序未配置"
"weappNotSet": "小程序未配置",
"developTitle": "开发环境配置",
"wapDomain": "wap域名WAP_DOMAIN",
"wapDomainPlaceholder": "请输入wap域名"
}

View File

@ -21,8 +21,8 @@
"mchPublicCertPath": "商户公钥",
"mchPublicCertPathPlaceholder": "请上传商户公钥",
"mchPublicCertPathTips": "微信支付API证书apiclient_cert.pem",
"appId": "app_id",
"appIdPlaceholder": "请输入app_id",
"appId": "支付宝应用ID",
"appIdPlaceholder": "请输入支付宝应用ID",
"appSecretCert": "应用私钥",
"appSecretCertPlaceholder": "请输入应用私钥",
"appPublicCertPath": "应用公钥",

View File

@ -13,8 +13,8 @@
"mchPublicCertPath": "商户公钥",
"mchPublicCertPathPlaceholder": "请上传商户公钥",
"mchPublicCertPathTips": "微信支付API证书apiclient_cert.pem",
"appId": "app_id",
"appIdPlaceholder": "请输入app_id",
"appId": "支付宝应用ID",
"appIdPlaceholder": "请输入支付宝应用ID",
"appSecretCert": "应用私钥",
"appSecretCertPlaceholder": "请输入应用私钥",
"appPublicCertPath": "应用公钥",

View File

@ -1,5 +1,6 @@
<template>
<el-container class="w-100 h-screen" :class="[{'sidebar-dark-mode':systemStore.sidebar == 'twoType'},{'sidebar-brightness-mode':systemStore.sidebar == 'oneType'}]">
<el-container class="w-100 h-screen"
:class="[{ 'sidebar-dark-mode': systemStore.sidebar == 'twoType' }, { 'sidebar-brightness-mode': systemStore.sidebar == 'oneType' }]">
<el-header class="logo-wrap w-100">
<div class="logo flex items-center m-auto max-w-[210px] h-[30px]" v-if="!systemStore.menuIsCollapse">
<img class="max-h-full max-w-full" v-if="storage.get('siteInfo').logo" :src="img(siteInfo.logo)" alt="">
@ -12,9 +13,12 @@
<el-main class="menu-wrap">
<el-scrollbar>
<el-menu :default-active="menuActive" :router="true" class="aside-menu h-full" unique-opened="true" :collapse="systemStore.menuIsCollapse">
<menu-item v-for="(route, index) in userStore.routers" :routes="route" :route-path="route.path" :key="index" />
<el-menu :default-active="menuActive" :router="true" class="aside-menu h-full" unique-opened="true"
:collapse="systemStore.menuIsCollapse">
<menu-item v-for="(route, index) in userStore.routers" :routes="route" :route-path="route.path"
:key="index" />
</el-menu>
<div class="h-[48px]"></div>
</el-scrollbar>
</el-main>
</el-container>
@ -37,19 +41,19 @@ const siteInfo = storage.get('siteInfo') || false
const menuActive = computed(() => String(route.name))
userStore.routers.forEach((item,index) => {
item.meta.class = 1;
if(item.children){
item.children.forEach((subItem,subIndex) => {
subItem.meta.class = 2;
if(subItem.children){
subItem.children.forEach((threeItem,threeIndex) => {
threeItem.meta.class = 3;
userStore.routers.forEach((item, index) => {
item.meta.class = 1
if (item.children) {
item.children.forEach((subItem, subIndex) => {
subItem.meta.class = 2
if (subItem.children) {
subItem.children.forEach((threeItem, threeIndex) => {
threeItem.meta.class = 3
})
}
})
}
});
})
</script>
<style lang="scss">
@ -86,41 +90,52 @@ userStore.routers.forEach((item,index) => {
border-right: 0 !important;
}
}
.sidebar-dark-mode{
.sidebar-dark-mode {
background-color: #191a23;
& > .logo-wrap{
.logo>i{
&>.logo-wrap {
.logo>i {
font-size: 20px;
}
border-bottom: 2px solid #101117;
}
.el-menu{
.el-menu {
background-color: #191a23;
.el-sub-menu{
.el-sub-menu {
background: transparent !important;
}
.el-sub-menu__title, .el-menu-item{
.el-sub-menu__title,
.el-menu-item {
background: transparent !important;
color: #B7B7ba;
&:hover{
&:hover {
background-color: transparent !important;
color: #fff !important;
}
}
.el-menu-item.is-active{
.el-menu-item.is-active {
color: #fff !important;
background-color: var(--el-color-primary) !important;
}
li::after{
li::after {
content: "";
width: 0;
height: 0;
}
}
}
.sidebar-brightness-mode{
& > .logo-wrap{
.logo>i{
.sidebar-brightness-mode {
&>.logo-wrap {
.logo>i {
font-size: 20px;
}
}

View File

@ -12,14 +12,6 @@
<div class="navbar-item flex items-center h-full cursor-pointer" @click="refreshRouter">
<icon name="element-Refresh" />
</div>
<!-- 返回上一页 -->
<div class="flex items-center cursor-pointer" v-if="appStore.pageReturn" @click="backFn">
<el-icon class="mr-1">
<Back />
</el-icon>
<span class="text-base mr-3">{{ t('returnToPreviousPage') }}</span>
<span class=" text-gray-300">|</span>
</div>
<!-- 面包屑导航 -->
<div class="flex items-center h-full pl-[10px] hidden-xs-only">
<el-breadcrumb separator="/">

View File

@ -25,6 +25,7 @@ const switchLang = (command: string) => {
storage.set({ key: 'lang', data: command })
})
language.loadLocaleMessages(route.path, systemStore.lang)
location.reload()
}
</script>

View File

@ -53,8 +53,8 @@
position: fixed;
height: inherit;
background:var(--el-bg-color-overlay);
padding-left: var(--aside-width);
width: 100%;
margin-left: var(--aside-width);
width:calc(100% - var(--aside-width));
left: 0;
bottom: 0;
z-index: 100;
@ -192,3 +192,27 @@ html.dark {
background: #191a23;
}
}
// 详情的头部
.detail-head{
display: flex;
align-items: center;
margin-left: 30px;
margin-top: 15px;
margin-bottom: 15px;
.left{
color: #666;
margin-top: 1px;
font-size: 14px;
line-height: 1;
cursor: pointer;
}
.adorn{
color: #999;
margin: 0 12px;
font-size: 14px;
}
.right{
font-size: 24px;
}
}

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 3883393 */
src: url('//at.alicdn.com/t/c/font_3883393_pok9rb5nvbr.woff2?t=1685440441519') format('woff2'),
url('//at.alicdn.com/t/c/font_3883393_pok9rb5nvbr.woff?t=1685440441519') format('woff'),
url('//at.alicdn.com/t/c/font_3883393_pok9rb5nvbr.ttf?t=1685440441519') format('truetype');
src: url('//at.alicdn.com/t/c/font_3883393_pwtqr51nps.woff2?t=1686032889350') format('woff2'),
url('//at.alicdn.com/t/c/font_3883393_pwtqr51nps.woff?t=1686032889350') format('woff'),
url('//at.alicdn.com/t/c/font_3883393_pwtqr51nps.ttf?t=1686032889350') format('truetype');
}
.iconfont {
@ -13,6 +13,18 @@
-moz-osx-font-smoothing: grayscale;
}
.iconxiangyoujiantou:before {
content: "\e660";
}
.iconxiangzuojiantou:before {
content: "\e663";
}
.icondingdan:before {
content: "\e61d";
}
.iconyingyongshichang1:before {
content: "\e61c";
}

View File

@ -148,17 +148,6 @@ export function strByteLength(str: string = ''): number {
return len;
}
/**
*
*/
export function getWapDomain(): string {
if (import.meta.env.MODE == 'development') {
return import.meta.env.VITE_WAP_DOMAIN || location.origin + '/wap';
} else {
return (import.meta.env.VITE_WAP_DOMAIN || location.origin + '/wap') + (storage.get('siteId') == 1 ? '' : '/s' + storage.get('siteId'));
}
}
/**
* url route
* @param url

View File

@ -1,35 +1,50 @@
<template>
<div class="main-container">
<div class="detail-head">
<div class="left" @click="router.push({ path: '/article/list' })">
<span class="iconfont iconxiangzuojiantou !text-xs"></span>
<span class="ml-[1px]">{{t('returnToPreviousPage')}}</span>
</div>
<span class="adorn">|</span>
<span class="right">{{ pageName }}</span>
</div>
<el-card class="box-card !border-none" shadow="never">
<el-form :model="formData" label-width="90px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-form :model="formData" label-width="90px" ref="formRef" :rules="formRules" class="page-form"
v-loading="loading">
<el-form-item :label="t('title')" prop="title">
<el-input v-model="formData.title" clearable :placeholder="t('titlePlaceholder')" class="input-width" maxlength="20" />
<el-input v-model="formData.title" clearable :placeholder="t('titlePlaceholder')" class="input-width"
maxlength="20" />
</el-form-item>
<el-form-item :label="t('categoryName')" prop="category_id">
<el-select v-model="formData.category_id" clearable :placeholder="t('categoryIdPlaceholder')" class="input-width">
<el-select v-model="formData.category_id" clearable :placeholder="t('categoryIdPlaceholder')"
class="input-width">
<el-option :label="item['name']" :value="item['category_id']" v-for="item in categoryList" />
</el-select>
</el-form-item>
<el-form-item :label="t('intro')" prop="intro">
<el-input v-model="formData.intro" type="textarea" rows="4" clearable :placeholder="t('introPlaceholder')" class="input-width" maxlength="50" />
<el-input v-model="formData.intro" type="textarea" rows="4" clearable
:placeholder="t('introPlaceholder')" class="input-width" maxlength="50" />
</el-form-item>
<el-form-item :label="t('summary')" prop="summary">
<el-input v-model="formData.summary" type="textarea" rows="4" clearable :placeholder="t('summaryPlaceholder')" class="input-width" maxlength="50" />
<el-input v-model="formData.summary" type="textarea" rows="4" clearable
:placeholder="t('summaryPlaceholder')" class="input-width" maxlength="50" />
</el-form-item>
<el-form-item :label="t('image')">
<upload-image v-model="formData.image" />
</el-form-item>
<el-form-item :label="t('author')" prop="author">
<el-input v-model="formData.author" clearable :placeholder="t('authorPlaceholder')" class="input-width" maxlength="20" />
<el-input v-model="formData.author" clearable :placeholder="t('authorPlaceholder')" class="input-width"
maxlength="20" />
</el-form-item>
<el-form-item :label="t('content')" prop="content">
<editor v-model="formData.content" />
</el-form-item>
<el-form-item :label="t('visitVirtual')">
<el-input v-model="formData.visit_virtual" clearable :placeholder="t('visitVirtualPlaceholder')" class="input-width" />
<el-input v-model="formData.visit_virtual" clearable :placeholder="t('visitVirtualPlaceholder')"
class="input-width" />
</el-form-item>
<el-form-item :label="t('isShow')">
<el-radio-group v-model="formData.is_show" :placeholder="t('isShowPlaceholder')">
@ -55,7 +70,7 @@
<script lang="ts" setup>
import { ref, reactive, computed, watch } from 'vue'
import { t } from '@/lang'
import type { FormInstance, ElNotification } from 'element-plus'
import type { FormInstance } from 'element-plus'
import { getArticleInfo, getArticleCategoryAll, addArticle, editArticle } from '@/api/article'
import { useRoute, useRouter } from 'vue-router'
import useTabbarStore from '@/stores/modules/tabbar'
@ -69,12 +84,7 @@ const loading = ref(false)
const categoryList = ref([])
const tabbarStore = useTabbarStore()
const appStore = useAppStore()
//
appStore.pageReturn = true;
watch(route, (newX, oldX) => {
appStore.pageReturn = false;
});
const pageName = route.meta.title
/**
* 表单数据
@ -97,25 +107,24 @@ const initialFormData = {
const formData: Record<string, any> = reactive({ ...initialFormData })
const setFormData = async (id: number = 0) => {
loading.value = true;
loading.value = true
Object.assign(formData, initialFormData)
if (id) {
const data = await (await getArticleInfo(id)).data
if (!data || Object.keys(data).length == 0) {
ElMessage.error(t('articleNull'))
setTimeout(() => {
router.go(-1);
router.go(-1)
}, 2000)
return false;
return false
}
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
loading.value = false;
loading.value = false
} else {
loading.value = false;
loading.value = false
}
}
if (id) setFormData(id)
@ -134,13 +143,13 @@ const formRules = computed(() => {
{ required: true, message: t('titlePlaceholder'), trigger: 'blur' }
],
category_id: [
{ required: true, message: t('categoryIdPlaceholder'), trigger: 'blur' },
{ required: true, message: t('categoryIdPlaceholder'), trigger: 'blur' }
],
content: [
{ required: true, message: t('contentPlaceholder'), trigger: 'blur' },
{
validator: (rule: any, value: string, callback: any) => {
let content = value.replace(/<[^<>]+>/g, "").replace(/&nbsp;/gi, "")
const content = value.replace(/<[^<>]+>/g, '').replace(/&nbsp;/gi, '')
if (!content && value.indexOf('img') === -1) {
callback(new Error(t('contentPlaceholder')))
} else callback()
@ -160,7 +169,7 @@ const onSave = async (formEl: FormInstance | undefined) => {
const save = id ? editArticle : addArticle
save(data).then(res => {
loading.value = false
back();
back()
}).catch(() => {
loading.value = false
})

View File

@ -1,8 +1,11 @@
<template>
<div class="main-container">
<el-form :model="formData" label-width="200px" ref="formRef" class="page-form" v-loading="loading">
<div class="flex ml-[18px] justify-between items-center mt-[20px] mb-[5px]">
<span class="text-[24px]">{{pageName}}</span>
</div>
<el-form :model="formData" label-width="150px" ref="formRef" class="page-form" v-loading="loading">
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title">{{ t('aliappSet') }}</h3>
<h3 class="panel-title !text-sm">{{ t('aliappSet') }}</h3>
<el-form-item :label="t('aliappName')">
<el-input v-model="formData.name" :placeholder="t('aliappNamePlaceholder')" class="input-width" clearable />
@ -16,7 +19,7 @@
</el-card>
<el-card class="box-card !border-none mt-[16px]" shadow="never">
<h3 class="panel-title">{{ t('aliappDevelopInfo') }}</h3>
<h3 class="panel-title !text-sm">{{ t('aliappDevelopInfo') }}</h3>
<el-form-item :label="t('aliappOriginal')">
<el-input v-model="formData.private_key" :placeholder="t('aliappOriginalPlaceholder')" class="input-width" clearable />
@ -53,7 +56,7 @@
</el-card>
<el-card class="box-card !border-none mt-[16px]" shadow="never">
<h3 class="panel-title">{{ t('theServerSetting') }}</h3>
<h3 class="panel-title !text-sm">{{ t('theServerSetting') }}</h3>
<el-form-item label="AESKey">
<el-input v-model="formData.aes_key" :placeholder="t('AESKeyPlaceholder')" class="input-width" show-word-limit clearable />
@ -62,7 +65,7 @@
<el-card class="box-card !border-none mt-[16px]" shadow="never">
<div class="flex">
<h3 class="panel-title">{{ t('functionSetting') }}</h3>
<h3 class="panel-title !text-sm">{{ t('functionSetting') }}</h3>
</div>
<el-form-item :label="t('serveWhiteList')">
@ -91,6 +94,9 @@ import { t } from '@/lang'
import { setAliappConfig, getAliappConfig, getAliappStatic } from '@/api/aliapp'
import { useClipboard } from '@vueuse/core'
import { ElMessage, FormInstance } from 'element-plus'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
const loading = ref(true)

View File

@ -1,11 +1,10 @@
<template>
<div class="main-container">
<el-form :model="formData" label-width="200px" ref="formRef" class="page-form" v-loading="loading">
<el-card class="box-card !border-none mt-[16px]" shadow="never">
<div class="flex">
<h3 class="panel-title">{{ t('H5Info') }}</h3>
</div>
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
<span class="text-[24px]">{{pageName}}</span>
</div>
<el-form :model="formData" label-width="150px" ref="formRef" class="page-form" v-loading="loading">
<el-card class="box-card !border-none" shadow="never">
<el-form-item :label="t('isOpen')">
<el-switch v-model="formData.is_open"/>
</el-form-item>
@ -30,92 +29,95 @@
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue'
import { t } from '@/lang'
import { setH5Config, getH5Config } from '@/api/h5'
import { getUrl } from '@/api/sys'
import { useClipboard } from '@vueuse/core'
import { ElMessage, FormInstance } from 'element-plus'
import { reactive, ref, watch } from 'vue'
import { t } from '@/lang'
import { setH5Config, getH5Config } from '@/api/h5'
import { getUrl } from '@/api/sys'
import { useClipboard } from '@vueuse/core'
import { ElMessage, FormInstance } from 'element-plus'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
const loading = ref(true)
const loading = ref(true)
const formData = reactive<Record<string, string | boolean>>({
is_open: false,
request_url: ''
})
const formData = reactive<Record<string, string | boolean>>({
is_open: false,
request_url: ''
})
const formRef = ref<FormInstance>()
const formRef = ref<FormInstance>()
/**
* 获取h5配置
*/
getH5Config().then(res => {
Object.assign(formData, res.data)
formData.is_open = Boolean(Number(formData.is_open));
loading.value = false
})
/**
* 获取h5域名
*/
getUrl().then(res => {
formData.request_url = res.data.wap_url + '/'
})
/**
* 获取h5配置
*/
getH5Config().then(res => {
Object.assign(formData, res.data)
formData.is_open = Boolean(Number(formData.is_open));
loading.value = false
})
/**
* 获取h5域名
*/
getUrl().then(res => {
formData.request_url = res.data.wap_url + '/'
})
/**
* 复制
*/
const { copy, isSupported, copied } = useClipboard()
const copyEvent = (text: string) => {
if (!isSupported.value) {
ElMessage({
message: t('notSupportCopy'),
type: 'warning'
})
return
}
copy(text)
/**
* 复制
*/
const { copy, isSupported, copied } = useClipboard()
const copyEvent = (text: string) => {
if (!isSupported.value) {
ElMessage({
message: t('notSupportCopy'),
type: 'warning'
})
return
}
copy(text)
}
watch(copied, () => {
if (copied.value) {
ElMessage({
message: t('copySuccess'),
type: 'success'
})
}
})
// 访
const visitFn = ()=>{
window.open(formData.request_url);
}
/**
* 保存
*/
const save = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = {...formData};
data.is_open = Number(data.is_open);
setH5Config(data).then(() => {
loading.value = false
}).catch(() => {
loading.value = false
})
}
watch(copied, () => {
if (copied.value) {
ElMessage({
message: t('copySuccess'),
type: 'success'
})
}
})
// 访
const visitFn = ()=>{
window.open(formData.request_url);
}
/**
* 保存
*/
const save = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = {...formData};
data.is_open = Number(data.is_open);
setH5Config(data).then(() => {
loading.value = false
}).catch(() => {
loading.value = false
})
}
})
}
</script>
<style lang="scss" scoped>
.visit-btn{
color:var(--el-color-primary);
}
.visit-btn{
color:var(--el-color-primary);
}
</style>

View File

@ -1,10 +1,11 @@
<template>
<div class="main-container" v-loading="loading">
<el-form :model="formData" label-width="120px" ref="formRef" class="page-form">
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
<span class="text-[24px]">{{pageName}}</span>
</div>
<el-form :model="formData" label-width="150px" ref="formRef" class="page-form">
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title">{{ t('pcInfo') }}</h3>
<el-form-item :label="t('preview')" prop="weapp_name">
<img class="w-[500px]" src="@/assets/images/channel/preview.png" alt="">
</el-form-item>
@ -24,65 +25,67 @@
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue'
import { t } from '@/lang'
import { getUrl } from '@/api/sys'
import { useClipboard } from '@vueuse/core'
import { ElMessage, FormInstance, FormRules } from 'element-plus'
import { useRouter } from 'vue-router'
import { reactive, ref, watch } from 'vue'
import { t } from '@/lang'
import { getUrl } from '@/api/sys'
import { useClipboard } from '@vueuse/core'
import { ElMessage, FormInstance, FormRules } from 'element-plus'
import { useRouter, useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
const loading = ref(true)
const loading = ref(true)
const formData = reactive<Record<string, string | boolean>>({
is_open: false,
request_url: ''
})
const formData = reactive<Record<string, string | boolean>>({
is_open: false,
request_url: ''
})
const formRef = ref<FormInstance>()
const router = useRouter()
const formRef = ref<FormInstance>()
const router = useRouter()
/**
* 获取pc域名
*/
getUrl().then(res => {
formData.request_url = res.data.web_url + '/';
loading.value = false;
})
/**
* 获取pc域名
*/
getUrl().then(res => {
formData.request_url = res.data.web_url + '/';
loading.value = false;
})
/**
* 复制
*/
const { copy, isSupported, copied } = useClipboard()
const copyEvent = (text: string) => {
if (!isSupported.value) {
ElMessage({
message: t('notSupportCopy'),
type: 'warning'
})
return
}
copy(text)
/**
* 复制
*/
const { copy, isSupported, copied } = useClipboard()
const copyEvent = (text: string) => {
if (!isSupported.value) {
ElMessage({
message: t('notSupportCopy'),
type: 'warning'
})
return
}
copy(text)
}
watch(copied, () => {
if (copied.value) {
ElMessage({
message: t('copySuccess'),
type: 'success'
})
}
})
// 访
const visitFn = ()=>{
window.open(formData.request_url);
watch(copied, () => {
if (copied.value) {
ElMessage({
message: t('copySuccess'),
type: 'success'
})
}
})
// 访
const visitFn = ()=>{
window.open(formData.request_url);
}
</script>
<style lang="scss" scoped>
.visit-btn{
color:var(--el-color-primary);
}
.visit-btn{
color:var(--el-color-primary);
}
</style>

View File

@ -1,8 +1,11 @@
<template>
<div class="main-container">
<el-form :model="formData" label-width="200px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
<span class="text-[24px]">{{pageName}}</span>
</div>
<el-form :model="formData" label-width="170px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title">{{ t('weappInfo') }}</h3>
<h3 class="panel-title !text-sm">{{ t('weappInfo') }}</h3>
<el-form-item :label="t('weappName')" prop="weapp_name">
<el-input v-model="formData.weapp_name" :placeholder="t('weappNamePlaceholder')" class="input-width" clearable />
@ -20,7 +23,7 @@
</el-card>
<el-card class="box-card !border-none mt-[16px]" shadow="never">
<h3 class="panel-title">{{ t('weappDevelopInfo') }}</h3>
<h3 class="panel-title !text-sm">{{ t('weappDevelopInfo') }}</h3>
<el-form-item :label="t('weappAppid')" prop="app_id">
<el-input v-model="formData.app_id" :placeholder="t('appidPlaceholder')" class="input-width" clearable />
@ -35,7 +38,7 @@
</el-card>
<el-card class="box-card !border-none mt-[16px]" shadow="never">
<h3 class="panel-title">{{ t('theServerSetting') }}</h3>
<h3 class="panel-title !text-sm">{{ t('theServerSetting') }}</h3>
<el-form-item label="URL">
<el-input :model-value="formData.serve_url" placeholder="Please input" class="input-width" :readonly="true">
@ -70,7 +73,7 @@
<el-card class="box-card !border-none mt-[16px]" shadow="never">
<div class="flex">
<h3 class="panel-title">{{ t('functionSetting') }}</h3>
<h3 class="panel-title !text-sm">{{ t('functionSetting') }}</h3>
</div>
<el-form-item :label="t('requestUrl')">
@ -123,6 +126,9 @@ import { t } from '@/lang'
import { getWeappConfig, setWeappConfig } from '@/api/weapp'
import { useClipboard } from '@vueuse/core'
import { ElMessage, FormInstance, FormRules } from 'element-plus'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
const loading = ref(true)

View File

@ -1,8 +1,12 @@
<template>
<div class="main-container">
<el-form :model="formData" label-width="200px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
<span class="text-[24px]">{{pageName}}</span>
</div>
<el-form :model="formData" label-width="150px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title">{{ t('wechatInfo') }}</h3>
<h3 class="panel-title !text-sm">{{ t('wechatInfo') }}</h3>
<el-form-item :label="t('wechatName')" prop="wechat_name">
<el-input v-model="formData.wechat_name" :placeholder="t('wechatNamePlaceholder')" class="input-width" clearable />
@ -20,7 +24,7 @@
</el-card>
<el-card class="box-card !border-none mt-[16px]" shadow="never">
<h3 class="panel-title">{{ t('wechatDevelopInfo') }}</h3>
<h3 class="panel-title !text-sm">{{ t('wechatDevelopInfo') }}</h3>
<el-form-item :label="t('wechatAppid')" prop="app_id">
<el-input v-model="formData.app_id" :placeholder="t('appidPlaceholder')" class="input-width" clearable />
@ -35,7 +39,7 @@
</el-card>
<el-card class="box-card !border-none mt-[16px]" shadow="never">
<h3 class="panel-title">{{ t('theServerSetting') }}</h3>
<h3 class="panel-title !text-sm">{{ t('theServerSetting') }}</h3>
<el-form-item label="URL">
<el-input :model-value="wechatStatic.serve_url" placeholder="Please input" class="input-width" :readonly="true">
@ -70,7 +74,7 @@
<el-card class="box-card !border-none mt-[16px]" shadow="never">
<div class="flex">
<h3 class="panel-title">{{ t('functionSetting') }}</h3>
<h3 class="panel-title !text-sm">{{ t('functionSetting') }}</h3>
</div>
<el-form-item label="">
@ -121,6 +125,9 @@ import { t } from '@/lang'
import { getWechatConfig, getWechatStatic, editWechatConfig } from '@/api/wechat'
import { useClipboard } from '@vueuse/core'
import { ElMessage, FormInstance, FormRules } from 'element-plus'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
const loading = ref(true)

View File

@ -6,7 +6,7 @@
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('imageHeight')" class="display-block">
<el-input v-model="diyStore.editComponent.imageHeight" :placeholder="t('imageHeightPlaceholder')" clearable maxlength="10">
<el-input v-model="diyStore.editComponent.imageHeight" :placeholder="t('imageHeightPlaceholder')" clearable maxlength="10" @blur="blurImageHeight">
<template #append>px</template>
</el-input>
<div class="text-sm text-gray-400 mb-[10px]">{{ t('imageAdsTips') }}</div>
@ -15,7 +15,7 @@
<div ref="imageBoxRef">
<div v-for="(item,index) in diyStore.editComponent.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
<el-form-item :label="t('image')">
<upload-image v-model="item.imageUrl" :limit="1"/>
<upload-image v-model="item.imageUrl" :limit="1" @change="selectImg" />
</el-form-item>
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]" v-show="diyStore.editComponent.list.length > 1" @click="diyStore.editComponent.list.splice(index,1)">
@ -86,22 +86,7 @@
() => diyStore.editComponent.list,
(newValue, oldValue) => {
//
diyStore.editComponent.list.forEach((item: any, index: number) => {
let image = new Image();
image.src = img(item.imageUrl);
image.onload = async () => {
item.imgWidth = image.width;
item.imgHeight = image.height;
//
if (index == 0) {
var ratio = item.imgHeight / item.imgWidth;
item.width = 375;
item.height = item.width * ratio;
diyStore.editComponent.imageHeight = item.height;
}
};
});
handleHeight();
},
{deep: true}
)
@ -116,6 +101,33 @@
})
}
const selectImg = (url:string)=> {
handleHeight(true);
};
//
const handleHeight = (isCalcHeight:boolean = false)=> {
diyStore.editComponent.list.forEach((item: any, index: number) => {
let image = new Image();
image.src = img(item.imageUrl);
image.onload = async () => {
item.imgWidth = image.width;
item.imgHeight = image.height;
//
if (isCalcHeight && index == 0) {
var ratio = item.imgHeight / item.imgWidth;
item.width = 375;
item.height = item.width * ratio;
diyStore.editComponent.imageHeight = item.height;
}
};
});
}
const blurImageHeight = ()=> {
diyStore.editComponent.imageHeight = parseFloat(diyStore.editComponent.imageHeight).toFixed(2);
}
const imageBoxRef = ref()
onMounted(() => {
@ -132,6 +144,7 @@
return value.toString();
})
);
handleHeight(true);
}
})
});

View File

@ -64,7 +64,16 @@
</ul>
<!-- 组件预览渲染区域 -->
<iframe id="previewIframe" v-show="wapDomain" :src="wapDomain" frameborder="0" class="preview-iframe w-[375px]"></iframe>
<iframe id="previewIframe" v-show="loadingIframe" :src="wapPreview" frameborder="0" class="preview-iframe w-[375px]" @load="loadIframe"></iframe>
<div v-show="loadingDev" class="preview-iframe w-[375px] pt-[20px] px-[20px]">
<div class="font-bold text-xl mb-[40px]">{{t('developTitle')}}</div>
<div class="mb-[20px] flex flex-col">
<text class="mb-[10px]">{{ t('wapDomain') }}</text>
<el-input v-model="wapDomain" :placeholder="t('wapDomainPlaceholder')" clearable />
</div>
<el-button type="primary" @click="saveWapDomain" >{{ t('confirm') }}</el-button>
</div>
</div>
</div>
@ -133,22 +142,32 @@
</template>
<script lang="ts" setup>
import { ref, reactive, toRaw, onMounted, watch } from 'vue'
import { ref, reactive, toRaw, watch } from 'vue'
import { t } from '@/lang'
import { addDiyPage, editDiyPage, initPage } from '@/api/diy';
import { useRoute, useRouter } from 'vue-router'
import { cloneDeep, range, isEmpty } from 'lodash-es'
import { ElMessage, ElMessageBox } from 'element-plus'
import useDiyStore from '@/stores/modules/diy'
import storage from '@/utils/storage'
const diyStore = useDiyStore()
const route = useRoute();
const router = useRouter()
const wapUrl = ref('')
const wapDomain = ref('')
const wapPreview = ref('')
const loadingIframe = ref(false) // iframe
const loadingDev = ref(false) //
const timeFrame = ref(0)
const backPath = route.query.back || '/diy/list'
const component = ref([])
const componentType: string[] = reactive([])
const page = ref('')
const siteId = ref(0)
const activeNames = ref(componentType)
const handleChange = (val: string[]) => { }
@ -275,12 +294,27 @@ initPage({
}
}
wapDomain.value = `${data.domain_url.wap_url}/${data.page}?mode=decorate&site_id=${data.site_id}`; // decorate 访
})
wapDomain.value = data.domain_url.wap_domain;
wapUrl.value = data.domain_url.wap_url;
page.value = data.page;
siteId.value = data.site_id;
setDomain();
//
if(import.meta.env.MODE == 'production') return;
// envwap
if (wapDomain.value) return;
let wap_domain_storage = storage.get('wap_domain');
if(wap_domain_storage){
wapUrl.value = wap_domain_storage
setDomain();
return;
}
timeFrame.value = new Date().getTime();
onMounted(() => {
// uniapp iframe
window.previewIframe = document.getElementById('previewIframe')
})
// uni-app
@ -311,14 +345,42 @@ window.addEventListener('message', (event) => {
}
}, false);
const loading = ref(false)
const saveWapDomain = ()=> {
wapUrl.value = wapDomain.value + '/wap'
setDomain();
storage.set({ key : 'wap_domain', data :wapUrl.value });
loadingIframe.value = true;
loadingDev.value = false;
}
const setDomain = ()=>{
wapPreview.value = `${wapUrl.value}/${page.value}?mode=decorate&site_id=${siteId.value}`; // decorate 访
}
// iframe
const loadIframe = ()=> {
if (!wapPreview.value) return
var loadTime = new Date().getTime();
var difference = loadTime - timeFrame.value;
// 1000wap
if (difference < 1000) {
loadingDev.value = true;
loadingIframe.value = false;
wapPreview.value = ''
} else {
loadingDev.value = false;
loadingIframe.value = true;
}
}
const isRepeat = ref(false)
const save = () => {
if (!diyStore.verify()) {
return;
}
if (loading.value) return
loading.value = true
if (isRepeat.value) return
isRepeat.value = true
let data = {
id: diyStore.id,
@ -334,16 +396,16 @@ const save = () => {
const save = diyStore.id ? editDiyPage : addDiyPage
save(data).then((res: any) => {
loading.value = false
isRepeat.value = false
if (res.code == 1) {
if (diyStore.id) {
loading.value = false //
isRepeat.value = false //
} else {
router.push(backPath);
}
}
}).catch(err => {
loading.value = false
isRepeat.value = false
})
}

View File

@ -1,8 +1,17 @@
<template>
<div class="main-container">
<div class="flex h-[700px] bg-body p-[20px]">
<iframe class="w-[375px] border border-slate-100" :src="wapDomain" frameborder="0"></iframe>
<div class="flex h-[700px] bg-body p-[20px]" v-show="loading">
<iframe v-show="loadingIframe" class="w-[375px] border border-slate-100" :src="wapPreview" frameborder="0" id="previewIframe" @load="loadIframe"></iframe>
<div v-show="loadingDev" class="w-[375px] border border-slate-100 pt-[20px] px-[20px]">
<div class="font-bold text-xl mb-[40px]">{{t('developTitle')}}</div>
<div class="mb-[20px] flex flex-col">
<text class="mb-[10px]">{{ t('wapDomain') }}</text>
<el-input v-model="wapDomain" :placeholder="t('wapDomainPlaceholder')" clearable />
</div>
<el-button type="primary" @click="save" >{{ t('confirm') }}</el-button>
</div>
<div class="w-[500px] ml-[40px]">
<el-button type="primary" @click="toDecorate()">{{ t('decorate') }}</el-button>
@ -15,14 +24,14 @@
</el-radio-group>
</el-form-item>
<template v-if="previewMode == 'wechat'">
<el-form-item :label="t('link')">
<el-input readonly :value="wapDomain">
<el-form-item :label="t('link')" v-show="wapPreview">
<el-input readonly :value="wapPreview">
<template #append>
<el-button @click="copyEvent(wapDomain)" class="bg-primary copy">{{ t('copy') }}</el-button>
<el-button @click="copyEvent(wapPreview)" class="bg-primary copy">{{ t('copy') }}</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item label=" ">
<el-form-item label=" " v-show="wapImage">
<el-image :src="wapImage"/>
</el-form-item>
</template>
@ -47,23 +56,83 @@
<script lang="ts" setup>
import {ref, reactive, watch} from 'vue'
import {t} from '@/lang'
import {useRoute, useRouter} from 'vue-router'
import { useRouter} from 'vue-router'
import {getWeappConfig} from '@/api/weapp'
import {getUrl} from '@/api/sys'
import {useClipboard} from '@vueuse/core'
import {ElMessage} from 'element-plus'
import {img} from '@/utils/common'
import QRCode from "qrcode";
import storage from '@/utils/storage'
const wapUrl = ref('')
const wapDomain = ref('')
const wapImage = ref('')
const wapPreview = ref('')
getUrl().then((res:any)=>{
wapDomain.value = res.data.wap_url + '/pages/index/index'
QRCode.toDataURL(wapDomain.value, {errorCorrectionLevel: 'L', margin: 0, width: 100}).then(url => {
const loading = ref(false)
const loadingIframe = ref(false) // iframe
const loadingDev = ref(false) //
const timeFrame = ref(0)
var time = new Date().getTime();
getUrl().then((res:any)=> {
wapDomain.value = res.data.wap_domain;
wapUrl.value = res.data.wap_url;
setDomain();
//
if(import.meta.env.MODE == 'production') return;
// envwap
if (wapDomain.value) return;
let wap_domain_storage = storage.get('wap_domain');
if(wap_domain_storage){
wapUrl.value = wap_domain_storage
setDomain();
return;
}
timeFrame.value = new Date().getTime();
});
const save = ()=> {
wapUrl.value = wapDomain.value + '/wap'
setDomain();
storage.set({ key : 'wap_domain', data :wapUrl.value });
loadingIframe.value = true;
loadingDev.value = false;
}
const setDomain = ()=> {
let siteInfo = storage.get('siteInfo');
let siteId = 0;
if (siteInfo) siteId = siteInfo.site_id;
wapPreview.value = `${wapUrl.value}/pages/index/index?mode=preview&site_id=${siteId}`;
QRCode.toDataURL(wapPreview.value, {errorCorrectionLevel: 'L', margin: 0, width: 100}).then(url => {
wapImage.value = url
})
});
}
// iframe
const loadIframe = ()=> {
if (!wapPreview.value) return
var loadTime = new Date().getTime();
var difference = loadTime - timeFrame.value;
// 1000wap
if (difference < 1000) {
loadingDev.value = true;
loadingIframe.value = false;
wapPreview.value = ''
wapImage.value = ''
} else {
loadingDev.value = false;
loadingIframe.value = true;
}
loading.value = true
}
const router = useRouter()

View File

@ -2,7 +2,7 @@
<div class="main-container">
<el-card class="box-card !border-none" shadow="never" v-loading="loading">
<div class="flex">
<div class="w-[360px] h-[615px] relative mr-[30px] border-[1px] border-gray-300">
<div class="w-[360px] h-[400px] absolute mr-[30px] border-[1px] border-gray-300">
<div class="flex items-center justify-between absolute h-[60px] left-[0px] right-[0px] bottom-[0px] bg-white border-[1px] border-primary" :style="{ 'backgroundColor': diyBottomData.backgroundColor }">
<div class="flex flex-1 flex-col items-center justify-center" v-for="(item, index) in diyBottomData.list" :key="'b' + index">
<el-image class="w-[22px] h-[22px] mb-[5px] leading-1" :src="img(item.iconPath)" :fit="contain">
@ -16,7 +16,7 @@
</div>
</div>
</div>
<div class="flex-1">
<div class="flex-1 ml-[430px]">
<div class="flex items-center border-l-[3px] border-primary pl-[5px] leading-[1.1] mt-[10px]">
<span class="text-[14px]">{{ t('bottomNav') }}</span>
<span class="text-[12px] ml-[8px] text-gray-500">{{ t('bottomNavHint') }}</span>

View File

@ -8,7 +8,7 @@
<el-row class="flex">
<el-col :span="8" class="min-w-[100px]">
<div class="statistic-card">
<el-statistic :value="balanceStatistics.money ? Number.parseFloat(balanceStatistics.money+balanceStatistics.balance).toFixed(2) : '0.00'"></el-statistic>
<el-statistic :value="balanceStatistics.money && balanceStatistics.balance ? (Number.parseFloat(balanceStatistics.money)+Number.parseFloat(balanceStatistics.balance)).toFixed(2) : '0.00'"></el-statistic>
<div class="statistic-footer">
<div class="footer-item text-[14px] text-[#666]">
<span>{{ t('totalAllBalance') }}</span>

View File

@ -1,9 +1,14 @@
<template>
<div class="main-container" v-loading="loading">
<el-card class="box-card !border-none mt-[16px]" shadow="never">
<div class="card-header mb-5 pb-[10px] border-b-[1px] border-[#EDEDED]">
<span class="font-bold text-[18px] text-[#333333]">{{ t('essentialInfo') }}</span>
<div class="detail-head !ml-[20px] !mb-[5px]">
<div class="left" @click="router.push({ path: '/member/member' })">
<span class="iconfont iconxiangzuojiantou !text-xs"></span>
<span class="ml-[1px]">{{t('returnToPreviousPage')}}</span>
</div>
<span class="adorn">|</span>
<span class="right">{{ pageName }}</span>
</div>
<el-card class="box-card !border-none" shadow="never">
<div class="bg-[#FAFAFD] py-[20px] pr-[80px] pl-[280px] relative">
<div class="member-info absolute w-[250px]">
<div class="flex items-center">
@ -248,14 +253,9 @@ import colorGradient from '../../../../uniapp/src/uni_modules/vk-uview-ui/libs/f
import useAppStore from '@/stores/modules/app'
const route = useRoute()
const pageName = route.meta.title
const appStore = useAppStore()
//
appStore.pageReturn = true
watch(route, (newX, oldX) => {
appStore.pageReturn = false
})
const loading = ref(true)
//

View File

@ -78,13 +78,6 @@ const router = useRouter()
const orderId: number = parseInt(route.query.order_id)
const loading = ref(true)
//
const appStore = useAppStore()
appStore.pageReturn = true
watch(route, (newX, oldX) => {
appStore.pageReturn = false
})
const formData: Record<string, any> | null = ref(null)
const setFormData = async (orderId: number = 0) => {

View File

@ -18,10 +18,10 @@
<el-statistic :value="rechargeStatistics.recharge_refund_money ? Number.parseFloat(rechargeStatistics.recharge_refund_money).toFixed(2) : '0.00'">
<template #title>
<div class="text-[14px] mb-[9px]">{{ t('totalRechargeRefundMoney') }}</div>
</template>
</template>
</el-statistic>
</el-col>
</el-row>
</el-card>
@ -164,7 +164,7 @@ import { AnyObject } from '@/types/global'
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title;
const pageName = route.meta.title
const memberId: number = parseInt(route.query.id || 0)
const channelList = ref([])
@ -184,7 +184,7 @@ const orderTableData = reactive({
order_status: '',
member_id: memberId,
create_time: [],
pay_time:[],
pay_time: [],
order_from: '',
start_money: '',
end_money: ''
@ -236,7 +236,7 @@ loadOrderList()
* @param data
*/
const infoEvent = (data: any) => {
router.push(`/finance/recharge/detail?order_id=${data.order_id}`)
router.push(`/order/recharge/detail?order_id=${data.order_id}`)
}
/**

View File

@ -2,44 +2,47 @@
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center mb-[5px]">
<span class="text-[24px]">{{pageName}}</span>
</div>
<span class="text-[24px]">{{ pageName }}</span>
</div>
<el-card class="box-card !border-none table-search-wra base-bg !px-[35px]" shadow="never">
<el-row class="flex">
<el-col :span="12">
<el-row class="flex">
<el-col :span="12">
<div class="statistic-card">
<el-statistic :value="refundStat.refund_all_money"></el-statistic>
<div class="statistic-footer">
<div class="footer-item text-[14px] text-[#666]">
<span>{{ t('accumulateRefundMoney') }}</span>
</div>
</div>
</div>
<el-statistic :value="refundStat.refund_all_money"></el-statistic>
<div class="statistic-footer">
<div class="footer-item text-[14px] text-[#666]">
<span>{{ t('accumulateRefundMoney') }}</span>
</div>
</div>
</div>
</el-col>
<el-col :span="12">
<div class="statistic-card">
<el-statistic :value="refundStat.refund_have_money"></el-statistic>
<div class="statistic-footer">
<div class="footer-item text-[14px] text-[#666]">
<span>{{ t('haveRefundMoney') }}</span>
</div>
</div>
</div>
<el-statistic :value="refundStat.refund_have_money"></el-statistic>
<div class="statistic-footer">
<div class="footer-item text-[14px] text-[#666]">
<span>{{ t('haveRefundMoney') }}</span>
</div>
</div>
</div>
</el-col>
</el-row>
</el-row>
</el-card>
<el-card class="box-card !border-none mb-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="refundTableData.searchParam" ref="searchFormRef">
<el-form-item :label="t('memberInfo')" prop="keywords">
<el-input v-model="refundTableData.searchParam.keywords" class="w-[240px]" :placeholder="t('memberInfoPlaceholder')" />
<el-input v-model="refundTableData.searchParam.keywords" class="w-[240px]"
:placeholder="t('memberInfoPlaceholder')" />
</el-form-item>
<el-form-item :label="t('refundNumber')" prop="refund_no">
<el-input v-model="refundTableData.searchParam.refund_no" class="w-[240px]" :placeholder="t('refundNumberPlaceholder')" />
<el-input v-model="refundTableData.searchParam.refund_no" class="w-[240px]"
:placeholder="t('refundNumberPlaceholder')" />
</el-form-item>
<el-form-item :label="t('orderNumber')" prop="order_no">
<el-input v-model="refundTableData.searchParam.order_no" class="w-[240px]" :placeholder="t('orderNumberPlaceholder')" />
<el-input v-model="refundTableData.searchParam.order_no" class="w-[240px]"
:placeholder="t('orderNumberPlaceholder')" />
</el-form-item>
<el-form-item :label="t('refundStatus')" prop="status">
@ -55,7 +58,7 @@
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadRefundList()">{{ t('search') }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
</el-form-item>
</el-form>
</el-card>
@ -69,8 +72,10 @@
<el-table-column :show-overflow-tooltip="true" :label="t('memberInfo')" align="left" min-width="140">
<template #default="{ row }">
<div class="flex items-center cursor-pointer " @click="toMember(row.member.member_id)">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.headimg" :src="img(row.member.headimg)" alt="">
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/assets/images/default_headimg.png" alt="">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.headimg" :src="img(row.member.headimg)"
alt="">
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/assets/images/default_headimg.png"
alt="">
<div class="flex flex flex-col">
<span class="">{{ row.member.nickname || '' }}</span>
<span class="">{{ row.member.mobile || '' }}</span>
@ -91,11 +96,11 @@
{{ row.status_name || '' }}
</template>
</el-table-column>
<el-table-column :label="t('operation')" fixed="right" width="130">
<template #default="{ row }">
<el-button type="primary" link @click="infoEvent(row)">{{ t('info') }}</el-button>
</template>
<template #default="{ row }">
<el-button type="primary" link @click="infoEvent(row)">{{ t('info') }}</el-button>
</template>
</el-table-column>
</el-table>
@ -107,51 +112,51 @@
</div>
</el-card>
<el-dialog v-model="refundInfoShowDialog" :title="t('refundDetail')" width="500px" :destroy-on-close="true">
<el-form :model="refundInfo" label-width="120px" ref="formRef" :rules="formRules" class="page-form" >
<el-form :model="refundInfo" label-width="120px" ref="formRef" :rules="formRules" class="page-form">
<el-form-item :label="t('nickname')">
<div class="input-width"> {{ refundInfo.member.nickname }} </div>
<div class="input-width"> {{ refundInfo.member.nickname }} </div>
</el-form-item>
<el-form-item :label="t('refundSource')">
<div class="input-width"> {{ refundInfo.item.item_name }} </div>
<div class="input-width"> {{ refundInfo.item.item_name }} </div>
</el-form-item>
<el-form-item :label="t('refundAmount')">
<div class="input-width"> {{ refundInfo.money }} </div>
<div class="input-width"> {{ refundInfo.money }} </div>
</el-form-item>
<el-form-item :label="t('orderNumber')">
<div class="input-width"> {{ refundInfo.item.order_no }} </div>
<div class="input-width"> {{ refundInfo.item.order_no }} </div>
</el-form-item>
<el-form-item :label="t('refundNumber')">
<div class="input-width"> {{ refundInfo.refund_no }} </div>
<div class="input-width"> {{ refundInfo.refund_no }} </div>
</el-form-item>
<el-form-item :label="t('refundTime')">
<div class="input-width"> {{ refundInfo.create_time }} </div>
<div class="input-width"> {{ refundInfo.create_time }} </div>
</el-form-item>
<el-form-item :label="t('statusName')">
<div class="input-width"> {{ refundInfo.status_name }} </div>
<div class="input-width"> {{ refundInfo.status_name }} </div>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="refundInfoShowDialog = false">{{t('confirm')}}</el-button>
</span>
</template>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="refundInfoShowDialog = false">{{ t('confirm') }}</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue'
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { img } from '@/utils/common'
import { useRouter, useRoute } from 'vue-router'
import { getRefund, getRefundStatus, getRefundStat } from '@/api/order'
import { getRechargeRefund, getRechargeRefundStatus, getRechargeRefundStat } from '@/api/order'
import { FormInstance } from 'element-plus'
const router = useRouter()
const route = useRoute()
const pageName = route.meta.title;
const pageName = route.meta.title
const searchFormRef = ref<FormInstance>()
const refundTableData = reactive({
page: 1,
@ -165,16 +170,15 @@ const refundTableData = reactive({
create_time: [],
status: '',
keywords: '',
order_no:''
order_no: ''
}
})
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
const resetForm = (formEl: FormInstance | undefined)=>{
if (!formEl) return
formEl.resetFields();
loadRefundList();
formEl.resetFields()
loadRefundList()
}
/**
* 获取退款列表
@ -183,7 +187,7 @@ const loadRefundList = (page: number = 1) => {
refundTableData.loading = true
refundTableData.page = page
getRefund({
getRechargeRefund({
page: refundTableData.page,
limit: refundTableData.limit,
...refundTableData.searchParam
@ -199,7 +203,7 @@ loadRefundList()
const refundList = ref([])
const checkRefundList = () => {
getRefundStatus().then(res => {
getRechargeRefundStatus().then(res => {
refundList.value = res.data
})
}
@ -211,29 +215,29 @@ const refundStat = reactive({
refund_Success_money: 0.00,
refund_fail_moey: 0.00
})
const checkRefundStat = () =>{
getRefundStat().then(res=>{
refundStat.refund_all_money = res.data['all'].money;
refundStat.refund_have_money = res.data['have'].money;
refundStat.refund_Success_money = res.data['3'].money;
refundStat.refund_fail_moey = res.data['-1'].money;
const checkRefundStat = () => {
getRechargeRefundStat().then(res => {
refundStat.refund_all_money = res.data.all.money
refundStat.refund_have_money = res.data.have.money
refundStat.refund_Success_money = res.data['3'].money
refundStat.refund_fail_moey = res.data['-1'].money
})
}
checkRefundStat()
const refundInfoShowDialog = ref(false)
const refundInfo = ref({});
// const refundInfoLoading = ref(true);
const refundInfo = ref({})
const infoEvent = (info) => {
refundInfo.value = info;
refundInfo.value = info
refundInfoShowDialog.value = true
}
/**
* 会员详情
*/
const toMember = (member_id: number) => {
router.push(`/member/detail?id=${member_id}`)
const toMember = (memberId: number) => {
router.push(`/member/detail?id=${memberId}`)
}
</script>

View File

@ -1,10 +1,13 @@
<template>
<div class="main-container">
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
<span class="text-[24px]">{{pageName}}</span>
</div>
<el-form :model="formData" label-width="150px" ref="ruleFormRef" :rules="formRules" class="page-form" v-loading="loading">
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title">{{ t('admin') }}</h3>
<h3 class="panel-title !text-sm">{{ t('admin') }}</h3>
<el-form-item :label="t('isCaptcha')" prop="formData.is_auth_register">
<el-switch v-model="formData.is_captcha"/>
@ -18,7 +21,7 @@
</el-card>
<el-card class="box-card !border-none mt-4" shadow="never">
<h3 class="panel-title">{{ t('site') }}</h3>
<h3 class="panel-title !text-sm">{{ t('site') }}</h3>
<el-form-item :label="t('isCaptcha')" prop="formData.is_auth_register">
<el-switch v-model="formData.is_site_captcha"/>
@ -44,6 +47,9 @@ import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { getConfigLogin, setConfigLogin } from '@/api/sys'
import { ElMessage, FormRules, FormInstance } from 'element-plus'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
const loading = ref(true),
ruleFormRef = ref<FormInstance>(),

View File

@ -1,5 +1,13 @@
<template>
<div class="main-container">
<div class="detail-head">
<div class="left" @click="router.push({ path: '/setting/agreement' })">
<span class="iconfont iconxiangzuojiantou !text-xs"></span>
<span class="ml-[1px]">{{t('returnToPreviousPage')}}</span>
</div>
<span class="adorn">|</span>
<span class="right">{{ pageName }}</span>
</div>
<el-card class="box-card !border-none" shadow="never" v-loading="loading">
<el-form :model="formData" label-width="90px" ref="formRef" :rules="formRules" class="page-form">
<el-form-item :label="t('type')">
@ -37,12 +45,7 @@ const router = useRouter()
const agreement_key: string = route.query.key || ''
const loading = ref(false)
const tabbarStore = useTabbarStore()
//
appStore.pageReturn = true;
watch(route, (newX, oldX) => {
appStore.pageReturn = false;
});
const pageName = route.meta.title
/**
* 表单数据

View File

@ -1,5 +1,8 @@
<template>
<div class="main-container">
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
<span class="text-[24px]">{{pageName}}</span>
</div>
<el-form :model="formData" label-width="150px" ref="ruleFormRef" :rules="rules" class="page-form" v-loading="loading">
<el-card class="box-card !border-none" shadow="never">
@ -50,6 +53,9 @@ import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { getCashOutConfig, setCashOutConfig, getTransfertype } from '@/api/member'
import { ElMessage, FormRules, FormInstance } from 'element-plus'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
const loading = ref(true),
ruleFormRef = ref<FormInstance>(),

View File

@ -1,8 +1,11 @@
<template>
<div class="main-container">
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
<span class="text-[24px]">{{pageName}}</span>
</div>
<el-form :model="formData" label-width="150px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title">{{ t('copyrightEdit') }}</h3>
<h3 class="panel-title !text-sm">{{ t('copyrightEdit') }}</h3>
<el-form-item :label="t('logo')">
<upload-image v-model="formData.logo" />
</el-form-item>
@ -22,7 +25,7 @@
</el-card>
<el-card class="box-card !border-none mt-[16px]" shadow="never">
<h3 class="panel-title">{{ t('putOnRecordEdit') }}</h3>
<h3 class="panel-title !text-sm">{{ t('putOnRecordEdit') }}</h3>
<el-form-item :label="t('icp')" prop="icp">
<el-input v-model="formData.icp" :placeholder="t('icpPlaceholder')" class="input-width" clearable maxlength="20"/>
@ -56,6 +59,9 @@ import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { setCopyright,getCopyright } from '@/api/sys'
import { ElMessage, FormInstance, FormRules } from 'element-plus'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
const loading = ref(true)

View File

@ -1,8 +1,11 @@
<template>
<div class="main-container">
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
<span class="text-[24px]">{{pageName}}</span>
</div>
<el-form :model="formData" label-width="150px" ref="ruleFormRef" class="page-form" v-loading="loading">
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title">{{ t('commonSetting') }}</h3>
<h3 class="panel-title !text-sm">{{ t('commonSetting') }}</h3>
<el-form-item :label="t('logonMode')">
<el-checkbox v-model="formData.is_username" :label="t('isUsername')" @change="switchChange($event, 'is_username')" />
@ -21,7 +24,7 @@
<div class="form-tip">{{ t('agreementTips') }}</div>
</el-form-item>
<h3 class="panel-title">{{ t('tripartiteSetting') }}</h3>
<h3 class="panel-title !text-sm">{{ t('tripartiteSetting') }}</h3>
<el-form-item :label="t('isAuthRegister')" prop="formData.is_auth_register">
<el-switch v-model="formData.is_auth_register" @change="switchChange($event, 'is_auth_register')" />
@ -42,6 +45,9 @@ import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { getLoginConfig, setLoginConfig } from '@/api/member'
import { FormInstance } from 'element-plus'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
const loading = ref(true)
const ruleFormRef = ref<FormInstance>()

View File

@ -0,0 +1,52 @@
<template>
<div class="main-container">
<el-form :model="formData" label-width="150px" ref="formRef" class="page-form"
v-loading="loading">
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title">{{ t('mapSetting') }}</h3>
<el-form-item :label="t('mapKey')" prop="site_name">
<el-input v-model="formData.key" class="input-width" clearable />
</el-form-item>
</el-card>
</el-form>
<div class="fixed-footer-wrap">
<div class="fixed-footer">
<el-button type="primary" :loading="loading" @click="save(formRef)">{{ t('save') }}</el-button>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { setMap, getMap } from '@/api/sys'
import { FormInstance, } from 'element-plus'
const loading = ref(false)
const formData = reactive<Record<string, string>>({
key : ''
})
const setFormData = async () => {
const service_data = await (await getMap()).data
formData.key = service_data.key
}
setFormData()
/**
* 保存
*/
const save = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
setMap(formData).then(() => {
loading.value = false
}).catch(() => {
loading.value = false
})
}
</script>
<style lang="scss" scoped></style>

View File

@ -1,7 +1,10 @@
<template>
<div class="main-container" v-loading="noticeTableData.loading">
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
<span class="text-[24px]">{{pageName}}</span>
</div>
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title">{{ t('buyerNotice') }}</h3>
<h3 class="panel-title !text-base">{{ t('buyerNotice') }}</h3>
<div class="flex flex-row flex-wrap m-[-4px]">
<el-table :data="noticeTableData.seller" size="large">
<el-table-column prop="name" :label="t('noticeType')" min-width="120" />
@ -28,7 +31,7 @@
</el-card>
<el-card class="box-card !border-none mt-[16px]" shadow="never">
<h3 class="panel-title">{{ t('sellerNotice') }}</h3>
<h3 class="panel-title !text-base">{{ t('sellerNotice') }}</h3>
<div class="flex flex-row flex-wrap m-[-4px]">
<el-table :data="noticeTableData.buyer" size="large">
<el-table-column prop="name" :label="t('noticeType')" min-width="120" />
@ -71,6 +74,9 @@ import Sms from '@/views/setting/components/notice-sms.vue'
import Wechat from '@/views/setting/components/notice-wechat.vue'
import Weapp from '@/views/setting/components/notice-weapp.vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
const smsDialog: Record<string, any> | null = ref(null)
const wechatDialog: Record<string, any> | null = ref(null)

View File

@ -1,9 +1,12 @@
<template>
<div class="main-container">
<div class="flex ml-[18px] justify-between items-center mt-[20px] mb-[5px]">
<span class="text-[24px]">{{pageName}}</span>
</div>
<el-form :model="formData" label-width="150px" ref="formRef" :rules="formRules" class="page-form"
v-loading="loading">
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title">{{ t('websiteInfo') }}</h3>
<h3 class="panel-title !text-sm">{{ t('websiteInfo') }}</h3>
<el-form-item :label="t('siteName')" prop="site_name">
<el-input v-model="formData.site_name" :placeholder="t('siteNamePlaceholder')" class="input-width" clearable maxlength="20" />
@ -26,7 +29,7 @@
</el-form-item>
</el-card>
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title">{{ t('frontEndInfo') }}</h3>
<h3 class="panel-title !text-sm">{{ t('frontEndInfo') }}</h3>
<el-form-item :label="t('frontEndName')">
<el-input v-model="formData.front_end_name" :placeholder="t('frontEndNamePlaceholder')" class="input-width" clearable maxlength="20" />
</el-form-item>
@ -36,7 +39,7 @@
</el-form-item>
</el-card>
<el-card class="box-card !border-none" shadow="never" v-if="app_type == 'admin' ">
<h3 class="panel-title">{{ t('serviceInformation') }}</h3>
<h3 class="panel-title !text-sm">{{ t('serviceInformation') }}</h3>
<el-form-item :label="t('contactsTel')">
<el-input v-model="formData.tel" :placeholder="t('contactsTelPlaceholder')" class="input-width" clearable maxlength="20" />
</el-form-item>
@ -64,6 +67,9 @@ import { setWebsite, getWebsite, getService } from '@/api/sys'
import { FormInstance, FormRules } from 'element-plus'
import storage from '@/utils/storage'
import { getAppType } from '@/utils/common'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
const loading = ref(true)
const app_type = ref()

View File

@ -8,9 +8,12 @@
</div>
</template>
</el-alert>
<el-form :model="formData" label-width="200px" ref="formRef" :rules="formRules" class="page-form mt-2" v-loading="loading">
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
<span class="text-[24px]">{{pageName}}</span>
</div>
<el-form :model="formData" label-width="200px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title">{{t('wechatpay')}}</h3>
<h3 class="panel-title !text-sm">{{t('wechatpay')}}</h3>
<el-form-item :label="t('mchId')" prop="wechatpay_config.mch_id">
<el-input v-model="formData.wechatpay_config.mch_id" :placeholder="t('mchIdPlaceholder')" class="input-width" maxlength="32" show-word-limit clearable />
@ -39,7 +42,7 @@
<el-card class="box-card mt-4 !border-none" shadow="never">
<h3 class="panel-title">{{t('alipay')}}</h3>
<h3 class="panel-title !text-sm">{{t('alipay')}}</h3>
<el-form-item :label="t('appId')" prop="alipay_config.app_id">
<el-input v-model="formData.alipay_config.app_id" :placeholder="t('appIdPlaceholder')" class="input-width" maxlength="32" show-word-limit clearable />
@ -84,6 +87,9 @@ import { t } from '@/lang'
import { getTransferInfo, setTransferInfo } from '@/api/sys'
import { useClipboard } from '@vueuse/core'
import { ElMessage, FormInstance, FormRules } from 'element-plus'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
const loading = ref(false)

View File

@ -1,8 +1,11 @@
<template>
<div class="main-container">
<el-form :model="formData" label-width="200px" ref="formRef" class="page-form" v-loading="loading">
<el-card class="box-card !border-none mt-[16px]" shadow="never">
<h3 class="panel-title">{{ t('oplatformSetting') }}</h3>
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
<span class="text-[24px]">{{pageName}}</span>
</div>
<el-form :model="formData" label-width="150px" ref="formRef" class="page-form" v-loading="loading">
<el-card class="box-card !border-none mt-[5px]" shadow="never">
<h3 class="panel-title !text-sm">{{ t('oplatformSetting') }}</h3>
<el-form-item label="APPID">
<el-input v-model="formData.appid" :placeholder="t('appidPlaceholder')" class="input-width" clearable/>
@ -12,7 +15,7 @@
<el-input v-model="formData.appsecret" :placeholder="t('appsecretPlaceholder')" class="input-width" clearable/>
</el-form-item>
<h3 class="panel-title">{{ t('oplatformComm') }}</h3>
<h3 class="panel-title !text-sm">{{ t('oplatformComm') }}</h3>
<el-form-item :label="t('empowerStartDomain')">
<span>{{ formData.start_domain }}</span>
</el-form-item>
@ -45,7 +48,7 @@
<span>{{ formData.host }}</span>
</el-form-item>
<h3 class="panel-title">{{ t('oplatformBuilder') }}</h3>
<h3 class="panel-title !text-sm">{{ t('oplatformBuilder') }}</h3>
<el-form-item :label="t('builderEmail')" >
<el-input v-model="formData.email" class="input-width" clearable/>
</el-form-item>
@ -78,6 +81,9 @@ import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { setCopyright,getCopyright } from '@/api/sys'
import { ElMessage, FormInstance, FormRules } from 'element-plus'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title
const loading = ref(true)
const formData = reactive<Record<string, string>>({

View File

@ -1,9 +1,16 @@
<template>
<div class="main-container">
<el-form :model="formData" label-width="150px" ref="formRef" class="page-form">
<div class="detail-head !mb-[10px]">
<div class="left" @click="router.push({ path: '/admin/site/list' })">
<span class="iconfont iconxiangzuojiantou !text-xs"></span>
<span class="ml-[1px]">{{t('returnToPreviousPage')}}</span>
</div>
<span class="adorn">|</span>
<span class="right">{{ pageName }}</span>
<el-button class="ml-auto w-[100px] mr-[10px]" type="primary" @click="editEvent(formRef)">{{ t('edit') }}</el-button>
</div>
<el-form :model="formData" label-width="90px" ref="formRef" class="page-form">
<el-card class="box-card !border-none relative" shadow="never">
<h3 class="panel-title">{{ t('siteInfo') }}</h3>
<el-form-item :label="t('siteName')">
<div class="input-width">{{ formData.site_name }}</div>
</el-form-item>
@ -36,8 +43,6 @@
<el-form-item :label="t('expireTime')">
<div class="input-width">{{ formData.expire_time || '' }}</div>
</el-form-item>
<el-button class="absolute right-5 top-5" type="primary" @click="editEvent(formRef)">{{ t('edit') }}</el-button>
</el-card>
</el-form>
@ -66,15 +71,10 @@ const appStore = useAppStore()
const tabbarStore = useTabbarStore()
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title
const id: number = parseInt(route.query.id)
const loading = ref(true)
//
appStore.pageReturn = true
watch(route, (newX, oldX) => {
appStore.pageReturn = false
})
/**
* 表单数据
*/

View File

@ -1,19 +1,30 @@
<template>
<div class="main-container mb-80" v-loading="loading">
<div class="detail-head !mb-[10px]">
<div class="left" @click="router.push({ path: '/admin/tools/code' })">
<span class="iconfont iconxiangzuojiantou !text-xs"></span>
<span class="ml-[1px]">{{t('returnToPreviousPage')}}</span>
</div>
<span class="adorn">|</span>
<span class="right">{{ pageName }}</span>
</div>
<el-card class="box-card !border-none" shadow="never">
<el-form :model="formData" label-width="90px" ref="formRef" :rules="formRules" class="page-form">
<el-form-item :label="t('tableName')" prop="table_name">
<el-input v-model="formData.table_name" clearable :placeholder="t('tableNamePlaceholder')" class="input-width" maxlength="64" />
<el-input v-model="formData.table_name" clearable :placeholder="t('tableNamePlaceholder')"
class="input-width" maxlength="64" />
</el-form-item>
<el-form-item :label="t('tableContent')" prop="table_content">
<el-input v-model="formData.table_content" clearable :placeholder="t('tableContentPlaceholder')" class="input-width" maxlength="64" />
<el-input v-model="formData.table_content" clearable :placeholder="t('tableContentPlaceholder')"
class="input-width" maxlength="64" />
</el-form-item>
<el-form-item :label="t('moduleName')">
<el-input v-model="formData.module_name" clearable :placeholder="t('moduleNamePlaceholder')" class="input-width" />
<el-input v-model="formData.module_name" clearable :placeholder="t('moduleNamePlaceholder')"
class="input-width" />
</el-form-item>
<el-form-item :label="t('className')">
<el-input v-model="formData.class_name" clearable :placeholder="t('classNamePlaceholder')" class="input-width" />
<el-input v-model="formData.class_name" clearable :placeholder="t('classNamePlaceholder')"
class="input-width" />
</el-form-item>
<el-form-item :label="t('editType')">
<el-radio-group v-model="formData.edit_type" :placeholder="t('editTypePlaceholder')">
@ -29,12 +40,16 @@
<el-card class="box-card !border-none p-none" shadow="never">
<el-divider content-position="left">{{ t('commentField') }}</el-divider>
<div class="flex flex-row m-0.5 cursor-pointer flex-wrap" :ref="tabsRefs.set">
<div class="border border-dashed border-gray-200 mt-2 text-sm mr-2 pt-1 pb-1 pl-1.5 pr-1.5 dashed-border design-field" v-for="(item, index) in fieldList.common" :key="index" :data-id="index">{{ item.column_comment }}
<div class="border border-dashed border-gray-200 mt-2 text-sm mr-2 pt-1 pb-1 pl-1.5 pr-1.5 dashed-border design-field"
v-for="(item, index) in fieldList.common" :key="index" :data-id="index">{{ item.column_comment
}}
</div>
</div>
<el-divider content-position="left">{{ t('baseField') }}</el-divider>
<div class="flex flex-row m-0.5 cursor-pointer flex-wrap" :ref="tabsRefs.set">
<div class="border border-dashed border-gray-200 mt-2 text-sm mr-2 pt-1 pb-1 pl-1.5 pr-1.5 dashed-border design-field" v-for="(item, index) in fieldList.base" :key="index" :data-id="index">{{ item.column_comment }}</div>
<div class="border border-dashed border-gray-200 mt-2 text-sm mr-2 pt-1 pb-1 pl-1.5 pr-1.5 dashed-border design-field"
v-for="(item, index) in fieldList.base" :key="index" :data-id="index">{{ item.column_comment }}
</div>
</div>
</el-card>
</el-col>
@ -46,19 +61,27 @@
@click="onActivateField(index)" :class="index === formData.editFiledIndex ? 'activate' : ''">
<div class="flex flex-row ">
<div class="flex flex-row design-field">
<div class="text-xs text-gray-500 w-28 items-center justify-end flex">{{t('columnName') }}</div>
<el-input class="w-50 m-2" v-model="item.column_name" size="small" :placeholder="t('columnNamePlaceholder')" />
<div class="text-xs text-gray-500 w-28 items-center justify-end flex">{{
t('columnName')
}}</div>
<el-input class="w-50 m-2" v-model="item.column_name" size="small"
:placeholder="t('columnNamePlaceholder')" />
</div>
<div class="flex flex-row design-field">
<div class="text-xs text-gray-500 w-28 items-center justify-end flex">{{t('columnComment') }}</div>
<el-input class="w-50 m-2" v-model="item.column_comment" size="small" :placeholder="t('columnCommentPlaceholder')" />
<div class="text-xs text-gray-500 w-28 items-center justify-end flex">
{{ t('columnComment') }}</div>
<el-input class="w-50 m-2" v-model="item.column_comment" size="small"
:placeholder="t('columnCommentPlaceholder')" />
</div>
<div class="flex flex-row design-field flex-shrink-0 w-40">
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{t('columnType') }}</div>
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{
t('columnType')
}}</div>
<div class="w-50 m-2">{{ item.column_type }}</div>
</div>
</div>
<div @click="onDel(index)" class="items-center justify-center flex items-center flex-shrink-0 rounded-full bg-red-400 text-white icon-btn w-7 h-7">
<div @click="onDel(index)"
class="items-center justify-center flex items-center flex-shrink-0 rounded-full bg-red-400 text-white icon-btn w-7 h-7">
<el-icon>
<Delete />
</el-icon>
@ -75,21 +98,29 @@
<el-divider content-position="left">{{ t('fieldAttribute') }}</el-divider>
<div>
<div class="flex flex-row">
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('columnName') }}</div>
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('columnName') }}
</div>
<div>
<el-input class="w-50 m-2" v-model="formData.table_column[formData.editFiledIndex]['column_name']" size="small" :placeholder="t('columnNamePlaceholder')" />
<el-input class="w-50 m-2"
v-model="formData.table_column[formData.editFiledIndex]['column_name']" size="small"
:placeholder="t('columnNamePlaceholder')" />
</div>
</div>
<div class="flex flex-row ">
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('columnComment') }}</div>
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('columnComment') }}
</div>
<div>
<el-input class="w-50 m-2" v-model="formData.table_column[formData.editFiledIndex]['column_comment']" size="small" :placeholder="t('columnCommentPlaceholder')" />
<el-input class="w-50 m-2"
v-model="formData.table_column[formData.editFiledIndex]['column_comment']" size="small"
:placeholder="t('columnCommentPlaceholder')" />
</div>
</div>
<div class="flex flex-row ">
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('isPk') }}</div><div>
<el-radio-group class="ml-4" v-model="formData.table_column[formData.editFiledIndex]['is_pk']">
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('isPk') }}</div>
<div>
<el-radio-group class="ml-4"
v-model="formData.table_column[formData.editFiledIndex]['is_pk']">
<el-radio :label="1" size="large">{{ t('yes') }}</el-radio>
<el-radio :label="0" size="large">{{ t('no') }}</el-radio>
</el-radio-group>
@ -99,26 +130,33 @@
<el-divider content-position="left">{{ t('commentField') }}</el-divider>
<div>
<div class="flex flex-row ">
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('isRequired') }}</div>
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('isRequired') }}
</div>
<div>
<el-radio-group class="ml-4" v-model="formData.table_column[formData.editFiledIndex]['is_required']">
<el-radio-group class="ml-4"
v-model="formData.table_column[formData.editFiledIndex]['is_required']">
<el-radio :label="1" size="large">{{ t('yes') }}</el-radio>
<el-radio :label="0" size="large">{{ t('no') }}</el-radio>
</el-radio-group>
</div>
</div>
<div class="flex flex-row ">
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('isInsert') }}</div><div>
<el-radio-group class="ml-4" v-model="formData.table_column[formData.editFiledIndex]['is_insert']">
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('isInsert') }}
</div>
<div>
<el-radio-group class="ml-4"
v-model="formData.table_column[formData.editFiledIndex]['is_insert']">
<el-radio :label="1" size="large">{{ t('yes') }}</el-radio>
<el-radio :label="0" size="large">{{ t('no') }}</el-radio>
</el-radio-group>
</div>
</div>
<div class="flex flex-row ">
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('isUpdate') }}</div>
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('isUpdate') }}
</div>
<div>
<el-radio-group class="ml-4" v-model="formData.table_column[formData.editFiledIndex]['is_update']">
<el-radio-group class="ml-4"
v-model="formData.table_column[formData.editFiledIndex]['is_update']">
<el-radio :label="1" size="large">{{ t('yes') }}</el-radio>
<el-radio :label="0" size="large">{{ t('no') }}</el-radio>
</el-radio-group>
@ -127,16 +165,19 @@
<div class="flex flex-row ">
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('isLists') }}</div>
<div>
<el-radio-group class="ml-4" v-model="formData.table_column[formData.editFiledIndex]['is_lists']">
<el-radio-group class="ml-4"
v-model="formData.table_column[formData.editFiledIndex]['is_lists']">
<el-radio :label="1" size="large">{{ t('yes') }}</el-radio>
<el-radio :label="0" size="large">{{ t('no') }}</el-radio>
</el-radio-group>
</div>
</div>
<div class="flex flex-row ">
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('isSearch') }}</div>
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('isSearch') }}
</div>
<div>
<el-radio-group class="ml-4" v-model="formData.table_column[formData.editFiledIndex]['is_search']">
<el-radio-group class="ml-4"
v-model="formData.table_column[formData.editFiledIndex]['is_search']">
<el-radio :label="1" size="large">{{ t('yes') }}</el-radio>
<el-radio :label="0" size="large">{{ t('no') }}</el-radio>
</el-radio-group>
@ -145,25 +186,32 @@
<div class="flex flex-row ">
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('isQuery') }}</div>
<div>
<el-radio-group class="ml-4" v-model="formData.table_column[formData.editFiledIndex]['is_query']">
<el-radio-group class="ml-4"
v-model="formData.table_column[formData.editFiledIndex]['is_query']">
<el-radio :label="1" size="large">{{ t('yes') }}</el-radio>
<el-radio :label="0" size="large">{{ t('no') }}</el-radio>
</el-radio-group>
</div>
</div>
<div class="flex flex-row ">
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('queryType') }}</div>
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('queryType') }}
</div>
<div>
<el-select class="m-2" :placeholder="t('selectPlaceholder')" size="small" v-model="formData.table_column[formData.editFiledIndex]['query_type']">
<el-option :label="item" :value="item" v-for="(item, index) in queryType" :key="index" />
<el-select class="m-2" :placeholder="t('selectPlaceholder')" size="small"
v-model="formData.table_column[formData.editFiledIndex]['query_type']">
<el-option :label="item" :value="item" v-for="(item, index) in queryType"
:key="index" />
</el-select>
</div>
</div>
<div class="flex flex-row ">
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('viewType') }}</div>
<div class="text-xs text-gray-500 w-20 items-center justify-end flex">{{ t('viewType') }}
</div>
<div>
<el-select class="m-2" :placeholder="t('selectPlaceholder')" size="small" v-model="formData.table_column[formData.editFiledIndex]['view_type']">
<el-option :label="item.label" :value="item.value" v-for="(item, index) in viewType" :key="index" />
<el-select class="m-2" :placeholder="t('selectPlaceholder')" size="small"
v-model="formData.table_column[formData.editFiledIndex]['view_type']">
<el-option :label="item.label" :value="item.value" v-for="(item, index) in viewType"
:key="index" />
</el-select>
</div>
</div>
@ -183,22 +231,24 @@
</template>
<script lang="ts" setup>
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
import { ref, reactive, computed, onMounted, nextTick, watch } from 'vue'
import { t } from '@/lang'
import { FormInstance, ElNotification } from 'element-plus'
import { getGenerateTableInfo } from '@/api/tools';
import { getGenerateTableInfo, editGenerateTable } from '@/api/tools'
import { useRoute, useRouter } from 'vue-router'
import Sortable, { SortableEvent } from 'sortablejs'
import { useTemplateRefsList } from '@vueuse/core'
import { cloneDeep, range, isEmpty } from 'lodash-es'
import { editGenerateTable } from '@/api/tools'
import { cloneDeep, range } from 'lodash-es'
import useTabbarStore from '@/stores/modules/tabbar'
import useAppStore from '@/stores/modules/app'
const tabbarStore = useTabbarStore()
const appStore = useAppStore()
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title
const id: number = parseInt(route.query.id || 0);
const id: number = parseInt(route.query.id || 0)
const loading = ref(true)
const tabsRefs = useTemplateRefsList<HTMLElement>()
@ -230,10 +280,9 @@ const initialFormData = {
class_name: '',
edit_type: 1,
table_column: [],
editFiledIndex: 0,
editFiledIndex: 0
}
const fieldList: {
common: fieldData[],
base: fieldData[],
@ -294,7 +343,7 @@ const fieldList: {
is_search: 0,
query_type: 'BETWEEN',
view_type: 'datetime'
},
}
],
base: [
@ -395,8 +444,7 @@ const fieldList: {
is_search: 1,
query_type: '=',
view_type: 'datetime'
},
}
]
}
@ -404,36 +452,36 @@ const fieldList: {
const queryType = ['=', '!=', '>', '>=', '<', '<=', 'LIKE', 'BETWEEN']
const viewType = [
{
'label': t('formInput'),
'value': 'input'
label: t('formInput'),
value: 'input'
},
{
'label': t('formTextarea'),
'value': 'textarea'
label: t('formTextarea'),
value: 'textarea'
},
{
'label': t('formSelect'),
'value': 'select'
label: t('formSelect'),
value: 'select'
},
{
'label': t('formRadio'),
'value': 'radio'
label: t('formRadio'),
value: 'radio'
},
{
'label': t('formCheckbox'),
'value': 'checkbox'
label: t('formCheckbox'),
value: 'checkbox'
},
{
'label': t('formDateTime'),
'value': 'datetime'
label: t('formDateTime'),
value: 'datetime'
},
{
'label': t('formImageSelect'),
'value': 'imageSelect'
label: t('formImageSelect'),
value: 'imageSelect'
},
{
'label': t('formEditor'),
'value': 'editor'
label: t('formEditor'),
value: 'editor'
}
]
@ -450,14 +498,12 @@ onMounted(() => {
group: 'design-field',
animation: 200,
onAdd: (evt: SortableEvt) => {
const name = evt.originalEvent?.dataTransfer?.getData('name')
const field = fieldList[name]
if (field && field[evt.oldIndex!]) {
const data = cloneDeep(field[evt.oldIndex!])
if (data.is_pk) {
const is_pk = formData.table_column.find((item: { is_pk: any; }) => {
return item.is_pk
@ -465,7 +511,7 @@ onMounted(() => {
if (is_pk) {
ElNotification({
type: 'error',
message: t('pkRepeatTip'),
message: t('pkRepeatTip')
})
return evt.item.remove()
}
@ -479,7 +525,6 @@ onMounted(() => {
nameRepeatCount++
}
formData.table_column.splice(evt.newIndex!, 0, data)
}
evt.item.remove()
nextTick(() => {
@ -494,7 +539,7 @@ onMounted(() => {
nextTick(() => {
sortable.sort(range(formData.table_column.length).map((value) => value.toString()))
})
},
}
})
tabsRefs.value.forEach((item, index) => {
@ -503,12 +548,12 @@ onMounted(() => {
group: {
name: 'design-field',
pull: 'clone',
put: false,
put: false
},
animation: 200,
setData: (dataTransfer) => {
dataTransfer.setData('name', Object.keys(fieldList)[index])
},
}
})
})
})
@ -533,13 +578,10 @@ const setFormData = async (id: number = 0) => {
loading.value = false
}
if (id) setFormData(id);
if (id) setFormData(id)
const formRef = ref<FormInstance>()
const validataVarName = (val: string) => {
return /^([a-zA-Z_$])([a-zA-Z0-9_$])*$/.test(val)
}
@ -562,19 +604,18 @@ const formRules = computed(() => {
],
table_content: [
{ required: true, message: t('tableContentPlaceholder'), trigger: 'blur' },
{ required: true, message: t('tableContentPlaceholder'), trigger: 'blur' }
]
}
})
const onSave = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
let msg = '';
let msg = ''
formData.table_column.find((item) => {
if (!validataVarName(item.column_name)) {
msg = item.column_name + " " + t('fieldNameValidata')
msg = item.column_name + ' ' + t('fieldNameValidata')
return true
}
})
@ -582,21 +623,19 @@ const onSave = async (formEl: FormInstance | undefined) => {
if (msg) {
ElNotification({
type: 'error',
message: msg,
message: msg
})
return
}
loading.value = true
let data = cloneDeep(formData)
const data = cloneDeep(formData)
data.table_column = JSON.stringify(data.table_column)
editGenerateTable(data).then((res: any) => {
loading.value = false;
}).catch((err: any) => {
loading.value = false
}).catch(() => {
loading.value = false
})
}
const onDel = (index: number) => {
if (!formData.table_column[index]) return
@ -609,7 +648,8 @@ const back = () => {
}
</script>
<style lang="scss" scoped>.dashed-border {
<style lang="scss" scoped>
.dashed-border {
border-color: var(--el-border-color-light);
&:hover {
@ -623,4 +663,5 @@ const back = () => {
.icon-btn {
background-color: var(--el-color-primary);
}</style>
}
</style>

View File

@ -5,7 +5,7 @@
<span class="text-[24px]">{{ pageName }}</span>
</div>
<div class="bg-[#fff] pb-[20px] mb-3">
<p class="pt-[20px] pb-[10px]">{{ t('serverInformation') }}</p>
<p class="pt-[20px] pb-[10px] text-sm">{{ t('serverInformation') }}</p>
<div class="text-[14px]">
<el-table :data="systemService.server" size="large" v-loading="loadingArr.server_load">
<el-table-column prop="name" :label="t('environment')" align="left" min-width="200" />
@ -14,7 +14,7 @@
</div>
</div>
<div class="bg-[#fff] pb-[20px] mb-3">
<p class="py-[20px]">{{ t('systemDemand') }}</p>
<p class="py-[20px] text-sm">{{ t('systemDemand') }}</p>
<div class="text-[14px]">
<el-table :data="systemService.server_version" size="large" v-loading="loadingArr.server_version_load">
<el-table-column prop="name" :label="t('environment')" align="left" min-width="200" />
@ -24,7 +24,7 @@
</div>
</div>
<div class="bg-[#fff] pb-[20px] mb-3">
<p class="py-[20px]">{{ t('authorityStatus') }}</p>
<p class="py-[20px] text-sm">{{ t('authorityStatus') }}</p>
<div class="text-[14px]">
<el-table :data="systemService.system_variables" size="large" v-loading="loadingArr.system_variables_load">
<el-table-column prop="name" :label="t('name')" align="left" min-width="200" />
@ -44,7 +44,7 @@
</div>
<div class="bg-[#fff] pb-[20px] mb-3">
<p class="py-[20px]">{{ t('process') }}</p>
<p class="py-[20px] text-sm">{{ t('process') }}</p>
<div class="text-[14px]">
<el-table :data="systemService.process" size="large" v-loading="loadingArr.process_load">
<el-table-column prop="name" :label="t('name')" align="left" min-width="200" />