mirror of
https://gitee.com/niucloud-team/niucloud.git
synced 2026-03-14 15:50:56 +00:00
0.0.8
This commit is contained in:
parent
045f63e74d
commit
8916a9662d
1
admin/auto-imports.d.ts
vendored
1
admin/auto-imports.d.ts
vendored
@ -1,6 +1,5 @@
|
||||
// Generated by 'unplugin-auto-import'
|
||||
export {}
|
||||
declare global {
|
||||
const ElMessage: typeof import('element-plus/es')['ElMessage']
|
||||
const ElNotification: typeof import('element-plus/es')['ElNotification']
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"build": "vite build && node publish.cjs",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -55,4 +55,4 @@
|
||||
"vite": "4.1.0",
|
||||
"vue-tsc": "1.0.24"
|
||||
}
|
||||
}
|
||||
}
|
||||
39
admin/publish.cjs
Normal file
39
admin/publish.cjs
Normal file
@ -0,0 +1,39 @@
|
||||
const fs = require('fs')
|
||||
|
||||
const publish = () => {
|
||||
const src = './dist'
|
||||
const dest = '../niucloud/public/admin'
|
||||
|
||||
solve()
|
||||
|
||||
// 目标目录不存在停止复制
|
||||
try {
|
||||
const dir = fs.readdirSync(dest)
|
||||
} catch (e) {
|
||||
return
|
||||
}
|
||||
|
||||
// 删除目标目录下文件
|
||||
fs.rm(dest, { recursive: true }, err => {
|
||||
if(err) {
|
||||
console.log(err)
|
||||
return
|
||||
}
|
||||
|
||||
fs.cp(src, dest, { recursive: true }, (err) => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const solve = () => {
|
||||
const fn = './dist/index.html'
|
||||
const fc = fs.readFileSync(fn, 'utf-8')
|
||||
let text = new String(fc)
|
||||
text = text.replaceAll('./assets/', '/admin/assets/')
|
||||
fs.writeFileSync(fn, text, 'utf8')
|
||||
}
|
||||
|
||||
publish()
|
||||
@ -4,7 +4,7 @@ import request from '@/utils/request'
|
||||
* 获取支付设置
|
||||
* @returns
|
||||
*/
|
||||
export function getUserInfo(type: string) {
|
||||
export function getUserInfo() {
|
||||
return request.get(`auth/get`)
|
||||
}
|
||||
|
||||
|
||||
@ -119,8 +119,8 @@ export function deleteSiteGroup(group_id: number) {
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function getSiteGroupAll(params: Record<string, any>) {
|
||||
return request.get(`site/group/all`, params)
|
||||
export function getSiteGroupAll(params: Record<string, any> = {}) {
|
||||
return request.get(`site/group/all`)
|
||||
}
|
||||
|
||||
/***************************************************** 当前站点用户 *************************************************/
|
||||
|
||||
@ -675,3 +675,20 @@ export function getAddonList() {
|
||||
export function getWapIndexList(params: Record<string, any>) {
|
||||
return request.get('sys/config/wap_index', { params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取开发者key
|
||||
* @returns
|
||||
*/
|
||||
export function getDeveloperToken() {
|
||||
return request.get('sys/config/developer_token')
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置开发者key
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function setDeveloperToken(params: Record<string, any>) {
|
||||
return request.put(`sys/config/developer_token`, params, { showSuccessMessage: true })
|
||||
}
|
||||
|
||||
@ -175,3 +175,10 @@ export function getGeneratorTableColumn(params: any) {
|
||||
export function generatorCheckFile(params: Record<string, any>) {
|
||||
return request.get(`generator/check_file`, {params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据模型获取表字段
|
||||
*/
|
||||
export function getGeneratorModelTableColumn(params: any) {
|
||||
return request.get(`generator/model_table_column`, {params})
|
||||
}
|
||||
|
||||
@ -265,4 +265,7 @@ defineExpose({
|
||||
.table-head-bg {
|
||||
background-color: var(--el-table-header-bg-color);
|
||||
}
|
||||
:deep(.terminal .t-log-box span) {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
<div class="mt-[20px]" v-for="(item, index) in upgradeContent.version_list" :key="index">
|
||||
<div class="font-bold text-lg">{{ item.version_no }}</div>
|
||||
<div class="mt-[5px]">{{ item.release_time }}</div>
|
||||
<div class="mt-[10px] p-[10px] rounded bg-[#f4f4f5]" v-if="item.upgrade_log" v-html="item.upgrade_log"></div>
|
||||
<div class="mt-[10px] p-[10px] rounded bg-[#f4f4f5] whitespace-pre" v-if="item.upgrade_log" v-html="item.upgrade_log"></div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
@ -233,7 +233,7 @@ const open = (addonKey: string = '') => {
|
||||
}
|
||||
getUpgradeContent(addonKey).then(({ data }) => {
|
||||
upgradeContent.value = data
|
||||
if (data.version == data.last_version) {
|
||||
if (!data.version_list.length) {
|
||||
ElMessage({ message: '已经是最新版本了', type: 'error' })
|
||||
return
|
||||
}
|
||||
@ -316,4 +316,7 @@ defineExpose({
|
||||
.table-head-bg {
|
||||
background-color: var(--el-table-header-bg-color);
|
||||
}
|
||||
:deep(.terminal .t-log-box span) {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,25 +1,28 @@
|
||||
{
|
||||
"menuName": "菜单名称",
|
||||
"menuType": "类型",
|
||||
"authId": "权限标识",
|
||||
"authId": "api路径",
|
||||
"menuTypeDir": "目录",
|
||||
"menuTypeMenu": "菜单",
|
||||
"menuTypeButton": "按钮",
|
||||
"menuDeleteTips": "确定要删除该菜单吗?",
|
||||
"menuDeleteTips": "删除菜单会删除当前菜单以及该菜单下所有子菜单,是否确认删除?",
|
||||
"addMenu": "添加菜单",
|
||||
"updateMenu": "编辑菜单",
|
||||
"routePath": "路由路径",
|
||||
"viewPath": "组件路径",
|
||||
"addon":"选择应用",
|
||||
"parentMenu": "父级菜单",
|
||||
"menuIcon": "菜单图标",
|
||||
"sort":"权重",
|
||||
"menuKey":"菜单标识",
|
||||
"menuKey":"权限标识",
|
||||
"menuNamePlaceholder": "请输入菜单名称",
|
||||
"menuKeyPlaceholder": "请输入菜单标识",
|
||||
"menuKeyPlaceholder": "请输入权限标识",
|
||||
"menuKeyValidata":"菜单标识只能使用字母数字下划线并且开头不能为数字",
|
||||
"routePathPlaceholder": "请输入路由路径",
|
||||
"viewPathPlaceholder": "请输入组件路径",
|
||||
"authIdPlaceholder": "请输入权限标识",
|
||||
"authIdPlaceholder": "请输入api路径",
|
||||
"selectIconPlaceholder": "请选择菜单图标",
|
||||
"topLevel": "顶级"
|
||||
}
|
||||
"topLevel": "顶级",
|
||||
"menuShortName":"菜单短标题",
|
||||
"menuShortNamePlaceholder":"请输入菜单短标题"
|
||||
}
|
||||
|
||||
@ -21,5 +21,10 @@
|
||||
"viewPathPlaceholder": "请输入组件路径",
|
||||
"authIdPlaceholder": "请输入权限标识",
|
||||
"selectIconPlaceholder": "请选择菜单图标",
|
||||
"topLevel": "顶级"
|
||||
"topLevel": "顶级",
|
||||
"menuShortName":"菜单短标题",
|
||||
"menuShortNamePlaceholder":"请输入菜单短标题",
|
||||
"addon":"选择应用",
|
||||
"system":"系统菜单",
|
||||
"application":"应用菜单"
|
||||
}
|
||||
5
admin/src/app/lang/zh-cn/setting.developer_token.json
Normal file
5
admin/src/app/lang/zh-cn/setting.developer_token.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"developerTokenEdit":"开发者KEY设置",
|
||||
"tokenPlaceholder":"请输入开发者令牌",
|
||||
"tokenTips": "开发者KEY可以在已安装的框架中设置。框架安装并配置好开发者KEY后,开发者自己开发的应用和插件,会像普通授权插件一样可以安装使用,特别是当开发者发布自己开发的插件或应用时,尚在未发布状态时,开发者也可以对其进行安装测试"
|
||||
}
|
||||
@ -18,7 +18,9 @@
|
||||
"reset": "重置",
|
||||
"search": "搜索",
|
||||
"foldText":"展开/折叠",
|
||||
"mainApp": "套餐主应用",
|
||||
"mainAppPlaceholder": "请选择套餐主应用",
|
||||
"containAddon": "套餐内含插件"
|
||||
"mainApp": "套餐内含应用",
|
||||
"mainAppPlaceholder": "请选择套餐内包含的应用",
|
||||
"containAddon": "套餐内含插件",
|
||||
"appListEmpty": "没有可选择的应用",
|
||||
"addonListEmpty": "没有可选择的插件"
|
||||
}
|
||||
|
||||
@ -131,6 +131,13 @@
|
||||
"setUp":"设置",
|
||||
"dictType":"数据字典",
|
||||
"dictTypePlaceholder":"请选择数据字典",
|
||||
"dictTypePlaceholder1":"部分字段未选择数据字典"
|
||||
"dictTypePlaceholder1":"部分字段未选择数据字典",
|
||||
"remotePullDown": "远程下拉",
|
||||
"remotePullDownValue":"远程下拉value字段",
|
||||
"remotePullDownValuePlaceholder":"请选择远程下拉value字段",
|
||||
"remotePullDownLabel":"远程下拉标题字段",
|
||||
"remotePullDownLabelPlaceholder":"请选择远程下拉label字段",
|
||||
"selectType":"下拉类型"
|
||||
|
||||
|
||||
}
|
||||
@ -98,9 +98,9 @@
|
||||
<el-card class="box-card !border-none " shadow="never" v-if="!loading">
|
||||
<div class="text-[20px] mb-[20px]">历史版本</div>
|
||||
<el-timeline>
|
||||
<el-timeline-item :timestamp="item.release_time + ' 版本:' + item.version_no" v-for="item in frameworkVersionList" type="primary" :hollow="true" placement="top">
|
||||
<div class="mt-[10px] p-[20px] bg-overlay rounded-md timeline-log-wrap" v-if="item.upgrade_log">
|
||||
<div v-html="item.upgrade_log"></div>
|
||||
<el-timeline-item :timestamp="item['release_time'] + ' 版本:' + item['version_no']" v-for="(item,index) in frameworkVersionList" type="primary" :hollow="true" placement="top" :key="index">
|
||||
<div class="mt-[10px] p-[20px] bg-overlay rounded-md timeline-log-wrap whitespace-pre" v-if="item['upgrade_log']">
|
||||
<div v-html="item['upgrade_log']"></div>
|
||||
</div>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
@ -117,16 +117,13 @@ import { t } from '@/lang'
|
||||
import { getVersions } from '@/app/api/auth'
|
||||
import { getAuthinfo, setAuthinfo, getFrameworkVersionList } from '@/app/api/module'
|
||||
import { ElMessageBox, FormInstance, FormRules } from 'element-plus'
|
||||
import { useRoute } from 'vue-router'
|
||||
import Upgrade from '@/app/components/upgrade/index.vue'
|
||||
import CloudBuild from '@/app/components/cloud-build/index.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
const upgradeRef = ref(null)
|
||||
const cloudBuildRef = ref(null)
|
||||
const upgradeRef = ref<any>(null)
|
||||
const cloudBuildRef = ref<any>(null)
|
||||
const getAuthCodeDialog: Record<string, any> | null = ref(null)
|
||||
|
||||
const getAuthCodeDialog = ref(null)
|
||||
const authCodeApproveDialog = ref(false)
|
||||
const isCheck = ref(false)
|
||||
const frameworkVersionList = ref([])
|
||||
@ -138,77 +135,87 @@ const getFrameworkVersionListFn = () => {
|
||||
}
|
||||
getFrameworkVersionListFn()
|
||||
|
||||
const newVersion = computed(() => {
|
||||
const newVersion:any = computed(() => {
|
||||
return frameworkVersionList.value.length ? frameworkVersionList.value[0] : null
|
||||
})
|
||||
|
||||
const hideAuthCode = (res) => {
|
||||
const authCode = JSON.parse(JSON.stringify(res))
|
||||
const data = authCode.slice(0, authCode.length / 2) + authCode.slice(authCode.length / 2, authCode.length - 1).replace(/./g, '*')
|
||||
return data
|
||||
const hideAuthCode = (res:any) => {
|
||||
const authCode = JSON.parse(JSON.stringify(res))
|
||||
const data = authCode.slice(0, authCode.length / 2) + authCode.slice(authCode.length / 2, authCode.length - 1).replace(/./g, '*')
|
||||
return data
|
||||
}
|
||||
|
||||
const authCodeApproveFn = () => {
|
||||
authCodeApproveDialog.value = true
|
||||
authCodeApproveDialog.value = true
|
||||
}
|
||||
|
||||
const authinfo = ref('')
|
||||
interface AuthInfo {
|
||||
company_name: string,
|
||||
site_address: string,
|
||||
auth_code: string
|
||||
}
|
||||
|
||||
const authinfo = ref<AuthInfo>({
|
||||
company_name: '',
|
||||
site_address: '',
|
||||
auth_code: ''
|
||||
})
|
||||
const loading = ref(true)
|
||||
const saveLoading = ref(false)
|
||||
const checkAppMange = () => {
|
||||
getAuthinfo()
|
||||
.then((res) => {
|
||||
loading.value = false
|
||||
if (res.data.data && res.data.data.length != 0) {
|
||||
authinfo.value = res.data.data
|
||||
authCodeApproveDialog.value = false
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false
|
||||
authCodeApproveDialog.value = false
|
||||
})
|
||||
getAuthinfo()
|
||||
.then((res) => {
|
||||
loading.value = false
|
||||
if (res.data.data && res.data.data.length != 0) {
|
||||
authinfo.value = res.data.data
|
||||
authCodeApproveDialog.value = false
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false
|
||||
authCodeApproveDialog.value = false
|
||||
})
|
||||
}
|
||||
checkAppMange()
|
||||
|
||||
const formData = reactive<Record<string, string>>({
|
||||
auth_code: '',
|
||||
auth_secret: ''
|
||||
auth_code: '',
|
||||
auth_secret: ''
|
||||
})
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = reactive<FormRules>({
|
||||
auth_code: [
|
||||
{ required: true, message: t('authCodePlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
auth_secret: [
|
||||
{ required: true, message: t('authSecretPlaceholder'), trigger: 'blur' }
|
||||
]
|
||||
auth_code: [
|
||||
{ required: true, message: t('authCodePlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
auth_secret: [
|
||||
{ required: true, message: t('authSecretPlaceholder'), trigger: 'blur' }
|
||||
]
|
||||
})
|
||||
|
||||
const save = async (formEl: FormInstance | undefined) => {
|
||||
if (saveLoading.value || !formEl) return
|
||||
if (saveLoading.value || !formEl) return
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
saveLoading.value = true
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
saveLoading.value = true
|
||||
|
||||
setAuthinfo(formData)
|
||||
.then(() => {
|
||||
saveLoading.value = false
|
||||
checkAppMange()
|
||||
})
|
||||
.catch(() => {
|
||||
saveLoading.value = false
|
||||
authCodeApproveDialog.value = false
|
||||
})
|
||||
}
|
||||
})
|
||||
setAuthinfo(formData)
|
||||
.then(() => {
|
||||
saveLoading.value = false
|
||||
checkAppMange()
|
||||
})
|
||||
.catch(() => {
|
||||
saveLoading.value = false
|
||||
authCodeApproveDialog.value = false
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const market = () => {
|
||||
window.open('https://www.niucloud.com/app')
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
|
||||
const versions = ref('')
|
||||
|
||||
@ -1,111 +1,83 @@
|
||||
<template>
|
||||
<div class="main-container w-full bg-white" v-loading="loading">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">应用管理</span>
|
||||
<el-form :inline="true" :model="appList.search" ref="searchFormRef">
|
||||
<el-form-item :label="t('appName')" prop="title">
|
||||
<el-input v-model="appList.search.title" :placeholder="t('appNamePlaceholder')" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="getAppList()">{{ t('search') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="flex flex-wrap plug-list pb-10 plug-large" v-if="appList.list.length">
|
||||
<div v-for="(item, index) in appList.list" :key="index + 'b'">
|
||||
<div
|
||||
class="relative app-item cursor-pointer px-4 mr-4 mt-[20px] bg-[#f7f7f7] border-[1px] hover:border-primary">
|
||||
<div @click="toLink(item.key)" class="flex py-5 items-center">
|
||||
<div class="flex justify-center items-center">
|
||||
<el-image class="w-[40px] h-[40px]" :src="img(item.icon)" fit="contain">
|
||||
<template #error>
|
||||
<div class="image-slot">
|
||||
<img class="w-[50px] h-[50px]"
|
||||
src="@/app/assets/images/index/app_default.png" />
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</div>
|
||||
<div class="flex flex-col justify-between text-left w-[190px]">
|
||||
<p class="app-text w-[190px] text-[17px] text-[#222] pl-3">{{ item.title }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="empty flex items-center justify-center" v-if="!loading && !appList.list.length">
|
||||
<el-empty :description="t('emptyAppData')" />
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
<div class="main-container w-full bg-white" v-loading="loading">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">应用管理</span>
|
||||
</div>
|
||||
<div class="flex flex-wrap plug-list pb-10 plug-large" v-if="appList.length">
|
||||
<div v-for="(item, index) in appList" :key="index + 'b'">
|
||||
<div
|
||||
class="relative app-item cursor-pointer px-4 mr-4 mt-[20px] bg-[#f7f7f7] border-[1px] hover:border-primary">
|
||||
<div @click="toLink(item.key)" class="flex py-5 items-center">
|
||||
<div class="flex justify-center items-center">
|
||||
<el-image class="w-[40px] h-[40px]" :src="img(item.icon)" fit="contain">
|
||||
<template #error>
|
||||
<div class="image-slot">
|
||||
<img class="w-[50px] h-[50px]"
|
||||
src="@/app/assets/images/index/app_default.png" />
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</div>
|
||||
<div class="flex flex-col justify-between text-left w-[190px]">
|
||||
<p class="app-text w-[190px] text-[17px] text-[#222] pl-3">{{ item.title }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="empty flex items-center justify-center" v-if="!loading && !appList.length">
|
||||
<el-empty :description="t('emptyAppData')" />
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
import { getSiteAddons } from '@/app/api/site'
|
||||
import { img } from '@/utils/common'
|
||||
import { findFirstValidRoute } from '@/router/routers'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { t } from '@/lang'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const addonIndexRoute = useUserStore().addonIndexRoute
|
||||
const router = useRouter()
|
||||
const appList = reactive({
|
||||
list: [],
|
||||
search: {
|
||||
title: ''
|
||||
}
|
||||
})
|
||||
const appList = ref<Record<string, any>[]>([])
|
||||
|
||||
const loading = ref(true)
|
||||
const getAppList = async () => {
|
||||
const res = await getSiteAddons({ title: appList.search.title })
|
||||
appList.list = res.data
|
||||
loading.value = false
|
||||
const res = await getSiteAddons()
|
||||
appList.value = res.data
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
const appLink = ref({})
|
||||
const getAppLink = () => {
|
||||
userStore.routers.forEach((item, index) => {
|
||||
if (item.meta.addon != '') {
|
||||
if (item.children && item.children.length) {
|
||||
appLink.value[item.meta.addon] = findFirstValidRoute(item.children)
|
||||
} else {
|
||||
appLink.value[item.meta.addon] = item.name
|
||||
}
|
||||
}
|
||||
})
|
||||
getAppList()
|
||||
}
|
||||
getAppLink()
|
||||
getAppList()
|
||||
|
||||
const toLink = (addon: string) => {
|
||||
appLink.value[addon] && router.push({ name: appLink.value[addon] })
|
||||
addonIndexRoute[addon] && router.push({ name: addonIndexRoute[addon] })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.main-container,
|
||||
.empty {
|
||||
min-height: calc(100vh - 84px);
|
||||
min-height: calc(100vh - 84px);
|
||||
}
|
||||
|
||||
.app-text {
|
||||
overflow: hidden;
|
||||
/* 超出部分隐藏 */
|
||||
white-space: nowrap;
|
||||
/* 禁止文本换行 */
|
||||
text-overflow: ellipsis;
|
||||
/* 显示省略号 */
|
||||
overflow: hidden;
|
||||
/* 超出部分隐藏 */
|
||||
white-space: nowrap;
|
||||
/* 禁止文本换行 */
|
||||
text-overflow: ellipsis;
|
||||
/* 显示省略号 */
|
||||
}
|
||||
|
||||
.app-item:hover .with-ite {
|
||||
display: block;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
margin-bottom: 0px !important;
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<div class="flex justify-between items-center h-[32px] mb-4">
|
||||
<span class="text-[26px] text-[#222] font-600">{{ t('localAppText') }}</span>
|
||||
<div class="w-[247px]">
|
||||
<el-input :placeholder="t('search')" v-model="search_name" @keyup.enter="query">
|
||||
<el-input :placeholder="t('search')" v-model="searchName" @keyup.enter="query">
|
||||
<template #suffix>
|
||||
<el-icon class="el-input__icon cursor-pointer" size="14px" @click="query">
|
||||
<search />
|
||||
@ -15,18 +15,18 @@
|
||||
</div>
|
||||
<div class="flex mt-[24px]">
|
||||
<div :class="{ '!bg-[#000] !border-0 !text-[#fff]': activeName === 'installed' }"
|
||||
class="w-[78px] h-[30rpx] text-[14px] text-[#242424] text-center rounded-[15px] leading-[30px] bg-[#F0F0F0] border-solid border-1 border-[#E0E0E0] cursor-pointer mr-[24px]"
|
||||
@click="activeName = 'installed'">
|
||||
class="w-[78px] h-[30rpx] text-[14px] text-[#242424] text-center rounded-[15px] leading-[30px] bg-[#F0F0F0] border-solid border-1 border-[#E0E0E0] cursor-pointer mr-[24px]"
|
||||
@click="activeName = 'installed'">
|
||||
{{ t('installLabel') }}
|
||||
</div>
|
||||
<div :class="{ '!bg-[#000] !border-0 !text-[#fff]': activeName === 'uninstalled' }"
|
||||
class="w-[78px] h-[30rpx] text-[14px] text-[#242424] text-center rounded-[15px] leading-[30px] bg-[#F0F0F0] border-solid border-1 border-[#E0E0E0] cursor-pointer mr-[24px]"
|
||||
@click="activeName = 'uninstalled'">
|
||||
class="w-[78px] h-[30rpx] text-[14px] text-[#242424] text-center rounded-[15px] leading-[30px] bg-[#F0F0F0] border-solid border-1 border-[#E0E0E0] cursor-pointer mr-[24px]"
|
||||
@click="activeName = 'uninstalled'">
|
||||
{{ t('uninstalledLabel') }}
|
||||
</div>
|
||||
<div :class="{ '!bg-[#000] !border-0 !text-[#fff]': activeName === 'all' }"
|
||||
class="w-[78px] h-[30rpx] text-[14px] text-[#242424] text-center rounded-[15px] leading-[30px] bg-[#F0F0F0] border-solid border-1 border-[#E0E0E0] cursor-pointer mr-[24px]"
|
||||
@click="activeName = 'all'">
|
||||
class="w-[78px] h-[30rpx] text-[14px] text-[#242424] text-center rounded-[15px] leading-[30px] bg-[#F0F0F0] border-solid border-1 border-[#E0E0E0] cursor-pointer mr-[24px]"
|
||||
@click="activeName = 'all'">
|
||||
{{ t('buyLabel') }}
|
||||
</div>
|
||||
</div>
|
||||
@ -35,8 +35,8 @@
|
||||
<el-table-column :label="t('appName')" align="left" width="320">
|
||||
<template #default="{ row }">
|
||||
<div class="flex items-center"
|
||||
:class="{ 'cursor-pointer': row.type == 'app' && Object.keys(row.install_info).length }"
|
||||
@click="itemPath(row)">
|
||||
:class="{ 'cursor-pointer': row.type == 'app' && Object.keys(row.install_info).length }"
|
||||
@click="itemPath(row)">
|
||||
<el-image class="w-[54px] h-[54px]" :src="row.icon" fit="contain">
|
||||
<template #error>
|
||||
<img class="w-[54px] h-[54px]" src="@/app/assets/images/icon-addon.png" alt="">
|
||||
@ -73,7 +73,7 @@
|
||||
<el-table-column :label="t('type')" align="left" min-width="100">
|
||||
<template #default="{ row }">
|
||||
<span class="text-[#222] font-500 text-[13px]">{{ row.type === 'app' ? t('app') : t('addon')
|
||||
}}</span>
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="" :label="t('author')" align="left" min-width="100">
|
||||
@ -84,21 +84,21 @@
|
||||
<el-table-column :label="t('operation')" fixed="right" align="right" width="150">
|
||||
<template #default="{ row }">
|
||||
<el-button class="!text-[13px]" type="primary" link @click="getAddonDetialFn(row)">{{
|
||||
t('detail') }}</el-button>
|
||||
t('detail') }}</el-button>
|
||||
<el-button class="!text-[13px]" v-if="row.install_info && Object.keys(row.install_info)?.length"
|
||||
type="primary" link @click="uninstallAddonFn(row.key)">{{ t('unload') }}</el-button>
|
||||
type="primary" link @click="uninstallAddonFn(row.key)">{{ t('unload') }}</el-button>
|
||||
|
||||
<el-button class="!text-[13px]" v-else-if="row.is_download && row.install_info <= 0"
|
||||
type="primary" link @click="installAddonFn(row.key)">{{ t('install')
|
||||
type="primary" link @click="installAddonFn(row.key)">{{ t('install')
|
||||
}}</el-button>
|
||||
<el-button class="!text-[13px]" v-else :loading="downloading == row.key"
|
||||
:disabled="downloading != ''" type="primary" link @click.stop="downEvent(row)">{{
|
||||
:disabled="downloading != ''" type="primary" link @click.stop="downEvent(row)">{{
|
||||
t('down') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty class="mx-auto overview-empty"
|
||||
v-if="!localList.installed.length && !loading && activeName == 'installed'">
|
||||
v-if="!localList.installed.length && !loading && activeName == 'installed'">
|
||||
<template #image>
|
||||
<div class="w-[230px] mx-auto">
|
||||
<img src="@/app/assets/images/index/apply_empty.png" class="max-w-full" alt="">
|
||||
@ -109,7 +109,7 @@
|
||||
</template>
|
||||
</el-empty>
|
||||
<el-empty class="mx-auto overview-empty"
|
||||
v-if="!localList.uninstalled.length && !loading && activeName == 'uninstalled'">
|
||||
v-if="!localList.uninstalled.length && !loading && activeName == 'uninstalled'">
|
||||
<template #image>
|
||||
<div class="w-[230px] mx-auto">
|
||||
<img src="@/app/assets/images/index/apply_empty.png" class="max-w-full" alt="">
|
||||
@ -124,20 +124,20 @@
|
||||
</template>
|
||||
</el-empty>
|
||||
<div v-if="!localList.all.length && !loading && !authinfo && activeName == 'all'"
|
||||
class="mx-auto overview-empty flex flex-col items-center pt-14 pb-6">
|
||||
class="mx-auto overview-empty flex flex-col items-center pt-14 pb-6">
|
||||
<div class="mb-[20px] text-sm text-[#888]">检测到当前账号尚未绑定授权,请先绑定授权!</div>
|
||||
<div class="flex flex-1 flex-wrap justify-center relative">
|
||||
<el-button class="w-[154px] !h-[48px] mt-[8px]" type="primary"
|
||||
@click="authCodeApproveFn">授权码认证</el-button>
|
||||
@click="authCodeApproveFn">授权码认证</el-button>
|
||||
<el-popover ref="getAuthCodeDialog" placement="bottom" :width="478" trigger="click"
|
||||
class="mt-[8px]">
|
||||
class="mt-[8px]">
|
||||
<div class="px-[18px] py-[8px]">
|
||||
<p class="leading-[32px] text-[14px]">
|
||||
您在官方应用市场购买任意一款应用,即可获得授权码。输入正确授权码认证通过后,即可支持在线升级和其它相关服务</p>
|
||||
<div class="flex justify-end mt-[36px]">
|
||||
<el-button class="w-[182px] !h-[48px]" plain @click="market">去应用市场逛逛</el-button>
|
||||
<el-button class="w-[100px] !h-[48px]" plain
|
||||
@click="getAuthCodeDialog.hide()">关闭</el-button>
|
||||
@click="getAuthCodeDialog.hide()">关闭</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<template #reference>
|
||||
@ -154,13 +154,13 @@
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<el-form-item prop="auth_code">
|
||||
<el-input v-model="formData.auth_code" :placeholder="t('authCodePlaceholder')"
|
||||
class="input-width" clearable size="large" />
|
||||
class="input-width" clearable size="large" />
|
||||
</el-form-item>
|
||||
|
||||
<div class="mt-[20px]">
|
||||
<el-form-item prop="auth_secret">
|
||||
<el-input v-model="formData.auth_secret" clearable :placeholder="t('authSecretPlaceholder')"
|
||||
class="input-width" size="large" />
|
||||
class="input-width" size="large" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
@ -168,7 +168,7 @@
|
||||
|
||||
<div class="mt-[20px]">
|
||||
<el-button type="primary" class="w-full" size="large" :loading="saveLoading"
|
||||
@click="save(formRef)">{{ t('confirm') }}</el-button>
|
||||
@click="save(formRef)">{{ t('confirm') }}</el-button>
|
||||
</div>
|
||||
<div class="mt-[10px] text-right">
|
||||
<el-button type="primary" link @click="market">{{ t('notHaveAuth') }}</el-button>
|
||||
@ -201,7 +201,7 @@
|
||||
|
||||
<!-- 安装弹窗 -->
|
||||
<el-dialog v-model="installShowDialog" :title="t('addonInstall')" width="850px" :close-on-click-modal="false"
|
||||
:close-on-press-escape="false" :before-close="installShowDialogClose">
|
||||
:close-on-press-escape="false" :before-close="installShowDialogClose">
|
||||
<el-steps :space="200" :active="installStep" finish-status="success" align-center>
|
||||
<el-step :title="t('envCheck')" class="flex-1" />
|
||||
<el-step :title="t('installProgress')" class="flex-1" />
|
||||
@ -225,7 +225,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]"
|
||||
v-for="item in installCheckResult.dir.is_readable">
|
||||
v-for="(item, index) in installCheckResult.dir.is_readable" :key="index">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
@ -242,7 +242,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]"
|
||||
v-for="item in installCheckResult.dir.is_write">
|
||||
v-for="(item, index) in installCheckResult.dir.is_write" :key="index">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
@ -265,13 +265,13 @@
|
||||
<div class="flex justify-end">
|
||||
<el-tooltip effect="dark" :content="t('installTips')" placement="top">
|
||||
<el-button type="default" :disabled="!installCheckResult.is_pass || cloudInstalling"
|
||||
:loading="localInstalling" @click="handleInstall">{{
|
||||
:loading="localInstalling" @click="handleInstall">{{
|
||||
t('localInstall')
|
||||
}}</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" :content="t('cloudInstallTips')" placement="top">
|
||||
<el-button type="primary" :disabled="!installCheckResult.is_pass || localInstalling"
|
||||
:loading="cloudInstalling" @click="handleCloudInstall">{{
|
||||
:loading="cloudInstalling" @click="handleCloudInstall">{{
|
||||
t('cloudInstall')
|
||||
}}</el-button>
|
||||
</el-tooltip>
|
||||
@ -279,19 +279,19 @@
|
||||
</div>
|
||||
<div v-show="installStep == 2" class="h-[50vh] mt-[20px]">
|
||||
<terminal name="my-terminal" :context="currAddon" :init-log="null" :show-header="false"
|
||||
:show-log-time="true" />
|
||||
:show-log-time="true" />
|
||||
</div>
|
||||
<div v-show="installStep == 3" class="h-[50vh] mt-[20px] flex flex-col">
|
||||
<el-result icon="success" :title="t('addonInstallSuccess')"></el-result>
|
||||
<!-- 提示信息 -->
|
||||
<div v-for="item in installAfterTips" class="mb-[10px]">
|
||||
<div v-for="(item, index) in installAfterTips" class="mb-[10px]" :key="index">
|
||||
<el-alert :title="item" type="error" :closable="false" />
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="uninstallShowDialog" :title="t('addonUninstall')" width="850px"
|
||||
:close-on-click-modal="false" :close-on-press-escape="false">
|
||||
:close-on-click-modal="false" :close-on-press-escape="false">
|
||||
<el-scrollbar max-height="50vh">
|
||||
<div class="min-h-[150px]">
|
||||
<div class="bg-[#fff] my-3" v-if="uninstallCheckResult.dir">
|
||||
@ -309,7 +309,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]"
|
||||
v-for="item in uninstallCheckResult.dir.is_readable">
|
||||
v-for="(item, index) in uninstallCheckResult.dir.is_readable" :key="index">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
@ -325,7 +325,8 @@
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]" v-for="item in uninstallCheckResult.dir.is_write">
|
||||
<el-row class="pb-[10px] items pl-[15px]"
|
||||
v-for="(item, index) in uninstallCheckResult.dir.is_write" :key="index">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
@ -355,20 +356,22 @@ import { ref, reactive, watch, h } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getAddonLocal, uninstallAddon, installAddon, preInstallCheck, cloudInstallAddon, getAddonInstalltask, getAddonCloudInstallLog, preUninstallCheck, cancelInstall } from '@/app/api/addon'
|
||||
import { downloadVersion, getAuthinfo, setAuthinfo } from '@/app/api/module'
|
||||
import { ElMessageBox, ElNotification, FormInstance, FormRules } from 'element-plus'
|
||||
import { img } from '@/utils/common'
|
||||
import { ElMessageBox, ElNotification, FormInstance, FormRules, NotificationHandle } from 'element-plus'
|
||||
// import { img } from '@/utils/common'
|
||||
import { Terminal, api as terminalApi } from 'vue-web-terminal'
|
||||
import { findFirstValidRoute } from '@/router/routers'
|
||||
import storage from '@/utils/storage'
|
||||
import { useRouter } from 'vue-router'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
import { AnyObject } from '@/types/global'
|
||||
|
||||
const router = useRouter()
|
||||
const activeName = ref('installed')
|
||||
|
||||
const loading = ref<Boolean>(true)
|
||||
const downloading = ref('')
|
||||
const installAfterTips = ref<string[]>([])
|
||||
const userStore = useUserStore()
|
||||
const userStore: any = useUserStore()
|
||||
|
||||
const downEvent = (param: Record<string, any>) => {
|
||||
if (downloading.value) return
|
||||
@ -395,25 +398,29 @@ getAuthinfo().then(res => {
|
||||
* 本地下载的插件列表
|
||||
*/
|
||||
// input 筛选
|
||||
const search_name = ref('')
|
||||
const searchName = ref('')
|
||||
// 表格展示数据
|
||||
const info = ref({
|
||||
const info:AnyObject = ref<{
|
||||
installed: never[];
|
||||
uninstalled: never[];
|
||||
all: never[];
|
||||
}>({
|
||||
installed: [],
|
||||
uninstalled: [],
|
||||
all: []
|
||||
})
|
||||
const query = () => {
|
||||
if (search_name.value == '' || search_name.value == null) {
|
||||
if (searchName.value == '' || searchName.value == null) {
|
||||
info.value.installed = localList.value.installed
|
||||
info.value.uninstalled = localList.value.uninstalled
|
||||
info.value.all = localList.value.all
|
||||
return false
|
||||
}
|
||||
info.value.installed = localList.value.installed.filter((el: any) => el.title.indexOf(search_name.value) != -1)
|
||||
info.value.uninstalled = localList.value.uninstalled.filter((el: any) => el.title.indexOf(search_name.value) != -1)
|
||||
info.value.all = localList.value.all.filter((el: any) => el.title.indexOf(search_name.value) != -1)
|
||||
info.value.installed = localList.value.installed.filter((el: any) => el.title.indexOf(searchName.value) != -1)
|
||||
info.value.uninstalled = localList.value.uninstalled.filter((el: any) => el.title.indexOf(searchName.value) != -1)
|
||||
info.value.all = localList.value.all.filter((el: any) => el.title.indexOf(searchName.value) != -1)
|
||||
}
|
||||
const localList = ref({
|
||||
const localList:AnyObject = ref({
|
||||
installed: [],
|
||||
uninstalled: [],
|
||||
all: [],
|
||||
@ -423,7 +430,7 @@ const localList = ref({
|
||||
const localListFn = () => {
|
||||
loading.value = true
|
||||
getAddonLocal({}).then(res => {
|
||||
const data = res.data.list
|
||||
const data:any = res.data.list
|
||||
localList.value.error = res.data.error
|
||||
localList.value.installed = []
|
||||
localList.value.uninstalled = []
|
||||
@ -438,7 +445,7 @@ const localListFn = () => {
|
||||
}
|
||||
}
|
||||
query()
|
||||
userStore.routers.forEach((item, index) => {
|
||||
userStore.routers.forEach((item:AnyObject, index:number) => {
|
||||
if (item.children && item.children.length) {
|
||||
item.name = findFirstValidRoute(item.children)
|
||||
appLink.value[item.meta.app] = findFirstValidRoute(item.children)
|
||||
@ -478,7 +485,7 @@ const installShowDialog = ref(false)
|
||||
const installStep = ref(1)
|
||||
|
||||
// 安装检测结果
|
||||
const installCheckResult = ref({})
|
||||
const installCheckResult = ref<AnyObject>({})
|
||||
|
||||
/**
|
||||
* 安装
|
||||
@ -499,7 +506,7 @@ const installAddonFn = (key: string) => {
|
||||
/**
|
||||
* 获取正在进行的安装任务
|
||||
*/
|
||||
let notificationEl = null
|
||||
let notificationEl: NotificationHandle | null | any = null
|
||||
const getInstallTask = (first: boolean = true) => {
|
||||
getAddonInstalltask().then(res => {
|
||||
if (res.data) {
|
||||
@ -614,7 +621,7 @@ const getCloudInstallLog = () => {
|
||||
.then(res => {
|
||||
const data = res.data.data ?? []
|
||||
if (data[0] && data[0].length && installShowDialog.value == true) {
|
||||
data[0].forEach(item => {
|
||||
data[0].forEach((item: { action: string; code: number; msg: any }) => {
|
||||
if (!installLog.includes(item.action)) {
|
||||
terminalApi.pushMessage('my-terminal', { content: `正在执行:${item.action}` })
|
||||
installLog.push(item.action)
|
||||
@ -639,7 +646,7 @@ watch(currAddon, (nval) => {
|
||||
const uninstallShowDialog = ref(false)
|
||||
|
||||
// 卸载环境检测结果
|
||||
const uninstallCheckResult = ref({})
|
||||
const uninstallCheckResult = ref<AnyObject>({})
|
||||
|
||||
/**
|
||||
* 卸载
|
||||
@ -698,7 +705,7 @@ const getAddonDetialFn = (data: AnyObject) => {
|
||||
// 授权
|
||||
const authCodeApproveDialog = ref(false)
|
||||
const authinfo = ref('')
|
||||
const getAuthCodeDialog = ref(null)
|
||||
const getAuthCodeDialog: Record<string, any> | null = ref(null)
|
||||
const saveLoading = ref(false)
|
||||
const checkAppMange = () => {
|
||||
getAuthinfo()
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<el-dialog v-model="showDialog" :title="popTitle" width="500px" :destroy-on-close="true">
|
||||
<el-form :model="formData" label-width="90px" class="page-form" ref="formRef" :rules="formRules" v-loading="loading">
|
||||
<el-form :model="formData" label-width="90px" class="page-form" ref="formRef" :rules="formRules"
|
||||
v-loading="loading">
|
||||
<el-form-item :label="t('menuName')" prop="menu_name">
|
||||
<el-input v-model="formData.menu_name" :placeholder="t('menuNamePlaceholder')" class="input-width" />
|
||||
</el-form-item>
|
||||
@ -16,13 +17,21 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('parentMenu')" prop="parent_key">
|
||||
<el-select v-model="formData.parent_key" placeholder="Select" class="input-width">
|
||||
<el-option :label="t('topLevel')" value="" />
|
||||
<select-menu-item :menu="item" v-for="(item, index) in prop.menuTree" :key="index" />
|
||||
<el-form-item :label="t('addon')" prop="addon" v-show="formData.app_type == 'site'">
|
||||
<el-select v-model="formData.addon" placeholder="Select" class="input-width" @change="addonChange">
|
||||
<el-option v-for="(item, index) in addonLst" :label="item.title" :value="item.key" :key="index" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('parentMenu')" prop="parent_key">
|
||||
<el-tree-select class="input-width" v-if="formData.addon != ''" v-model="formData.parent_key"
|
||||
:props="{ label: 'menu_name', value: 'menu_key' }" :data="addonMenuList" check-strictly
|
||||
:render-after-expand="false" />
|
||||
<el-tree-select class="input-width" v-else v-model="formData.parent_key"
|
||||
:props="{ label: 'menu_name', value: 'menu_key' }" :data="sysMenuList" check-strictly
|
||||
:render-after-expand="false" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('routePath')" prop="router_path" v-show="formData.menu_type != 2">
|
||||
<el-input v-model="formData.router_path" :placeholder="t('routePathPlaceholder')" class="input-width" />
|
||||
</el-form-item>
|
||||
@ -34,7 +43,7 @@
|
||||
<el-form-item :label="t('authId')" prop="api_url" v-show="formData.menu_type != 0">
|
||||
<el-input v-model="formData.api_url" :placeholder="t('authIdPlaceholder')" class="input-width">
|
||||
<template #append>
|
||||
<el-select class="w-[90px] border-none" v-model="method">
|
||||
<el-select class="w-[90px] border-none" v-model="formData.methods">
|
||||
<el-option label="POST" value="post" />
|
||||
<el-option label="GET" value="get" />
|
||||
<el-option label="PUT" value="put" />
|
||||
@ -64,6 +73,11 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('menuShortName')">
|
||||
<el-input v-model="formData.menu_short_name" :placeholder="t('menuShortNamePlaceholder')"
|
||||
class="input-width" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('sort')">
|
||||
<el-input-number v-model="formData.sort" :min="0" />
|
||||
</el-form-item>
|
||||
@ -72,7 +86,7 @@
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{t('confirm')}}</el-button>
|
||||
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -82,13 +96,12 @@
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import selectMenuItem from './select-menu-item.vue'
|
||||
import { addMenu, editMenu, getMenuInfo } from '@/app/api/sys'
|
||||
import { addMenu, editMenu, getMenuInfo, getSystemMenu, getAddonMenu } from '@/app/api/sys'
|
||||
import { getAddonDevelop } from '@/app/api/tools'
|
||||
|
||||
const showDialog = ref(false)
|
||||
const method = ref('post')
|
||||
const loading = ref(false)
|
||||
let popTitle: string = '';
|
||||
let popTitle: string = ''
|
||||
|
||||
/**
|
||||
* 表单数据
|
||||
@ -102,22 +115,20 @@ const initialFormData = {
|
||||
api_url: '',
|
||||
router_path: '',
|
||||
view_path: '',
|
||||
methods: '',
|
||||
methods: 'post',
|
||||
sort: '',
|
||||
status: 1,
|
||||
is_show: 1,
|
||||
menu_key: '',
|
||||
app_type: ''
|
||||
app_type: '',
|
||||
addon: '',
|
||||
menu_short_name: ''
|
||||
}
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
|
||||
const prop = defineProps({
|
||||
menuTree: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
const addonLst = ref<Array<any>>([])
|
||||
const sysMenuList = ref<Array<any>>([])
|
||||
const addonMenuList = ref<Array<any>>([])
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
const validataMenuKey = (val: string) => {
|
||||
@ -143,7 +154,7 @@ const formRules = computed(() => {
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
//return /^([a-zA-Z_$])([a-zA-Z0-9_$])*$/.test(val)
|
||||
// return /^([a-zA-Z_$])([a-zA-Z0-9_$])*$/.test(val)
|
||||
router_path: [
|
||||
{ required: formData.menu_type != 2, message: t('routePathPlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
@ -154,11 +165,40 @@ const formRules = computed(() => {
|
||||
{ required: formData.menu_type != 2, message: t('selectIconPlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
api_url: [
|
||||
{ required: formData.menu_type == 2, message: t('selectIconPlaceholder'), trigger: 'blur' }
|
||||
{ required: formData.menu_type == 2, message: t('authIdPlaceholder'), trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
// 获取插件列表
|
||||
const getAddonDevelopFn = async () => {
|
||||
const { data } = await getAddonDevelop({})
|
||||
addonLst.value = [{ title: '系统', key: '' }]
|
||||
addonLst.value.push(...data)
|
||||
}
|
||||
|
||||
// 获取系统菜单列表
|
||||
const getSystemMenuFn = async () => {
|
||||
const { data } = await getSystemMenu()
|
||||
sysMenuList.value = [{ menu_name: '顶级', menu_key: '' }]
|
||||
sysMenuList.value.push(...data)
|
||||
}
|
||||
|
||||
// 获取系统应用列表
|
||||
const getAddonMenuFn = async (key: any) => {
|
||||
const { data } = await getAddonMenu(key)
|
||||
addonMenuList.value = data
|
||||
}
|
||||
|
||||
// 选择应用
|
||||
const addonChange = async (val: any) => {
|
||||
formData.parent_key = ''
|
||||
if (val != '') {
|
||||
await getAddonMenuFn(val)
|
||||
formData.parent_key = addonMenuList.value[0].menu_key
|
||||
}
|
||||
}
|
||||
|
||||
const emit = defineEmits(['complete'])
|
||||
|
||||
/**
|
||||
@ -174,7 +214,7 @@ const confirm = async (formEl: FormInstance | undefined) => {
|
||||
loading.value = true
|
||||
|
||||
const data = formData
|
||||
data.api_url = data.api_url ? `${data.api_url}/${method.value}` : ''
|
||||
data.api_url = data.api_url ? `${data.api_url}/${formData.methods}` : ''
|
||||
|
||||
save(data).then(res => {
|
||||
loading.value = false
|
||||
@ -182,7 +222,6 @@ const confirm = async (formEl: FormInstance | undefined) => {
|
||||
emit('complete')
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
// showDialog.value = false
|
||||
})
|
||||
}
|
||||
})
|
||||
@ -192,17 +231,21 @@ const setFormData = async (row: any = null) => {
|
||||
loading.value = true
|
||||
Object.assign(formData, initialFormData)
|
||||
popTitle = t('addMenu')
|
||||
getAddonDevelopFn()
|
||||
getSystemMenuFn()
|
||||
if (row.menu_key) {
|
||||
popTitle = t('updateMenu')
|
||||
const data = await (await getMenuInfo(row.menu_key)).data
|
||||
const data = await (await getMenuInfo(row.app_type, row.menu_key)).data
|
||||
Object.keys(formData).forEach((key: string) => {
|
||||
if (data[key] != undefined) formData[key] = data[key]
|
||||
})
|
||||
if (formData.addon != '') getAddonMenuFn(formData.addon)
|
||||
} else {
|
||||
Object.keys(formData).forEach((key: string) => {
|
||||
if (row[key] != undefined) formData[key] = row[key]
|
||||
})
|
||||
}
|
||||
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ const showDialog = ref(false)
|
||||
const loading = ref(false)
|
||||
const isOpen = ref(true)
|
||||
|
||||
let popTitle: string = '';
|
||||
let popTitle: string = ''
|
||||
|
||||
// 获取权限数据
|
||||
const menus = ref<Record<string, any>[]>([])
|
||||
@ -55,7 +55,6 @@ getSiteMenus().then((res) => {
|
||||
menus.value = res.data
|
||||
})
|
||||
|
||||
|
||||
// 全选
|
||||
const selectAll = ref(false)
|
||||
const checkStrictly = ref(false)
|
||||
@ -73,28 +72,27 @@ const handleCheckChange = debounce((e) => {
|
||||
})
|
||||
|
||||
const menuAction = () => {
|
||||
if(isOpen.value){
|
||||
collapseAll(menus.value);
|
||||
isOpen.value = false;
|
||||
}else{
|
||||
unFoldAll(menus.value);
|
||||
isOpen.value = true;
|
||||
if (isOpen.value) {
|
||||
collapseAll(menus.value)
|
||||
isOpen.value = false
|
||||
} else {
|
||||
unFoldAll(menus.value)
|
||||
isOpen.value = true
|
||||
}
|
||||
}
|
||||
|
||||
// 全部展开
|
||||
const unFoldAll = (data:any) => {
|
||||
|
||||
Object.keys(data).forEach((key:string|any) => {
|
||||
treeRef.value.store.nodesMap[data[key]['menu_key']].expanded = true;
|
||||
if(data[key].children && data[key].children.length > 0) collapseAll(data[key].children);
|
||||
treeRef.value.store.nodesMap[data[key].menu_key].expanded = true
|
||||
if (data[key].children && data[key].children.length > 0) collapseAll(data[key].children)
|
||||
})
|
||||
}
|
||||
// 全部折叠
|
||||
const collapseAll = (data:any) => {
|
||||
Object.keys(data).forEach((key:string|any) => {
|
||||
treeRef.value.store.nodesMap[data[key]['menu_key']].expanded = false;
|
||||
if(data[key].children && data[key].children.length > 0) collapseAll(data[key].children);
|
||||
treeRef.value.store.nodesMap[data[key].menu_key].expanded = false
|
||||
if (data[key].children && data[key].children.length > 0) collapseAll(data[key].children)
|
||||
})
|
||||
}
|
||||
/**
|
||||
@ -143,7 +141,7 @@ const confirm = async (formEl: FormInstance | undefined) => {
|
||||
loading.value = true
|
||||
|
||||
const data = Object.assign({}, formData)
|
||||
data.rules = data.rules.concat(treeRef.value.getHalfCheckedKeys());
|
||||
data.rules = data.rules.concat(treeRef.value.getHalfCheckedKeys())
|
||||
|
||||
save(data).then(res => {
|
||||
loading.value = false
|
||||
@ -167,42 +165,37 @@ const setFormData = async (row: any = null) => {
|
||||
popTitle = t('updateRole')
|
||||
const data = await (await getRoleInfo(row.role_id)).data
|
||||
Object.keys(formData).forEach((key: string) => {
|
||||
|
||||
if (data[key] != undefined) {
|
||||
if(key == 'rules'){
|
||||
var arr = data.rules;
|
||||
var newArr:any = [];
|
||||
if (key == 'rules') {
|
||||
const arr = data.rules
|
||||
const newArr:any = []
|
||||
|
||||
Object.keys(data.rules).forEach( (i) => {
|
||||
checked(data.rules[i],menus.value,newArr)
|
||||
} )
|
||||
formData[key] = newArr;
|
||||
|
||||
}else{
|
||||
Object.keys(data.rules).forEach((i) => {
|
||||
checked(data.rules[i], menus.value, newArr)
|
||||
})
|
||||
formData[key] = newArr
|
||||
} else {
|
||||
formData[key] = data[key]
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
|
||||
function checked(menu_key:string,data:any,newArr:any) {
|
||||
Object.keys(data).forEach( (key:string) =>{
|
||||
let item = data[key]
|
||||
if(item.menu_key == menu_key){
|
||||
if(!item.children || item.children.length == 0){
|
||||
function checked (menuKey:string, data:any, newArr:any) {
|
||||
Object.keys(data).forEach((key:string) => {
|
||||
const item = data[key]
|
||||
if (item.menu_key == menuKey) {
|
||||
if (!item.children || item.children.length == 0) {
|
||||
newArr.push(item.menu_key)
|
||||
}
|
||||
}else{
|
||||
if(item.children && item.children.length > 0){
|
||||
checked(menu_key,item.children,newArr)
|
||||
} else {
|
||||
if (item.children && item.children.length > 0) {
|
||||
checked(menuKey, item.children, newArr)
|
||||
}
|
||||
}
|
||||
} )
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
|
||||
@ -69,15 +69,16 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed, toRaw, watch } from 'vue'
|
||||
import { ref, reactive, computed, toRaw } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { getUserInfo, getAllUserList } from '@/app/api/user'
|
||||
import { addUser, editUser } from '@/app/api/site'
|
||||
import { allRole } from '@/app/api/sys'
|
||||
import { img, deepClone } from '@/utils/common'
|
||||
import { AnyObject } from '@/types/global'
|
||||
|
||||
const userList = ref([])
|
||||
const userList = ref<AnyObject>([])
|
||||
const uid = ref<number | string>('')
|
||||
|
||||
const selectUser = (value: any) => {
|
||||
@ -165,7 +166,7 @@ const emit = defineEmits(['complete'])
|
||||
const roles = ref<Record<string, any>>([])
|
||||
allRole().then(res => {
|
||||
roles.value = res.data
|
||||
roles.value.forEach(element => {
|
||||
roles.value.forEach((element:any) => {
|
||||
element.role_id = element.role_id.toString()
|
||||
})
|
||||
})
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<span v-html="`${menuLevel}${prop.menu.menu_name}`"></span>
|
||||
</el-option>
|
||||
<template v-if="prop.menu.children">
|
||||
<select-menu-item :menu="item" v-for="item in prop.menu.children" :level="prop.level + 1" />
|
||||
<select-menu-item :menu="item" v-for="(item,index) in prop.menu.children" :level="prop.level + 1" :key="index" />
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
@ -12,7 +12,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
|
||||
const prop = defineProps({
|
||||
const prop:any = defineProps({
|
||||
menu: Object,
|
||||
level: {
|
||||
type: Number,
|
||||
@ -31,4 +31,4 @@ const menuLevel = computed(() => {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -21,26 +21,40 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
// import type { FormInstance } from 'element-plus'
|
||||
import { getLogInfo } from '@/app/api/site'
|
||||
|
||||
const showDialog = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
const logData = ref([])
|
||||
interface LogData {
|
||||
username: string
|
||||
ip: string,
|
||||
url: string,
|
||||
type: string,
|
||||
params:any
|
||||
}
|
||||
|
||||
const logData = ref<LogData>({
|
||||
username: '',
|
||||
ip: '',
|
||||
url: '',
|
||||
type: '',
|
||||
params: ''
|
||||
})
|
||||
const getLogDetail = async () => {
|
||||
logData.value = await (await getLogInfo(id)).data
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
let id = 0;
|
||||
let id = 0
|
||||
const setFormData = async (row: any = null) => {
|
||||
loading.value = true
|
||||
if (row) {
|
||||
id = row.id;
|
||||
getLogDetail();
|
||||
id = row.id
|
||||
getLogDetail()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -56,30 +56,27 @@ import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getLogList } from '@/app/api/site'
|
||||
import UserLogDetail from '@/app/views/auth/components/user-log-detail.vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { FormInstance } from 'element-plus'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title;
|
||||
|
||||
let sysUserLogTableData = reactive({
|
||||
const sysUserLogTableData = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam:{
|
||||
ip:"",
|
||||
username:"",
|
||||
searchParam: {
|
||||
ip: '',
|
||||
username: '',
|
||||
url: ''
|
||||
}
|
||||
})
|
||||
|
||||
const searchFormRef = ref<FormInstance>()
|
||||
const resetForm = (formEl: FormInstance | undefined)=>{
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
|
||||
formEl.resetFields();
|
||||
loadSysUserLogList();
|
||||
formEl.resetFields()
|
||||
loadSysUserLogList()
|
||||
}
|
||||
/**
|
||||
* 获取管理员操作记录表列表
|
||||
@ -91,7 +88,7 @@ const loadSysUserLogList = (page: number = 1) => {
|
||||
getLogList({
|
||||
page: sysUserLogTableData.page,
|
||||
limit: sysUserLogTableData.limit,
|
||||
...sysUserLogTableData.searchParam
|
||||
...sysUserLogTableData.searchParam
|
||||
}).then(res => {
|
||||
sysUserLogTableData.loading = false
|
||||
sysUserLogTableData.data = res.data.data
|
||||
@ -106,7 +103,7 @@ const userLogDetailDialog: Record<string, any> | null = ref(null)
|
||||
* 查看详情
|
||||
* @param data
|
||||
*/
|
||||
const detailEvent = (data: any) => {
|
||||
const detailEvent = (data: any) => {
|
||||
userLogDetailDialog.value.setFormData(data)
|
||||
userLogDetailDialog.value.showDialog = true
|
||||
}
|
||||
|
||||
@ -1,6 +1,13 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center mb-[20px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<el-button type="primary" class="w-[100px]" @click="addEvent">
|
||||
{{ t('addMenu') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-table :data="menusTableData.data" row-key="menu_key" size="large" v-loading="menusTableData.loading">
|
||||
<template #empty>
|
||||
<span>{{ !menusTableData.loading ? t('emptyData') : '' }}</span>
|
||||
@ -22,19 +29,19 @@
|
||||
<el-table-column :label="t('status')" min-width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag class="ml-2" type="success" v-if="row.status == 1">{{ t('statusNormal') }}</el-tag>
|
||||
<el-tag class="ml-2" type="error" v-if="row.status == 0">{{t('statusDeactivate') }}</el-tag>
|
||||
<el-tag class="ml-2" type="error" v-if="row.status == 0">{{ t('statusDeactivate') }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sort" :label="t('sort')" min-width="100" />
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right" width="130">
|
||||
<template #default="{ row }">
|
||||
<!-- <el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteEvent(row.menu_key)">{{ t('delete') }}</el-button> -->
|
||||
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteEvent(row.menu_key)">{{ t('delete') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<edit-menu ref="editMenuDialog" :menu-tree="menusTableData.data" @complete="getMenuList" />
|
||||
<edit-menu ref="editMenuDialog" :menu-tree="menusTableData.data" @complete="getMenuList" app-type="admin" />
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
@ -45,11 +52,10 @@ import { getMenus, deleteMenu } from '@/app/api/sys'
|
||||
import { t } from '@/lang'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import EditMenu from '@/app/views/auth/components/edit-menu.vue'
|
||||
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const menusTableData = reactive({
|
||||
loading: true,
|
||||
data: []
|
||||
@ -91,7 +97,7 @@ const editEvent = (data: any) => {
|
||||
/**
|
||||
* 删除菜单
|
||||
*/
|
||||
const deleteEvent = (menu_key: string) => {
|
||||
const deleteEvent = (key: string) => {
|
||||
ElMessageBox.confirm(t('menuDeleteTips'), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
@ -99,7 +105,7 @@ const deleteEvent = (menu_key: string) => {
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
deleteMenu(menu_key).then(res => {
|
||||
deleteMenu('admin', key).then(() => {
|
||||
getMenuList()
|
||||
}).catch(() => {
|
||||
})
|
||||
|
||||
@ -52,27 +52,23 @@ import { getRoleList, deleteRole } from '@/app/api/sys'
|
||||
import { ElMessageBox, FormInstance } from 'element-plus'
|
||||
import EditRole from '@/app/views/auth/components/edit-role.vue'
|
||||
|
||||
import { useRoute } from 'vue-router'
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title;
|
||||
|
||||
const roleTableData = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam:{
|
||||
seach:''
|
||||
searchParam: {
|
||||
seach: ''
|
||||
}
|
||||
})
|
||||
|
||||
const searchFormRef = ref<FormInstance>()
|
||||
const resetForm = (formEl: FormInstance | undefined)=>{
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
|
||||
formEl.resetFields();
|
||||
loadRoleList();
|
||||
formEl.resetFields()
|
||||
loadRoleList()
|
||||
}
|
||||
/**
|
||||
* 获取角色列表
|
||||
|
||||
@ -1,39 +1,91 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center mb-[20px]">
|
||||
<span class="text-[20px]"></span>
|
||||
<el-button type="primary" class="w-[100px]" @click="addEvent">
|
||||
{{ t('addMenu') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-table :data="menusTableData.data" row-key="menu_key" size="large" v-loading="menusTableData.loading">
|
||||
<template #empty>
|
||||
<span>{{ !menusTableData.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
<el-table-column prop="menu_name" :show-overflow-tooltip="true" :label="t('menuName')" min-width="150" />
|
||||
<el-table-column :label="t('icon')" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<icon v-if="row.icon" :name="row.icon" size="18px" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('menuType')" width="80">
|
||||
<template #default="{ row }">
|
||||
<div v-if="row.menu_type == 0">{{ t('menuTypeDir') }}</div>
|
||||
<div v-else-if="row.menu_type == 1">{{ t('menuTypeMenu') }}</div>
|
||||
<div v-else-if="row.menu_type == 2">{{ t('menuTypeButton') }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="api_url" :label="t('authId')" min-width="150" align="center" />
|
||||
<el-table-column :label="t('status')" min-width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag class="ml-2" type="success" v-if="row.status == 1">{{ t('statusNormal') }}</el-tag>
|
||||
<el-tag class="ml-2" type="error" v-if="row.status == 0">{{t('statusDeactivate') }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sort" :label="t('sort')" min-width="100" />
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right" width="130">
|
||||
<template #default="{ row }">
|
||||
<!-- <el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteEvent(row.menu_key)">{{ t('delete') }}</el-button> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-tabs v-model="active">
|
||||
<el-tab-pane :label="t('system')" name="system">
|
||||
<el-table :data="menusTableData.system" row-key="menu_key" size="large"
|
||||
v-loading="menusTableData.loading">
|
||||
<template #empty>
|
||||
<span>{{ !menusTableData.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
<el-table-column prop="menu_name" :show-overflow-tooltip="true" :label="t('menuName')"
|
||||
min-width="150" />
|
||||
<el-table-column :label="t('icon')" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<icon v-if="row.icon" :name="row.icon" size="18px" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('menuType')" width="80">
|
||||
<template #default="{ row }">
|
||||
<div v-if="row.menu_type == 0">{{ t('menuTypeDir') }}</div>
|
||||
<div v-else-if="row.menu_type == 1">{{ t('menuTypeMenu') }}</div>
|
||||
<div v-else-if="row.menu_type == 2">{{ t('menuTypeButton') }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="api_url" :label="t('authId')" min-width="150" align="center" />
|
||||
<el-table-column :label="t('status')" min-width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag class="ml-2" type="success" v-if="row.status == 1">{{ t('statusNormal') }}</el-tag>
|
||||
<el-tag class="ml-2" type="error" v-if="row.status == 0">{{ t('statusDeactivate')
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sort" :label="t('sort')" min-width="100" />
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right" width="130">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteEvent(row.menu_key)">{{ t('delete')
|
||||
}}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="t('application')" name="application">
|
||||
<el-table :data="menusTableData.application" row-key="menu_key" size="large"
|
||||
v-loading="menusTableData.loading">
|
||||
<template #empty>
|
||||
<span>{{ !menusTableData.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
<el-table-column prop="menu_name" :show-overflow-tooltip="true" :label="t('menuName')"
|
||||
min-width="150" />
|
||||
<el-table-column :label="t('icon')" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<icon v-if="row.icon" :name="row.icon" size="18px" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('menuType')" width="80">
|
||||
<template #default="{ row }">
|
||||
<div v-if="row.menu_type == 0">{{ t('menuTypeDir') }}</div>
|
||||
<div v-else-if="row.menu_type == 1">{{ t('menuTypeMenu') }}</div>
|
||||
<div v-else-if="row.menu_type == 2">{{ t('menuTypeButton') }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="api_url" :label="t('authId')" min-width="150" align="center" />
|
||||
<el-table-column :label="t('status')" min-width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag class="ml-2" type="success" v-if="row.status == 1">{{ t('statusNormal') }}</el-tag>
|
||||
<el-tag class="ml-2" type="error" v-if="row.status == 0">{{ t('statusDeactivate')
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sort" :label="t('sort')" min-width="100" />
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right" width="130">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteEvent(row.menu_key)">{{ t('delete')
|
||||
}}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<edit-menu ref="editMenuDialog" :menu-tree="menusTableData.data" @complete="getMenuList" />
|
||||
</el-card>
|
||||
@ -49,11 +101,12 @@ import EditMenu from '@/app/views/auth/components/edit-menu.vue'
|
||||
|
||||
import { useRoute } from 'vue-router'
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
const active = ref('system')
|
||||
|
||||
const menusTableData = reactive({
|
||||
const menusTableData = reactive<Record<string, any>>({
|
||||
loading: true,
|
||||
data: []
|
||||
system: [],
|
||||
application: []
|
||||
})
|
||||
|
||||
/**
|
||||
@ -61,9 +114,15 @@ const menusTableData = reactive({
|
||||
*/
|
||||
const getMenuList = () => {
|
||||
menusTableData.loading = true
|
||||
getMenus('site').then(res => {
|
||||
getMenus('site').then(({ data }) => {
|
||||
menusTableData.loading = false
|
||||
menusTableData.data = res.data
|
||||
const system: Record<string, any>[] = []
|
||||
const application: Record<string, any> = []
|
||||
data.forEach((item: any) => {
|
||||
item.addon == '' ? system.push(item) : application.push(item)
|
||||
})
|
||||
menusTableData.system = system
|
||||
menusTableData.application = application
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
@ -92,7 +151,7 @@ const editEvent = (data: any) => {
|
||||
/**
|
||||
* 删除菜单
|
||||
*/
|
||||
const deleteEvent = (menu_key: string) => {
|
||||
const deleteEvent = (key: string) => {
|
||||
ElMessageBox.confirm(t('menuDeleteTips'), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
@ -100,7 +159,7 @@ const deleteEvent = (menu_key: string) => {
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
deleteMenu(menu_key).then(res => {
|
||||
deleteMenu('site', key).then(res => {
|
||||
getMenuList()
|
||||
}).catch(() => {
|
||||
})
|
||||
|
||||
@ -97,7 +97,8 @@ const userTableData = reactive({
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam: {
|
||||
seach: ''
|
||||
seach: '',
|
||||
user_type: ''
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@ -77,7 +77,6 @@
|
||||
<p class="text-[#999] text-[12px]">{{ t('aliappSet') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="w-full p-5 bg-white">
|
||||
@ -219,10 +218,10 @@
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div class="flex justify-center">
|
||||
<el-image class="w-[180px] h-[180px]" :src="qr_code ? img(qr_code) : ''">
|
||||
<el-image class="w-[180px] h-[180px]" :src="qrCode ? img(qrCode) : ''">
|
||||
<template #error>
|
||||
<div class="w-[100%] h-[100%] flex items-center justify-center bg-[#f5f7fa]">
|
||||
<span>{{ qr_code ? t('fileErr') : t('emptyQrCode') }}</span>
|
||||
<span>{{ qrCode ? t('fileErr') : t('emptyQrCode') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
@ -236,26 +235,26 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { t } from '@/lang'
|
||||
import { img } from '@/utils/common'
|
||||
import { getAliappConfig } from '@/app/api/aliapp'
|
||||
|
||||
const router = useRouter()
|
||||
let activeName = ref("/channel/aliapp");
|
||||
let active = ref(2);
|
||||
let qr_code = ref('')
|
||||
const activeName = ref('/channel/aliapp')
|
||||
const active = ref(2)
|
||||
const qrCode = ref<string>('')
|
||||
onMounted(async () => {
|
||||
let res = await getAliappConfig()
|
||||
qr_code.value = res.data.qr_code
|
||||
const res = await getAliappConfig()
|
||||
qrCode.value = res.data.qr_code
|
||||
})
|
||||
const linkEvent = (url: string) => {
|
||||
window.open(url, "_blank")
|
||||
window.open(url, '_blank')
|
||||
}
|
||||
const handleClick = (val: any) => {
|
||||
router.push({ path: activeName.value });
|
||||
};
|
||||
router.push({ path: activeName.value })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@ -310,4 +309,5 @@ const handleClick = (val: any) => {
|
||||
:deep(.el-step__title) {
|
||||
height: 40px;
|
||||
line-height: 40px !important;
|
||||
}</style>
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -100,10 +100,10 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getWechatConfig } from '@/app/api/wechat'
|
||||
import { img } from '@/utils/common'
|
||||
// import { img } from '@/utils/common'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
@ -111,26 +111,26 @@ const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
const loading = ref(true)
|
||||
const formData = reactive<Record<string, string>>({
|
||||
wechat_name: '',
|
||||
wechat_original: '',
|
||||
app_id: '',
|
||||
app_secret: '',
|
||||
qr_code: '',
|
||||
token: '',
|
||||
encoding_aes_key: '',
|
||||
encryption_type: 'not_encrypt'
|
||||
wechat_name: '',
|
||||
wechat_original: '',
|
||||
app_id: '',
|
||||
app_secret: '',
|
||||
qr_code: '',
|
||||
token: '',
|
||||
encoding_aes_key: '',
|
||||
encryption_type: 'not_encrypt'
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取微信配置
|
||||
*/
|
||||
getWechatConfig().then(res => {
|
||||
Object.assign(formData, res.data)
|
||||
loading.value = false
|
||||
Object.assign(formData, res.data)
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
const linkEvent = () => {
|
||||
window.open("https://open.alipay.com/develop/manage", "_blank")
|
||||
window.open('https://open.alipay.com/develop/manage', '_blank')
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@ -42,7 +42,7 @@ const pageName = route.meta.title
|
||||
|
||||
const loading = ref(true)
|
||||
|
||||
const formData = reactive<Record<string, string | boolean>>({
|
||||
const formData = reactive<Record<string, string | boolean | any>>({
|
||||
is_open: false,
|
||||
request_url: ''
|
||||
})
|
||||
@ -54,13 +54,13 @@ const formRef = ref<FormInstance>()
|
||||
*/
|
||||
getH5Config().then(res => {
|
||||
Object.assign(formData, res.data)
|
||||
formData.is_open = Boolean(Number(formData.is_open));
|
||||
formData.is_open = Boolean(Number(formData.is_open))
|
||||
loading.value = false
|
||||
})
|
||||
/**
|
||||
* 获取h5域名
|
||||
*/
|
||||
getUrl().then(res => {
|
||||
getUrl().then(res => {
|
||||
formData.request_url = res.data.wap_url + '/'
|
||||
})
|
||||
|
||||
@ -89,8 +89,8 @@ watch(copied, () => {
|
||||
})
|
||||
|
||||
// 点击访问
|
||||
const visitFn = ()=>{
|
||||
window.open(formData.request_url);
|
||||
const visitFn = () => {
|
||||
window.open(formData.request_url)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,8 +102,8 @@ const save = async (formEl: FormInstance | undefined) => {
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
loading.value = true
|
||||
let data = {...formData};
|
||||
data.is_open = Number(data.is_open);
|
||||
const data = { ...formData }
|
||||
data.is_open = Number(data.is_open)
|
||||
setH5Config(data).then(() => {
|
||||
loading.value = false
|
||||
}).catch(() => {
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
</div>
|
||||
<el-form :model="formData" label-width="150px" ref="formRef" class="page-form">
|
||||
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<el-form-item :label="t('preview')" prop="weapp_name">
|
||||
<img class="w-[500px]" src="@/app/assets/images/channel/preview.png" alt="">
|
||||
@ -30,26 +29,25 @@ import { t } from '@/lang'
|
||||
import { getUrl } from '@/app/api/sys'
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
import { ElMessage, FormInstance } from 'element-plus'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
const loading = ref(true)
|
||||
|
||||
const formData = reactive<Record<string, string | boolean>>({
|
||||
const formData = reactive<Record<string, string | boolean | any>>({
|
||||
is_open: false,
|
||||
request_url: ''
|
||||
})
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
const router = useRouter()
|
||||
|
||||
/**
|
||||
* 获取pc域名
|
||||
*/
|
||||
getUrl().then(res => {
|
||||
formData.request_url = res.data.web_url + '/';
|
||||
loading.value = false;
|
||||
getUrl().then(res => {
|
||||
formData.request_url = res.data.web_url + '/'
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
/**
|
||||
@ -77,8 +75,8 @@ watch(copied, () => {
|
||||
})
|
||||
|
||||
// 点击访问
|
||||
const visitFn = ()=>{
|
||||
window.open(formData.request_url);
|
||||
const visitFn = () => {
|
||||
window.open(formData.request_url)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -137,10 +137,10 @@
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div class="flex justify-center">
|
||||
<el-image class="w-[180px] h-[180px]" :src="qr_code ? img(qr_code) : ''">
|
||||
<el-image class="w-[180px] h-[180px]" :src="qrCode ? img(qrCode) : ''">
|
||||
<template #error>
|
||||
<div class="w-[100%] h-[100%] flex items-center justify-center bg-[#f5f7fa]">
|
||||
<span>{{ qr_code ? t('fileErr') : t('emptyQrCode') }}</span>
|
||||
<span>{{ qrCode ? t('fileErr') : t('emptyQrCode') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
@ -155,26 +155,26 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { t } from "@/lang";
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { t } from '@/lang'
|
||||
import { img } from '@/utils/common'
|
||||
import { getWeappConfig } from '@/app/api/weapp'
|
||||
|
||||
const router = useRouter();
|
||||
let activeName = ref("/channel/weapp");
|
||||
let active = ref(2);
|
||||
let qr_code = ref('')
|
||||
const router = useRouter()
|
||||
const activeName = ref('/channel/weapp')
|
||||
const active = ref(2)
|
||||
const qrCode = ref('')
|
||||
onMounted(async () => {
|
||||
let res = await getWeappConfig()
|
||||
qr_code.value = res.data.qr_code
|
||||
const res = await getWeappConfig()
|
||||
qrCode.value = res.data.qr_code
|
||||
})
|
||||
const linkEvent = (url: string) => {
|
||||
window.open(url, "_blank");
|
||||
};
|
||||
window.open(url, '_blank')
|
||||
}
|
||||
const handleClick = (val: any) => {
|
||||
router.push({ path: activeName.value });
|
||||
};
|
||||
router.push({ path: activeName.value })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -45,7 +45,7 @@
|
||||
</div>
|
||||
</el-card>
|
||||
<el-dialog v-model="dialogVisible" :title="t('codeDownTwoDesc')" width="30%" :before-close="handleClose">
|
||||
<el-form ref="ruleFormRef" :model="form" :rules="rules" label-width="120px">
|
||||
<el-form ref="ruleFormRef" :model="form" label-width="120px">
|
||||
<el-form-item prop="code" :label="t('code')">
|
||||
<el-input v-model="form.code" :placeholder="t('codePlaceholder')"
|
||||
onkeyup="this.value = this.value.replace(/[^\d\.]/g,'');" />
|
||||
@ -76,13 +76,20 @@ import { t } from '@/lang'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { getAuthinfo } from '@/app/api/module'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { AnyObject } from '@/types/global'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
const activeNames = ref('1')
|
||||
// const activeNames = ref('1')
|
||||
const dialogVisible = ref(false)
|
||||
const weappTableData = reactive({
|
||||
const weappTableData:{
|
||||
page: number,
|
||||
limit: number,
|
||||
total: number,
|
||||
loading: boolean,
|
||||
data: AnyObject
|
||||
} = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
@ -90,7 +97,10 @@ const weappTableData = reactive({
|
||||
data: []
|
||||
})
|
||||
const form = ref({
|
||||
desc: ''
|
||||
desc: '',
|
||||
code: '',
|
||||
path: '',
|
||||
content: ''
|
||||
})
|
||||
|
||||
const authCode = ref('')
|
||||
@ -102,7 +112,13 @@ getAuthinfo().then(res => {
|
||||
}).catch(() => {
|
||||
})
|
||||
|
||||
const weappConfig = ref({})
|
||||
const weappConfig = ref<{
|
||||
app_id:string,
|
||||
app_secret:string
|
||||
}>({
|
||||
app_id: '',
|
||||
app_secret: ''
|
||||
})
|
||||
getWeappConfig().then(res => {
|
||||
weappConfig.value = res.data
|
||||
})
|
||||
@ -111,7 +127,7 @@ const activeName = ref('/channel/weapp/code')
|
||||
const handleClick = (val: any) => {
|
||||
router.push({ path: activeName.value })
|
||||
}
|
||||
const ruleFormRef = ref(null)
|
||||
const ruleFormRef = ref<any>(null)
|
||||
|
||||
/**
|
||||
* 获取版本列表
|
||||
|
||||
@ -68,7 +68,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { t } from '@/lang'
|
||||
import { img } from '@/utils/common'
|
||||
// import { img } from '@/utils/common'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
@ -76,7 +76,7 @@ const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const linkEvent = () => {
|
||||
window.open("https://mp.weixin.qq.com/", "_blank")
|
||||
window.open('https://mp.weixin.qq.com/', '_blank')
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@ -68,14 +68,15 @@ import { getTemplateList, getBatchAcquisition } from '@/app/api/weapp'
|
||||
import { editNoticeStatus } from '@/app/api/notice'
|
||||
import { ElLoading } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { AnyObject } from '@/types/global'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
let activeName = ref("/channel/weapp/message");
|
||||
const activeName = ref('/channel/weapp/message')
|
||||
const handleClick = (val: any) => {
|
||||
router.push({ path: activeName.value });
|
||||
};
|
||||
router.push({ path: activeName.value })
|
||||
}
|
||||
const cronTableData = reactive({
|
||||
loading: true,
|
||||
data: []
|
||||
@ -117,7 +118,7 @@ interface Switch {
|
||||
type: string;
|
||||
status: number
|
||||
}
|
||||
const infoSwitch = (res) => {
|
||||
const infoSwitch = (res:any) => {
|
||||
const data = ref<Switch>({
|
||||
key: '',
|
||||
type: '',
|
||||
|
||||
@ -56,13 +56,13 @@ const prop = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const formRef = ref(null)
|
||||
const formRef = ref()
|
||||
|
||||
const buttonData = computed({
|
||||
get() {
|
||||
get () {
|
||||
return prop.data
|
||||
},
|
||||
set(value) {
|
||||
set (value) {
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
@ -60,10 +60,9 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getWechatConfig } from '@/app/api/wechat'
|
||||
import { img } from '@/utils/common'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
@ -71,26 +70,26 @@ const pageName = route.meta.title
|
||||
const router = useRouter()
|
||||
const loading = ref(true)
|
||||
const formData = reactive<Record<string, string>>({
|
||||
wechat_name: '',
|
||||
wechat_original: '',
|
||||
app_id: '',
|
||||
app_secret: '',
|
||||
qr_code: '',
|
||||
token: '',
|
||||
encoding_aes_key: '',
|
||||
encryption_type: 'not_encrypt'
|
||||
wechat_name: '',
|
||||
wechat_original: '',
|
||||
app_id: '',
|
||||
app_secret: '',
|
||||
qr_code: '',
|
||||
token: '',
|
||||
encoding_aes_key: '',
|
||||
encryption_type: 'not_encrypt'
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取微信配置
|
||||
*/
|
||||
getWechatConfig().then(res => {
|
||||
Object.assign(formData, res.data)
|
||||
loading.value = false
|
||||
Object.assign(formData, res.data)
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
const linkEvent = () => {
|
||||
window.open('https://mp.weixin.qq.com/', '_blank')
|
||||
window.open('https://mp.weixin.qq.com/', '_blank')
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@ -99,16 +99,16 @@ const button = ref<Record<string, any>[]>([])
|
||||
const buttonIndex = ref<number>(0)
|
||||
const subButtonIndex = ref<number>(-1)
|
||||
const formRef = ref<Record<string, any>[] | null>(null)
|
||||
let activeName = ref("/channel/wechat/menu");
|
||||
const activeName = ref('/channel/wechat/menu')
|
||||
const handleClick = (val: any) => {
|
||||
router.push({ path: activeName.value });
|
||||
};
|
||||
router.push({ path: activeName.value })
|
||||
}
|
||||
/**
|
||||
* 获取公众号菜单配置
|
||||
*/
|
||||
getWechatMenu().then((res) => {
|
||||
button.value = res.data
|
||||
loading.value = false;
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
/**
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
<template></template>
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -84,15 +84,15 @@ import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title;
|
||||
const pageName = route.meta.title
|
||||
const cronTableData = reactive({
|
||||
loading: true,
|
||||
data: []
|
||||
})
|
||||
let activeName = ref("/channel/wechat/message");
|
||||
const activeName = ref('/channel/wechat/message')
|
||||
const handleClick = (val: any) => {
|
||||
router.push({ path: activeName.value });
|
||||
};
|
||||
router.push({ path: activeName.value })
|
||||
}
|
||||
/**
|
||||
* 获取消息模板列表
|
||||
*/
|
||||
|
||||
@ -64,13 +64,13 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { setDictData, getDictInfo } from '@/app/api/dict'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
let showDialog = ref(false)
|
||||
const showDialog = ref(false)
|
||||
const loading = ref(false)
|
||||
const dialogVisible = ref(false)
|
||||
|
||||
@ -86,7 +86,7 @@ const initialFormData = {
|
||||
name: '',
|
||||
value: '',
|
||||
sort: 0,
|
||||
memo:'',
|
||||
memo: ''
|
||||
}
|
||||
const formData = ref({ ...initialFormData })
|
||||
// 表单验证规则
|
||||
@ -99,7 +99,7 @@ const formRules = computed(() => {
|
||||
value: [
|
||||
{ required: true, message: t('dataValuePlaceholder'), trigger: 'blur' }
|
||||
|
||||
],
|
||||
]
|
||||
}
|
||||
})
|
||||
const addEvent = () => {
|
||||
@ -112,7 +112,7 @@ const editEvent = (row: any, index: number) => {
|
||||
type.value = 'edit'
|
||||
tabelIndex.value = index
|
||||
formData.value = cloneDeep(initialFormData)
|
||||
formData.value = Object.assign(formData.value,cloneDeep( row))
|
||||
formData.value = Object.assign(formData.value, cloneDeep(row))
|
||||
dialogVisible.value = true
|
||||
}
|
||||
/**
|
||||
@ -126,9 +126,8 @@ const submit = async (formEl: FormInstance | undefined) => {
|
||||
tableDate.value.push(cloneDeep(formData.value))
|
||||
} else {
|
||||
tableDate.value.splice(tabelIndex.value, 1, cloneDeep(formData.value))
|
||||
|
||||
}
|
||||
tableDate.value.sort(function(a,b){return b.sort-a.sort})
|
||||
tableDate.value.sort(function (a, b) { return b.sort - a.sort })
|
||||
dialogVisible.value = false
|
||||
}
|
||||
})
|
||||
@ -162,12 +161,10 @@ const setFormData = async (row: any = null) => {
|
||||
id.value = row.id
|
||||
name.value = row.name
|
||||
const data = await (await getDictInfo(row.id)).data
|
||||
tableDate.value = data.dictionary
|
||||
tableDate.value = data.dictionary
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
|
||||
|
||||
defineExpose({
|
||||
showDialog,
|
||||
setFormData
|
||||
|
||||
@ -31,7 +31,7 @@ import { t } from '@/lang'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { addDict, editDict, getDictInfo } from '@/app/api/dict'
|
||||
|
||||
let showDialog = ref(false)
|
||||
const showDialog = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
/**
|
||||
@ -41,7 +41,7 @@ const initialFormData = {
|
||||
id: '',
|
||||
name: '',
|
||||
key: '',
|
||||
memo: '',
|
||||
memo: ''
|
||||
|
||||
}
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
@ -52,13 +52,13 @@ const formRef = ref<FormInstance>()
|
||||
const formRules = computed(() => {
|
||||
return {
|
||||
name: [
|
||||
{required: true, message: t('namePlaceholder'), trigger: 'blur'}
|
||||
{ required: true, message: t('namePlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
key: [
|
||||
{required: true, message: t('keyPlaceholder'), trigger: 'blur'}
|
||||
{ required: true, message: t('keyPlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
data: [
|
||||
{required: true, message: t('dataPlaceholder'), trigger: 'blur'}
|
||||
{ required: true, message: t('dataPlaceholder'), trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
})
|
||||
@ -71,19 +71,19 @@ const emit = defineEmits(['complete'])
|
||||
*/
|
||||
const confirm = async (formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
let save = formData.id ? editDict : addDict
|
||||
const save = formData.id ? editDict : addDict
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
loading.value = true
|
||||
|
||||
let data = formData
|
||||
const data = formData
|
||||
|
||||
save(data).then(res => {
|
||||
loading.value = false
|
||||
showDialog.value = false
|
||||
emit('complete')
|
||||
}).catch(err => {
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
@ -93,11 +93,13 @@ const confirm = async (formEl: FormInstance | undefined) => {
|
||||
const setFormData = async (row: any = null) => {
|
||||
Object.assign(formData, initialFormData)
|
||||
loading.value = true
|
||||
if(row){
|
||||
if (row) {
|
||||
const data = await (await getDictInfo(row.id)).data
|
||||
if (data) Object.keys(formData).forEach((key: string) => {
|
||||
if (data[key] != undefined) formData[key] = data[key]
|
||||
})
|
||||
if (data) {
|
||||
Object.keys(formData).forEach((key: string) => {
|
||||
if (data[key] != undefined) formData[key] = data[key]
|
||||
})
|
||||
}
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
@ -57,27 +57,27 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getDictList, deleteDict } from '@/app/api/dict'
|
||||
import { img } from '@/utils/common'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import Edit from '@/app/views/dict/components/edit.vue'
|
||||
import dict from '@/app/views/dict/components/dict.vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title;
|
||||
const pageName = route.meta.title
|
||||
|
||||
let dictTable = reactive({
|
||||
const dictTable = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam:{
|
||||
"name":"",
|
||||
"key":""
|
||||
searchParam: {
|
||||
name: '',
|
||||
key: ''
|
||||
}
|
||||
})
|
||||
|
||||
@ -93,7 +93,7 @@ const loadDictList = (page: number = 1) => {
|
||||
getDictList({
|
||||
page: dictTable.page,
|
||||
limit: dictTable.limit,
|
||||
...dictTable.searchParam
|
||||
...dictTable.searchParam
|
||||
}).then(res => {
|
||||
dictTable.loading = false
|
||||
dictTable.data = res.data.data
|
||||
@ -137,7 +137,7 @@ const deleteEvent = (id: number) => {
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning',
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
deleteDict(id).then(() => {
|
||||
@ -147,14 +147,12 @@ const deleteEvent = (id: number) => {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields()
|
||||
loadDictList()
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -60,105 +60,103 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {t} from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import {ref, reactive,onMounted, nextTick} from 'vue'
|
||||
import {img} from '@/utils/common'
|
||||
import { getWapIndexList } from '@/app/api/sys'
|
||||
import Sortable from 'sortablejs'
|
||||
import {range} from 'lodash-es'
|
||||
import { t } from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import { ref, reactive, onMounted, nextTick } from 'vue'
|
||||
import { img } from '@/utils/common'
|
||||
import { getWapIndexList } from '@/app/api/sys'
|
||||
import Sortable from 'sortablejs'
|
||||
import { range } from 'lodash-es'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = []; // 忽略公共属性
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = [] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
var res = {code: true, message: ''};
|
||||
// if (diyStore.value[index].list.length === 0) {
|
||||
// res.code = false;
|
||||
// res.message = t('selectAddonTips');
|
||||
// }
|
||||
return res;
|
||||
};
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
// if (diyStore.value[index].list.length === 0) {
|
||||
// res.code = false;
|
||||
// res.message = t('selectAddonTips');
|
||||
// }
|
||||
return res
|
||||
}
|
||||
|
||||
const showDialog = ref(false)
|
||||
const showDialog = ref(false)
|
||||
|
||||
const addonBoxRef = ref()
|
||||
const addonBoxRef = ref()
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
const sortable = Sortable.create(addonBoxRef.value, {
|
||||
group: 'item-wrap',
|
||||
animation: 200,
|
||||
onEnd: event => {
|
||||
const temp = diyStore.editComponent.list[event.oldIndex!];
|
||||
diyStore.editComponent.list.splice(event.oldIndex!, 1);
|
||||
diyStore.editComponent.list.splice(event.newIndex!, 0, temp);
|
||||
sortable.sort(
|
||||
range(diyStore.editComponent.list.length).map(value => {
|
||||
return value.toString();
|
||||
})
|
||||
);
|
||||
}
|
||||
})
|
||||
});
|
||||
})
|
||||
|
||||
const addonTableData = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam: {
|
||||
title: '',
|
||||
key: '',
|
||||
}
|
||||
})
|
||||
|
||||
// 获取插件列表
|
||||
const loadAddonList = (page: number = 1) => {
|
||||
addonTableData.loading = true
|
||||
addonTableData.page = page
|
||||
|
||||
getWapIndexList({
|
||||
...addonTableData.searchParam
|
||||
}).then(res => {
|
||||
addonTableData.loading = false
|
||||
addonTableData.data = res.data
|
||||
addonTableData.total = res.data.length
|
||||
}).catch(() => {
|
||||
addonTableData.loading = false
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
const sortable = Sortable.create(addonBoxRef.value, {
|
||||
group: 'item-wrap',
|
||||
animation: 200,
|
||||
onEnd: event => {
|
||||
const temp = diyStore.editComponent.list[event.oldIndex!]
|
||||
diyStore.editComponent.list.splice(event.oldIndex!, 1)
|
||||
diyStore.editComponent.list.splice(event.newIndex!, 0, temp)
|
||||
sortable.sort(
|
||||
range(diyStore.editComponent.list.length).map(value => {
|
||||
return value.toString()
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const addonTableData = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam: {
|
||||
title: '',
|
||||
key: '',
|
||||
}
|
||||
})
|
||||
|
||||
// 获取插件列表
|
||||
const loadAddonList = (page: number = 1) => {
|
||||
addonTableData.loading = true
|
||||
addonTableData.page = page
|
||||
|
||||
getWapIndexList({
|
||||
...addonTableData.searchParam
|
||||
}).then(res => {
|
||||
addonTableData.loading = false
|
||||
addonTableData.data = res.data
|
||||
addonTableData.total = res.data.length
|
||||
}).catch(() => {
|
||||
addonTableData.loading = false
|
||||
})
|
||||
}
|
||||
|
||||
loadAddonList()
|
||||
|
||||
const handleCurrentChange = (val:any) => {
|
||||
const item:any = {
|
||||
id: diyStore.generateRandom(),
|
||||
key: '',
|
||||
title: '',
|
||||
url: '',
|
||||
icon: '',
|
||||
desc: ''
|
||||
}
|
||||
for (let k in val) {
|
||||
item[k] = val[k]
|
||||
}
|
||||
|
||||
loadAddonList()
|
||||
diyStore.editComponent.list.push(item)
|
||||
showDialog.value = false
|
||||
}
|
||||
|
||||
const handleCurrentChange = (val) => {
|
||||
let item:any = {
|
||||
id: diyStore.generateRandom(),
|
||||
key: '',
|
||||
title: '',
|
||||
url: '',
|
||||
icon: '',
|
||||
desc: ''
|
||||
};
|
||||
for (let k in val) {
|
||||
item[k] = val[k];
|
||||
}
|
||||
const addAddon = () => {
|
||||
showDialog.value = true
|
||||
}
|
||||
|
||||
diyStore.editComponent.list.push(item)
|
||||
showDialog.value = false
|
||||
}
|
||||
|
||||
const addAddon = () => {
|
||||
showDialog.value = true;
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
defineExpose({})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -135,96 +135,96 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {ref, watch, onMounted, nextTick} from 'vue'
|
||||
import {t} from '@/lang'
|
||||
import Sortable from 'sortablejs'
|
||||
import {img} from '@/utils/common'
|
||||
import {range} from 'lodash-es'
|
||||
import { ref, watch, onMounted, nextTick } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import Sortable from 'sortablejs'
|
||||
import { img } from '@/utils/common'
|
||||
import { range } from 'lodash-es'
|
||||
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = []; // 忽略公共属性
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = [] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
var res = {code: true, message: ''};
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
|
||||
diyStore.value[index].list.forEach((item: any) => {
|
||||
if ((diyStore.value[index].mode === 'graphic' || diyStore.value[index].mode === 'img') && item.imageUrl === '') {
|
||||
res.code = false;
|
||||
res.message = t('imageUrlTip');
|
||||
return res;
|
||||
}
|
||||
if ((diyStore.value[index].mode === 'graphic' || diyStore.value[index].mode === 'text') && item.title === '') {
|
||||
res.code = false;
|
||||
res.message = t('graphicNavTitlePlaceholder');
|
||||
return res;
|
||||
}
|
||||
});
|
||||
return res;
|
||||
};
|
||||
|
||||
diyStore.editComponent.list.forEach((item: any) => {
|
||||
if (!item.id) item.id = diyStore.generateRandom();
|
||||
diyStore.value[index].list.forEach((item: any) => {
|
||||
if ((diyStore.value[index].mode === 'graphic' || diyStore.value[index].mode === 'img') && item.imageUrl === '') {
|
||||
res.code = false
|
||||
res.message = t('imageUrlTip')
|
||||
return res
|
||||
}
|
||||
if ((diyStore.value[index].mode === 'graphic' || diyStore.value[index].mode === 'text') && item.title === '') {
|
||||
res.code = false
|
||||
res.message = t('graphicNavTitlePlaceholder')
|
||||
return res
|
||||
}
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
watch(
|
||||
() => diyStore.editComponent.list,
|
||||
(newValue, oldValue) => {
|
||||
// 设置图片宽高
|
||||
diyStore.editComponent.list.forEach((item: any) => {
|
||||
let image = new Image();
|
||||
image.src = img(item.imageUrl);
|
||||
image.onload = async () => {
|
||||
item.imgWidth = image.width;
|
||||
item.imgHeight = image.height;
|
||||
};
|
||||
});
|
||||
},
|
||||
{deep: true}
|
||||
)
|
||||
diyStore.editComponent.list.forEach((item: any) => {
|
||||
if (!item.id) item.id = diyStore.generateRandom()
|
||||
})
|
||||
|
||||
const addGraphicNav = () => {
|
||||
diyStore.editComponent.list.push({
|
||||
id: diyStore.generateRandom(),
|
||||
title: '',
|
||||
imageUrl: '',
|
||||
imgWidth: 0,
|
||||
imgHeight: 0,
|
||||
link: {name: ''},
|
||||
label: {
|
||||
control: false,
|
||||
text: '热门',
|
||||
textColor: '#FFFFFF',
|
||||
bgColorStart: '#F83287',
|
||||
bgColorEnd: '#FE3423'
|
||||
watch(
|
||||
() => diyStore.editComponent.list,
|
||||
(newValue, oldValue) => {
|
||||
// 设置图片宽高
|
||||
diyStore.editComponent.list.forEach((item: any) => {
|
||||
const image = new Image()
|
||||
image.src = img(item.imageUrl)
|
||||
image.onload = async () => {
|
||||
item.imgWidth = image.width
|
||||
item.imgHeight = image.height
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
const imageBoxRef = ref()
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
const sortable = Sortable.create(imageBoxRef.value, {
|
||||
group: 'item-wrap',
|
||||
animation: 200,
|
||||
onEnd: event => {
|
||||
const temp = diyStore.editComponent.list[event.oldIndex!];
|
||||
diyStore.editComponent.list.splice(event.oldIndex!, 1);
|
||||
diyStore.editComponent.list.splice(event.newIndex!, 0, temp);
|
||||
sortable.sort(
|
||||
range(diyStore.editComponent.list.length).map(value => {
|
||||
return value.toString();
|
||||
})
|
||||
);
|
||||
}
|
||||
})
|
||||
});
|
||||
const addGraphicNav = () => {
|
||||
diyStore.editComponent.list.push({
|
||||
id: diyStore.generateRandom(),
|
||||
title: '',
|
||||
imageUrl: '',
|
||||
imgWidth: 0,
|
||||
imgHeight: 0,
|
||||
link: { name: '' },
|
||||
label: {
|
||||
control: false,
|
||||
text: '热门',
|
||||
textColor: '#FFFFFF',
|
||||
bgColorStart: '#F83287',
|
||||
bgColorEnd: '#FE3423'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
const imageBoxRef = ref()
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
const sortable = Sortable.create(imageBoxRef.value, {
|
||||
group: 'item-wrap',
|
||||
animation: 200,
|
||||
onEnd: event => {
|
||||
const temp = diyStore.editComponent.list[event.oldIndex!]
|
||||
diyStore.editComponent.list.splice(event.oldIndex!, 1)
|
||||
diyStore.editComponent.list.splice(event.newIndex!, 0, temp)
|
||||
sortable.sort(
|
||||
range(diyStore.editComponent.list.length).map(value => {
|
||||
return value.toString()
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
defineExpose({})
|
||||
|
||||
</script>
|
||||
|
||||
@ -250,4 +250,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -21,13 +21,13 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {t} from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import { t } from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = ['pageBgColor','topRounded','bottomRounded','marginTop','marginBottom','marginBoth']; // 忽略公共属性
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = ['pageBgColor', 'topRounded', 'bottomRounded', 'marginTop', 'marginBottom', 'marginBoth'] // 忽略公共属性
|
||||
|
||||
defineExpose({})
|
||||
defineExpose({})
|
||||
|
||||
</script>
|
||||
|
||||
@ -38,4 +38,4 @@
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -33,41 +33,41 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {t} from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import {img} from '@/utils/common'
|
||||
import { t } from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import { img } from '@/utils/common'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = []; // 忽略公共属性
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = [] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
var res = {code: true, message: ''};
|
||||
if (diyStore.value[index].imageUrl === '') {
|
||||
res.code = false;
|
||||
res.message = t('imageUrlTip');
|
||||
return res;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
const selectImg = (url: string) => {
|
||||
handleHeight();
|
||||
};
|
||||
|
||||
// 处理高度
|
||||
const handleHeight = () => {
|
||||
let image = new Image();
|
||||
image.src = img(diyStore.editComponent.imageUrl);
|
||||
image.onload = async () => {
|
||||
diyStore.editComponent.imgWidth = image.width;
|
||||
diyStore.editComponent.imgHeight = image.height;
|
||||
};
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
if (diyStore.value[index].imageUrl === '') {
|
||||
res.code = false
|
||||
res.message = t('imageUrlTip')
|
||||
return res
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
const selectImg = (url: string) => {
|
||||
handleHeight()
|
||||
}
|
||||
|
||||
// 处理高度
|
||||
const handleHeight = () => {
|
||||
const image = new Image()
|
||||
image.src = img(diyStore.editComponent.imageUrl)
|
||||
image.onload = async () => {
|
||||
diyStore.editComponent.imgWidth = image.width
|
||||
diyStore.editComponent.imgHeight = image.height
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -44,112 +44,112 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {ref, watch, onMounted, nextTick} from 'vue'
|
||||
import {t} from '@/lang'
|
||||
import Sortable from 'sortablejs'
|
||||
import {img} from '@/utils/common'
|
||||
import {range} from 'lodash-es'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import { ref, watch, onMounted, nextTick } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import Sortable from 'sortablejs'
|
||||
import { img } from '@/utils/common'
|
||||
import { range } from 'lodash-es'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = []; // 忽略公共属性
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = [] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
var res = {code: true, message: ''};
|
||||
if(diyStore.value[index].imageHeight == 0){
|
||||
res.code = false;
|
||||
res.message = t('imageHeightPlaceholder');
|
||||
return res;
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
if (diyStore.value[index].imageHeight == 0) {
|
||||
res.code = false
|
||||
res.message = t('imageHeightPlaceholder')
|
||||
return res
|
||||
}
|
||||
if (!/^\d+.?\d{0,2}$/.test(diyStore.value[index].imageHeight)) {
|
||||
res.code = false
|
||||
res.message = t('imageHeightRegNum')
|
||||
return res
|
||||
}
|
||||
diyStore.value[index].list.forEach((item: any) => {
|
||||
if (item.imageUrl === '') {
|
||||
res.code = false
|
||||
res.message = t('imageUrlTip')
|
||||
return res
|
||||
}
|
||||
if(!/^\d+.?\d{0,2}$/.test(diyStore.value[index].imageHeight)){
|
||||
res.code = false;
|
||||
res.message = t('imageHeightRegNum');
|
||||
return res;
|
||||
}
|
||||
diyStore.value[index].list.forEach((item: any) => {
|
||||
if (item.imageUrl === '') {
|
||||
res.code = false;
|
||||
res.message = t('imageUrlTip');
|
||||
return res;
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
diyStore.editComponent.list.forEach((item: any) => {
|
||||
if (!item.id) item.id = diyStore.generateRandom()
|
||||
})
|
||||
|
||||
watch(
|
||||
() => diyStore.editComponent.list,
|
||||
(newValue, oldValue) => {
|
||||
// 设置图片宽高
|
||||
handleHeight()
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
const addImageAd = () => {
|
||||
diyStore.editComponent.list.push({
|
||||
id: diyStore.generateRandom(),
|
||||
imageUrl: '',
|
||||
imgWidth: 0,
|
||||
imgHeight: 0,
|
||||
link: { name: '' }
|
||||
})
|
||||
}
|
||||
|
||||
const selectImg = (url:string) => {
|
||||
handleHeight(true)
|
||||
}
|
||||
|
||||
// 处理高度
|
||||
const handleHeight = (isCalcHeight:boolean = false)=> {
|
||||
diyStore.editComponent.list.forEach((item: any, index: number) => {
|
||||
const image = new Image()
|
||||
image.src = img(item.imageUrl)
|
||||
image.onload = async () => {
|
||||
item.imgWidth = image.width
|
||||
item.imgHeight = image.height
|
||||
// 计算第一张图片高度
|
||||
if (isCalcHeight && index == 0) {
|
||||
const ratio = item.imgHeight / item.imgWidth
|
||||
item.width = 375
|
||||
item.height = item.width * ratio
|
||||
diyStore.editComponent.imageHeight = parseInt(item.height)
|
||||
}
|
||||
});
|
||||
return res;
|
||||
};
|
||||
|
||||
diyStore.editComponent.list.forEach((item: any) => {
|
||||
if (!item.id) item.id = diyStore.generateRandom();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
watch(
|
||||
() => diyStore.editComponent.list,
|
||||
(newValue, oldValue) => {
|
||||
// 设置图片宽高
|
||||
handleHeight();
|
||||
},
|
||||
{deep: true}
|
||||
)
|
||||
const blurImageHeight = () => {
|
||||
diyStore.editComponent.imageHeight = parseInt(diyStore.editComponent.imageHeight)
|
||||
}
|
||||
|
||||
const addImageAd = () => {
|
||||
diyStore.editComponent.list.push({
|
||||
id: diyStore.generateRandom(),
|
||||
imageUrl: '',
|
||||
imgWidth: 0,
|
||||
imgHeight: 0,
|
||||
link: {name: ''}
|
||||
const imageBoxRef = ref()
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
const sortable = Sortable.create(imageBoxRef.value, {
|
||||
group: 'item-wrap',
|
||||
animation: 200,
|
||||
onEnd: event => {
|
||||
const temp = diyStore.editComponent.list[event.oldIndex!]
|
||||
diyStore.editComponent.list.splice(event.oldIndex!, 1)
|
||||
diyStore.editComponent.list.splice(event.newIndex!, 0, temp)
|
||||
sortable.sort(
|
||||
range(diyStore.editComponent.list.length).map(value => {
|
||||
return value.toString()
|
||||
})
|
||||
)
|
||||
handleHeight(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
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 = parseInt(item.height);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const blurImageHeight = ()=> {
|
||||
diyStore.editComponent.imageHeight = parseInt(diyStore.editComponent.imageHeight);
|
||||
}
|
||||
|
||||
const imageBoxRef = ref()
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
const sortable = Sortable.create(imageBoxRef.value, {
|
||||
group: 'item-wrap',
|
||||
animation: 200,
|
||||
onEnd: event => {
|
||||
const temp = diyStore.editComponent.list[event.oldIndex!];
|
||||
diyStore.editComponent.list.splice(event.oldIndex!, 1);
|
||||
diyStore.editComponent.list.splice(event.newIndex!, 0, temp);
|
||||
sortable.sort(
|
||||
range(diyStore.editComponent.list.length).map(value => {
|
||||
return value.toString();
|
||||
})
|
||||
);
|
||||
handleHeight(true);
|
||||
}
|
||||
})
|
||||
});
|
||||
})
|
||||
})
|
||||
|
||||
defineExpose({})
|
||||
defineExpose({})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@ -167,4 +167,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -28,14 +28,14 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {t} from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import { t } from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = []; // 忽略公共属性
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = [] // 忽略公共属性
|
||||
|
||||
defineExpose({})
|
||||
defineExpose({})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -55,7 +55,6 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
@ -63,39 +62,39 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {t} from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import {ref, reactive} from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = []; // 忽略公共属性
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = [] // 忽略公共属性
|
||||
|
||||
const showDialog = ref(false)
|
||||
|
||||
const showStyle = () => {
|
||||
showDialog.value = true
|
||||
const showDialog = ref(false)
|
||||
|
||||
const showStyle = () => {
|
||||
showDialog.value = true
|
||||
}
|
||||
|
||||
const selectStyle = ref(diyStore.editComponent.style)
|
||||
|
||||
const changeStyle = () => {
|
||||
switch (selectStyle.value) {
|
||||
case 'style-1':
|
||||
diyStore.editComponent.subTitle.control = false
|
||||
diyStore.editComponent.more.control = false
|
||||
diyStore.editComponent.styleName = '风格1'
|
||||
break
|
||||
case 'style-2':
|
||||
diyStore.editComponent.subTitle.control = true
|
||||
diyStore.editComponent.more.control = true
|
||||
diyStore.editComponent.styleName = '风格2'
|
||||
break
|
||||
}
|
||||
diyStore.editComponent.style = selectStyle.value
|
||||
showDialog.value = false
|
||||
}
|
||||
|
||||
const selectStyle = ref(diyStore.editComponent.style)
|
||||
|
||||
const changeStyle = () => {
|
||||
switch (selectStyle.value) {
|
||||
case 'style-1':
|
||||
diyStore.editComponent.subTitle.control = false
|
||||
diyStore.editComponent.more.control = false
|
||||
diyStore.editComponent.styleName = "风格1"
|
||||
break;
|
||||
case 'style-2':
|
||||
diyStore.editComponent.subTitle.control = true
|
||||
diyStore.editComponent.more.control = true
|
||||
diyStore.editComponent.styleName = "风格2"
|
||||
break;
|
||||
}
|
||||
diyStore.editComponent.style = selectStyle.value
|
||||
showDialog.value = false
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
defineExpose({})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@ -108,4 +107,4 @@
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -40,27 +40,27 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {t} from '@/lang'
|
||||
import {ref,watch} from 'vue'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import {img} from '@/utils/common'
|
||||
import { t } from '@/lang'
|
||||
import { watch } from 'vue'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import { img } from '@/utils/common'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
const diyStore = useDiyStore()
|
||||
|
||||
watch(
|
||||
() => diyStore.global.bgUrl,
|
||||
(newValue, oldValue) => {
|
||||
// 设置图片宽高
|
||||
let image = new Image();
|
||||
image.src = img(diyStore.global.bgUrl);
|
||||
image.onload = async () => {
|
||||
diyStore.global.imgWidth = image.width;
|
||||
diyStore.global.imgHeight = image.height;
|
||||
};
|
||||
watch(
|
||||
() => diyStore.global.bgUrl,
|
||||
(newValue, oldValue) => {
|
||||
// 设置图片宽高
|
||||
const image = new Image()
|
||||
image.src = img(diyStore.global.bgUrl)
|
||||
image.onload = async () => {
|
||||
diyStore.global.imgWidth = image.width
|
||||
diyStore.global.imgHeight = image.height
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
defineExpose({})
|
||||
defineExpose({})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<span>{{ selectTemplate.name }}</span>
|
||||
</el-form-item>
|
||||
<ul class="selected-template-list">
|
||||
<li v-for="(item,i) in templateList" :class="[(item.className == diyStore.editComponent.mode) ? 'selected' : '' ]" @click="changeTemplateList(i)">
|
||||
<li v-for="(item,i) in templateList" :key="i" :class="[(item.className == diyStore.editComponent.mode) ? 'selected' : '' ]" @click="changeTemplateList(i)">
|
||||
<icon :name="'iconfont-' + item.src" size="16px"/>
|
||||
</li>
|
||||
</ul>
|
||||
@ -20,7 +20,7 @@
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
|
||||
<ul class="layout">
|
||||
<li v-for="(li,i) in selectTemplate.dimensionScale" :class="[selectTemplate.className]" :style="{ width: rubikCubeList[i].widthStyle, height: rubikCubeList[i].imgHeight + 'px' }">
|
||||
<li v-for="(li,i) in selectTemplate.dimensionScale" :key="i" :class="[selectTemplate.className]" :style="{ width: rubikCubeList[i].widthStyle, height: rubikCubeList[i].imgHeight + 'px' }">
|
||||
<div class="have-preview-image" v-show="diyStore.editComponent.list[i].imageUrl">
|
||||
<img class="!w-full !h-full" :src="img(diyStore.editComponent.list[i].imageUrl)"/>
|
||||
</div>
|
||||
@ -31,7 +31,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<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]">
|
||||
<div v-for="(item) 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" @change="selectImg"/>
|
||||
</el-form-item>
|
||||
@ -72,423 +72,422 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {ref, watch, onMounted, nextTick, computed} from 'vue'
|
||||
import {t} from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import {img} from '@/utils/common'
|
||||
import { ref, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import { img } from '@/utils/common'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = []; // 忽略公共属性
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = [] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
var res = {code: true, message: ''};
|
||||
diyStore.value[index].list.forEach((item: any) => {
|
||||
if (item.imageUrl === '') {
|
||||
res.code = false;
|
||||
res.message = t('imageUrlTip');
|
||||
return res;
|
||||
}
|
||||
});
|
||||
return res;
|
||||
};
|
||||
|
||||
const templateList = ref([
|
||||
{
|
||||
name: "1行2个",
|
||||
src: 'iconyihangliangge',
|
||||
className: "row1-of2",
|
||||
dimensionScale: [
|
||||
{
|
||||
desc: "宽度50%",
|
||||
size: "200px * 200px",
|
||||
name: "图一"
|
||||
},
|
||||
{
|
||||
desc: "宽度50%",
|
||||
size: "200px * 200px",
|
||||
name: "图二"
|
||||
}
|
||||
],
|
||||
descAux: "选定布局区域,在下方添加图片,建议添加尺寸一致的图片,宽度最小建议为:200px"
|
||||
},
|
||||
{
|
||||
name: "1行3个",
|
||||
src: 'iconyihangsange',
|
||||
className: "row1-of3",
|
||||
dimensionScale: [
|
||||
{
|
||||
desc: "宽度33.33%",
|
||||
size: "200px * 200px",
|
||||
name: "图一"
|
||||
},
|
||||
{
|
||||
desc: "宽度33.33%",
|
||||
size: "200px * 200px",
|
||||
name: "图二"
|
||||
},
|
||||
{
|
||||
desc: "宽度33.33%",
|
||||
size: "200px * 200px",
|
||||
name: "图三"
|
||||
}
|
||||
],
|
||||
descAux: "选定布局区域,在下方添加图片,建议添加尺寸一致的图片,宽度最小建议为:130px"
|
||||
},
|
||||
{
|
||||
name: "1行4个",
|
||||
src: 'iconyihangsige',
|
||||
className: "row1-of4",
|
||||
dimensionScale: [
|
||||
{
|
||||
desc: "宽度25%",
|
||||
size: "200px * 200px",
|
||||
name: "图一"
|
||||
},
|
||||
{
|
||||
desc: "宽度25%",
|
||||
size: "200px * 200px",
|
||||
name: "图二"
|
||||
},
|
||||
{
|
||||
desc: "宽度25%",
|
||||
size: "200px * 200px",
|
||||
name: "图三"
|
||||
},
|
||||
{
|
||||
desc: "宽度25%",
|
||||
size: "200px * 200px",
|
||||
name: "图四"
|
||||
}
|
||||
],
|
||||
descAux: "选定布局区域,在下方添加图片,建议添加尺寸一致的图片,宽度最小建议为:100px"
|
||||
},
|
||||
{
|
||||
name: "2左2右",
|
||||
src: 'iconmofang-liangzuoliangyou',
|
||||
className: "row2-lt-of2-rt",
|
||||
dimensionScale: [
|
||||
{
|
||||
desc: "宽度50%",
|
||||
size: "200px * 200px",
|
||||
name: "图一"
|
||||
},
|
||||
{
|
||||
desc: "宽度50%",
|
||||
size: "200px * 200px",
|
||||
name: "图二"
|
||||
},
|
||||
{
|
||||
desc: "宽度50%",
|
||||
size: "200px * 200px",
|
||||
name: "图三"
|
||||
},
|
||||
{
|
||||
desc: "宽度50%",
|
||||
size: "200px * 200px",
|
||||
name: "图四"
|
||||
}
|
||||
],
|
||||
descAux: "选定布局区域,在下方添加图片,建议添加尺寸一致的图片,宽度最小建议为:200px"
|
||||
},
|
||||
{
|
||||
name: "1左2右",
|
||||
src: 'iconmofang-yizuoliangyou',
|
||||
className: "row1-lt-of2-rt",
|
||||
dimensionScale: [
|
||||
{
|
||||
desc: "宽度50% * 高度100%",
|
||||
size: "200px * 400px",
|
||||
name: "图一"
|
||||
},
|
||||
{
|
||||
desc: "宽度50% * 高度50%",
|
||||
size: "200px * 200px",
|
||||
name: "图二"
|
||||
},
|
||||
{
|
||||
desc: "宽度50% * 高度50%",
|
||||
size: "200px * 200px",
|
||||
name: "图三"
|
||||
}
|
||||
],
|
||||
descAux: "选定布局区域,在下方添加图片,宽度最小建议为:200px,右侧两张图片高度一致,左侧图片高度为右侧两张图片高度之和(例:左侧图片尺寸:200px * 300px,右侧两张图片尺寸:200px * 150px)"
|
||||
},
|
||||
{
|
||||
name: "1上2下",
|
||||
src: 'iconmofang-yishangliangxia',
|
||||
className: "row1-tp-of2-bm",
|
||||
dimensionScale: [
|
||||
{
|
||||
desc: "宽度100% * 高度50%",
|
||||
size: "400px * 200px",
|
||||
name: "图一"
|
||||
},
|
||||
{
|
||||
desc: "宽度50% * 高度50%",
|
||||
size: "200px * 200px",
|
||||
name: "图二"
|
||||
},
|
||||
{
|
||||
desc: "宽度50% * 高度50%",
|
||||
size: "200px * 200px",
|
||||
name: "图三"
|
||||
}
|
||||
],
|
||||
descAux: "选定布局区域,在下方添加图片,上方一张图片的宽度为下方两张图片宽度之和,下放两张图片尺寸一致,高度可根据实际需求自行确定(例:上方图片尺寸:400px * 150px,下方两张图片尺寸:200px * 150px)"
|
||||
},
|
||||
{
|
||||
name: "1左3右",
|
||||
src: 'iconxuanzemoban-yizuosanyou',
|
||||
className: "row1-lt-of1-tp-of2-bm",
|
||||
dimensionScale: [
|
||||
{
|
||||
desc: "宽度50% * 高度100%",
|
||||
size: "200px * 400px",
|
||||
name: "图一"
|
||||
},
|
||||
{
|
||||
desc: "宽度50% * 高度50%",
|
||||
size: "200px * 200px",
|
||||
name: "图二"
|
||||
},
|
||||
{
|
||||
desc: "宽度25% * 高度50%",
|
||||
size: "100px * 200px",
|
||||
name: "图三"
|
||||
},
|
||||
{
|
||||
desc: "宽度25% * 高度50%",
|
||||
size: "100px * 200px",
|
||||
name: "图四"
|
||||
}
|
||||
],
|
||||
descAux: "选定布局区域,在下方添加图片,左右两侧内容宽高相同,右侧上下区域高度各占50%,右侧内容下半部分两张图片的宽度相同,各占右侧内容宽度的50%(例:左侧图片尺寸:200px * 400px,右侧上半部分图片尺寸:200px * 200px,右侧下半部分两张图片尺寸:100px * 200px)"
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
diyStore.value[index].list.forEach((item: any) => {
|
||||
if (item.imageUrl === '') {
|
||||
res.code = false
|
||||
res.message = t('imageUrlTip')
|
||||
return res
|
||||
}
|
||||
]);
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
let rubikCubeList = ref([]);
|
||||
const selectTemplate = computed(() => {
|
||||
var data;
|
||||
templateList.value.forEach((item) => {
|
||||
if (item.className == diyStore.editComponent.mode) {
|
||||
data = item;
|
||||
|
||||
rubikCubeList.value = JSON.parse(JSON.stringify(diyStore.editComponent.list));
|
||||
if (item.className == 'row2-lt-of2-rt') {
|
||||
calcFourSquare();
|
||||
} else if (item.className == 'row1-lt-of2-rt') {
|
||||
calcRowOneLeftOfTwoRight();
|
||||
} else if (item.className == 'row1-tp-of2-bm') {
|
||||
calcRowOneTopOfTwoBottom();
|
||||
} else if (item.className == 'row1-lt-of1-tp-of2-bm') {
|
||||
calcRowOneLeftOfOneTopOfTwoBottom();
|
||||
} else {
|
||||
calcSingleRow(item.className);
|
||||
}
|
||||
const templateList = ref([
|
||||
{
|
||||
name: '1行2个',
|
||||
src: 'iconyihangliangge',
|
||||
className: 'row1-of2',
|
||||
dimensionScale: [
|
||||
{
|
||||
desc: '宽度50%',
|
||||
size: '200px * 200px',
|
||||
name: '图一'
|
||||
},
|
||||
{
|
||||
desc: '宽度50%',
|
||||
size: '200px * 200px',
|
||||
name: '图二'
|
||||
}
|
||||
})
|
||||
return data;
|
||||
});
|
||||
],
|
||||
descAux: '选定布局区域,在下方添加图片,建议添加尺寸一致的图片,宽度最小建议为:200px'
|
||||
},
|
||||
{
|
||||
name: '1行3个',
|
||||
src: 'iconyihangsange',
|
||||
className: 'row1-of3',
|
||||
dimensionScale: [
|
||||
{
|
||||
desc: '宽度33.33%',
|
||||
size: '200px * 200px',
|
||||
name: '图一'
|
||||
},
|
||||
{
|
||||
desc: '宽度33.33%',
|
||||
size: '200px * 200px',
|
||||
name: '图二'
|
||||
},
|
||||
{
|
||||
desc: '宽度33.33%',
|
||||
size: '200px * 200px',
|
||||
name: '图三'
|
||||
}
|
||||
],
|
||||
descAux: '选定布局区域,在下方添加图片,建议添加尺寸一致的图片,宽度最小建议为:130px'
|
||||
},
|
||||
{
|
||||
name: '1行4个',
|
||||
src: 'iconyihangsige',
|
||||
className: 'row1-of4',
|
||||
dimensionScale: [
|
||||
{
|
||||
desc: '宽度25%',
|
||||
size: '200px * 200px',
|
||||
name: '图一'
|
||||
},
|
||||
{
|
||||
desc: '宽度25%',
|
||||
size: '200px * 200px',
|
||||
name: '图二'
|
||||
},
|
||||
{
|
||||
desc: '宽度25%',
|
||||
size: '200px * 200px',
|
||||
name: '图三'
|
||||
},
|
||||
{
|
||||
desc: '宽度25%',
|
||||
size: '200px * 200px',
|
||||
name: '图四'
|
||||
}
|
||||
],
|
||||
descAux: '选定布局区域,在下方添加图片,建议添加尺寸一致的图片,宽度最小建议为:100px'
|
||||
},
|
||||
{
|
||||
name: '2左2右',
|
||||
src: 'iconmofang-liangzuoliangyou',
|
||||
className: 'row2-lt-of2-rt',
|
||||
dimensionScale: [
|
||||
{
|
||||
desc: '宽度50%',
|
||||
size: '200px * 200px',
|
||||
name: '图一'
|
||||
},
|
||||
{
|
||||
desc: '宽度50%',
|
||||
size: '200px * 200px',
|
||||
name: '图二'
|
||||
},
|
||||
{
|
||||
desc: '宽度50%',
|
||||
size: '200px * 200px',
|
||||
name: '图三'
|
||||
},
|
||||
{
|
||||
desc: '宽度50%',
|
||||
size: '200px * 200px',
|
||||
name: '图四'
|
||||
}
|
||||
],
|
||||
descAux: '选定布局区域,在下方添加图片,建议添加尺寸一致的图片,宽度最小建议为:200px'
|
||||
},
|
||||
{
|
||||
name: '1左2右',
|
||||
src: 'iconmofang-yizuoliangyou',
|
||||
className: 'row1-lt-of2-rt',
|
||||
dimensionScale: [
|
||||
{
|
||||
desc: '宽度50% * 高度100%',
|
||||
size: '200px * 400px',
|
||||
name: '图一'
|
||||
},
|
||||
{
|
||||
desc: '宽度50% * 高度50%',
|
||||
size: '200px * 200px',
|
||||
name: '图二'
|
||||
},
|
||||
{
|
||||
desc: '宽度50% * 高度50%',
|
||||
size: '200px * 200px',
|
||||
name: '图三'
|
||||
}
|
||||
],
|
||||
descAux: '选定布局区域,在下方添加图片,宽度最小建议为:200px,右侧两张图片高度一致,左侧图片高度为右侧两张图片高度之和(例:左侧图片尺寸:200px * 300px,右侧两张图片尺寸:200px * 150px)'
|
||||
},
|
||||
{
|
||||
name: '1上2下',
|
||||
src: 'iconmofang-yishangliangxia',
|
||||
className: 'row1-tp-of2-bm',
|
||||
dimensionScale: [
|
||||
{
|
||||
desc: '宽度100% * 高度50%',
|
||||
size: '400px * 200px',
|
||||
name: '图一'
|
||||
},
|
||||
{
|
||||
desc: '宽度50% * 高度50%',
|
||||
size: '200px * 200px',
|
||||
name: '图二'
|
||||
},
|
||||
{
|
||||
desc: '宽度50% * 高度50%',
|
||||
size: '200px * 200px',
|
||||
name: '图三'
|
||||
}
|
||||
],
|
||||
descAux: '选定布局区域,在下方添加图片,上方一张图片的宽度为下方两张图片宽度之和,下放两张图片尺寸一致,高度可根据实际需求自行确定(例:上方图片尺寸:400px * 150px,下方两张图片尺寸:200px * 150px)'
|
||||
},
|
||||
{
|
||||
name: '1左3右',
|
||||
src: 'iconxuanzemoban-yizuosanyou',
|
||||
className: 'row1-lt-of1-tp-of2-bm',
|
||||
dimensionScale: [
|
||||
{
|
||||
desc: '宽度50% * 高度100%',
|
||||
size: '200px * 400px',
|
||||
name: '图一'
|
||||
},
|
||||
{
|
||||
desc: '宽度50% * 高度50%',
|
||||
size: '200px * 200px',
|
||||
name: '图二'
|
||||
},
|
||||
{
|
||||
desc: '宽度25% * 高度50%',
|
||||
size: '100px * 200px',
|
||||
name: '图三'
|
||||
},
|
||||
{
|
||||
desc: '宽度25% * 高度50%',
|
||||
size: '100px * 200px',
|
||||
name: '图四'
|
||||
}
|
||||
],
|
||||
descAux: '选定布局区域,在下方添加图片,左右两侧内容宽高相同,右侧上下区域高度各占50%,右侧内容下半部分两张图片的宽度相同,各占右侧内容宽度的50%(例:左侧图片尺寸:200px * 400px,右侧上半部分图片尺寸:200px * 200px,右侧下半部分两张图片尺寸:100px * 200px)'
|
||||
}
|
||||
])
|
||||
|
||||
const changeTemplateList = (v: number) => {
|
||||
for (var i = 0; i < templateList.value.length; i++) {
|
||||
if (i == v) {
|
||||
diyStore.editComponent.mode = templateList.value[i].className;
|
||||
var count = templateList.value[i].dimensionScale.length;
|
||||
const rubikCubeList = ref([])
|
||||
const selectTemplate = computed(() => {
|
||||
let data
|
||||
templateList.value.forEach((item) => {
|
||||
if (item.className == diyStore.editComponent.mode) {
|
||||
data = item
|
||||
|
||||
//重置当前编辑的图片集合
|
||||
rubikCubeList.value = JSON.parse(JSON.stringify(diyStore.editComponent.list))
|
||||
if (item.className == 'row2-lt-of2-rt') {
|
||||
calcFourSquare()
|
||||
} else if (item.className == 'row1-lt-of2-rt') {
|
||||
calcRowOneLeftOfTwoRight()
|
||||
} else if (item.className == 'row1-tp-of2-bm') {
|
||||
calcRowOneTopOfTwoBottom()
|
||||
} else if (item.className == 'row1-lt-of1-tp-of2-bm') {
|
||||
calcRowOneLeftOfOneTopOfTwoBottom()
|
||||
} else {
|
||||
calcSingleRow(item.className)
|
||||
}
|
||||
}
|
||||
})
|
||||
return data
|
||||
})
|
||||
|
||||
//数量不够,进行添加
|
||||
if (count > diyStore.editComponent.list.length) {
|
||||
for (var j = 0; j < count; j++) {
|
||||
if ((j + 1) > diyStore.editComponent.list.length) diyStore.editComponent.list.push({
|
||||
imageUrl: "",
|
||||
const changeTemplateList = (v: number) => {
|
||||
for (let i = 0; i < templateList.value.length; i++) {
|
||||
if (i == v) {
|
||||
diyStore.editComponent.mode = templateList.value[i].className
|
||||
const count = templateList.value[i].dimensionScale.length
|
||||
|
||||
// 重置当前编辑的图片集合
|
||||
|
||||
// 数量不够,进行添加
|
||||
if (count > diyStore.editComponent.list.length) {
|
||||
for (let j = 0; j < count; j++) {
|
||||
if ((j + 1) > diyStore.editComponent.list.length) {
|
||||
diyStore.editComponent.list.push({
|
||||
imageUrl: '',
|
||||
imgWidth: 0,
|
||||
imgHeight: 0,
|
||||
link: {name: ""}
|
||||
});
|
||||
link: { name: '' }
|
||||
})
|
||||
}
|
||||
} else {
|
||||
//数量不相同时,并且数量超出,减去
|
||||
if (count != diyStore.editComponent.list.length) {
|
||||
for (var j = 0; j < diyStore.editComponent.list.length; j++) {
|
||||
if ((j + 1) > count) {
|
||||
diyStore.editComponent.list.splice(j, 1);
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 数量不相同时,并且数量超出,减去
|
||||
if (count != diyStore.editComponent.list.length) {
|
||||
for (let j = 0; j < diyStore.editComponent.list.length; j++) {
|
||||
if ((j + 1) > count) {
|
||||
diyStore.editComponent.list.splice(j, 1)
|
||||
j = 0
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
const selectImg = (url:string) => {
|
||||
handleHeight(true)
|
||||
}
|
||||
|
||||
/**
|
||||
// 处理高度
|
||||
const handleHeight = (isCalcHeight:boolean = false) => {
|
||||
diyStore.editComponent.list.forEach((item: any, index: number) => {
|
||||
const image = new Image()
|
||||
image.src = img(item.imageUrl)
|
||||
image.onload = async () => {
|
||||
item.imgWidth = image.width
|
||||
item.imgHeight = image.height
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
|
||||
/**
|
||||
* 魔方:单行多个,平分宽度
|
||||
* 公式:
|
||||
* 宽度:屏幕宽度/2,示例:375/2=187.5
|
||||
* 比例:原图高/原图宽,示例:322/690=0.46
|
||||
* 高度:宽度*比例,示例:187.5*0.46=86.25
|
||||
*/
|
||||
const calcSingleRow = (type) => {
|
||||
let maxHeight = 0;
|
||||
var paramsRatio = 2;
|
||||
var paramsWidth = 'calc(100% / 2)';
|
||||
if(type == 'row1-of3'){
|
||||
paramsRatio = 3;
|
||||
paramsWidth = 'calc(100% / 3)';
|
||||
}
|
||||
if(type == 'row1-of4'){
|
||||
paramsRatio = 4
|
||||
paramsWidth = 'calc(100% / 4)';
|
||||
}
|
||||
const calcSingleRow = (type:any) => {
|
||||
let maxHeight = 0
|
||||
let paramsRatio = 2
|
||||
let paramsWidth = 'calc(100% / 2)'
|
||||
if (type == 'row1-of3') {
|
||||
paramsRatio = 3
|
||||
paramsWidth = 'calc(100% / 3)'
|
||||
}
|
||||
if (type == 'row1-of4') {
|
||||
paramsRatio = 4
|
||||
paramsWidth = 'calc(100% / 4)'
|
||||
}
|
||||
|
||||
rubikCubeList.value.forEach((item, index) => {
|
||||
var ratio = item.imgHeight / item.imgWidth;
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
const ratio = item.imgHeight / item.imgWidth
|
||||
|
||||
let width = 330;
|
||||
item.imgWidth = width / paramsRatio;
|
||||
item.imgHeight = item.imgWidth * ratio;
|
||||
const width = 330
|
||||
item.imgWidth = width / paramsRatio
|
||||
item.imgHeight = item.imgWidth * ratio
|
||||
|
||||
if (maxHeight == 0 || maxHeight < item.imgHeight) maxHeight = item.imgHeight;
|
||||
})
|
||||
if (maxHeight == 0 || maxHeight < item.imgHeight) maxHeight = item.imgHeight
|
||||
})
|
||||
|
||||
rubikCubeList.value.forEach((item, index) => {
|
||||
item.widthStyle = paramsWidth;
|
||||
item.imgHeight = maxHeight;
|
||||
});
|
||||
};
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
item.widthStyle = paramsWidth
|
||||
item.imgHeight = maxHeight
|
||||
})
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* 魔方:四方型,各占50%
|
||||
*/
|
||||
const calcFourSquare = () => {
|
||||
let maxHeightFirst = 0;
|
||||
let maxHeightTwo = 0;
|
||||
rubikCubeList.value.forEach((item, index) => {
|
||||
var ratio = item.imgHeight / item.imgWidth;
|
||||
item.imgWidth = 330;
|
||||
item.imgWidth = item.imgWidth / 2;
|
||||
item.imgHeight = item.imgWidth * ratio;
|
||||
const calcFourSquare = () => {
|
||||
let maxHeightFirst = 0
|
||||
let maxHeightTwo = 0
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
const ratio = item.imgHeight / item.imgWidth
|
||||
item.imgWidth = 330
|
||||
item.imgWidth = item.imgWidth / 2
|
||||
item.imgHeight = item.imgWidth * ratio
|
||||
|
||||
// 获取每行最大高度
|
||||
if (index <= 1) {
|
||||
if (maxHeightFirst == 0 || maxHeightFirst < item.imgHeight) {
|
||||
maxHeightFirst = item.imgHeight
|
||||
}
|
||||
} else if (index > 1) {
|
||||
if (maxHeightTwo == 0 || maxHeightTwo < item.imgHeight) {
|
||||
maxHeightTwo = item.imgHeight
|
||||
}
|
||||
}
|
||||
})
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
item.imgWidth = 'calc(100% / 2)'
|
||||
item.widthStyle = item.imgWidth
|
||||
if (index <= 1) {
|
||||
item.imgHeight = maxHeightFirst
|
||||
} else if (index > 1) {
|
||||
item.imgHeight = maxHeightTwo
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 获取每行最大高度
|
||||
if (index <= 1) {
|
||||
if (maxHeightFirst == 0 || maxHeightFirst < item.imgHeight) {
|
||||
maxHeightFirst = item.imgHeight;
|
||||
}
|
||||
} else if (index > 1) {
|
||||
if (maxHeightTwo == 0 || maxHeightTwo < item.imgHeight) {
|
||||
maxHeightTwo = item.imgHeight;
|
||||
}
|
||||
}
|
||||
});
|
||||
rubikCubeList.value.forEach((item, index) => {
|
||||
item.imgWidth = 'calc(100% / 2)';
|
||||
item.widthStyle = item.imgWidth;
|
||||
if (index <= 1) {
|
||||
item.imgHeight = maxHeightFirst;
|
||||
} else if (index > 1) {
|
||||
item.imgHeight = maxHeightTwo;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* 魔方:1左2右
|
||||
*/
|
||||
const calcRowOneLeftOfTwoRight = () => {
|
||||
let rightHeight = 0; // 右侧两图平分高度
|
||||
let divide = 'left'; // 划分规则,left:左,right:右
|
||||
if (rubikCubeList.value[1].imgWidth === rubikCubeList.value[2].imgWidth) divide = 'right';
|
||||
rubikCubeList.value.forEach((item, index) => {
|
||||
if (index == 0) {
|
||||
var ratio = item.imgHeight / item.imgWidth; // 获取左图的尺寸比例
|
||||
item.imgWidth = 330;
|
||||
item.imgWidth = item.imgWidth / 2;
|
||||
item.imgHeight = item.imgWidth * ratio;
|
||||
rightHeight = item.imgHeight / 2;
|
||||
item.imgWidth += 'px';
|
||||
} else {
|
||||
item.imgWidth = rubikCubeList.value[0].imgWidth;
|
||||
item.imgHeight = rightHeight;
|
||||
}
|
||||
});
|
||||
}
|
||||
const calcRowOneLeftOfTwoRight = () => {
|
||||
let rightHeight = 0 // 右侧两图平分高度
|
||||
let divide = 'left' // 划分规则,left:左,right:右
|
||||
if (rubikCubeList.value[1].imgWidth === rubikCubeList.value[2].imgWidth) divide = 'right'
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
if (index == 0) {
|
||||
const ratio = item.imgHeight / item.imgWidth // 获取左图的尺寸比例
|
||||
item.imgWidth = 330
|
||||
item.imgWidth = item.imgWidth / 2
|
||||
item.imgHeight = item.imgWidth * ratio
|
||||
rightHeight = item.imgHeight / 2
|
||||
item.imgWidth += 'px'
|
||||
} else {
|
||||
item.imgWidth = rubikCubeList.value[0].imgWidth
|
||||
item.imgHeight = rightHeight
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* 魔方:1上2下
|
||||
*/
|
||||
const calcRowOneTopOfTwoBottom = () => {
|
||||
var maxHeight = 0;
|
||||
rubikCubeList.value.forEach((item, index) => {
|
||||
const calcRowOneTopOfTwoBottom = () => {
|
||||
let maxHeight = 0
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
const ratio = item.imgHeight / item.imgWidth // 获取左图的尺寸比例
|
||||
if (index == 0) {
|
||||
item.imgWidth = 330
|
||||
} else if (index > 0) {
|
||||
item.imgWidth = 330
|
||||
item.imgWidth = item.imgWidth / 2
|
||||
}
|
||||
|
||||
var ratio = item.imgHeight / item.imgWidth; // 获取左图的尺寸比例
|
||||
if (index == 0) {
|
||||
item.imgWidth = 330;
|
||||
} else if (index > 0) {
|
||||
item.imgWidth = 330;
|
||||
item.imgWidth = item.imgWidth / 2;
|
||||
}
|
||||
item.imgHeight = item.imgWidth * ratio
|
||||
|
||||
item.imgHeight = item.imgWidth * ratio;
|
||||
// 获取最大高度
|
||||
if (index > 0 && (maxHeight == 0 || maxHeight < item.imgHeight)) {
|
||||
maxHeight = item.imgHeight
|
||||
}
|
||||
})
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
item.imgWidth += 'px'
|
||||
item.widthStyle = item.imgWidth
|
||||
if (index > 0) item.imgHeight = maxHeight
|
||||
})
|
||||
}
|
||||
|
||||
// 获取最大高度
|
||||
if (index > 0 && (maxHeight == 0 || maxHeight < item.imgHeight))
|
||||
maxHeight = item.imgHeight;
|
||||
|
||||
});
|
||||
rubikCubeList.value.forEach((item, index) => {
|
||||
item.imgWidth += 'px';
|
||||
item.widthStyle = item.imgWidth;
|
||||
if (index > 0) item.imgHeight = maxHeight;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* 魔方:1左3右
|
||||
*/
|
||||
const calcRowOneLeftOfOneTopOfTwoBottom = () => {
|
||||
rubikCubeList.value.forEach((item, index) => {
|
||||
// 左图
|
||||
if (index == 0) {
|
||||
var ratio = item.imgHeight / item.imgWidth; // 获取左图的尺寸比例
|
||||
item.imgWidth = 330;
|
||||
item.imgWidth = item.imgWidth / 2;
|
||||
item.imgHeight = item.imgWidth * ratio;
|
||||
} else if (index == 1) {
|
||||
item.imgWidth = rubikCubeList.value[0].imgWidth;
|
||||
item.imgHeight = rubikCubeList.value[0].imgHeight / 2;
|
||||
} else if (index > 1) {
|
||||
item.imgWidth = rubikCubeList.value[0].imgWidth / 2;
|
||||
item.imgHeight = rubikCubeList.value[1].imgHeight;
|
||||
}
|
||||
});
|
||||
const calcRowOneLeftOfOneTopOfTwoBottom = () => {
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
// 左图
|
||||
if (index == 0) {
|
||||
const ratio = item.imgHeight / item.imgWidth // 获取左图的尺寸比例
|
||||
item.imgWidth = 330
|
||||
item.imgWidth = item.imgWidth / 2
|
||||
item.imgHeight = item.imgWidth * ratio
|
||||
} else if (index == 1) {
|
||||
item.imgWidth = rubikCubeList.value[0].imgWidth
|
||||
item.imgHeight = rubikCubeList.value[0].imgHeight / 2
|
||||
} else if (index > 1) {
|
||||
item.imgWidth = rubikCubeList.value[0].imgWidth / 2
|
||||
item.imgHeight = rubikCubeList.value[1].imgHeight
|
||||
}
|
||||
})
|
||||
|
||||
rubikCubeList.value.forEach((item, index) => {
|
||||
item.imgWidth += 'px';
|
||||
});
|
||||
}
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
item.imgWidth += 'px'
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@ -5,9 +5,10 @@
|
||||
<h3 class="mb-[10px]">{{ t('styleSet') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('selectStyle')" class="flex">
|
||||
<span class="text-primary flex-1 cursor-pointer" @click="showStyle">{{ diyStore.editComponent.styleName }}</span>
|
||||
<span class="text-primary flex-1 cursor-pointer" @click="showStyle">{{ diyStore.editComponent.styleName
|
||||
}}</span>
|
||||
<el-icon>
|
||||
<ArrowRight/>
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@ -16,15 +17,16 @@
|
||||
<h3 class="mb-[10px]">{{ t('titleContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('title')">
|
||||
<el-input v-model="diyStore.editComponent.text" :placeholder="t('titlePlaceholder')" clearable maxlength="15" show-word-limit/>
|
||||
<el-input v-model="diyStore.editComponent.text" :placeholder="t('titlePlaceholder')" clearable
|
||||
maxlength="15" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="diyStore.editComponent.link"/>
|
||||
<diy-link v-model="diyStore.editComponent.link" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textAlign')" v-show="diyStore.editComponent.style == 'style-1'">
|
||||
<el-radio-group v-model="diyStore.editComponent.textAlign">
|
||||
<el-radio :label="'left'">{{t('textAlignLeft')}}</el-radio>
|
||||
<el-radio :label="'center'">{{t('textAlignCenter')}}</el-radio>
|
||||
<el-radio :label="'left'">{{ t('textAlignLeft') }}</el-radio>
|
||||
<el-radio :label="'center'">{{ t('textAlignCenter') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@ -34,13 +36,15 @@
|
||||
<h3 class="mb-[10px]">{{ t('subTitleContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('subTitle')">
|
||||
<el-input v-model="diyStore.editComponent.subTitle.text" :placeholder="t('subTitlePlaceholder')" clearable maxlength="30" show-word-limit/>
|
||||
<el-input v-model="diyStore.editComponent.subTitle.text" :placeholder="t('subTitlePlaceholder')"
|
||||
clearable maxlength="30" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textFontSize')">
|
||||
<el-slider v-model="diyStore.editComponent.subTitle.fontSize" show-input size="small" class="ml-[10px] article-slider" :min="12" :max="16"/>
|
||||
<el-slider v-model="diyStore.editComponent.subTitle.fontSize" show-input size="small"
|
||||
class="ml-[10px] article-slider" :min="12" :max="16" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.subTitle.color"/>
|
||||
<el-color-picker v-model="diyStore.editComponent.subTitle.color" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
@ -49,16 +53,17 @@
|
||||
<h3 class="mb-[10px]">{{ t('moreContent') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('more')">
|
||||
<el-input v-model="diyStore.editComponent.more.text" :placeholder="t('morePlaceholder')" clearable maxlength="8" show-word-limit/>
|
||||
<el-input v-model="diyStore.editComponent.more.text" :placeholder="t('morePlaceholder')" clearable
|
||||
maxlength="8" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('link')">
|
||||
<diy-link v-model="diyStore.editComponent.more.link"/>
|
||||
<diy-link v-model="diyStore.editComponent.more.link" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('moreIsShow')">
|
||||
<el-switch v-model="diyStore.editComponent.more.isShow"/>
|
||||
<el-switch v-model="diyStore.editComponent.more.isShow" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.more.color"/>
|
||||
<el-color-picker v-model="diyStore.editComponent.more.color" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
@ -66,19 +71,21 @@
|
||||
<el-dialog v-model="showDialog" :title="t('selectStyle')" width="40%">
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<div class="flex items-center justify-center overflow-hidden w-[280px] h-[100px] mr-[12px] cursor-pointer border bg-gray-50" :class="{ 'border-primary' : selectStyle == 'style-1'}" @click="selectStyle = 'style-1'">
|
||||
<img class="max-w-[280px] max-h-[220px]" src="@/app/assets/images/diy/text/style1.png"/>
|
||||
<div class="flex items-center justify-center overflow-hidden w-[280px] h-[100px] mr-[12px] cursor-pointer border bg-gray-50"
|
||||
:class="{ 'border-primary': selectStyle == 'style-1' }" @click="selectStyle = 'style-1'">
|
||||
<img class="max-w-[280px] max-h-[220px]" src="@/app/assets/images/diy/text/style1.png" />
|
||||
</div>
|
||||
<div class="flex items-center justify-center overflow-hidden w-[280px] h-[100px] mr-[12px] cursor-pointer border bg-gray-50" :class="{ 'border-primary' : selectStyle == 'style-2'}" @click="selectStyle = 'style-2'">
|
||||
<img class="max-w-[280px] max-h-[220px]" src="@/app/assets/images/diy/text/style2.png"/>
|
||||
<div class="flex items-center justify-center overflow-hidden w-[280px] h-[100px] mr-[12px] cursor-pointer border bg-gray-50"
|
||||
:class="{ 'border-primary': selectStyle == 'style-2' }" @click="selectStyle = 'style-2'">
|
||||
<img class="max-w-[280px] max-h-[220px]" src="@/app/assets/images/diy/text/style2.png" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showDialog = false">{{ t('cancel')}}</el-button>
|
||||
<el-button type="primary" @click="changeStyle">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="changeStyle">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
</el-dialog>
|
||||
@ -91,16 +98,17 @@
|
||||
<h3 class="mb-[10px]">{{ t('titleStyle') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('textFontSize')">
|
||||
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] article-slider" :min="12" :max="20"/>
|
||||
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small"
|
||||
class="ml-[10px] article-slider" :min="12" :max="20" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textFontWeight')">
|
||||
<el-radio-group v-model="diyStore.editComponent.fontWeight">
|
||||
<el-radio :label="'normal'">{{t('fontWeightNormal')}}</el-radio>
|
||||
<el-radio :label="'bold'">{{t('fontWeightBold')}}</el-radio>
|
||||
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
|
||||
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('textColor')">
|
||||
<el-color-picker v-model="diyStore.editComponent.textColor"/>
|
||||
<el-color-picker v-model="diyStore.editComponent.textColor" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
@ -109,51 +117,49 @@
|
||||
<slot name="style"></slot>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {t} from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import {ref, reactive} from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = []; // 忽略公共属性
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = [] // 忽略公共属性
|
||||
|
||||
const showDialog = ref(false)
|
||||
const showDialog = ref(false)
|
||||
|
||||
const showStyle = () => {
|
||||
showDialog.value = true
|
||||
const showStyle = () => {
|
||||
showDialog.value = true
|
||||
}
|
||||
|
||||
const selectStyle = ref(diyStore.editComponent.style)
|
||||
|
||||
const changeStyle = () => {
|
||||
switch (selectStyle.value) {
|
||||
case 'style-1':
|
||||
diyStore.editComponent.subTitle.control = false
|
||||
diyStore.editComponent.more.control = false
|
||||
diyStore.editComponent.styleName = '风格1'
|
||||
break
|
||||
case 'style-2':
|
||||
diyStore.editComponent.subTitle.control = true
|
||||
diyStore.editComponent.more.control = true
|
||||
diyStore.editComponent.styleName = '风格2'
|
||||
break
|
||||
}
|
||||
diyStore.editComponent.style = selectStyle.value
|
||||
showDialog.value = false
|
||||
}
|
||||
|
||||
const selectStyle = ref(diyStore.editComponent.style)
|
||||
|
||||
const changeStyle = () => {
|
||||
switch (selectStyle.value) {
|
||||
case 'style-1':
|
||||
diyStore.editComponent.subTitle.control = false
|
||||
diyStore.editComponent.more.control = false
|
||||
diyStore.editComponent.styleName = "风格1"
|
||||
break;
|
||||
case 'style-2':
|
||||
diyStore.editComponent.subTitle.control = true
|
||||
diyStore.editComponent.more.control = true
|
||||
diyStore.editComponent.styleName = "风格2"
|
||||
break;
|
||||
}
|
||||
diyStore.editComponent.style = selectStyle.value
|
||||
showDialog.value = false
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
defineExpose({})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.horz-blank-slider {
|
||||
.el-slider__input {
|
||||
width: 100px;
|
||||
}
|
||||
.horz-blank-slider {
|
||||
.el-slider__input {
|
||||
width: 100px;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
}</style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,460 +1,457 @@
|
||||
<template>
|
||||
<div class="flex flex-wrap">
|
||||
<div class="page-item relative bg-no-repeat ml-[20px] mr-[40px] mt-[20px] bg-[#f7f7f7] w-[300px] pt-[80px] pb-[20px]"
|
||||
:class="{ 'cursor-pointer' : !item.isDisabledPop }" v-for="(item,key) in page" :key="key">
|
||||
<p class="absolute top-[46px] left-[50%] translate-x-[-50%] text-[14px] truncate w-[130px] text-center">
|
||||
{{item.use_template.title}}</p>
|
||||
<div class="flex flex-wrap">
|
||||
<div class="page-item relative bg-no-repeat ml-[20px] mr-[40px] mt-[20px] bg-[#f7f7f7] w-[300px] pt-[80px] pb-[20px]"
|
||||
:class="{ 'cursor-pointer': !item.isDisabledPop }" v-for="(item, key) in page" :key="key">
|
||||
<p class="absolute top-[46px] left-[50%] translate-x-[-50%] text-[14px] truncate w-[130px] text-center">
|
||||
{{ item.use_template.title }}</p>
|
||||
|
||||
<div v-show="item.use_template.url" class="w-[282px] h-[493px] mx-auto">
|
||||
<iframe :id="'previewIframe_' + key" v-show="item.loadingIframe" class="w-[282px] h-[493px] mx-auto"
|
||||
:src="item.use_template.wapPreview" frameborder="0"></iframe>
|
||||
<div v-show="item.loadingDev" class="w-[282px] h-[493px] mx-auto bg-body 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>
|
||||
<div v-show="item.use_template.url" class="w-[282px] h-[493px] mx-auto">
|
||||
<iframe :id="'previewIframe_' + key" v-show="item.loadingIframe" class="w-[282px] h-[493px] mx-auto"
|
||||
:src="item.use_template.wapPreview" frameborder="0"></iframe>
|
||||
<div v-show="item.loadingDev" class="w-[282px] h-[493px] mx-auto bg-body 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>
|
||||
<div class="flex">
|
||||
<el-button type="primary" @click="saveDomain()">{{ t('confirm') }}</el-button>
|
||||
<el-button type="primary" @click="settingTips()" plain>{{ t('settingTips') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="!item.use_template.wapPreview" class="overflow-hidden w-[282px] h-[493px] mx-auto">
|
||||
<img class="max-w-full" v-if="item.use_template.cover" :src="img(item.use_template.cover)"/>
|
||||
</div>
|
||||
<div v-show="!item.use_template.wapPreview" class="overflow-hidden w-[282px] h-[493px] mx-auto">
|
||||
<img class="max-w-full" v-if="item.use_template.cover" :src="img(item.use_template.cover)" />
|
||||
</div>
|
||||
|
||||
<p class="text-[12px] text-[#999] mt-[10px] mx-auto truncate text-center w-[250px]">
|
||||
{{item.use_template.desc}}</p>
|
||||
<p class="text-[12px] text-[#999] mt-[10px] mx-auto truncate text-center w-[250px]">
|
||||
{{ item.use_template.desc }}</p>
|
||||
|
||||
<div class="item-hide absolute inset-x-0 inset-y-0 bg-black bg-opacity-50 text-center"
|
||||
:class="{ 'disabled' : item.isDisabledPop }">
|
||||
<div class="item-btn-box absolute top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] flex flex-col flex-wrap">
|
||||
<el-button @click="show(key,item)">{{ t('changePage') }}</el-button>
|
||||
<el-button @click="toDecorate(item.use_template)"
|
||||
v-show="item.use_template.mode != 'other' || item.use_template.action == 'decorate'">{{
|
||||
t('decorate') }}
|
||||
</el-button>
|
||||
<el-button @click="toPreview(item.use_template)">{{ t('preview') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-hide absolute inset-x-0 inset-y-0 bg-black bg-opacity-50 text-center"
|
||||
:class="{ 'disabled': item.isDisabledPop }">
|
||||
<div
|
||||
class="item-btn-box absolute top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] flex flex-col flex-wrap">
|
||||
<el-button @click="show(key, item)">{{ t('changePage') }}</el-button>
|
||||
<el-button @click="toDecorate(item.use_template)"
|
||||
v-show="item.use_template.mode != 'other' || item.use_template.action == 'decorate'">{{
|
||||
t('decorate') }}
|
||||
</el-button>
|
||||
<el-button @click="toPreview(item.use_template)">{{ t('preview') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="showDialog" :title="t('changeTemplate')" width="400px" :close-on-press-escape="false"
|
||||
:destroy-on-close="true" :close-on-click-modal="false">
|
||||
<el-dialog v-model="showDialog" :title="t('changeTemplate')" width="400px" :close-on-press-escape="false"
|
||||
:destroy-on-close="true" :close-on-click-modal="false">
|
||||
|
||||
<el-form :model="form" label-width="0px" v-if="formData.type">
|
||||
<el-form-item label="">
|
||||
<div>{{t('hopeBeforeTip')}}<span class="text-primary px-[5px]">{{ page[formData.type].title }}</span>{{t('hopeAfterTip')}}
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form :model="form" label-width="0px" v-if="formData.type">
|
||||
<el-form-item label="">
|
||||
<div>{{ t('hopeBeforeTip') }}<span class="text-primary px-[5px]">{{ page[formData.type].title
|
||||
}}</span>{{ t('hopeAfterTip') }}
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="">
|
||||
<el-select v-model="hope" class="w-full">
|
||||
<el-option :label="t('changeTemplateTip') + ' ' + page[formData.type].title + ' ' + t('template')"
|
||||
value="template"/>
|
||||
<el-option :label="t('changeMyPageTip') + ' ' + page[formData.type].title" value="diy"/>
|
||||
<el-option :label="t('changeOtherPageTip') + ' ' + page[formData.type].title" value="other"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="">
|
||||
<el-select v-model="hope" class="w-full">
|
||||
<el-option :label="t('changeTemplateTip') + ' ' + page[formData.type].title + ' ' + t('template')"
|
||||
value="template" />
|
||||
<el-option :label="t('changeMyPageTip') + ' ' + page[formData.type].title" value="diy" />
|
||||
<el-option :label="t('changeOtherPageTip') + ' ' + page[formData.type].title" value="other" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="" v-show="hope == 'template'">
|
||||
<el-select v-model="formData.template" class="w-full">
|
||||
<el-option v-for="(item, key) in page[formData.type].template" :label="item.title" :value="key"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="" v-show="hope == 'template'">
|
||||
<el-select v-model="formData.template" class="w-full">
|
||||
<el-option v-for="(item, key) in page[formData.type].template" :label="item.title" :value="key" :key="key"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="" v-show="hope == 'diy'">
|
||||
<el-select v-model="formData.id" class="w-full">
|
||||
<el-option v-for="(item, index) in page[formData.type].my_page" :label="item.title"
|
||||
:value="item.id"/>
|
||||
</el-select>
|
||||
<div class="mt-[10px]">
|
||||
<span class="cursor-pointer text-primary mr-[10px]" @click="toDiyList">{{ t('createPage') }}</span>
|
||||
<span class="cursor-pointer text-primary" @click="refreshMyPage">{{ t('refreshPage') }}</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="" v-show="hope == 'diy'">
|
||||
<el-select v-model="formData.id" class="w-full">
|
||||
<el-option v-for="(item, index) in page[formData.type].my_page" :label="item.title" :value="item.id" :key="index" />
|
||||
</el-select>
|
||||
<div class="mt-[10px]">
|
||||
<span class="cursor-pointer text-primary mr-[10px]" @click="toDiyList">{{ t('createPage') }}</span>
|
||||
<span class="cursor-pointer text-primary" @click="refreshMyPage">{{ t('refreshPage') }}</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="" v-show="hope == 'other'">
|
||||
<el-select v-model="formData.page" class="w-full">
|
||||
<el-option v-for="(item, index) in page[formData.type].other_page" :label="item.title"
|
||||
:value="item.page"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="" v-show="hope == 'other'">
|
||||
<el-select v-model="formData.page" class="w-full">
|
||||
<el-option v-for="(item, index) in page[formData.type].other_page" :label="item.title"
|
||||
:value="item.page" :key="index" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showDialog = false">{{ t('cancel')}}</el-button>
|
||||
<el-button type="primary" @click="save">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="save">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {reactive, ref, watch} from 'vue'
|
||||
import {t} from '@/lang'
|
||||
import {img} from '@/utils/common'
|
||||
import {useRouter} from 'vue-router'
|
||||
import {ElMessage} from 'element-plus'
|
||||
import {getDecoratePage, getDiyList, changeTemplate} from '@/app/api/diy'
|
||||
import storage from '@/utils/storage'
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { img } from '@/utils/common'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { getDecoratePage, getDiyList, changeTemplate } from '@/app/api/diy'
|
||||
import storage from '@/utils/storage'
|
||||
|
||||
const page: any = reactive({})
|
||||
const showDialog = ref(false)
|
||||
const router = useRouter()
|
||||
const hope = ref('template')
|
||||
const wapDomain = ref('')
|
||||
const page: any = reactive({})
|
||||
const showDialog = ref(false)
|
||||
const router = useRouter()
|
||||
const hope = ref('template')
|
||||
const wapDomain = ref('')
|
||||
|
||||
// 添加自定义页面
|
||||
const formData = reactive({
|
||||
type: '',
|
||||
name: '',
|
||||
mode: '',
|
||||
template: '',
|
||||
id: '',
|
||||
page: '',
|
||||
title: '',
|
||||
action: ''
|
||||
})
|
||||
// 添加自定义页面
|
||||
const formData = reactive({
|
||||
type: '',
|
||||
name: '',
|
||||
mode: '',
|
||||
template: '',
|
||||
id: '',
|
||||
page: '',
|
||||
title: '',
|
||||
action: ''
|
||||
})
|
||||
|
||||
// 初始化数据
|
||||
const refreshData = () => {
|
||||
formData.type = '';
|
||||
formData.name = '';
|
||||
formData.mode = '';
|
||||
formData.template = '';
|
||||
formData.id = '';
|
||||
formData.page = '';
|
||||
formData.title = '';
|
||||
formData.action = '';
|
||||
getDecoratePage({}).then((res => {
|
||||
for (let key in res.data) {
|
||||
page[key] = res.data[key]
|
||||
}
|
||||
|
||||
for (let key in page) {
|
||||
if (page[key].use_template.url) {
|
||||
|
||||
page[key].loadingIframe = false; // 加载iframe
|
||||
page[key].loadingDev = false; // 加载开发环境配置
|
||||
page[key].isDisabledPop = false; // 是否禁止打开遮罩层
|
||||
page[key].difference = 0; // 检测页面加载差异,小于1000毫秒,则配置wap端域名
|
||||
|
||||
wapDomain.value = page[key].domain_url.wap_domain;
|
||||
page[key].wapUrl = page[key].domain_url.wap_url;
|
||||
|
||||
if (import.meta.env.MODE == 'development') {
|
||||
// 开发模式情况下,并且未配置wap域名,则获取缓存域名
|
||||
if (wapDomain.value) {
|
||||
page[key].wapUrl = wapDomain.value + '/wap';
|
||||
setDomain(key);
|
||||
}
|
||||
if (storage.get('wap_domain')) {
|
||||
page[key].wapUrl = storage.get('wap_domain')
|
||||
setDomain(key);
|
||||
}
|
||||
}
|
||||
|
||||
setDomain(key);
|
||||
}
|
||||
}
|
||||
|
||||
}));
|
||||
}
|
||||
|
||||
refreshData();
|
||||
|
||||
// 监听 uni-app 端 是否加载完成
|
||||
window.addEventListener('message', (event) => {
|
||||
try {
|
||||
let data = JSON.parse(event.data);
|
||||
if (['appOnLaunch', 'appOnReady'].indexOf(data.type) != -1) {
|
||||
for (let key in page) {
|
||||
page[key].loadingDev = false; // 禁用开发环境配置
|
||||
page[key].loadingIframe = true; // 加载iframe
|
||||
var loadTime = new Date().getTime();
|
||||
page[key].difference = loadTime - page[key].timeIframe;
|
||||
page[key].isDisabledPop = false; // 是否禁止打开遮罩层
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
for (let key in page) {
|
||||
initLoad(key);
|
||||
}
|
||||
console.log('后台接受数据错误', e)
|
||||
// 初始化数据
|
||||
const refreshData = () => {
|
||||
formData.type = ''
|
||||
formData.name = ''
|
||||
formData.mode = ''
|
||||
formData.template = ''
|
||||
formData.id = ''
|
||||
formData.page = ''
|
||||
formData.title = ''
|
||||
formData.action = ''
|
||||
getDecoratePage({}).then(res => {
|
||||
for (const key in res.data) {
|
||||
page[key] = res.data[key]
|
||||
}
|
||||
}, false);
|
||||
|
||||
// 将数据发送到uniapp
|
||||
const postMessage = (key: string) => {
|
||||
var diyData = JSON.stringify({
|
||||
type: 'appOnReady',
|
||||
message: '加载完成'
|
||||
});
|
||||
if (window['previewIframe_' + key]) window['previewIframe_' + key].contentWindow.postMessage(diyData, '*');
|
||||
};
|
||||
for (const key in page) {
|
||||
if (page[key].use_template.url) {
|
||||
page[key].loadingIframe = false // 加载iframe
|
||||
page[key].loadingDev = false // 加载开发环境配置
|
||||
page[key].isDisabledPop = false // 是否禁止打开遮罩层
|
||||
page[key].difference = 0 // 检测页面加载差异,小于1000毫秒,则配置wap端域名
|
||||
|
||||
// 初始化加载状态
|
||||
const initLoad = (key: string) => {
|
||||
page[key].loadingDev = true;
|
||||
page[key].isDisabledPop = true;
|
||||
page[key].loadingIframe = false;
|
||||
wapDomain.value = page[key].domain_url.wap_domain
|
||||
page[key].wapUrl = page[key].domain_url.wap_url
|
||||
|
||||
if (import.meta.env.MODE == 'development') {
|
||||
// 开发模式情况下,并且未配置wap域名,则获取缓存域名
|
||||
if (wapDomain.value) {
|
||||
page[key].wapUrl = wapDomain.value + '/wap'
|
||||
setDomain(key)
|
||||
}
|
||||
if (storage.get('wap_domain')) {
|
||||
page[key].wapUrl = storage.get('wap_domain')
|
||||
setDomain(key)
|
||||
}
|
||||
}
|
||||
|
||||
setDomain(key)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
refreshData()
|
||||
|
||||
// 监听 uni-app 端 是否加载完成
|
||||
window.addEventListener('message', (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data)
|
||||
if (['appOnLaunch', 'appOnReady'].indexOf(data.type) != -1) {
|
||||
for (const key in page) {
|
||||
page[key].loadingDev = false // 禁用开发环境配置
|
||||
page[key].loadingIframe = true // 加载iframe
|
||||
const loadTime = new Date().getTime()
|
||||
page[key].difference = loadTime - page[key].timeIframe
|
||||
page[key].isDisabledPop = false // 是否禁止打开遮罩层
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
for (const key in page) {
|
||||
initLoad(key)
|
||||
}
|
||||
console.log('后台接受数据错误', e)
|
||||
}
|
||||
}, false)
|
||||
|
||||
const saveDomain = () => {
|
||||
if (wapDomain.value.trim().length == 0) {
|
||||
// 将数据发送到uniapp
|
||||
const postMessage = (key: string) => {
|
||||
const diyData = JSON.stringify({
|
||||
type: 'appOnReady',
|
||||
message: '加载完成'
|
||||
})
|
||||
if (window['previewIframe_' + key]) window['previewIframe_' + key].contentWindow.postMessage(diyData, '*')
|
||||
}
|
||||
|
||||
// 初始化加载状态
|
||||
const initLoad = (key: string) => {
|
||||
page[key].loadingDev = true
|
||||
page[key].isDisabledPop = true
|
||||
page[key].loadingIframe = false
|
||||
}
|
||||
|
||||
const saveDomain = () => {
|
||||
if (wapDomain.value.trim().length == 0) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: `${t('wapDomainPlaceholder')}`,
|
||||
})
|
||||
return
|
||||
}
|
||||
const wapUrl = wapDomain.value + '/wap'
|
||||
storage.set({ key: 'wap_domain', data: wapUrl })
|
||||
|
||||
for (const key in page) {
|
||||
if (page[key].use_template.url) {
|
||||
page[key].wapUrl = wapUrl
|
||||
setDomain(key)
|
||||
}
|
||||
}
|
||||
setTimeout(() => {
|
||||
for (const key in page) {
|
||||
if (page[key].use_template.url) {
|
||||
page[key].loadingIframe = true // 加载iframe
|
||||
page[key].loadingDev = false // 加载开发环境配置
|
||||
page[key].isDisabledPop = false // 是否禁止打开遮罩层
|
||||
}
|
||||
}
|
||||
}, 100 * 3)
|
||||
}
|
||||
|
||||
const settingTips = () => {
|
||||
window.open('https://www.kancloud.cn/niucloud/niucloud-admin-develop/3213393')
|
||||
}
|
||||
|
||||
const setDomain = (key: string) => {
|
||||
page[key].use_template.wapPreview = page[key].wapUrl + page[key].use_template.url
|
||||
page[key].timeIframe = new Date().getTime()
|
||||
postMessage(key)
|
||||
setTimeout(() => {
|
||||
if (page[key].difference == 0) initLoad(key)
|
||||
}, 1000 * 2)
|
||||
}
|
||||
|
||||
const show = (key: string, data: any) => {
|
||||
// 每次打开时赋值
|
||||
showDialog.value = true
|
||||
|
||||
hope.value = data.use_template.hope
|
||||
formData.type = key
|
||||
formData.name = data.use_template.name
|
||||
formData.mode = data.use_template.mode
|
||||
formData.action = data.use_template.action
|
||||
|
||||
if (hope.value == 'template') {
|
||||
formData.template = data.use_template.template
|
||||
} else if (hope.value == 'diy') {
|
||||
formData.id = data.use_template.id
|
||||
} else if (hope.value == 'other') {
|
||||
formData.page = data.use_template.page
|
||||
formData.title = data.use_template.title
|
||||
}
|
||||
}
|
||||
|
||||
// 跳转去装修
|
||||
const toDecorate = (data: any) => {
|
||||
const query: any = {
|
||||
back: '/site/diy/index'
|
||||
}
|
||||
if (data.id) {
|
||||
query.id = data.id
|
||||
} else if (data.name) {
|
||||
query.name = data.name
|
||||
} else if (data.url) {
|
||||
query.url = data.url
|
||||
}
|
||||
const url = router.resolve({
|
||||
path: '/decorate/edit',
|
||||
query
|
||||
})
|
||||
window.open(url.href)
|
||||
}
|
||||
|
||||
// 跳转去预览
|
||||
const toPreview = (data: any) => {
|
||||
let page = data.page
|
||||
if (data.url) {
|
||||
page = data.url
|
||||
} else if (data.id) {
|
||||
page += '?id=' + data.id
|
||||
}
|
||||
const url = router.resolve({
|
||||
path: '/preview/wap',
|
||||
query: {
|
||||
page
|
||||
}
|
||||
})
|
||||
window.open(url.href)
|
||||
}
|
||||
|
||||
// 创建微页面
|
||||
const toDiyList = (data: any) => {
|
||||
const url = router.resolve({
|
||||
path: '/diy/list'
|
||||
})
|
||||
window.open(url.href)
|
||||
}
|
||||
|
||||
// 刷新我的微页面
|
||||
const refreshMyPage = () => {
|
||||
getDiyList({ type: formData.type }).then((res) => {
|
||||
let isExist = true // 检测选择的微页面是否存在,不存在则清空
|
||||
for (let i = 0; i < res.data.length; i++) {
|
||||
if (formData.id == res.data[i].id) {
|
||||
isExist = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if (isExist) {
|
||||
formData.id = ''
|
||||
}
|
||||
page[formData.type].my_page = {}
|
||||
Object.assign(page[formData.type].my_page, res.data)
|
||||
})
|
||||
}
|
||||
|
||||
watch(
|
||||
() => hope.value,
|
||||
(newValue, oldValue) => {
|
||||
// 选择某个,清空其余
|
||||
if (newValue == 'template') {
|
||||
// 选择模板
|
||||
formData.id = ''
|
||||
formData.page = ''
|
||||
formData.action = 'decorate'
|
||||
formData.name = formData.type
|
||||
} else if (newValue == 'diy') {
|
||||
// 选择微页面
|
||||
formData.mode = 'diy'
|
||||
formData.template = ''
|
||||
formData.page = ''
|
||||
formData.action = 'decorate'
|
||||
formData.name = formData.type
|
||||
} else if (newValue == 'other') {
|
||||
// 选择其他页面
|
||||
formData.mode = 'other'
|
||||
formData.template = ''
|
||||
formData.id = ''
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// 监听模板变化
|
||||
watch(
|
||||
() => formData.template,
|
||||
(newValue, oldValue) => {
|
||||
if (newValue) {
|
||||
formData.mode = page[formData.type].template[newValue].mode
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// 监听其他页面
|
||||
watch(
|
||||
() => formData.page,
|
||||
(newValue, oldValue) => {
|
||||
if (newValue) {
|
||||
for (let i = 0; i < page[formData.type].other_page.length; i++) {
|
||||
if (page[formData.type].other_page[i].page == newValue) {
|
||||
formData.name = page[formData.type].other_page[i].name
|
||||
formData.title = page[formData.type].other_page[i].title
|
||||
formData.action = page[formData.type].other_page[i].action
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const isRepeat = ref(false)
|
||||
const save = () => {
|
||||
if (hope.value == 'template') {
|
||||
if (formData.template == '') {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: `${t('wapDomainPlaceholder')}`,
|
||||
});
|
||||
return;
|
||||
message: `${t('placeholderTemplate')}`
|
||||
})
|
||||
return
|
||||
}
|
||||
let wapUrl = wapDomain.value + '/wap';
|
||||
storage.set({key: 'wap_domain', data: wapUrl});
|
||||
|
||||
for (let key in page) {
|
||||
if (page[key].use_template.url) {
|
||||
page[key].wapUrl = wapUrl;
|
||||
setDomain(key);
|
||||
}
|
||||
} else if (hope.value == 'diy') {
|
||||
if (formData.id == '') {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: `${t('placeholderMyPage')}`
|
||||
})
|
||||
return
|
||||
}
|
||||
setTimeout(() => {
|
||||
for (let key in page) {
|
||||
if (page[key].use_template.url) {
|
||||
page[key].loadingIframe = true; // 加载iframe
|
||||
page[key].loadingDev = false; // 加载开发环境配置
|
||||
page[key].isDisabledPop = false; // 是否禁止打开遮罩层
|
||||
}
|
||||
}
|
||||
}, 100 * 3);
|
||||
}
|
||||
|
||||
const settingTips = () => {
|
||||
window.open('https://www.kancloud.cn/niucloud/niucloud-admin-develop/3213393')
|
||||
}
|
||||
|
||||
const setDomain = (key: string) => {
|
||||
page[key].use_template.wapPreview = page[key].wapUrl + page[key].use_template.url;
|
||||
page[key].timeIframe = new Date().getTime();
|
||||
postMessage(key);
|
||||
setTimeout(() => {
|
||||
if (page[key].difference == 0) initLoad(key);
|
||||
}, 1000 * 2);
|
||||
}
|
||||
|
||||
const show = (key: string, data: any) => {
|
||||
// 每次打开时赋值
|
||||
showDialog.value = true;
|
||||
|
||||
hope.value = data.use_template.hope;
|
||||
formData.type = key;
|
||||
formData.name = data.use_template.name;
|
||||
formData.mode = data.use_template.mode;
|
||||
formData.action = data.use_template.action;
|
||||
|
||||
if (hope.value == 'template') {
|
||||
formData.template = data.use_template.template;
|
||||
} else if (hope.value == 'diy') {
|
||||
formData.id = data.use_template.id;
|
||||
} else if (hope.value == 'other') {
|
||||
formData.page = data.use_template.page;
|
||||
formData.title = data.use_template.title;
|
||||
} else if (hope.value == 'other') {
|
||||
if (formData.page == '') {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: `${t('placeholderOtherPage')}`
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 跳转去装修
|
||||
const toDecorate = (data: any) => {
|
||||
let query: any = {
|
||||
back: '/site/diy/index'
|
||||
};
|
||||
if (data.id) {
|
||||
query.id = data.id;
|
||||
} else if (data.name) {
|
||||
query.name = data.name;
|
||||
} else if (data.url) {
|
||||
query.url = data.url;
|
||||
}
|
||||
let url = router.resolve({
|
||||
path: '/decorate/edit',
|
||||
query
|
||||
});
|
||||
window.open(url.href);
|
||||
}
|
||||
if (isRepeat.value) return
|
||||
isRepeat.value = true
|
||||
|
||||
// 跳转去预览
|
||||
const toPreview = (data: any) => {
|
||||
let page = data.page;
|
||||
if (data.url) {
|
||||
page = data.url;
|
||||
} else if (data.id) {
|
||||
page += '?id=' + data.id;
|
||||
}
|
||||
let url = router.resolve({
|
||||
path: '/preview/wap',
|
||||
query: {
|
||||
page
|
||||
}
|
||||
});
|
||||
window.open(url.href);
|
||||
}
|
||||
|
||||
// 创建微页面
|
||||
const toDiyList = (data: any) => {
|
||||
let url = router.resolve({
|
||||
path: '/diy/list'
|
||||
});
|
||||
window.open(url.href);
|
||||
}
|
||||
|
||||
// 刷新我的微页面
|
||||
const refreshMyPage = () => {
|
||||
getDiyList({type: formData.type}).then((res) => {
|
||||
let isExist = true; // 检测选择的微页面是否存在,不存在则清空
|
||||
for (let i = 0; i < res.data.length; i++) {
|
||||
if (formData.id == res.data[i].id) {
|
||||
isExist = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isExist) {
|
||||
formData.id = '';
|
||||
}
|
||||
page[formData.type].my_page = {};
|
||||
Object.assign(page[formData.type].my_page, res.data);
|
||||
})
|
||||
}
|
||||
|
||||
watch(
|
||||
() => hope.value,
|
||||
(newValue, oldValue) => {
|
||||
// 选择某个,清空其余
|
||||
if (newValue == 'template') {
|
||||
// 选择模板
|
||||
formData.id = '';
|
||||
formData.page = '';
|
||||
formData.action = 'decorate';
|
||||
formData.name = formData.type;
|
||||
} else if (newValue == 'diy') {
|
||||
// 选择微页面
|
||||
formData.mode = 'diy';
|
||||
formData.template = '';
|
||||
formData.page = '';
|
||||
formData.action = 'decorate';
|
||||
formData.name = formData.type;
|
||||
} else if (newValue == 'other') {
|
||||
// 选择其他页面
|
||||
formData.mode = 'other';
|
||||
formData.template = '';
|
||||
formData.id = '';
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// 监听模板变化
|
||||
watch(
|
||||
() => formData.template,
|
||||
(newValue, oldValue) => {
|
||||
if (newValue) {
|
||||
formData.mode = page[formData.type].template[newValue].mode;
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// 监听其他页面
|
||||
watch(
|
||||
() => formData.page,
|
||||
(newValue, oldValue) => {
|
||||
if (newValue) {
|
||||
for (let i = 0; i < page[formData.type].other_page.length; i++) {
|
||||
if (page[formData.type].other_page[i].page == newValue) {
|
||||
formData.name = page[formData.type].other_page[i].name;
|
||||
formData.title = page[formData.type].other_page[i].title;
|
||||
formData.action = page[formData.type].other_page[i].action;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const isRepeat = ref(false)
|
||||
const save = () => {
|
||||
if (hope.value == 'template') {
|
||||
if (formData.template == '') {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: `${t('placeholderTemplate')}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else if (hope.value == 'diy') {
|
||||
if (formData.id == '') {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: `${t('placeholderMyPage')}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else if (hope.value == 'other') {
|
||||
if (formData.page == '') {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: `${t('placeholderOtherPage')}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isRepeat.value) return
|
||||
isRepeat.value = true
|
||||
|
||||
changeTemplate({
|
||||
...formData
|
||||
}).then((res) => {
|
||||
isRepeat.value = false;
|
||||
showDialog.value = false;
|
||||
refreshData();
|
||||
})
|
||||
|
||||
}
|
||||
changeTemplate({
|
||||
...formData
|
||||
}).then((res) => {
|
||||
isRepeat.value = false
|
||||
showDialog.value = false
|
||||
refreshData()
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-item {
|
||||
.page-item {
|
||||
|
||||
background-image: url(@/app/assets/images/iphone_bg.png);
|
||||
background-color: var(--el-bg-color);
|
||||
background-size: 100%;
|
||||
background-image: url(@/app/assets/images/iphone_bg.png);
|
||||
background-color: var(--el-bg-color);
|
||||
background-size: 100%;
|
||||
|
||||
.item-hide {
|
||||
display: none;
|
||||
.item-hide {
|
||||
display: none;
|
||||
|
||||
.item-btn-box {
|
||||
.item-btn-box {
|
||||
|
||||
button {
|
||||
height: 35px;
|
||||
width: 100px;
|
||||
button {
|
||||
height: 35px;
|
||||
width: 100px;
|
||||
|
||||
& ~ button {
|
||||
margin-top: 15px;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
&~button {
|
||||
margin-top: 15px;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.item-hide:not(.disabled) {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.item-hide:not(.disabled) {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,338 +1,337 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<el-button type="primary" class="w-[100px]" @click="dialogVisible = true">
|
||||
{{ t('addDiyPage') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<el-button type="primary" class="w-[100px]" @click="dialogVisible = true">
|
||||
{{ t('addDiyPage') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="diyPageTableData.searchParam" ref="searchFormDiyPageRef">
|
||||
<el-form-item :label="t('title')" prop="title">
|
||||
<el-input v-model="diyPageTableData.searchParam.title" :placeholder="t('titlePlaceholder')"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('typeName')" prop="type">
|
||||
<el-select v-model="diyPageTableData.searchParam.type" :placeholder="t('pageTypePlaceholder')">
|
||||
<el-option :label="t('all')" value=""/>
|
||||
<el-option v-for="(item, key) in pageType" :label="item.title" :value="key"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadDiyPageList()">{{ t('search') }}</el-button>
|
||||
<el-button @click="resetForm(searchFormDiyPageRef)">{{ t('reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="diyPageTableData.searchParam" ref="searchFormDiyPageRef">
|
||||
<el-form-item :label="t('title')" prop="title">
|
||||
<el-input v-model="diyPageTableData.searchParam.title" :placeholder="t('titlePlaceholder')" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('typeName')" prop="type">
|
||||
<el-select v-model="diyPageTableData.searchParam.type" :placeholder="t('pageTypePlaceholder')">
|
||||
<el-option :label="t('all')" value="" />
|
||||
<el-option v-for="(item, key) in pageType" :label="item.title" :value="key" :key="key"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadDiyPageList()">{{ t('search') }}</el-button>
|
||||
<el-button @click="resetForm(searchFormDiyPageRef)">{{ t('reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-table :data="diyPageTableData.data" size="large" v-loading="diyPageTableData.loading">
|
||||
<el-table :data="diyPageTableData.data" size="large" v-loading="diyPageTableData.loading">
|
||||
|
||||
<template #empty>
|
||||
<span>{{ !diyPageTableData.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
<template #empty>
|
||||
<span>{{ !diyPageTableData.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
|
||||
<el-table-column prop="title" :label="t('title')" min-width="120"/>
|
||||
<el-table-column prop="type_name" :label="t('typeName')" min-width="80"/>
|
||||
<!-- <el-table-column :label="t('status')" min-width="80">-->
|
||||
<!-- <template #default="{ row }">-->
|
||||
<!-- <span v-if="row.type == 'DIY_PAGE'">-</span>-->
|
||||
<!-- <template v-else>-->
|
||||
<!-- <span v-if="row.is_default == 1" class="text-primary">{{ t('isUse') }}</span>-->
|
||||
<!-- <span v-else>{{ t('unused') }}</span>-->
|
||||
<!-- </template>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<el-table-column prop="update_time" :label="t('updateTime')" min-width="120"/>
|
||||
<el-table-column prop="title" :label="t('title')" min-width="120" />
|
||||
<el-table-column prop="type_name" :label="t('typeName')" min-width="80" />
|
||||
<!-- <el-table-column :label="t('status')" min-width="80">-->
|
||||
<!-- <template #default="{ row }">-->
|
||||
<!-- <span v-if="row.type == 'DIY_PAGE'">-</span>-->
|
||||
<!-- <template v-else>-->
|
||||
<!-- <span v-if="row.is_default == 1" class="text-primary">{{ t('isUse') }}</span>-->
|
||||
<!-- <span v-else>{{ t('unused') }}</span>-->
|
||||
<!-- </template>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<el-table-column prop="update_time" :label="t('updateTime')" min-width="120" />
|
||||
|
||||
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="toPreview(row)">{{ t('promote') }}</el-button>
|
||||
<el-button v-if="row.type == 'DIY_PAGE'" type="primary" link @click="openShare(row)">{{
|
||||
t('shareSet') }}
|
||||
</el-button>
|
||||
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
|
||||
<!-- <el-button v-if="row.type == 'DIY_PAGE' || row.is_default == 0" type="danger" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>-->
|
||||
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="toPreview(row)">{{ t('promote') }}</el-button>
|
||||
<el-button v-if="row.type == 'DIY_PAGE'" type="primary" link @click="openShare(row)">{{
|
||||
t('shareSet') }}
|
||||
</el-button>
|
||||
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
|
||||
<!-- <el-button v-if="row.type == 'DIY_PAGE' || row.is_default == 0" type="danger" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>-->
|
||||
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
<div class="mt-[16px] flex justify-end">
|
||||
<el-pagination v-model:current-page="diyPageTableData.page" v-model:page-size="diyPageTableData.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="diyPageTableData.total"
|
||||
@size-change="loadDiyPageList()" @current-change="loadDiyPageList"/>
|
||||
</div>
|
||||
</el-table>
|
||||
<div class="mt-[16px] flex justify-end">
|
||||
<el-pagination v-model:current-page="diyPageTableData.page" v-model:page-size="diyPageTableData.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="diyPageTableData.total"
|
||||
@size-change="loadDiyPageList()" @current-change="loadDiyPageList" />
|
||||
</div>
|
||||
|
||||
</el-card>
|
||||
</el-card>
|
||||
|
||||
<!--添加页面-->
|
||||
<el-dialog v-model="dialogVisible" :title="t('addPageTips')" width="25%">
|
||||
<!--添加页面-->
|
||||
<el-dialog v-model="dialogVisible" :title="t('addPageTips')" width="25%">
|
||||
|
||||
<el-form :model="formData" label-width="90px" ref="formRef" :rules="formRules">
|
||||
<el-form-item :label="t('title')" prop="title">
|
||||
<el-input v-model="formData.title" :placeholder="t('titlePlaceholder')" clearable maxlength="12"
|
||||
show-word-limit class="w-full"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('addType')" prop="type">
|
||||
<el-select v-model="formData.type" :placeholder="t('pageTypePlaceholder')" class="w-full">
|
||||
<el-option v-for="(item, key) in pageType" :label="item.title" :value="key"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('templateName')" prop="template" v-show="pageTypeData">
|
||||
<el-select v-model="formData.template" class="w-full">
|
||||
<el-option :label="t('emptyTemplate')" value=""/>
|
||||
<el-option v-for="(item, key) in pageTypeData" :label="item.title" :value="key"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form :model="formData" label-width="90px" ref="formRef" :rules="formRules">
|
||||
<el-form-item :label="t('title')" prop="title">
|
||||
<el-input v-model="formData.title" :placeholder="t('titlePlaceholder')" clearable maxlength="12"
|
||||
show-word-limit class="w-full" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('addType')" prop="type">
|
||||
<el-select v-model="formData.type" :placeholder="t('pageTypePlaceholder')" class="w-full">
|
||||
<el-option v-for="(item, key) in pageType" :label="item.title" :value="key" :key="key"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('templateName')" prop="template" v-show="pageTypeData">
|
||||
<el-select v-model="formData.template" class="w-full">
|
||||
<el-option :label="t('emptyTemplate')" value="" />
|
||||
<el-option v-for="(item, key) in pageTypeData" :label="item.title" :value="key" :key="key"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="addEvent(formRef)">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 分享设置-->
|
||||
<el-dialog v-model="shareDialogVisible" :title="t('shareSet')" width="30%">
|
||||
<el-tabs v-model="tabShareType">
|
||||
<el-tab-pane :label="t('wechat')" name="wechat"></el-tab-pane>
|
||||
<el-tab-pane :label="t('weapp')" name="weapp"></el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-form :model="shareFormData[tabShareType]" label-width="90px" ref="shareFormRef" :rules="shareFormRules">
|
||||
<el-form-item :label="t('sharePage')">
|
||||
<span>{{ sharePage }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('shareTitle')" prop="title">
|
||||
<el-input v-model="shareFormData[tabShareType].title" :placeholder="t('shareTitlePlaceholder')"
|
||||
clearable maxlength="30" show-word-limit/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('shareDesc')" prop="desc" v-if="tabShareType == 'wechat'">
|
||||
<el-input v-model="shareFormData[tabShareType].desc" :placeholder="t('shareDescPlaceholder')"
|
||||
type="textarea" rows="4" clearable maxlength="100" show-word-limit/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('shareImageUrl')" prop="url">
|
||||
<upload-image v-model="shareFormData[tabShareType].url" :limit="1"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 分享设置-->
|
||||
<el-dialog v-model="shareDialogVisible" :title="t('shareSet')" width="30%">
|
||||
<el-tabs v-model="tabShareType">
|
||||
<el-tab-pane :label="t('wechat')" name="wechat"></el-tab-pane>
|
||||
<el-tab-pane :label="t('weapp')" name="weapp"></el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-form :model="shareFormData[tabShareType]" label-width="90px" ref="shareFormRef" :rules="shareFormRules">
|
||||
<el-form-item :label="t('sharePage')">
|
||||
<span>{{ sharePage }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('shareTitle')" prop="title">
|
||||
<el-input v-model="shareFormData[tabShareType].title" :placeholder="t('shareTitlePlaceholder')"
|
||||
clearable maxlength="30" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('shareDesc')" prop="desc" v-if="tabShareType == 'wechat'">
|
||||
<el-input v-model="shareFormData[tabShareType].desc" :placeholder="t('shareDescPlaceholder')"
|
||||
type="textarea" rows="4" clearable maxlength="100" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('shareImageUrl')" prop="url">
|
||||
<upload-image v-model="shareFormData[tabShareType].url" :limit="1" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="shareDialogVisible = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="shareEvent(shareFormRef)">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {reactive, ref, computed} from 'vue'
|
||||
import {t} from '@/lang'
|
||||
import {getDiyPageList, deleteDiyPage, getDiyTemplate, editDiyPageShare} from '@/app/api/diy'
|
||||
import {ElMessageBox, FormInstance} from 'element-plus'
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import {getUrl} from '@/app/api/sys'
|
||||
import { reactive, ref, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getDiyPageList, deleteDiyPage, getDiyTemplate, editDiyPageShare } from '@/app/api/diy'
|
||||
import { ElMessageBox, FormInstance } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { getUrl } from '@/app/api/sys'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title;
|
||||
const pageType: any = reactive({}) // 页面模板类型
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
const pageType: any = reactive({}) // 页面模板类型
|
||||
|
||||
// 添加自定义页面
|
||||
const formData = reactive({
|
||||
// 添加自定义页面
|
||||
const formData = reactive({
|
||||
title: '',
|
||||
type: '',
|
||||
template: ''
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = computed(() => {
|
||||
return {
|
||||
title: [
|
||||
{ required: true, message: t('titlePlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
type: [
|
||||
{ required: true, message: t('pageTypePlaceholder'), trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
const pageTypeData = computed(() => {
|
||||
let data: any = ''
|
||||
formData.template = ''
|
||||
if (formData.type) {
|
||||
data = pageType[formData.type].template
|
||||
}
|
||||
return data
|
||||
})
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
const dialogVisible = ref(false)
|
||||
const addEvent = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
dialogVisible.value = false
|
||||
let url = `/decorate/edit?type=${formData.type}&title=${formData.title}`
|
||||
if (formData.template) url += `&template=${formData.template}`
|
||||
router.push(url)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const wapDomain = ref('')
|
||||
const getDomain = async () => {
|
||||
wapDomain.value = (await getUrl()).data.wap_url
|
||||
}
|
||||
getDomain()
|
||||
|
||||
// 获取自定义页面模板
|
||||
getDiyTemplate({ mode: '' }).then(res => {
|
||||
for (const key in res.data) {
|
||||
pageType[key] = res.data[key]
|
||||
}
|
||||
})
|
||||
|
||||
const diyPageTableData: any = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam: {
|
||||
title: '',
|
||||
type: '',
|
||||
template: ''
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = computed(() => {
|
||||
return {
|
||||
title: [
|
||||
{required: true, message: t('titlePlaceholder'), trigger: 'blur'},
|
||||
],
|
||||
type: [
|
||||
{required: true, message: t('pageTypePlaceholder'), trigger: 'blur'},
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
const pageTypeData = computed(() => {
|
||||
let data: any = '';
|
||||
formData.template = '';
|
||||
if (formData.type) {
|
||||
data = pageType[formData.type].template;
|
||||
}
|
||||
return data;
|
||||
})
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
const dialogVisible = ref(false)
|
||||
const addEvent = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
dialogVisible.value = false;
|
||||
let url = `/decorate/edit?type=${formData.type}&title=${formData.title}`;
|
||||
if (formData.template) url += `&template=${formData.template}`;
|
||||
router.push(url);
|
||||
}
|
||||
})
|
||||
mode: ''
|
||||
}
|
||||
})
|
||||
|
||||
const wapDomain = ref('')
|
||||
const getDomain = async () => {
|
||||
wapDomain.value = (await getUrl()).data.wap_url;
|
||||
};
|
||||
getDomain();
|
||||
const searchFormDiyPageRef = ref<FormInstance>()
|
||||
|
||||
// 获取自定义页面模板
|
||||
getDiyTemplate({mode: ''}).then(res => {
|
||||
for (let key in res.data) {
|
||||
pageType[key] = res.data[key]
|
||||
}
|
||||
// 获取自定义页面列表
|
||||
const loadDiyPageList = (page: number = 1) => {
|
||||
diyPageTableData.loading = true
|
||||
diyPageTableData.page = page
|
||||
|
||||
getDiyPageList({
|
||||
page: diyPageTableData.page,
|
||||
limit: diyPageTableData.limit,
|
||||
...diyPageTableData.searchParam
|
||||
}).then(res => {
|
||||
diyPageTableData.loading = false
|
||||
diyPageTableData.data = res.data.data
|
||||
diyPageTableData.total = res.data.total
|
||||
}).catch(() => {
|
||||
diyPageTableData.loading = false
|
||||
})
|
||||
}
|
||||
|
||||
let diyPageTableData: any = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam: {
|
||||
"title": "",
|
||||
"type": '',
|
||||
'mode': ''
|
||||
}
|
||||
loadDiyPageList()
|
||||
|
||||
// 编辑自定义页面
|
||||
const editEvent = (data: any) => {
|
||||
const url = router.resolve({
|
||||
path: '/decorate/edit',
|
||||
query: { id: data.id }
|
||||
})
|
||||
window.open(url.href)
|
||||
}
|
||||
|
||||
const searchFormDiyPageRef = ref<FormInstance>()
|
||||
|
||||
// 获取自定义页面列表
|
||||
const loadDiyPageList = (page: number = 1) => {
|
||||
diyPageTableData.loading = true
|
||||
diyPageTableData.page = page
|
||||
|
||||
getDiyPageList({
|
||||
page: diyPageTableData.page,
|
||||
limit: diyPageTableData.limit,
|
||||
...diyPageTableData.searchParam
|
||||
}).then(res => {
|
||||
diyPageTableData.loading = false
|
||||
diyPageTableData.data = res.data.data
|
||||
diyPageTableData.total = res.data.total
|
||||
// 删除自定义页面
|
||||
const deleteEvent = (id: number) => {
|
||||
ElMessageBox.confirm(t('diyPageDeleteTips'), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
deleteDiyPage(id).then(() => {
|
||||
loadDiyPageList()
|
||||
}).catch(() => {
|
||||
diyPageTableData.loading = false
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 跳转去预览
|
||||
const toPreview = (data: any) => {
|
||||
const url = router.resolve({
|
||||
path: '/preview/wap',
|
||||
query: {
|
||||
page: data.type_page + '?id=' + data.id
|
||||
}
|
||||
})
|
||||
window.open(url.href)
|
||||
}
|
||||
|
||||
const tabShareType = ref('wechat')
|
||||
const sharePage = ref('')
|
||||
const shareFormId = ref(0)
|
||||
const shareFormData = reactive({
|
||||
wechat: {
|
||||
title: '',
|
||||
desc: '',
|
||||
url: ''
|
||||
},
|
||||
weapp: {
|
||||
title: '',
|
||||
url: ''
|
||||
}
|
||||
})
|
||||
const shareDialogVisible = ref(false)
|
||||
const shareFormRules = computed(() => {
|
||||
return {}
|
||||
})
|
||||
|
||||
const shareFormRef = ref<FormInstance>()
|
||||
const openShare = async (row: any) => {
|
||||
shareFormId.value = row.id
|
||||
sharePage.value = row.title
|
||||
const share = row.share ? JSON.parse(row.share) : {
|
||||
wechat: { title: '', desc: '', url: '' },
|
||||
weapp: { title: '', url: '' }
|
||||
}
|
||||
if (share) {
|
||||
shareFormData.wechat = share.wechat
|
||||
shareFormData.weapp = share.weapp
|
||||
}
|
||||
|
||||
loadDiyPageList()
|
||||
shareDialogVisible.value = true
|
||||
}
|
||||
|
||||
// 编辑自定义页面
|
||||
const editEvent = (data: any) => {
|
||||
let url = router.resolve({
|
||||
path: '/decorate/edit',
|
||||
query: {id: data.id}
|
||||
});
|
||||
window.open(url.href);
|
||||
}
|
||||
const shareEvent = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
|
||||
// 删除自定义页面
|
||||
const deleteEvent = (id: number) => {
|
||||
ElMessageBox.confirm(t('diyPageDeleteTips'), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning',
|
||||
}
|
||||
).then(() => {
|
||||
deleteDiyPage(id).then(() => {
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
editDiyPageShare({
|
||||
id: shareFormId.value,
|
||||
share: JSON.stringify(shareFormData)
|
||||
}).then(() => {
|
||||
loadDiyPageList()
|
||||
shareDialogVisible.value = false
|
||||
}).catch(() => {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 跳转去预览
|
||||
const toPreview = (data: any) => {
|
||||
let url = router.resolve({
|
||||
path: '/preview/wap',
|
||||
query: {
|
||||
page: data.type_page + '?id=' + data.id
|
||||
}
|
||||
});
|
||||
window.open(url.href);
|
||||
}
|
||||
|
||||
const tabShareType = ref('wechat')
|
||||
const sharePage = ref('')
|
||||
const shareFormId = ref(0)
|
||||
const shareFormData = reactive({
|
||||
wechat: {
|
||||
title: '',
|
||||
desc: '',
|
||||
url: ''
|
||||
},
|
||||
weapp: {
|
||||
title: '',
|
||||
url: ''
|
||||
}
|
||||
})
|
||||
const shareDialogVisible = ref(false)
|
||||
const shareFormRules = computed(() => {
|
||||
return {}
|
||||
})
|
||||
}
|
||||
|
||||
const shareFormRef = ref<FormInstance>()
|
||||
const openShare = async (row: any) => {
|
||||
shareFormId.value = row.id;
|
||||
sharePage.value = row.title;
|
||||
let share = row.share ? JSON.parse(row.share) : {
|
||||
wechat: {title: '', desc: '', url: ''},
|
||||
weapp: {title: '', url: ''}
|
||||
};
|
||||
if (share) {
|
||||
shareFormData.wechat = share.wechat;
|
||||
shareFormData.weapp = share.weapp;
|
||||
}
|
||||
|
||||
shareDialogVisible.value = true;
|
||||
}
|
||||
|
||||
const shareEvent = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
editDiyPageShare({
|
||||
id: shareFormId.value,
|
||||
share: JSON.stringify(shareFormData),
|
||||
}).then(() => {
|
||||
loadDiyPageList()
|
||||
shareDialogVisible.value = false;
|
||||
}).catch(() => {
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields();
|
||||
loadDiyPageList();
|
||||
}
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields()
|
||||
loadDiyPageList()
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.copy {
|
||||
background: var(--el-color-primary) !important;
|
||||
color: var(--el-color-white) !important;
|
||||
}
|
||||
.copy {
|
||||
background: var(--el-color-primary) !important;
|
||||
color: var(--el-color-white) !important;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
@ -53,140 +53,140 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {ref, reactive, watch} from 'vue'
|
||||
import {t} from '@/lang'
|
||||
import {useRoute} from 'vue-router'
|
||||
import {getWeappConfig} from '@/app/api/weapp'
|
||||
import {getUrl} from '@/app/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'
|
||||
import {getPreviewData} from '@/app/api/diy'
|
||||
import { ref, reactive, watch } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { getWeappConfig } from '@/app/api/weapp'
|
||||
import { getUrl } from '@/app/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'
|
||||
import { getPreviewData } from '@/app/api/diy'
|
||||
|
||||
const wapUrl = ref('')
|
||||
const wapDomain = ref('')
|
||||
const wapImage = ref('')
|
||||
const wapPreview = ref('')
|
||||
const wapUrl = ref('')
|
||||
const wapDomain = ref('')
|
||||
const wapImage = ref('')
|
||||
const wapPreview = ref('')
|
||||
|
||||
const loading = ref(false)
|
||||
const loadingIframe = ref(false) // 加载iframe
|
||||
const loadingDev = ref(false) // 加载开发环境配置
|
||||
const timeFrame = ref(0)
|
||||
const loading = ref(false)
|
||||
const loadingIframe = ref(false) // 加载iframe
|
||||
const loadingDev = ref(false) // 加载开发环境配置
|
||||
const timeFrame = ref(0)
|
||||
|
||||
var time = new Date().getTime();
|
||||
const route = useRoute();
|
||||
route.query.id = route.query.id || 0;
|
||||
route.query.name = route.query.name || '';
|
||||
let time = new Date().getTime()
|
||||
const route = useRoute()
|
||||
route.query.id = route.query.id || 0
|
||||
route.query.name = route.query.name || ''
|
||||
|
||||
getUrl().then((res: any) => {
|
||||
wapDomain.value = res.data.wap_domain;
|
||||
wapUrl.value = res.data.wap_url;
|
||||
setDomain();
|
||||
getUrl().then((res: any) => {
|
||||
wapDomain.value = res.data.wap_domain
|
||||
wapUrl.value = res.data.wap_url
|
||||
setDomain()
|
||||
|
||||
// 生产模式禁止
|
||||
if (import.meta.env.MODE == 'production') return;
|
||||
// 生产模式禁止
|
||||
if (import.meta.env.MODE == 'production') return
|
||||
|
||||
// env文件配置过wap域名
|
||||
if (wapDomain.value) return;
|
||||
// env文件配置过wap域名
|
||||
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 = () => {
|
||||
if (wapDomain.value.trim().length == 0) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: `${t('wapDomainPlaceholder')}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
wapUrl.value = wapDomain.value + '/wap';
|
||||
setDomain();
|
||||
storage.set({key: 'wap_domain', data: wapUrl.value});
|
||||
loadingIframe.value = true;
|
||||
loadingDev.value = false;
|
||||
let wap_domain_storage = storage.get('wap_domain')
|
||||
if (wap_domain_storage) {
|
||||
wapUrl.value = wap_domain_storage
|
||||
setDomain()
|
||||
return
|
||||
}
|
||||
|
||||
const setDomain = () => {
|
||||
getPreviewData({
|
||||
id: route.query.id,
|
||||
name: route.query.name,
|
||||
}).then((res: any) => {
|
||||
let data = res.data;
|
||||
wapPreview.value = `${wapUrl.value}/${data.page}`;
|
||||
timeFrame.value = new Date().getTime()
|
||||
})
|
||||
|
||||
// 开发模式增加站点id
|
||||
if (import.meta.env.MODE == 'development') {
|
||||
let siteId = storage.get('siteId') || 0;
|
||||
wapPreview.value += `&site_id=${siteId}`;
|
||||
}
|
||||
QRCode.toDataURL(wapPreview.value, {errorCorrectionLevel: 'L', margin: 0, width: 100}).then(url => {
|
||||
wapImage.value = url
|
||||
})
|
||||
const save = () => {
|
||||
if (wapDomain.value.trim().length == 0) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: `${t('wapDomainPlaceholder')}`
|
||||
})
|
||||
return
|
||||
}
|
||||
wapUrl.value = wapDomain.value + '/wap'
|
||||
setDomain()
|
||||
storage.set({ key: 'wap_domain', data: wapUrl.value })
|
||||
loadingIframe.value = true
|
||||
loadingDev.value = false
|
||||
}
|
||||
|
||||
const setDomain = () => {
|
||||
getPreviewData({
|
||||
id: route.query.id,
|
||||
name: route.query.name
|
||||
}).then((res: any) => {
|
||||
const data = res.data
|
||||
wapPreview.value = `${wapUrl.value}/${data.page}`
|
||||
|
||||
// 开发模式增加站点id
|
||||
if (import.meta.env.MODE == 'development') {
|
||||
const siteId = storage.get('siteId') || 0
|
||||
wapPreview.value += `&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
|
||||
const loadTime = new Date().getTime()
|
||||
const difference = loadTime - timeFrame.value
|
||||
// 检测页面加载差异,小于1000毫秒,则配置wap端域名
|
||||
if (difference < 1000) {
|
||||
loadingDev.value = true
|
||||
loadingIframe.value = false
|
||||
wapPreview.value = ''
|
||||
wapImage.value = ''
|
||||
} else {
|
||||
loadingDev.value = false
|
||||
loadingIframe.value = true
|
||||
}
|
||||
loading.value = true
|
||||
}
|
||||
|
||||
const weappConfig = reactive({
|
||||
qr_code: ''
|
||||
})
|
||||
|
||||
const previewMode = ref('weapp')
|
||||
|
||||
// 获取微信配置
|
||||
getWeappConfig().then((res: any) => {
|
||||
if (res.code == 1) {
|
||||
const data = res.data
|
||||
weappConfig.qr_code = data.qr_code
|
||||
}
|
||||
})
|
||||
|
||||
// 复制
|
||||
const { copy, isSupported, copied } = useClipboard()
|
||||
const copyEvent = (text: string) => {
|
||||
if (!isSupported.value) {
|
||||
ElMessage({
|
||||
message: t('notSupportCopy'),
|
||||
type: 'warning'
|
||||
})
|
||||
}
|
||||
copy(text)
|
||||
}
|
||||
|
||||
// 监听iframe加载事件
|
||||
const loadIframe = () => {
|
||||
if (!wapPreview.value) return;
|
||||
var loadTime = new Date().getTime();
|
||||
var difference = loadTime - timeFrame.value;
|
||||
// 检测页面加载差异,小于1000毫秒,则配置wap端域名
|
||||
if (difference < 1000) {
|
||||
loadingDev.value = true;
|
||||
loadingIframe.value = false;
|
||||
wapPreview.value = '';
|
||||
wapImage.value = '';
|
||||
} else {
|
||||
loadingDev.value = false;
|
||||
loadingIframe.value = true;
|
||||
}
|
||||
loading.value = true
|
||||
watch(copied, () => {
|
||||
if (copied.value) {
|
||||
ElMessage({
|
||||
message: t('copySuccess'),
|
||||
type: 'success'
|
||||
})
|
||||
}
|
||||
|
||||
const weappConfig = reactive({
|
||||
qr_code: ''
|
||||
})
|
||||
|
||||
const previewMode = ref('weapp')
|
||||
|
||||
// 获取微信配置
|
||||
getWeappConfig().then((res: any) => {
|
||||
if (res.code == 1) {
|
||||
let data = res.data;
|
||||
weappConfig.qr_code = data.qr_code;
|
||||
}
|
||||
})
|
||||
|
||||
// 复制
|
||||
const {copy, isSupported, copied} = useClipboard()
|
||||
const copyEvent = (text: string) => {
|
||||
if (!isSupported.value) {
|
||||
ElMessage({
|
||||
message: t('notSupportCopy'),
|
||||
type: 'warning'
|
||||
})
|
||||
}
|
||||
copy(text)
|
||||
}
|
||||
|
||||
watch(copied, () => {
|
||||
if (copied.value) {
|
||||
ElMessage({
|
||||
message: t('copySuccess'),
|
||||
type: 'success'
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
|
||||
<el-table :data="diyRouteTableData.data" size="large" v-loading="diyRouteTableData.loading">
|
||||
<template #empty>
|
||||
<span>{{ !diyRouteTableData.loading ? t('emptyData') : '' }}</span>
|
||||
@ -83,7 +83,7 @@
|
||||
import { reactive, ref, watch, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getDiyTemplate, getDiyRouteList, getDiyRouteInfo, editDiyRouteShare } from '@/app/api/diy'
|
||||
import { ElMessage, FormInstance, ElMessageBox } from 'element-plus'
|
||||
import { ElMessage, FormInstance } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
import { getUrl } from '@/app/api/sys'
|
||||
@ -91,28 +91,28 @@ import { getUrl } from '@/app/api/sys'
|
||||
const pageTemplate: any = reactive({})
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title;
|
||||
const pageName = route.meta.title
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
const dialogVisible = ref(false)
|
||||
|
||||
let diyRouteTableData = reactive({
|
||||
const diyRouteTableData = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam: {
|
||||
"title": "",
|
||||
title: ''
|
||||
}
|
||||
})
|
||||
|
||||
const wapDomain = ref('')
|
||||
const getDomain = async () => {
|
||||
wapDomain.value = (await getUrl()).data.wap_url;
|
||||
};
|
||||
wapDomain.value = (await getUrl()).data.wap_url
|
||||
}
|
||||
|
||||
getDomain();
|
||||
getDomain()
|
||||
|
||||
/**
|
||||
* 获取自定义路由列表
|
||||
@ -126,15 +126,15 @@ const loadDiyRouteList = (page: number = 1) => {
|
||||
limit: diyRouteTableData.limit,
|
||||
...diyRouteTableData.searchParam
|
||||
}).then(res => {
|
||||
diyRouteTableData.loading = false;
|
||||
diyRouteTableData.loading = false
|
||||
|
||||
let len = Math.ceil(res.data.length / diyRouteTableData.limit);
|
||||
let data = JSON.parse(JSON.stringify(res.data));
|
||||
let dataGather = [];
|
||||
for(var i = 0; i < len; i++){
|
||||
dataGather[i] = data.splice(0, diyRouteTableData.limit);
|
||||
const len = Math.ceil(res.data.length / diyRouteTableData.limit)
|
||||
const data = JSON.parse(JSON.stringify(res.data))
|
||||
const dataGather = []
|
||||
for (let i = 0; i < len; i++) {
|
||||
dataGather[i] = data.splice(0, diyRouteTableData.limit)
|
||||
}
|
||||
diyRouteTableData.data = dataGather[diyRouteTableData.page-1];
|
||||
diyRouteTableData.data = dataGather[diyRouteTableData.page - 1]
|
||||
|
||||
diyRouteTableData.total = res.data.length
|
||||
}).catch(() => {
|
||||
@ -145,7 +145,7 @@ loadDiyRouteList()
|
||||
|
||||
// 获取自定义页面模板
|
||||
getDiyTemplate({}).then(res => {
|
||||
for (let key in res.data) {
|
||||
for (const key in res.data) {
|
||||
pageTemplate[key] = res.data[key]
|
||||
}
|
||||
})
|
||||
@ -204,12 +204,12 @@ const shareFormRules = computed(() => {
|
||||
const shareFormRef = ref<FormInstance>()
|
||||
const openShare = async (row: any) => {
|
||||
// 基础页面
|
||||
let info = (await getDiyRouteInfo({
|
||||
const info = (await getDiyRouteInfo({
|
||||
name: row.name
|
||||
})).data;
|
||||
})).data
|
||||
|
||||
if (info.title) {
|
||||
row.id = info.id;
|
||||
row.id = info.id
|
||||
row.title = info.title
|
||||
row.name = info.name
|
||||
row.page = info.page
|
||||
@ -224,18 +224,18 @@ const openShare = async (row: any) => {
|
||||
diyRouteData.is_share = row.is_share
|
||||
diyRouteData.sort = row.sort
|
||||
|
||||
shareFormId.value = row.id;
|
||||
sharePage.value = row.title;
|
||||
let share = row.share ? JSON.parse(row.share) : {
|
||||
wechat: {title: '', desc: '', url: ''},
|
||||
weapp: {title: '', url: ''}
|
||||
};
|
||||
shareFormId.value = row.id
|
||||
sharePage.value = row.title
|
||||
const share = row.share ? JSON.parse(row.share) : {
|
||||
wechat: { title: '', desc: '', url: '' },
|
||||
weapp: { title: '', url: '' }
|
||||
}
|
||||
if (share) {
|
||||
shareFormData.wechat = share.wechat;
|
||||
shareFormData.weapp = share.weapp;
|
||||
shareFormData.wechat = share.wechat
|
||||
shareFormData.weapp = share.weapp
|
||||
}
|
||||
|
||||
shareDialogVisible.value = true;
|
||||
shareDialogVisible.value = true
|
||||
}
|
||||
|
||||
const shareEvent = async (formEl: FormInstance | undefined) => {
|
||||
@ -243,24 +243,24 @@ const shareEvent = async (formEl: FormInstance | undefined) => {
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let save = editDiyRouteShare
|
||||
const save = editDiyRouteShare
|
||||
save({
|
||||
id: shareFormId.value,
|
||||
share: JSON.stringify(shareFormData),
|
||||
...diyRouteData
|
||||
}).then(() => {
|
||||
loadDiyRouteList()
|
||||
shareDialogVisible.value = false;
|
||||
shareDialogVisible.value = false
|
||||
}).catch(() => {
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const resetForm = (formEl: FormInstance | undefined)=>{
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields();
|
||||
loadDiyRouteList();
|
||||
formEl.resetFields()
|
||||
loadDiyRouteList()
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -270,4 +270,4 @@ const resetForm = (formEl: FormInstance | undefined)=>{
|
||||
color: var(--el-color-white) !important;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -2,18 +2,18 @@
|
||||
<div class="error">
|
||||
<div class="flex items-center">
|
||||
<slot name="content">
|
||||
<div>
|
||||
<img class="w-[300px]" src="@/app/assets/images/error.png"/>
|
||||
</div>
|
||||
<div>
|
||||
<img class="w-[300px]" src="@/app/assets/images/error.png" />
|
||||
</div>
|
||||
</slot>
|
||||
<div class="text-left ml-[100px]">
|
||||
<div class="error-text text-[28px] font-bold">404错误!</div>
|
||||
<div class="text-[#222] text-[20px] mt-[15px]">哎呀,出错了!您访问的页面不存在...</div>
|
||||
<div class="text-[#c4c2c2] text-[12px] mt-[5px]">尝试检查URL的错误,然后点击浏览器刷新按钮。</div>
|
||||
<div class="mt-[40px]">
|
||||
<el-button class="bottom" @click="router.go(-1)">{{ second }} 秒后返回上一页</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-left ml-[100px]">
|
||||
<div class="error-text text-[28px] font-bold">404错误!</div>
|
||||
<div class="text-[#222] text-[20px] mt-[15px]">哎呀,出错了!您访问的页面不存在...</div>
|
||||
<div class="text-[#c4c2c2] text-[12px] mt-[5px]">尝试检查URL的错误,然后点击浏览器刷新按钮。</div>
|
||||
<div class="mt-[40px]">
|
||||
<el-button class="bottom" @click="router.go(-1)">{{ second }} 秒后返回上一页</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@ -53,13 +53,15 @@ onUnmounted(() => {
|
||||
@apply text-primary;
|
||||
font-size: 150px;
|
||||
}
|
||||
.error-text {
|
||||
color:#0e77fd;
|
||||
}
|
||||
|
||||
.error-text {
|
||||
color: #0e77fd;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
width: 176px;
|
||||
background-color: #0e77fd;
|
||||
color:#fff
|
||||
background-color: #0e77fd;
|
||||
color: #fff
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,230 +1,196 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none base-bg !px-[35px]" shadow="never">
|
||||
<el-row class="flex">
|
||||
<el-col :span="8" class="min-w-[100px]">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="accountStat.pay ? Number.parseFloat(accountStat.pay).toFixed(2) : '0.00'"></el-statistic>
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-[#666]">
|
||||
<span>{{ t('totalPay') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none base-bg !px-[35px]" shadow="never">
|
||||
<el-row class="flex">
|
||||
<el-col :span="8" class="min-w-[100px]">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="accountStat.refund ? Number.parseFloat(accountStat.refund).toFixed(2) : '0.00'"></el-statistic>
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-[#666]">
|
||||
<span>{{ t('totalRefund') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8" class="min-w-[100px]">
|
||||
<el-statistic
|
||||
:value="accountStat.pay ? accountStat.pay.toFixed(2) : '0.00'"></el-statistic>
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-[#666]">
|
||||
<span>{{ t('totalPay') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8" class="min-w-[100px]">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="accountStat.transfer ? Number.parseFloat(accountStat.transfer).toFixed(2) : '0.00'"></el-statistic>
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-[#666]">
|
||||
<span>{{ t('totalTransfer') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-statistic
|
||||
:value="accountStat.refund ? accountStat.refund.toFixed(2) : '0.00'"></el-statistic>
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-[#666]">
|
||||
<span>{{ t('totalRefund') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8" class="min-w-[100px]">
|
||||
<div class="statistic-card">
|
||||
<el-statistic
|
||||
:value="accountStat.transfer ? accountStat.transfer.toFixed(2) : '0.00'"></el-statistic>
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-[#666]">
|
||||
<span>{{ t('totalTransfer') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="siteAccountLogTable.searchParam" ref="searchFormRef">
|
||||
<el-form-item :label="t('type')" class="items-center">
|
||||
<el-select v-model="siteAccountLogTable.searchParam.type" class="m-2" :placeholder="t('accountType')" >
|
||||
<el-option
|
||||
v-for="(item, index) in accountType"
|
||||
:key="index"
|
||||
:label="item"
|
||||
:value="index"
|
||||
/>
|
||||
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="siteAccountLogTable.searchParam" ref="searchFormRef">
|
||||
<el-form-item :label="t('type')" class="items-center">
|
||||
<el-select v-model="siteAccountLogTable.searchParam.type" class="m-2"
|
||||
:placeholder="t('accountType')">
|
||||
<el-option v-for="(item, index) in accountType" :key="index" :label="item" :value="index" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('tradeNo')" prop="trade_no">
|
||||
<el-input v-model="siteAccountLogTable.searchParam.trade_no" :placeholder="t('tradeNoPlaceholder')" />
|
||||
</el-form-item>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('tradeNo')" prop="trade_no">
|
||||
<el-input v-model="siteAccountLogTable.searchParam.trade_no"
|
||||
:placeholder="t('tradeNoPlaceholder')" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('createTime')" prop="create_time">
|
||||
<el-date-picker v-model="siteAccountLogTable.searchParam.create_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
<el-date-picker v-model="siteAccountLogTable.searchParam.create_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadSiteAccountLogList()">{{ t('search') }}</el-button>
|
||||
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadSiteAccountLogList()">{{ t('search') }}</el-button>
|
||||
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<div class="mt-[10px]">
|
||||
<el-table :data="siteAccountLogTable.data" size="large" v-loading="siteAccountLogTable.loading">
|
||||
<template #empty>
|
||||
<span>{{ !siteAccountLogTable.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
<el-table-column prop="trade_no" :label="t('tradeNo')" min-width="120" />
|
||||
<el-table-column prop= "type_name" :label="t('type')" min-width="120" />
|
||||
<el-table-column prop="money" :label="t('money')" min-width="120" align="right" />
|
||||
<el-table-column :label="t('createTime')" min-width="150" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.create_time || '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<div class="mt-[10px]">
|
||||
<el-table :data="siteAccountLogTable.data" size="large" v-loading="siteAccountLogTable.loading">
|
||||
<template #empty>
|
||||
<span>{{ !siteAccountLogTable.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
<el-table-column prop="trade_no" :label="t('tradeNo')" min-width="120" />
|
||||
<el-table-column prop="type_name" :label="t('type')" min-width="120" />
|
||||
<el-table-column prop="money" :label="t('money')" min-width="120" align="right" />
|
||||
<el-table-column :label="t('createTime')" min-width="150" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.create_time || '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="detailEvent(row)">{{ t('detail') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="detailEvent(row)">{{ t('detail') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
<div class="mt-[16px] flex justify-end">
|
||||
<el-pagination v-model:current-page="siteAccountLogTable.page" v-model:page-size="siteAccountLogTable.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="siteAccountLogTable.total"
|
||||
@size-change="loadSiteAccountLogList()" @current-change="loadSiteAccountLogList" />
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-table>
|
||||
<div class="mt-[16px] flex justify-end">
|
||||
<el-pagination v-model:current-page="siteAccountLogTable.page"
|
||||
v-model:page-size="siteAccountLogTable.limit" layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="siteAccountLogTable.total" @size-change="loadSiteAccountLogList()"
|
||||
@current-change="loadSiteAccountLogList" />
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-dialog v-model="showDialog" :title="t('accountDetail')" width="550px" :destroy-on-close="true">
|
||||
<el-form :model="formData" label-width="110px" ref="formRef" class="page-form">
|
||||
<el-form :model="formData" label-width="110px" ref="formRef" class="page-form">
|
||||
|
||||
<el-form-item :label="t('tradeNo')" >
|
||||
<div class="input-width"> {{ formData.trade_no }} </div>
|
||||
<el-form-item :label="t('tradeNo')">
|
||||
<div class="input-width"> {{ formData.trade_no }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('type')" >
|
||||
<div class="input-width"> {{ formData.type_name }} </div>
|
||||
<el-form-item :label="t('type')">
|
||||
<div class="input-width"> {{ formData.type_name }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('money')" >
|
||||
<div class="input-width"> {{ formData.money }} </div>
|
||||
<el-form-item :label="t('money')">
|
||||
<div class="input-width"> {{ formData.money }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('createTime')" >
|
||||
<div class="input-width"> {{ formData.create_time }} </div>
|
||||
<el-form-item :label="t('createTime')">
|
||||
<div class="input-width"> {{ formData.create_time }} </div>
|
||||
</el-form-item>
|
||||
<div v-if="formData.type == 'transfer'">
|
||||
<el-form-item :label="t('transferNo')" >
|
||||
<div class="input-width"> {{ formData.pay_info.transfer_no }} </div>
|
||||
<el-form-item :label="t('transferNo')">
|
||||
<div class="input-width"> {{ formData.pay_info.transfer_no }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('transferTime')" >
|
||||
<div class="input-width"> {{ formData.pay_info.transfer_time }} </div>
|
||||
<el-form-item :label="t('transferTime')">
|
||||
<div class="input-width"> {{ formData.pay_info.transfer_time }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('transferType')" >
|
||||
<div class="input-width"> {{ formData.pay_info.transfer_type }} </div>
|
||||
<el-form-item :label="t('transferType')">
|
||||
<div class="input-width"> {{ formData.pay_info.transfer_type }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('transferMoney')" >
|
||||
<div class="input-width"> {{ formData.pay_info.money }} </div>
|
||||
<el-form-item :label="t('transferMoney')">
|
||||
<div class="input-width"> {{ formData.pay_info.money }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('transferRemark')" >
|
||||
<div class="input-width"> {{ formData.pay_info.remark }} </div>
|
||||
<el-form-item :label="t('transferRemark')">
|
||||
<div class="input-width"> {{ formData.pay_info.remark }} </div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="formData.type == 'refund'">
|
||||
<el-form-item :label="t('outTradeNo')" >
|
||||
<div class="input-width"> {{ formData.pay_info.out_trade_no }} </div>
|
||||
<el-form-item :label="t('outTradeNo')">
|
||||
<div class="input-width"> {{ formData.pay_info.out_trade_no }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('createTime')" >
|
||||
<div class="input-width"> {{ formData.pay_info.create_time }} </div>
|
||||
<el-form-item :label="t('createTime')">
|
||||
<div class="input-width"> {{ formData.pay_info.create_time }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('refundMoney')" >
|
||||
<div class="input-width"> {{ formData.pay_info.money }} </div>
|
||||
<el-form-item :label="t('refundMoney')">
|
||||
<div class="input-width"> {{ formData.pay_info.money }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('failReason')" >
|
||||
<div class="input-width"> {{ formData.pay_info.fail_reason }} </div>
|
||||
<el-form-item :label="t('failReason')">
|
||||
<div class="input-width"> {{ formData.pay_info.fail_reason }} </div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="formData.type == 'pay'">
|
||||
<el-form-item :label="t('outTradeNo')" >
|
||||
<div class="input-width"> {{ formData.pay_info.out_trade_no }} </div>
|
||||
<el-form-item :label="t('outTradeNo')">
|
||||
<div class="input-width"> {{ formData.pay_info.out_trade_no }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('createTime')" >
|
||||
<div class="input-width"> {{ formData.pay_info.create_time }} </div>
|
||||
<el-form-item :label="t('createTime')">
|
||||
<div class="input-width"> {{ formData.pay_info.create_time }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('money')" >
|
||||
<div class="input-width"> {{ formData.pay_info.money }} </div>
|
||||
<el-form-item :label="t('money')">
|
||||
<div class="input-width"> {{ formData.pay_info.money }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('body')" >
|
||||
<div class="input-width"> {{ formData.pay_info.body }} </div>
|
||||
<el-form-item :label="t('body')">
|
||||
<div class="input-width"> {{ formData.pay_info.body }} </div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<!-- <el-form-item :label="t('headimg')" >
|
||||
<div class="flex items-center">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-if="formData.member.headimg" :src="img(formData.member.headimg)" alt="" >
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/app/assets/images/default_headimg.png" alt="" >
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('memberId')" >
|
||||
<div class="input-width"> {{ formData.member.member_no }} </div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-form-item :label="t('nickName')" >
|
||||
<div class="input-width"> {{ formData.member.nickname }} </div>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
<el-form-item :label="t('mobile')" >
|
||||
<div class="input-width"> {{ formData.member.mobile }} </div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('accountData')" >
|
||||
<div class="input-width"> {{ formData.account_data }} </div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('fromType')" >
|
||||
<div class="input-width"> {{ formData.from_type_name }} </div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('memo')" >
|
||||
<div class="input-width"> {{ formData.memo }} </div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('createTime')" >
|
||||
<div class="input-width"> {{ formData.create_time }} </div>
|
||||
</el-form-item> -->
|
||||
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button type="primary" @click="showDialog = false">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button type="primary" @click="showDialog = false">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getAccountList, getAccountStat, getAccountType } from '@/app/api/site'
|
||||
import { img } from '@/utils/common'
|
||||
// import { img } from '@/utils/common'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title;
|
||||
const pageName = route.meta.title
|
||||
|
||||
let siteAccountLogTable = reactive({
|
||||
const siteAccountLogTable = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam:{
|
||||
site_id: "",
|
||||
type: "",
|
||||
money: "",
|
||||
trade_no: "",
|
||||
create_time: ""
|
||||
searchParam: {
|
||||
site_id: '',
|
||||
type: '',
|
||||
money: '',
|
||||
trade_no: '',
|
||||
create_time: ''
|
||||
}
|
||||
})
|
||||
|
||||
@ -240,7 +206,7 @@ const loadSiteAccountLogList = (page: number = 1) => {
|
||||
getAccountList({
|
||||
page: siteAccountLogTable.page,
|
||||
limit: siteAccountLogTable.limit,
|
||||
...siteAccountLogTable.searchParam
|
||||
...siteAccountLogTable.searchParam
|
||||
}).then(res => {
|
||||
siteAccountLogTable.loading = false
|
||||
siteAccountLogTable.data = res.data.data
|
||||
@ -251,8 +217,6 @@ const loadSiteAccountLogList = (page: number = 1) => {
|
||||
}
|
||||
loadSiteAccountLogList()
|
||||
|
||||
|
||||
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields()
|
||||
@ -261,19 +225,46 @@ const resetForm = (formEl: FormInstance | undefined) => {
|
||||
|
||||
const accountType = ref([])
|
||||
const checkAccountType = () => {
|
||||
getAccountType().then(res=>{
|
||||
accountType.value = res.data
|
||||
})
|
||||
getAccountType().then(res => {
|
||||
accountType.value = res.data
|
||||
})
|
||||
}
|
||||
checkAccountType()
|
||||
const showDialog = ref(false)
|
||||
const formData = ref([]);
|
||||
const detailEvent = (info) => {
|
||||
showDialog.value = true
|
||||
formData.value = info
|
||||
const formData = ref({
|
||||
trade_no: '',
|
||||
type_name: '',
|
||||
money: 0,
|
||||
create_time: '',
|
||||
type: '',
|
||||
pay_info: {
|
||||
transfer_no: '',
|
||||
transfer_time: '',
|
||||
transfer_type: '',
|
||||
money: 0,
|
||||
remark: '',
|
||||
out_trade_no: '',
|
||||
create_time: '',
|
||||
fail_reason: '',
|
||||
body: ''
|
||||
}
|
||||
})
|
||||
const detailEvent = (info:any) => {
|
||||
showDialog.value = true
|
||||
formData.value = info
|
||||
}
|
||||
|
||||
const accountStat = ref([])
|
||||
interface AccountStat{
|
||||
pay: number,
|
||||
refund: number,
|
||||
transfer: number
|
||||
}
|
||||
|
||||
const accountStat = ref<AccountStat>({
|
||||
pay: 0,
|
||||
refund: 0,
|
||||
transfer: 0
|
||||
})
|
||||
const checkAccountStat = async () => {
|
||||
accountStat.value = await (await getAccountStat()).data
|
||||
}
|
||||
|
||||
@ -2,32 +2,34 @@
|
||||
<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-[20px]">{{pageName}}</span>
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none base-bg !px-[35px]" shadow="never">
|
||||
<el-row class="flex">
|
||||
<el-row class="flex">
|
||||
<el-col :span="12">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="statistics.transfered ? Number.parseFloat(statistics.transfered).toFixed(2) : '0.00'"></el-statistic>
|
||||
<div class="statistic-card">
|
||||
<el-statistic
|
||||
:value="statistics.transfered ? statistics.transfered.toFixed(2) : '0.00'"></el-statistic>
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-[#666]">
|
||||
<span>{{ t('totalTransfered') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="statistics.cash_outing ? Number.parseFloat(statistics.cash_outing).toFixed(2) : '0'"></el-statistic>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="statistic-card">
|
||||
<el-statistic
|
||||
:value="statistics.cash_outing ? statistics.cash_outing.toFixed(2) : '0'"></el-statistic>
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-[#666]">
|
||||
<span>{{ t('totalCashOuting') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card !border-none mb-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="orderTableData.searchParam" ref="searchFormRef">
|
||||
@ -36,39 +38,39 @@
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('cashOutNumber')" prop="cash_out_no">
|
||||
<el-input v-model="orderTableData.searchParam.cash_out_no" class="w-[240px]"
|
||||
:placeholder="t('cashOutNumberPlaceholder')" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('cashOutNumber')" prop="cash_out_no">
|
||||
<el-input v-model="orderTableData.searchParam.cash_out_no" class="w-[240px]"
|
||||
:placeholder="t('cashOutNumberPlaceholder')" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('memberInfo')" prop="keyword">
|
||||
<el-input v-model="orderTableData.searchParam.keyword" class="w-[240px]"
|
||||
:placeholder="t('memberInfoPlaceholder')" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('memberInfo')" prop="keyword">
|
||||
<el-input v-model="orderTableData.searchParam.keyword" class="w-[240px]"
|
||||
:placeholder="t('memberInfoPlaceholder')" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('cashOutMethod')" prop="transfer_type">
|
||||
<el-select v-model="orderTableData.searchParam.transfer_type" clearable class="input-width">
|
||||
<el-option :label="t('selectPlaceholder')" value="" />
|
||||
<el-option :label="item.name" :value="key" v-for="(item, key) in Transfertype" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('cashOutMethod')" prop="transfer_type">
|
||||
<el-select v-model="orderTableData.searchParam.transfer_type" clearable class="input-width">
|
||||
<el-option :label="t('selectPlaceholder')" value="" />
|
||||
<el-option :label="item.name" :value="key" v-for="(item, key) in Transfertype" :key="key"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('cashOutStatus')" prop="order_from">
|
||||
<el-select v-model="orderTableData.searchParam.status" clearable class="input-width">
|
||||
<el-option :label="t('selectPlaceholder')" value="" />
|
||||
<el-option :label="item" :value="key" v-for="(item, key) in cashOutStatusList" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('auditTime')" prop="audit_time">
|
||||
<el-date-picker v-model="orderTableData.searchParam.audit_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('transferTime')" prop="transfer_time">
|
||||
<el-date-picker v-model="orderTableData.searchParam.transfer_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('cashOutStatus')" prop="order_from">
|
||||
<el-select v-model="orderTableData.searchParam.status" clearable class="input-width">
|
||||
<el-option :label="t('selectPlaceholder')" value="" />
|
||||
<el-option :label="item" :value="key" v-for="(item, key) in cashOutStatusList" :key="key"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('auditTime')" prop="audit_time">
|
||||
<el-date-picker v-model="orderTableData.searchParam.audit_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('transferTime')" prop="transfer_time">
|
||||
<el-date-picker v-model="orderTableData.searchParam.transfer_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadOrderList()">{{ t('search') }}</el-button>
|
||||
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
|
||||
@ -82,11 +84,14 @@
|
||||
<span>{{ !orderTableData.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
|
||||
<el-table-column prop="order_no" :show-overflow-tooltip="true" :label="t('memberInfo')" align="center" min-width="140">
|
||||
<el-table-column prop="order_no" :show-overflow-tooltip="true" :label="t('memberInfo')" align="center"
|
||||
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.member.headimg" :src="img(row.member.headimg)" alt="" >
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/app/assets/images/default_headimg.png" alt="" >
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg"
|
||||
:src="img(row.member.headimg)" alt="">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-else
|
||||
src="@/app/assets/images/default_headimg.png" alt="">
|
||||
<div class="flex flex flex-col">
|
||||
<span class="">{{ row.member.nickname || '' }}</span>
|
||||
<span class="">{{ row.member.mobile || '' }}</span>
|
||||
@ -94,15 +99,16 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('cashOutMethod')" align="center" min-width="140" >
|
||||
<el-table-column :label="t('cashOutMethod')" align="center" min-width="140">
|
||||
<template #default="{ row }">
|
||||
{{ Transfertype[row.transfer_type].name }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="apply_money" :label="t('applicationForWithdrawalAmount')" min-width="140" align="center" />
|
||||
<el-table-column prop="apply_money" :label="t('applicationForWithdrawalAmount')" min-width="140"
|
||||
align="center" />
|
||||
|
||||
<el-table-column prop="money" :label="t('actualTransferAmount')" min-width="200" align="center"/>
|
||||
<el-table-column prop="money" :label="t('actualTransferAmount')" min-width="200" align="center" />
|
||||
|
||||
<el-table-column prop="service_money" :label="t('cashOutCommission')" align="center" min-width="140" />
|
||||
|
||||
@ -114,21 +120,23 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column :label="t('auditTime')" min-width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.audit_time || '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('auditTime')" min-width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.audit_time || '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column :label="t('transferTime')" min-width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.transfer_time || '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('transferTime')" min-width="180" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.transfer_time || '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right" width="230">
|
||||
<template #default="{ row }">
|
||||
<el-button v-for="(item,index) in operationBtn[row.status.toString()].value" :key="index+'a'" @click="fnProcessing(operationBtn[row.status.toString()].clickArr[index],row)" type="primary" link>{{ item }}</el-button>
|
||||
<el-button v-for="(item, index) in operationBtn[row.status.toString()].value" :key="index + 'a'"
|
||||
@click="fnProcessing(operationBtn[row.status.toString()].clickArr[index], row)"
|
||||
type="primary" link>{{ item }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
@ -144,7 +152,8 @@
|
||||
|
||||
<!-- 详情 -->
|
||||
<el-dialog v-model="cashOutShowDialog" :title="t('cashOutDetail')" width="500px" :destroy-on-close="true">
|
||||
<el-form :model="cashOutInfo" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="cashOutLoading">
|
||||
<el-form :model="cashOutInfo" label-width="120px" ref="formRef" :rules="formRules" class="page-form"
|
||||
v-loading="cashOutLoading">
|
||||
<el-form-item :label="t('nickname')">
|
||||
<div class="input-width"> {{ cashOutInfo.nickname }} </div>
|
||||
</el-form-item>
|
||||
@ -169,33 +178,35 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button type="primary" @click="cashOutShowDialog = false">{{t('confirm')}}</el-button>
|
||||
<el-button type="primary" @click="cashOutShowDialog = false">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 是否审核 -->
|
||||
<el-dialog v-model="auditShowDialog" :title="t('rejectionAudit')" width="500px" :destroy-on-close="true">
|
||||
<el-form :model="auditFailure" label-width="90px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
|
||||
<el-form :model="auditFailure" label-width="90px" ref="formRef" :rules="formRules" class="page-form"
|
||||
v-loading="loading">
|
||||
<el-form-item :label="t('reasonsRefusal')" prop="label_name">
|
||||
<el-input v-model="auditFailure.refuse_reason" clearable :placeholder="t('reasonsRefusalPlaceholder')" class="input-width" type="textarea" />
|
||||
<el-input v-model="auditFailure.refuse_reason" clearable :placeholder="t('reasonsRefusalPlaceholder')"
|
||||
class="input-width" type="textarea" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="auditShowDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{t('confirm')}}</el-button>
|
||||
<el-button type="primary" :loading="loading" @click="confirm()">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 是否转账 -->
|
||||
<el-dialog v-model="transferShowDialog" :title="t('rejectionAudit')" width="500px" :destroy-on-close="true">
|
||||
<p>{{t('isTransfer')}}</p>
|
||||
<p>{{ t('isTransfer') }}</p>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="transferShowDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="confirm(formRef)">{{t('confirm')}}</el-button>
|
||||
<el-button type="primary" @click="confirm()">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -205,44 +216,46 @@
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getCashOutList, getTransfertype, memberTransfer, memberAudit, getCashOutDetail, getCashOutStatusList,getCashOutStat } from '@/app/api/member'
|
||||
import { getCashOutList, getTransfertype, memberTransfer, memberAudit, getCashOutDetail, getCashOutStatusList, getCashOutStat } from '@/app/api/member'
|
||||
import { img } from '@/utils/common'
|
||||
import { ElMessageBox, FormInstance } from 'element-plus'
|
||||
import { ElMessageBox, FormInstance, FormRules } from 'element-plus'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { AnyObject } from '@/types/global'
|
||||
|
||||
const cashOutStatusList = ref([])
|
||||
const checkStatusList = async () => {
|
||||
cashOutStatusList.value = await (await getCashOutStatusList({})).data
|
||||
cashOutStatusList.value = await (await getCashOutStatusList()).data
|
||||
}
|
||||
checkStatusList()
|
||||
|
||||
const transferShowDialog = ref(false)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title;
|
||||
const member_id: number = parseInt(route.query.id || 0)
|
||||
const operationBtn = ref({
|
||||
"1": {
|
||||
value: [t('successfulAudit'),t('auditFailure'),t('detail')],
|
||||
clickArr: ['successfulAuditFn','auditFailureFn','detailFn']
|
||||
const pageName = route.meta.title
|
||||
const operationBtn = ref<AnyObject>({
|
||||
1: {
|
||||
value: [t('successfulAudit'), t('auditFailure'), t('detail')],
|
||||
clickArr: ['successfulAuditFn', 'auditFailureFn', 'detailFn']
|
||||
},
|
||||
"2": {
|
||||
value: [t('transfer'),t('detail')],
|
||||
clickArr: ['transferFn','detailFn']
|
||||
2: {
|
||||
value: [t('transfer'), t('detail')],
|
||||
clickArr: ['transferFn', 'detailFn']
|
||||
},
|
||||
"3": {
|
||||
3: {
|
||||
value: [t('detail')],
|
||||
clickArr: ['detailFn']
|
||||
},
|
||||
"-1": {
|
||||
'-1': {
|
||||
value: [t('detail')],
|
||||
clickArr: ['detailFn']
|
||||
},
|
||||
"-2": {
|
||||
'-2': {
|
||||
value: [t('detail')],
|
||||
clickArr: ['detailFn']
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = reactive<FormRules>({})
|
||||
|
||||
const orderTableData = reactive({
|
||||
page: 1,
|
||||
@ -252,40 +265,41 @@ const orderTableData = reactive({
|
||||
data: [],
|
||||
searchParam: {
|
||||
order_no: '',
|
||||
member_id,
|
||||
member_id: 0,
|
||||
create_time: [],
|
||||
status: '',
|
||||
cash_out_no: '',
|
||||
keyword: '',
|
||||
audit_time: '',
|
||||
transfer_time: '',
|
||||
transfer_type: ''
|
||||
cash_out_no: '',
|
||||
keyword: '',
|
||||
audit_time: '',
|
||||
transfer_time: '',
|
||||
transfer_type: ''
|
||||
}
|
||||
})
|
||||
|
||||
const statistics = ref([])
|
||||
const statistics = ref({
|
||||
transfered: 0,
|
||||
cash_outing: 0
|
||||
})
|
||||
const checkStatInfo = () => {
|
||||
getCashOutStat().then(res => {
|
||||
statistics.value = res.data;
|
||||
})
|
||||
getCashOutStat().then(res => {
|
||||
statistics.value = res.data
|
||||
})
|
||||
}
|
||||
checkStatInfo()
|
||||
|
||||
|
||||
// 获取会员转账方式
|
||||
const Transfertype = ref<Array<Object>>([])
|
||||
const getTransfertypeFn = async()=>{
|
||||
const Transfertype = ref<Array<Object|any>>([])
|
||||
const getTransfertypeFn = async () => {
|
||||
Transfertype.value = await (await getTransfertype()).data
|
||||
}
|
||||
getTransfertypeFn()
|
||||
|
||||
|
||||
const searchFormRef = ref<FormInstance>()
|
||||
const resetForm = (formEl: FormInstance | undefined)=>{
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
|
||||
formEl.resetFields();
|
||||
loadOrderList();
|
||||
formEl.resetFields()
|
||||
loadOrderList()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -310,38 +324,37 @@ const loadOrderList = (page: number = 1) => {
|
||||
loadOrderList()
|
||||
|
||||
// 函数总处理
|
||||
let auditFailure = ref({refuse_reason:'',id:0,action: 0})
|
||||
let auditShowDialog = ref(false);
|
||||
const fnProcessing = (type:string, data: any)=>{
|
||||
let obj = {}
|
||||
if(['successfulAuditFn','auditFailureFn'].includes(type)){
|
||||
obj.id = data.id;
|
||||
if(type == 'successfulAuditFn'){
|
||||
obj.action = 'agree';
|
||||
const auditFailure = ref({ refuse_reason: '', id: 0, action: 0 })
|
||||
const auditShowDialog = ref(false)
|
||||
const fnProcessing = (type: string, data: any) => {
|
||||
const obj = {}
|
||||
if (['successfulAuditFn', 'auditFailureFn'].includes(type)) {
|
||||
obj.id = data.id
|
||||
if (type == 'successfulAuditFn') {
|
||||
obj.action = 'agree'
|
||||
cashOutAuditFn(obj)
|
||||
}else{
|
||||
obj.action = 'refuse';
|
||||
auditFailure.value = Object.assign(auditFailure.value,obj);
|
||||
auditShowDialog.value = true;
|
||||
} else {
|
||||
obj.action = 'refuse'
|
||||
auditFailure.value = Object.assign(auditFailure.value, obj)
|
||||
auditShowDialog.value = true
|
||||
}
|
||||
}else if(type == 'transferFn'){
|
||||
obj.id = data.id;
|
||||
ElMessageBox.confirm(`${t('isTransfer')}`,`${t('transfer')}`)
|
||||
.then(() => {
|
||||
transferFn(obj);
|
||||
})
|
||||
}else{
|
||||
detailFn(data.id);
|
||||
} else if (type == 'transferFn') {
|
||||
obj.id = data.id
|
||||
ElMessageBox.confirm(`${t('isTransfer')}`, `${t('transfer')}`)
|
||||
.then(() => {
|
||||
transferFn(obj)
|
||||
})
|
||||
} else {
|
||||
detailFn(data.id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转账
|
||||
* @param data
|
||||
*/
|
||||
const transferFn = (data)=>{
|
||||
memberTransfer({...data}).then(res => {
|
||||
const transferFn = (data:any) => {
|
||||
memberTransfer({ ...data }).then(res => {
|
||||
loadOrderList()
|
||||
}).catch(() => {
|
||||
loadOrderList()
|
||||
@ -353,14 +366,22 @@ const transferFn = (data)=>{
|
||||
* @param data
|
||||
*/
|
||||
|
||||
let cashOutShowDialog = ref(false);
|
||||
let cashOutInfo = ref({});
|
||||
let cashOutLoading = ref(true);
|
||||
const detailFn = (id)=>{
|
||||
const cashOutShowDialog = ref(false)
|
||||
const cashOutInfo = ref({
|
||||
nickname: '',
|
||||
account_type_name: '',
|
||||
transfer_type: '',
|
||||
apply_money: 0,
|
||||
service_money: 0,
|
||||
money: 0,
|
||||
status_name: ''
|
||||
})
|
||||
const cashOutLoading = ref(true)
|
||||
const detailFn = (id:any) => {
|
||||
getCashOutDetail(id).then(res => {
|
||||
cashOutInfo.value = res.data;
|
||||
cashOutShowDialog.value = true;
|
||||
cashOutLoading.value = false;
|
||||
cashOutInfo.value = res.data
|
||||
cashOutShowDialog.value = true
|
||||
cashOutLoading.value = false
|
||||
}).catch(() => {
|
||||
loadOrderList()
|
||||
})
|
||||
@ -370,7 +391,7 @@ const detailFn = (id)=>{
|
||||
* 提现审核
|
||||
* @param data
|
||||
*/
|
||||
const cashOutAuditFn = (data)=>{
|
||||
const cashOutAuditFn = (data:any) => {
|
||||
memberAudit({
|
||||
...data
|
||||
}).then(res => {
|
||||
@ -384,25 +405,16 @@ const cashOutAuditFn = (data)=>{
|
||||
* 拒绝审核
|
||||
* @param data
|
||||
*/
|
||||
const confirm = ()=>{
|
||||
auditShowDialog.value = false;
|
||||
cashOutAuditFn(auditFailure.value);
|
||||
const confirm = () => {
|
||||
auditShowDialog.value = false
|
||||
cashOutAuditFn(auditFailure.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单详情
|
||||
* @param data
|
||||
*/
|
||||
const infoEvent = (data: any) => {
|
||||
router.push(`/finance/recharge/detail?order_id=${data.order_id}`)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 会员详情
|
||||
*/
|
||||
const toMember = (member_id: number) => {
|
||||
router.push(`/member/detail?id=${member_id}`)
|
||||
const toMember = (memberId: number) => {
|
||||
router.push(`/member/detail?id=${memberId}`)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@ -52,11 +52,11 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getPayRefundPages } from '@/app/api/pay'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
import type { FormInstance } from 'element-plus'
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
@ -76,7 +76,7 @@ const payRefundTable = reactive({
|
||||
const searchFormRef = ref<FormInstance>()
|
||||
|
||||
// 选中数据
|
||||
const selectData = ref<any[]>([])
|
||||
// const selectData = ref<any[]>([])
|
||||
|
||||
/**
|
||||
* 获取商品标签列表
|
||||
@ -99,7 +99,7 @@ const loadPayRefundList = (page: number = 1) => {
|
||||
}
|
||||
loadPayRefundList()
|
||||
|
||||
const infoEvent = (data) => {
|
||||
const infoEvent = (data:any) => {
|
||||
router.push('/finance/refund/detail?refund_no=' + data.refund_no)
|
||||
}
|
||||
|
||||
|
||||
@ -8,54 +8,56 @@
|
||||
<span class="adorn">|</span>
|
||||
<span class="right">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none relative" shadow="never" v-if="formData">
|
||||
<div class="flex px-[20px] py-[20px] justify-between">
|
||||
<span>{{ t('refundMoney') }}:<span>¥{{ formData.money }}</span></span>
|
||||
<span>{{ t('refundNo') }}:<span>{{ formData.refund_no }}</span></span>
|
||||
</div>
|
||||
<el-table :data="refundList" size="large">
|
||||
<el-table-column prop="out_trade_no" :label="t('outTradeNo')" min-width="200" />
|
||||
<el-table-column prop="create_time" :label="t('createTime')" min-width="160" />
|
||||
<el-table-column prop="refund_type_name" :label="t('refundTypeName')" min-width="120" />
|
||||
<el-table-column :label="t('refundMoney')" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<span>¥{{ row.money }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status_name" :label="t('statusName')" min-width="120" />
|
||||
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="transferEvent(row)" v-if="row.status == 'wait'">{{ t('transfer') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
<el-card class="box-card !border-none relative" shadow="never" v-if="formData">
|
||||
<div class="flex px-[20px] py-[20px] justify-between">
|
||||
<span>{{ t('refundMoney') }}:<span>¥{{ formData.money }}</span></span>
|
||||
<span>{{ t('refundNo') }}:<span>{{ formData.refund_no }}</span></span>
|
||||
</div>
|
||||
<el-table :data="refundList" size="large">
|
||||
<el-table-column prop="out_trade_no" :label="t('outTradeNo')" min-width="200" />
|
||||
<el-table-column prop="create_time" :label="t('createTime')" min-width="160" />
|
||||
<el-table-column prop="refund_type_name" :label="t('refundTypeName')" min-width="120" />
|
||||
<el-table-column :label="t('refundMoney')" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<span>¥{{ row.money }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status_name" :label="t('statusName')" min-width="120" />
|
||||
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="transferEvent(row)" v-if="row.status == 'wait'">{{
|
||||
t('transfer') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-dialog v-model="transferDialog" :title="title" width="500px" class="diy-dialog-wrap"
|
||||
:destroy-on-close="true">
|
||||
<el-form :model="transfeFormData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
|
||||
<el-form-item :label="t('transferType')">
|
||||
<el-radio-group v-model="transfeFormData.refund_type">
|
||||
<el-radio :label="item.value" v-for="(item, index) in refundTypeData" :key="index">{{ item.name }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('refundMoney')" >
|
||||
<span>{{ transfeFormData.refund_money }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('voucher')" v-if="transfeFormData.refund_type == 'offline'">
|
||||
<upload-image v-model="transfeFormData.voucher" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-dialog v-model="transferDialog" :title="title" width="500px" class="diy-dialog-wrap" :destroy-on-close="true">
|
||||
<el-form :model="transfeFormData" label-width="120px" ref="formRef" :rules="formRules" class="page-form"
|
||||
v-loading="loading">
|
||||
<el-form-item :label="t('transferType')">
|
||||
<el-radio-group v-model="transfeFormData.refund_type">
|
||||
<el-radio :label="item.value" v-for="(item, index) in refundTypeData" :key="index">{{ item.name
|
||||
}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('refundMoney')">
|
||||
<span>{{ transfeFormData.refund_money }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('voucher')" v-if="transfeFormData.refund_type == 'offline'">
|
||||
<upload-image v-model="transfeFormData.voucher" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="transferDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{
|
||||
t('confirm')
|
||||
}}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="transferDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{
|
||||
t('confirm')
|
||||
}}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -64,15 +66,13 @@ import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getPayRefundInfo, getRefundType, getRefundTransfer } from '@/app/api/pay'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { img, getAppType } from '@/utils/common'
|
||||
import { ElMessageBox, FormInstance } from 'element-plus'
|
||||
import { FormInstance } from 'element-plus'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
const refundNo: string = route.query.refund_no
|
||||
const loading = ref(true)
|
||||
const appType = getAppType()
|
||||
|
||||
const refundList = ref([])
|
||||
const formData: Record<string, any> | null = ref(null)
|
||||
@ -102,7 +102,7 @@ getRefundType().then((data) => {
|
||||
})
|
||||
|
||||
const transferDialog = ref(false)
|
||||
const transferEvent = (data) => {
|
||||
const transferEvent = (data:any) => {
|
||||
transferDialog.value = true
|
||||
transfeFormData.refund_no = data.refund_no
|
||||
transfeFormData.refund_money = data.money
|
||||
@ -140,7 +140,7 @@ const confirm = async (formEl: FormInstance | undefined) => {
|
||||
transferDialog.value = false
|
||||
refundList.value = []
|
||||
setFormData(refundNo)
|
||||
}).catch(err => {
|
||||
}).catch(() => {
|
||||
transferDialog.value = false
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
@ -1,23 +1,24 @@
|
||||
<template>
|
||||
<div class="main-container w-full pt-[64px] bg-white" v-loading="loading">
|
||||
<div class="main-container w-full pt-[64px] bg-white" v-loading="loading">
|
||||
<div class="flex justify-between items-center h-[32px] mb-4">
|
||||
<span class="text-[20px]">{{ t('editPersonal') }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<el-form :model="saveInfo" label-width="90px" ref="formRef" :rules="formRules" class="page-form">
|
||||
<el-form :model="saveInfo" label-width="90px" ref="formRef" class="page-form">
|
||||
<el-form-item :label="t('headImg')">
|
||||
<upload-image v-model="saveInfo.head_img" :limit="1" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('userName')">
|
||||
<span>{{saveInfo.username}}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('userName')">
|
||||
<span>{{ saveInfo.username }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('realName')">
|
||||
<el-input v-model="saveInfo.real_name" :placeholder="t('realNamePlaceholder')" clearable class="input-width" />
|
||||
<el-input v-model="saveInfo.real_name" :placeholder="t('realNamePlaceholder')" clearable
|
||||
class="input-width" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="flex justify-center mt-[50px]">
|
||||
<el-button type="primary" @click="submitForm(formRef)">{{ t('save') }}</el-button>
|
||||
<el-button type="primary" @click="returnFn(formRef)">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="returnFn()">{{ t('cancel') }}</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
@ -26,77 +27,83 @@
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance, FormRules, ElNotification } from 'element-plus'
|
||||
import { img } from '@/utils/common'
|
||||
import { getUserInfo,setUserInfo } from '@/app/api/personal'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { getUserInfo, setUserInfo } from '@/app/api/personal'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
// 提交信息
|
||||
let saveInfo = reactive({
|
||||
head_img: '',
|
||||
real_name: '',
|
||||
username: ''
|
||||
});
|
||||
const saveInfo: {
|
||||
head_img: string;
|
||||
real_name: string;
|
||||
username: string;
|
||||
} = reactive({
|
||||
head_img: '',
|
||||
real_name: '',
|
||||
username: ''
|
||||
})
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
const loading = ref(true);
|
||||
const formRef = ref<FormInstance>()
|
||||
const loading = ref(true)
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
const getUserInfoFn = () => {
|
||||
loading.value = true;
|
||||
loading.value = true
|
||||
getUserInfo().then(res => {
|
||||
loading.value = false;
|
||||
|
||||
let data = res.data;
|
||||
saveInfo.head_img = data.head_img;
|
||||
saveInfo.real_name = data.real_name;
|
||||
saveInfo.username = data.username;
|
||||
loading.value = false
|
||||
|
||||
const data = res.data
|
||||
saveInfo.head_img = data.head_img
|
||||
saveInfo.real_name = data.real_name
|
||||
saveInfo.username = data.username
|
||||
}).catch(() => {
|
||||
loading.value = false;
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
getUserInfoFn();
|
||||
getUserInfoFn()
|
||||
|
||||
const submitForm = (formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
loading.value = true;
|
||||
loading.value = true
|
||||
|
||||
setUserInfo(saveInfo).then((res: any) => {
|
||||
loading.value = false;
|
||||
}).catch((err: any) => {
|
||||
loading.value = false
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
const returnFn = ()=>{
|
||||
const returnFn = () => {
|
||||
router.push('/user/center')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.personal-body){
|
||||
:deep(.personal-body) {
|
||||
background-color: #fff;
|
||||
.el-form-item__content{
|
||||
.el-input{
|
||||
|
||||
.el-form-item__content {
|
||||
.el-input {
|
||||
width: 250px;
|
||||
}
|
||||
.el-form-item__content{
|
||||
|
||||
.el-form-item__content {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.el-button{
|
||||
|
||||
.el-button {
|
||||
margin-left: auto;
|
||||
}
|
||||
.personal-option{
|
||||
|
||||
.personal-option {
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
}</style>
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
<!-- eslint-disable vue/no-deprecated-v-on-native-modifier -->
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex justify-between items-center py-[24px] pl-[62px] pr-[64px] home-head">
|
||||
@ -63,18 +64,38 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, toRefs } from 'vue'
|
||||
import { CollectionTag, Search } from '@element-plus/icons-vue'
|
||||
import { Search } from '@element-plus/icons-vue'
|
||||
import { getHomeSite } from '@/app/api/home'
|
||||
import { getWebConfig } from '@/app/api/sys'
|
||||
import { img } from '@/utils/common'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
import storage from '@/utils/storage'
|
||||
import { getInstalledAddonList } from '@/app/api/addon'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { AnyObject } from '@/types/global'
|
||||
const userStore:AnyObject = useUserStore()
|
||||
|
||||
const userStore = useUserStore()
|
||||
const router = useRouter()
|
||||
const state = reactive({
|
||||
interface State{
|
||||
params: {
|
||||
keywords: string,
|
||||
page: number,
|
||||
limit: number,
|
||||
app: string,
|
||||
sort: boolean
|
||||
},
|
||||
loading: boolean,
|
||||
tableData: {
|
||||
logo: string,
|
||||
app_name: string,
|
||||
site_name: string,
|
||||
create_time: string,
|
||||
expire_time: string,
|
||||
site_id: number,
|
||||
group_name: string
|
||||
}[]
|
||||
}
|
||||
|
||||
const state:State = reactive({
|
||||
params: {
|
||||
keywords: '',
|
||||
page: 1,
|
||||
@ -99,17 +120,19 @@ const getHomeSiteFn = () => {
|
||||
getHomeSiteFn()
|
||||
|
||||
// 切换应用
|
||||
const cutAppFn = (app)=>{
|
||||
state.params.app = app;
|
||||
getHomeSiteFn();
|
||||
const cutAppFn = (app:any) => {
|
||||
state.params.app = app
|
||||
getHomeSiteFn()
|
||||
}
|
||||
|
||||
|
||||
// 网络设置
|
||||
let webConfig = ref({})
|
||||
const getWebConfigFn = () =>{
|
||||
getWebConfig().then(res =>{
|
||||
webConfig.value = res.data;
|
||||
const webConfig = ref({
|
||||
icon: '',
|
||||
site_name: ''
|
||||
})
|
||||
const getWebConfigFn = () => {
|
||||
getWebConfig().then(res => {
|
||||
webConfig.value = res.data
|
||||
})
|
||||
}
|
||||
getWebConfigFn()
|
||||
@ -128,19 +151,19 @@ const selectSite = (site: any) => {
|
||||
})
|
||||
location.href = `${location.origin}/site/`
|
||||
}
|
||||
const logoutFn = ()=>{
|
||||
userStore.logout();
|
||||
}
|
||||
const toLinkFn = (link)=>{
|
||||
router.push(link)
|
||||
const logoutFn = () => {
|
||||
userStore.logout()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取应用列表
|
||||
*/
|
||||
const addonList = ref([])
|
||||
const addonList = ref<{
|
||||
key: string,
|
||||
title: string
|
||||
}[]>([])
|
||||
getInstalledAddonList().then(({ data }) => {
|
||||
const apps = []
|
||||
const apps:any = []
|
||||
Object.keys(data).forEach(key => {
|
||||
const addon = data[key]
|
||||
addon.type == 'app' && apps.push(addon)
|
||||
@ -149,7 +172,7 @@ getInstalledAddonList().then(({ data }) => {
|
||||
}).catch()
|
||||
|
||||
const handleChick = () => {
|
||||
ElMessage('加班加点研发中...')
|
||||
ElMessage('加班加点研发中...')
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -1,25 +1,28 @@
|
||||
<template>
|
||||
<div class="main-container w-full pt-[64px] bg-white" v-loading="loading">
|
||||
<div class="main-container w-full pt-[64px] bg-white" v-loading="loading">
|
||||
<div class="flex justify-between items-center h-[32px] mb-4">
|
||||
<span class="text-[20px]">{{ t('personal') }}</span>
|
||||
<span class="text-[14px] text-[#999] cursor-pointer" @click="toEditPersonal">{{ t('editPersonal') }}</span>
|
||||
<span class="text-[20px]">{{ t("personal") }}</span>
|
||||
<span class="text-[14px] text-[#999] cursor-pointer" @click="toEditPersonal">{{ t("editPersonal") }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<el-form :model="saveInfo" label-width="90px" ref="formRef" class="page-form">
|
||||
<el-form-item :label="t('headImg')">
|
||||
<el-image class="w-[70px] h-[70px]" :src="img(saveInfo.head_img)" fit="contain">
|
||||
<template #error>
|
||||
<div class="image-slot bg-[#c0c4cc] flex items-center justify-center w-[70px] h-[70px] rounded-full">
|
||||
<el-icon class="!text-[#fff] !text-[45px]"><UserFilled /></el-icon>
|
||||
<div
|
||||
class="image-slot bg-[#c0c4cc] flex items-center justify-center w-[70px] h-[70px] rounded-full">
|
||||
<el-icon class="!text-[#fff] !text-[45px]">
|
||||
<UserFilled />
|
||||
</el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('userName')">
|
||||
<div>{{saveInfo.username}}</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('userName')">
|
||||
<div>{{ saveInfo.username }}</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('realName')">
|
||||
<div>{{saveInfo.real_name}}</div>
|
||||
<div>{{ saveInfo.real_name }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
@ -29,45 +32,46 @@
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance, FormRules, ElNotification } from 'element-plus'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { img } from '@/utils/common'
|
||||
import { getUserInfo,setUserInfo } from '@/app/api/personal'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { getUserInfo } from '@/app/api/personal'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
// 提交信息
|
||||
let saveInfo = reactive({
|
||||
const saveInfo = reactive({
|
||||
head_img: '',
|
||||
real_name: '',
|
||||
original_password: '',
|
||||
password: '',
|
||||
password_copy: '',
|
||||
username: ''
|
||||
});
|
||||
})
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
const loading = ref(true);
|
||||
const formRef = ref<FormInstance>()
|
||||
const loading = ref(true)
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
const getUserInfoFn = () => {
|
||||
loading.value = true;
|
||||
getUserInfo().then(res => {
|
||||
loading.value = false;
|
||||
|
||||
let data = res.data;
|
||||
saveInfo.head_img = data.head_img;
|
||||
saveInfo.real_name = data.real_name;
|
||||
saveInfo.original_password = data.original_password;
|
||||
saveInfo.password = data.password;
|
||||
saveInfo.password_copy = data.password;
|
||||
saveInfo.username = data.username;
|
||||
}).catch(() => {
|
||||
loading.value = false;
|
||||
loading.value = true
|
||||
getUserInfo().then((res) => {
|
||||
loading.value = false
|
||||
|
||||
const data = res.data
|
||||
saveInfo.head_img = data.head_img
|
||||
saveInfo.real_name = data.real_name
|
||||
saveInfo.original_password = data.original_password
|
||||
saveInfo.password = data.password
|
||||
saveInfo.password_copy = data.password
|
||||
saveInfo.username = data.username
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
getUserInfoFn();
|
||||
getUserInfoFn()
|
||||
|
||||
// 编辑个人中心
|
||||
const toEditPersonal = () => {
|
||||
@ -76,19 +80,23 @@ const toEditPersonal = () => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.personal-body){
|
||||
:deep(.personal-body) {
|
||||
background-color: #fff;
|
||||
.el-form-item__content{
|
||||
.el-input{
|
||||
|
||||
.el-form-item__content {
|
||||
.el-input {
|
||||
width: 250px;
|
||||
}
|
||||
.el-form-item__content{
|
||||
|
||||
.el-form-item__content {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.el-button{
|
||||
|
||||
.el-button {
|
||||
margin-left: auto;
|
||||
}
|
||||
.personal-option{
|
||||
|
||||
.personal-option {
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,20 +56,26 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted, computed } from 'vue'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getInstalledAddonList } from '@/app/api/addon'
|
||||
import { img } from '@/utils/common'
|
||||
import { useRouter } from 'vue-router'
|
||||
import storage from '@/utils/storage'
|
||||
import { findFirstValidRoute } from '@/router/routers'
|
||||
import { UserFilled } from '@element-plus/icons-vue'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
import { AnyObject } from '@/types/global'
|
||||
|
||||
const router = useRouter()
|
||||
const userStore = useUserStore()
|
||||
const userStore:AnyObject = useUserStore()
|
||||
const loading = ref(true)
|
||||
const detail = reactive({
|
||||
const detail:{
|
||||
appList: {
|
||||
title: string,
|
||||
desc: string,
|
||||
icon: string
|
||||
}[]
|
||||
} = reactive({
|
||||
appList: []
|
||||
})
|
||||
const appLink: any = ref({})
|
||||
@ -82,7 +88,7 @@ const getAuthaddonFn = () => {
|
||||
detail.appList.push(item)
|
||||
}
|
||||
})
|
||||
userStore.routers.forEach((item, index) => {
|
||||
userStore.routers.forEach((item:any, index:number) => {
|
||||
if (item.children && item.children.length) {
|
||||
item.name = findFirstValidRoute(item.children)
|
||||
appLink.value[item.meta.app] = findFirstValidRoute(item.children)
|
||||
@ -93,7 +99,6 @@ const getAuthaddonFn = () => {
|
||||
loading.value = false
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@ -105,30 +110,14 @@ const itemPath = (data: any) => {
|
||||
const appMenuList = userStore.appMenuList
|
||||
appMenuList.push(data.key)
|
||||
userStore.setAppMenuList(appMenuList)
|
||||
let name: any = appLink.value[data.key]
|
||||
router.push({ name: name })
|
||||
}
|
||||
|
||||
const goAppManage = () => {
|
||||
router.push('/app_manage')
|
||||
}
|
||||
|
||||
const goRouter = () => {
|
||||
window.open('https://www.niucloud.com/app')
|
||||
const name: any = appLink.value[data.key]
|
||||
router.push({ name })
|
||||
}
|
||||
|
||||
// 跳转至开发者
|
||||
const toAppStore = () => {
|
||||
router.push('/app_manage/app_store')
|
||||
}
|
||||
|
||||
const goNiucloud = () => {
|
||||
window.open('https://www.niucloud.com')
|
||||
}
|
||||
|
||||
const logout = () => {
|
||||
userStore.logout();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<span class="text-[20px]">{{ t('editPersonal') }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<el-form :model="saveInfo" label-width="90px" ref="formRef" :rules="formRules" class="page-form">
|
||||
<el-form :model="saveInfo" label-width="90px" ref="formRef" class="page-form">
|
||||
<el-form-item :label="t('headImg')">
|
||||
<upload-image v-model="saveInfo.head_img" :limit="1" />
|
||||
</el-form-item>
|
||||
@ -17,7 +17,7 @@
|
||||
</el-form>
|
||||
<div class="flex justify-center mt-[50px]">
|
||||
<el-button type="primary" @click="submitForm(formRef)">{{ t('save') }}</el-button>
|
||||
<el-button type="primary" @click="returnFn(formRef)">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="returnFn()">{{ t('cancel') }}</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
@ -26,57 +26,56 @@
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance, FormRules, ElNotification } from 'element-plus'
|
||||
import { img } from '@/utils/common'
|
||||
import { getUserInfo,setUserInfo } from '@/app/api/personal'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
|
||||
import { getUserInfo, setUserInfo } from '@/app/api/personal'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
// 提交信息
|
||||
let saveInfo = reactive({
|
||||
head_img: '',
|
||||
real_name: '',
|
||||
username: ''
|
||||
});
|
||||
const saveInfo = reactive({
|
||||
head_img: '',
|
||||
real_name: '',
|
||||
username: ''
|
||||
})
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
const loading = ref(true);
|
||||
const formRef = ref<FormInstance>()
|
||||
const loading = ref(true)
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
const getUserInfoFn = () => {
|
||||
loading.value = true;
|
||||
loading.value = true
|
||||
getUserInfo().then(res => {
|
||||
loading.value = false;
|
||||
|
||||
let data = res.data;
|
||||
saveInfo.head_img = data.head_img;
|
||||
saveInfo.real_name = data.real_name;
|
||||
saveInfo.username = data.username;
|
||||
loading.value = false
|
||||
const data = res.data
|
||||
saveInfo.head_img = data.head_img
|
||||
saveInfo.real_name = data.real_name
|
||||
saveInfo.username = data.username
|
||||
}).catch(() => {
|
||||
loading.value = false;
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
getUserInfoFn();
|
||||
getUserInfoFn()
|
||||
|
||||
const submitForm = (formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
loading.value = true;
|
||||
loading.value = true
|
||||
|
||||
setUserInfo(saveInfo).then((res: any) => {
|
||||
loading.value = false;
|
||||
}).catch((err: any) => {
|
||||
loading.value = false
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
const returnFn = ()=>{
|
||||
const returnFn = () => {
|
||||
router.push('/user/center')
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
<!-- eslint-disable no-undef -->
|
||||
<template>
|
||||
<div class="bg-[#FAFAFA] box-border pb-[77px]">
|
||||
<div class="main-container" v-loading="loading">
|
||||
@ -164,33 +165,43 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, watch } from "vue";
|
||||
import useSystemStore from "@/stores/modules/system";
|
||||
import { t } from "@/lang";
|
||||
import { getStatInfo } from "@/app/api/stat";
|
||||
import * as echarts from "echarts";
|
||||
import { img } from "@/utils/common";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useRoute } from "vue-router";
|
||||
import { ref, watch } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getStatInfo } from '@/app/api/stat'
|
||||
import * as echarts from 'echarts'
|
||||
import useStyleStore from '@/stores/modules/style'
|
||||
import { getFrameworkNewVersion } from '@/app/api/module'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { AnyObject } from '@/types/global'
|
||||
const loading = ref(true)
|
||||
|
||||
const loading = ref(true);
|
||||
const visitStat = ref<any>(null);
|
||||
const memberStat = ref<any>(null);
|
||||
const newSiteStat = ref<any>(null)
|
||||
const siteStat = ref<any>(null)
|
||||
|
||||
const newSiteStat = ref<any>(null);
|
||||
const siteStat = ref<any>(null);
|
||||
|
||||
const systemStore = useSystemStore();
|
||||
const styleStore = useStyleStore()
|
||||
const newVersion = ref(null)
|
||||
|
||||
interface NewVersion{
|
||||
last_version: string
|
||||
}
|
||||
interface StatInfo {
|
||||
today_data: AnyObject,
|
||||
system: AnyObject,
|
||||
version: AnyObject,
|
||||
about: any,
|
||||
site_stat: AnyObject,
|
||||
site_group_stat: AnyObject,
|
||||
app: AnyObject
|
||||
}
|
||||
|
||||
const newVersion = ref<NewVersion>({
|
||||
last_version: ''
|
||||
})
|
||||
|
||||
getFrameworkNewVersion().then(({ data }) => {
|
||||
newVersion.value = data
|
||||
}).catch()
|
||||
|
||||
let statInfo = ref({
|
||||
const statInfo = ref<StatInfo>({
|
||||
today_data: {},
|
||||
system: {},
|
||||
version: {},
|
||||
@ -198,44 +209,44 @@ let statInfo = ref({
|
||||
site_stat: {},
|
||||
site_group_stat: {},
|
||||
app: {}
|
||||
});
|
||||
})
|
||||
const getStatInfoFn = async (id: number = 0) => {
|
||||
statInfo.value = await (await getStatInfo()).data;
|
||||
loading.value = false;
|
||||
statInfo.value = await (await getStatInfo()).data
|
||||
loading.value = false
|
||||
setTimeout(() => {
|
||||
drawChart();
|
||||
}, 20);
|
||||
};
|
||||
getStatInfoFn();
|
||||
drawChart()
|
||||
}, 20)
|
||||
}
|
||||
getStatInfoFn()
|
||||
|
||||
// 绘制折线图
|
||||
const drawChart = () => {
|
||||
//新增站点
|
||||
const newSiteStatChart = echarts.init(newSiteStat.value);
|
||||
// 新增站点
|
||||
const newSiteStatChart = echarts.init(newSiteStat.value)
|
||||
const newSiteStatOption = ref({
|
||||
legend: {},
|
||||
xAxis: {
|
||||
data: [],
|
||||
data: []
|
||||
},
|
||||
yAxis: {},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
trigger: 'axis'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: t("newSite"),
|
||||
type: "line",
|
||||
data: [],
|
||||
},
|
||||
],
|
||||
});
|
||||
newSiteStatOption.value.xAxis.data = statInfo.value.site_stat.date;
|
||||
newSiteStatOption.value.series[0].data = statInfo.value.site_stat.value;
|
||||
newSiteStatChart.setOption(newSiteStatOption.value);
|
||||
name: t('newSite'),
|
||||
type: 'line',
|
||||
data: []
|
||||
}
|
||||
]
|
||||
})
|
||||
newSiteStatOption.value.xAxis.data = statInfo.value.site_stat.date
|
||||
newSiteStatOption.value.series[0].data = statInfo.value.site_stat.value
|
||||
newSiteStatChart.setOption(newSiteStatOption.value)
|
||||
|
||||
// 站点分布
|
||||
const siteStatChart = echarts.init(siteStat.value);
|
||||
const siteStatOption = ref({
|
||||
const siteStatChart = echarts.init(siteStat.value)
|
||||
const siteStatOption:AnyObject = ref({
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
right: 20,
|
||||
@ -244,34 +255,40 @@ const drawChart = () => {
|
||||
tooltip: {},
|
||||
series: [
|
||||
{
|
||||
type: "pie",
|
||||
data: [],
|
||||
},
|
||||
],
|
||||
});
|
||||
type: 'pie',
|
||||
data: []
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
const len = statInfo.value.site_group_stat.type.length;
|
||||
const len = statInfo.value.site_group_stat.type.length
|
||||
for (let i = 0; i < len; i++) {
|
||||
let obj = {};
|
||||
obj.name = statInfo.value.site_group_stat.type[i];
|
||||
obj.value = statInfo.value.site_group_stat.value[i];
|
||||
siteStatOption.value.series[0].data.push(obj);
|
||||
const obj:{
|
||||
name: string,
|
||||
value: number
|
||||
} = {
|
||||
name: '',
|
||||
value: 0
|
||||
}
|
||||
obj.name = statInfo.value.site_group_stat.type[i]
|
||||
obj.value = statInfo.value.site_group_stat.value[i]
|
||||
siteStatOption.value.series[0].data.push(obj)
|
||||
}
|
||||
siteStatChart.setOption(siteStatOption.value);
|
||||
window.addEventListener("resize", () => {
|
||||
//页面大小变化后Echarts也更改大小
|
||||
newSiteStatChart.resize();
|
||||
siteStatChart.resize();
|
||||
});
|
||||
};
|
||||
siteStatChart.setOption(siteStatOption.value)
|
||||
window.addEventListener('resize', () => {
|
||||
// 页面大小变化后Echarts也更改大小
|
||||
newSiteStatChart.resize()
|
||||
siteStatChart.resize()
|
||||
})
|
||||
}
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
if(route.path == '/admin/index'){
|
||||
if (route.path == '/admin/index') {
|
||||
styleStore.changeStyle()
|
||||
}
|
||||
watch(() => route.path, (newval, oldval) => {
|
||||
if(newval !== '/admin/index'){
|
||||
if (newval !== '/admin/index') {
|
||||
styleStore.changeBlack()
|
||||
}
|
||||
})
|
||||
@ -279,19 +296,19 @@ watch(() => route.path, (newval, oldval) => {
|
||||
/**
|
||||
* 链接跳转
|
||||
*/
|
||||
const toLink = (link) => {
|
||||
router.push(link);
|
||||
};
|
||||
const toHref = (url:any,id:any) =>{
|
||||
router.push({
|
||||
path:url,
|
||||
query:{id}
|
||||
})
|
||||
const toLink = (link:any) => {
|
||||
router.push(link)
|
||||
}
|
||||
const toApplication = ()=>{
|
||||
const toHref = (url:any, id:any) => {
|
||||
router.push({
|
||||
path: url,
|
||||
query: { id }
|
||||
})
|
||||
}
|
||||
const toApplication = () => {
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
//更新时间
|
||||
// 更新时间
|
||||
const time = ref('')
|
||||
const nowTime = () => {
|
||||
const date = new Date()
|
||||
@ -301,7 +318,7 @@ const nowTime = () => {
|
||||
const hh = checkTime(date.getHours())
|
||||
const mm = checkTime(date.getMinutes())
|
||||
const ss = checkTime(date.getSeconds())
|
||||
function checkTime (i) {
|
||||
function checkTime (i:any) {
|
||||
if (i < 10) {
|
||||
return '0' + i
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="main-container w-full pt-[64px] bg-white" v-loading="loading">
|
||||
<div class="main-container w-full pt-[64px] bg-white" v-loading="loading">
|
||||
<div class="flex justify-between items-center h-[32px] mb-4">
|
||||
<span class="text-[20px]">{{ t('personal') }}</span>
|
||||
<span class="text-[14px] text-[#999] cursor-pointer" @click="toEditPersonal">{{ t('editPersonal') }}</span>
|
||||
@ -9,17 +9,20 @@
|
||||
<el-form-item :label="t('headImg')">
|
||||
<el-image class="w-[70px] h-[70px]" :src="img(saveInfo.head_img)" fit="contain">
|
||||
<template #error>
|
||||
<div class="image-slot bg-[#c0c4cc] flex items-center justify-center w-[70px] h-[70px] rounded-full">
|
||||
<el-icon class="!text-[#fff] !text-[45px]"><UserFilled /></el-icon>
|
||||
<div
|
||||
class="image-slot bg-[#c0c4cc] flex items-center justify-center w-[70px] h-[70px] rounded-full">
|
||||
<el-icon class="!text-[#fff] !text-[45px]">
|
||||
<UserFilled />
|
||||
</el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('userName')">
|
||||
<div>{{saveInfo.username}}</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('userName')">
|
||||
<div>{{ saveInfo.username }}</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('realName')">
|
||||
<div>{{saveInfo.real_name}}</div>
|
||||
<div>{{ saveInfo.real_name }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
@ -29,45 +32,45 @@
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance, FormRules, ElNotification } from 'element-plus'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { img } from '@/utils/common'
|
||||
import { getUserInfo,setUserInfo } from '@/app/api/personal'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { getUserInfo } from '@/app/api/personal'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
// 提交信息
|
||||
let saveInfo = reactive({
|
||||
const saveInfo = reactive({
|
||||
head_img: '',
|
||||
real_name: '',
|
||||
original_password: '',
|
||||
password: '',
|
||||
password_copy: '',
|
||||
username: ''
|
||||
});
|
||||
})
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
const loading = ref(true);
|
||||
const formRef = ref<FormInstance>()
|
||||
const loading = ref(true)
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
const getUserInfoFn = () => {
|
||||
loading.value = true;
|
||||
loading.value = true
|
||||
getUserInfo().then(res => {
|
||||
loading.value = false;
|
||||
|
||||
let data = res.data;
|
||||
saveInfo.head_img = data.head_img;
|
||||
saveInfo.real_name = data.real_name;
|
||||
saveInfo.original_password = data.original_password;
|
||||
saveInfo.password = data.password;
|
||||
saveInfo.password_copy = data.password;
|
||||
saveInfo.username = data.username;
|
||||
loading.value = false
|
||||
|
||||
const data = res.data
|
||||
saveInfo.head_img = data.head_img
|
||||
saveInfo.real_name = data.real_name
|
||||
saveInfo.original_password = data.original_password
|
||||
saveInfo.password = data.password
|
||||
saveInfo.password_copy = data.password
|
||||
saveInfo.username = data.username
|
||||
}).catch(() => {
|
||||
loading.value = false;
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
getUserInfoFn();
|
||||
getUserInfoFn()
|
||||
|
||||
// 编辑个人中心
|
||||
const toEditPersonal = () => {
|
||||
@ -76,21 +79,24 @@ const toEditPersonal = () => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.personal-body){
|
||||
:deep(.personal-body) {
|
||||
background-color: #fff;
|
||||
.el-form-item__content{
|
||||
.el-input{
|
||||
|
||||
.el-form-item__content {
|
||||
.el-input {
|
||||
width: 250px;
|
||||
}
|
||||
.el-form-item__content{
|
||||
|
||||
.el-form-item__content {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.el-button{
|
||||
|
||||
.el-button {
|
||||
margin-left: auto;
|
||||
}
|
||||
.personal-option{
|
||||
|
||||
.personal-option {
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
}</style>
|
||||
|
||||
@ -1,215 +1,211 @@
|
||||
<template>
|
||||
<div class="main-container w-[375px] mx-auto mt-[20px] mb-[40px] relative">
|
||||
<div class="main-container w-[375px] mx-auto mt-[20px] mb-[40px] relative">
|
||||
|
||||
<div class="flex full-container">
|
||||
<iframe v-show="loadingIframe" class="w-[375px]" :src="wapPreview" frameborder="0"
|
||||
id="previewIframe"></iframe>
|
||||
<div v-show="loadingDev" class="w-[375px] border border-slate-100 bg-body 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="flex full-container">
|
||||
<iframe v-show="loadingIframe" class="w-[375px]" :src="wapPreview" frameborder="0" id="previewIframe"></iframe>
|
||||
<div v-show="loadingDev" class="w-[375px] border border-slate-100 bg-body 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-[400px] absolute bg-body top-[10%] -right-[450px]" v-if="loadingIframe">
|
||||
<div class="w-[400px] absolute bg-body top-[10%] -right-[450px]" v-if="loadingIframe">
|
||||
|
||||
<div class="info-wrap mt-[20px]">
|
||||
<div class="info-wrap mt-[20px]">
|
||||
|
||||
<div class="px-[20px] pb-[10px] font-bold">{{t('h5')}}</div>
|
||||
<el-form label-width="40px" class="px-[20px]">
|
||||
<div class="px-[20px] pb-[10px] font-bold">{{ t('h5') }}</div>
|
||||
<el-form label-width="40px" class="px-[20px]">
|
||||
|
||||
<el-form-item :label="t('link')" v-show="wapPreview">
|
||||
<el-input readonly :value="wapPreview">
|
||||
<template #append>
|
||||
<el-button @click="copyEvent(wapPreview)" class="bg-primary copy">{{ t('copy') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('link')" v-show="wapPreview">
|
||||
<el-input readonly :value="wapPreview">
|
||||
<template #append>
|
||||
<el-button @click="copyEvent(wapPreview)" class="bg-primary copy">{{ t('copy') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label=" " v-show="wapImage">
|
||||
<el-image :src="wapImage"/>
|
||||
</el-form-item>
|
||||
<el-form-item label=" " v-show="wapImage">
|
||||
<el-image :src="wapImage" />
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
</el-form>
|
||||
|
||||
<div class="px-[20px] pb-[10px] font-bold mt-[40px]">{{t('weapp')}}</div>
|
||||
<el-form label-width="40px" class="px-[20px]">
|
||||
<el-form-item label=" " v-if="weappConfig.qr_code">
|
||||
<el-image class="w-[100px] h-[100px]" :src="img(weappConfig.qr_code)"/>
|
||||
</el-form-item>
|
||||
<el-form-item label=" " v-else>
|
||||
<span class="text-gray-400">{{t('weappNotSet')}}</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="px-[20px] pb-[10px] font-bold mt-[40px]">{{ t('weapp') }}</div>
|
||||
<el-form label-width="40px" class="px-[20px]">
|
||||
<el-form-item label=" " v-if="weappConfig.qr_code">
|
||||
<el-image class="w-[100px] h-[100px]" :src="img(weappConfig.qr_code)" />
|
||||
</el-form-item>
|
||||
<el-form-item label=" " v-else>
|
||||
<span class="text-gray-400">{{ t('weappNotSet') }}</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {ref, reactive, watch} from 'vue'
|
||||
import {t} from '@/lang'
|
||||
import {useRoute} from 'vue-router'
|
||||
import {getWeappConfig} from '@/app/api/weapp'
|
||||
import {getUrl} from '@/app/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'
|
||||
import { ref, reactive, watch } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { getWeappConfig } from '@/app/api/weapp'
|
||||
import { getUrl } from '@/app/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('')
|
||||
const wapUrl = ref('')
|
||||
const wapDomain = ref('')
|
||||
const wapImage = ref('')
|
||||
const wapPreview = ref('')
|
||||
|
||||
const loadingIframe = ref(false) // 加载iframe
|
||||
const loadingDev = ref(false) // 加载开发环境配置
|
||||
const timeIframe = ref(0) // iframe打开时间
|
||||
const difference = ref(0) // 检测页面加载差异,小于1000毫秒,则配置wap端域名
|
||||
const loadingIframe = ref(false) // 加载iframe
|
||||
const loadingDev = ref(false) // 加载开发环境配置
|
||||
const timeIframe = ref(0) // iframe打开时间
|
||||
const difference = ref(0) // 检测页面加载差异,小于1000毫秒,则配置wap端域名
|
||||
|
||||
var time = new Date().getTime();
|
||||
const route = useRoute();
|
||||
route.query.page = route.query.page || ''; // 页面路径
|
||||
const route = useRoute()
|
||||
route.query.page = route.query.page || '' // 页面路径
|
||||
|
||||
getUrl().then((res: any) => {
|
||||
wapUrl.value = res.data.wap_url;
|
||||
setDomain();
|
||||
getUrl().then((res: any) => {
|
||||
wapUrl.value = res.data.wap_url
|
||||
setDomain()
|
||||
|
||||
// 生产模式禁止
|
||||
if (import.meta.env.MODE == 'production') return;
|
||||
// 生产模式禁止
|
||||
if (import.meta.env.MODE == 'production') return
|
||||
|
||||
wapDomain.value = res.data.wap_domain;
|
||||
wapDomain.value = res.data.wap_domain
|
||||
|
||||
// env文件配置过wap域名
|
||||
if (wapDomain.value) {
|
||||
wapUrl.value = wapDomain.value + '/wap';
|
||||
setDomain();
|
||||
}
|
||||
|
||||
let wap_domain_storage = storage.get('wap_domain');
|
||||
if (wap_domain_storage) {
|
||||
wapUrl.value = wap_domain_storage;
|
||||
setDomain();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
const save = () => {
|
||||
if (wapDomain.value.trim().length == 0) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: `${t('wapDomainPlaceholder')}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
wapUrl.value = wapDomain.value + '/wap';
|
||||
setDomain();
|
||||
storage.set({key: 'wap_domain', data: wapUrl.value});
|
||||
loadingIframe.value = true;
|
||||
loadingDev.value = false;
|
||||
// env文件配置过wap域名
|
||||
if (wapDomain.value) {
|
||||
wapUrl.value = wapDomain.value + '/wap'
|
||||
setDomain()
|
||||
}
|
||||
|
||||
const setDomain = () => {
|
||||
if (route.query.page) {
|
||||
wapPreview.value = `${wapUrl.value}${route.query.page}`;
|
||||
console.log(wapPreview.value)
|
||||
// errorCorrectionLevel:密度容错率L(低)H(高)
|
||||
QRCode.toDataURL(wapPreview.value, {errorCorrectionLevel: 'L', margin: 0, width: 100}).then(url => {
|
||||
wapImage.value = url
|
||||
})
|
||||
timeIframe.value = new Date().getTime();
|
||||
setTimeout(() => {
|
||||
if (difference.value == 0) initLoad();
|
||||
}, 1000 * 2);
|
||||
}
|
||||
const wap_domain_storage = storage.get('wap_domain')
|
||||
if (wap_domain_storage) {
|
||||
wapUrl.value = wap_domain_storage
|
||||
setDomain()
|
||||
}
|
||||
})
|
||||
|
||||
// 监听 uni-app 端 是否加载完成
|
||||
window.addEventListener('message', (event) => {
|
||||
try {
|
||||
let data = JSON.parse(event.data);
|
||||
if (['appOnLaunch', 'appOnReady'].indexOf(data.type) != -1) {
|
||||
loadingDev.value = false;
|
||||
loadingIframe.value = true;
|
||||
var loadTime = new Date().getTime();
|
||||
difference.value = loadTime - timeIframe.value;
|
||||
}
|
||||
} catch (e) {
|
||||
initLoad();
|
||||
console.log('后台接受数据错误', e)
|
||||
}
|
||||
}, false);
|
||||
|
||||
// 将数据发送到uniapp
|
||||
const postMessage = () => {
|
||||
let data = JSON.stringify({
|
||||
type: 'appOnReady',
|
||||
message: '加载完成'
|
||||
});
|
||||
if (window.previewIframe) window.previewIframe.contentWindow.postMessage(data, '*');
|
||||
};
|
||||
|
||||
// 初始化加载状态
|
||||
const initLoad = () => {
|
||||
loadingDev.value = true;
|
||||
loadingIframe.value = false;
|
||||
wapPreview.value = '';
|
||||
wapImage.value = '';
|
||||
const save = () => {
|
||||
if (wapDomain.value.trim().length == 0) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: `${t('wapDomainPlaceholder')}`
|
||||
})
|
||||
return
|
||||
}
|
||||
wapUrl.value = wapDomain.value + '/wap'
|
||||
setDomain()
|
||||
storage.set({ key: 'wap_domain', data: wapUrl.value })
|
||||
loadingIframe.value = true
|
||||
loadingDev.value = false
|
||||
}
|
||||
|
||||
const weappConfig = reactive({
|
||||
qr_code: ''
|
||||
const setDomain = () => {
|
||||
if (route.query.page) {
|
||||
wapPreview.value = `${wapUrl.value}${route.query.page}`
|
||||
console.log(wapPreview.value)
|
||||
// errorCorrectionLevel:密度容错率L(低)H(高)
|
||||
QRCode.toDataURL(wapPreview.value, { errorCorrectionLevel: 'L', margin: 0, width: 100 }).then(url => {
|
||||
wapImage.value = url
|
||||
})
|
||||
timeIframe.value = new Date().getTime()
|
||||
setTimeout(() => {
|
||||
if (difference.value == 0) initLoad()
|
||||
}, 1000 * 2)
|
||||
}
|
||||
}
|
||||
|
||||
// 监听 uni-app 端 是否加载完成
|
||||
window.addEventListener('message', (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data)
|
||||
if (['appOnLaunch', 'appOnReady'].indexOf(data.type) != -1) {
|
||||
loadingDev.value = false
|
||||
loadingIframe.value = true
|
||||
const loadTime = new Date().getTime()
|
||||
difference.value = loadTime - timeIframe.value
|
||||
}
|
||||
} catch (e) {
|
||||
initLoad()
|
||||
console.log('后台接受数据错误', e)
|
||||
}
|
||||
}, false)
|
||||
|
||||
// 将数据发送到uniapp
|
||||
const postMessage = () => {
|
||||
const data = JSON.stringify({
|
||||
type: 'appOnReady',
|
||||
message: '加载完成'
|
||||
})
|
||||
if (window.previewIframe) window.previewIframe.contentWindow.postMessage(data, '*')
|
||||
}
|
||||
|
||||
// 获取微信配置
|
||||
getWeappConfig().then((res: any) => {
|
||||
if (res.code == 1) {
|
||||
let data = res.data;
|
||||
weappConfig.qr_code = data.qr_code;
|
||||
}
|
||||
})
|
||||
// 初始化加载状态
|
||||
const initLoad = () => {
|
||||
loadingDev.value = true
|
||||
loadingIframe.value = false
|
||||
wapPreview.value = ''
|
||||
wapImage.value = ''
|
||||
}
|
||||
|
||||
// 复制
|
||||
const {copy, isSupported, copied} = useClipboard()
|
||||
const copyEvent = (text: string) => {
|
||||
if (!isSupported.value) {
|
||||
ElMessage({
|
||||
message: t('notSupportCopy'),
|
||||
type: 'warning'
|
||||
})
|
||||
}
|
||||
copy(text)
|
||||
const weappConfig = reactive({
|
||||
qr_code: ''
|
||||
})
|
||||
|
||||
// 获取微信配置
|
||||
getWeappConfig().then((res: any) => {
|
||||
if (res.code == 1) {
|
||||
const data = res.data
|
||||
weappConfig.qr_code = data.qr_code
|
||||
}
|
||||
})
|
||||
|
||||
watch(copied, () => {
|
||||
if (copied.value) {
|
||||
ElMessage({
|
||||
message: t('copySuccess'),
|
||||
type: 'success'
|
||||
})
|
||||
}
|
||||
})
|
||||
// 复制
|
||||
const { copy, isSupported, copied } = useClipboard()
|
||||
const copyEvent = (text: string) => {
|
||||
if (!isSupported.value) {
|
||||
ElMessage({
|
||||
message: t('notSupportCopy'),
|
||||
type: 'warning'
|
||||
})
|
||||
}
|
||||
copy(text)
|
||||
}
|
||||
|
||||
watch(copied, () => {
|
||||
if (copied.value) {
|
||||
ElMessage({
|
||||
message: t('copySuccess'),
|
||||
type: 'success'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
body {
|
||||
background: #edf0f3;
|
||||
}
|
||||
body {
|
||||
background: #edf0f3;
|
||||
}
|
||||
|
||||
.copy {
|
||||
background: var(--el-color-primary) !important;
|
||||
color: var(--el-color-white) !important;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.copy {
|
||||
background: var(--el-color-primary) !important;
|
||||
color: var(--el-color-white) !important;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -249,7 +249,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]"
|
||||
v-for="item in installCheckResult.dir.is_readable">
|
||||
v-for="(item,index) in installCheckResult.dir.is_readable" :key="index">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
@ -266,7 +266,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]"
|
||||
v-for="item in installCheckResult.dir.is_write">
|
||||
v-for="(item,index) in installCheckResult.dir.is_write" :key="index">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
@ -308,7 +308,7 @@
|
||||
<div v-show="installStep == 3" class="h-[50vh] mt-[20px] flex flex-col">
|
||||
<el-result icon="success" :title="t('addonInstallSuccess')"></el-result>
|
||||
<!-- 提示信息 -->
|
||||
<div v-for="item in installAfterTips" class="mb-[10px]">
|
||||
<div v-for="(item,index) in installAfterTips" class="mb-[10px]" :key="index">
|
||||
<el-alert :title="item" type="error" :closable="false" />
|
||||
</div>
|
||||
</div>
|
||||
@ -333,7 +333,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]"
|
||||
v-for="item in uninstallCheckResult.dir.is_readable">
|
||||
v-for="(item,index) in uninstallCheckResult.dir.is_readable" :key="index">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
@ -349,7 +349,7 @@
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]" v-for="item in uninstallCheckResult.dir.is_write">
|
||||
<el-row class="pb-[10px] items pl-[15px]" v-for="(item,index) in uninstallCheckResult.dir.is_write" :key="index">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
@ -394,7 +394,6 @@ import { t } from '@/lang'
|
||||
import { getAddonLocal, uninstallAddon, installAddon, preInstallCheck, cloudInstallAddon, getAddonInstalltask, getAddonCloudInstallLog, preUninstallCheck, cancelInstall } from '@/app/api/addon'
|
||||
import { downloadVersion, getAuthinfo, setAuthinfo } from '@/app/api/module'
|
||||
import { ElMessage, ElMessageBox, ElNotification, FormInstance, FormRules } from 'element-plus'
|
||||
import { img } from '@/utils/common'
|
||||
import 'vue-web-terminal/lib/theme/dark.css'
|
||||
import { Terminal, TerminalFlash } from 'vue-web-terminal'
|
||||
import { findFirstValidRoute } from '@/router/routers'
|
||||
@ -421,7 +420,7 @@ const downEventHintFn = () => {
|
||||
downEvent(currDownData.value, true)
|
||||
}
|
||||
|
||||
const activeNameTabFn = (data) => {
|
||||
const activeNameTabFn = (data:any) => {
|
||||
activeName.value = data
|
||||
storage.set({ key: 'storeActiveName', data })
|
||||
}
|
||||
@ -563,7 +562,7 @@ const onExecCmd = (key, command, success, failed, name)=> {
|
||||
}
|
||||
|
||||
function makeIterator(array: string[]) {
|
||||
var nextIndex = 0
|
||||
let nextIndex = 0
|
||||
return {
|
||||
next() {
|
||||
if ((nextIndex + 1) == array.length) {
|
||||
@ -614,6 +613,7 @@ const getInstallTask = (first: boolean = true) => {
|
||||
}
|
||||
}
|
||||
if (res.data.error) {
|
||||
ElMessage({ message: '插件安装失败', type: 'error', duration: 5000 })
|
||||
return
|
||||
}
|
||||
if (res.data.mode == 'cloud') {
|
||||
@ -982,6 +982,9 @@ html.dark .table-head-bg {
|
||||
height: calc(100vh - 120px);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
:deep(.terminal .t-log-box span) {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
|
||||
@ -123,28 +123,22 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {reactive, ref, onMounted, computed} from 'vue'
|
||||
import {t} from '@/lang'
|
||||
import {getAuthaddon} from '@/app/api/auth'
|
||||
import {img} from '@/utils/common'
|
||||
import {useRouter} from 'vue-router'
|
||||
import storage from '@/utils/storage'
|
||||
import {findFirstValidRoute} from '@/router/routers'
|
||||
import {UserFilled} from '@element-plus/icons-vue'
|
||||
import useSystemStore from '@/stores/modules/system'
|
||||
|
||||
const systemStore = useSystemStore()
|
||||
systemStore.setHeadMenu('');
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import useSystemStore from '@/stores/modules/system'
|
||||
|
||||
const router = useRouter()
|
||||
let developerDialogVisible = ref(false)
|
||||
const systemStore = useSystemStore()
|
||||
systemStore.setHeadMenu('')
|
||||
|
||||
const toLink = (link)=>{
|
||||
router.push(link)
|
||||
}
|
||||
const goRouter = () => {
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
const router = useRouter()
|
||||
const developerDialogVisible = ref(false)
|
||||
|
||||
const toLink = (link:any) => {
|
||||
router.push(link)
|
||||
}
|
||||
const goRouter = () => {
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -129,7 +129,7 @@ if (loginType.value == 'site') {
|
||||
|
||||
// 验证码 - start
|
||||
const verifyRef = ref(null)
|
||||
const success = (params) => {
|
||||
const success = (params:any) => {
|
||||
loginFn({ captcha_code: params.captchaVerification })
|
||||
}
|
||||
// 验证码 - end
|
||||
@ -178,7 +178,7 @@ const loginFn = (data = {}) => {
|
||||
const { query: { redirect } } = route
|
||||
const path = typeof redirect === 'string' ? redirect : '/'
|
||||
router.push(path)
|
||||
}).catch(err => {
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,23 +1,24 @@
|
||||
<template>
|
||||
<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-[20px]">{{pageName}}</span>
|
||||
<div class="flex justify-between items-center mb-[5px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none base-bg !px-[35px]" shadow="never">
|
||||
<el-row class="flex">
|
||||
<el-col :span="8" class="min-w-[100px]">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="balanceStatistics.money && balanceStatistics.balance ? (Number.parseFloat(balanceStatistics.money)+Number.parseFloat(balanceStatistics.balance)).toFixed(2) : '0.00'"></el-statistic>
|
||||
<el-card class="box-card !border-none base-bg !px-[35px]" shadow="never">
|
||||
<el-row class="flex">
|
||||
<el-col :span="8" class="min-w-[100px]">
|
||||
<div class="statistic-card">
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8" class="min-w-[100px]">
|
||||
<div class="statistic-card">
|
||||
</el-col>
|
||||
<el-col :span="8" class="min-w-[100px]">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="balanceStatistics.money"></el-statistic>
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-[#666]">
|
||||
@ -25,9 +26,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8" class="min-w-[100px]">
|
||||
<div class="statistic-card">
|
||||
</el-col>
|
||||
<el-col :span="8" class="min-w-[100px]">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="balanceStatistics.balance"></el-statistic>
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-[#666]">
|
||||
@ -35,37 +36,36 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<el-card class="box-card !border-none mb-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="memberAccountLogTableData.searchParam" ref="searchFormRef">
|
||||
|
||||
<el-form-item :label="t('memberInfo')" prop="keywords">
|
||||
<el-input v-model="memberAccountLogTableData.searchParam.keywords" class="w-[240px]" :placeholder="t('memberInfoPlaceholder')" />
|
||||
<el-form-item :label="t('memberInfo')" prop="keywords">
|
||||
<el-input v-model="memberAccountLogTableData.searchParam.keywords" class="w-[240px]"
|
||||
:placeholder="t('memberInfoPlaceholder')" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('balanceType')" prop="from_type">
|
||||
<el-select v-model="memberAccountLogTableData.balance_type" clearable :placeholder="t('fromTypePlaceholder')" class="input-width" @change="checkAccountType">
|
||||
<el-option :label="t('selectPlaceholder')" value="" />
|
||||
<el-option :label="item.name" :value="item.type" v-for="(item,key) in balanceStatus" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('balanceType')" prop="from_type">
|
||||
<el-select v-model="memberAccountLogTableData.balance_type" clearable
|
||||
:placeholder="t('fromTypePlaceholder')" class="input-width" @change="checkAccountType">
|
||||
<el-option :label="t('selectPlaceholder')" value="" />
|
||||
<el-option :label="item.name" :value="item.type" v-for="(item, key) in balanceStatus" :key="key"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('fromType')" prop="from_type">
|
||||
<el-select v-model="memberAccountLogTableData.searchParam.from_type" clearable :placeholder="t('fromTypePlaceholder')" class="input-width">
|
||||
<el-select v-model="memberAccountLogTableData.searchParam.from_type" clearable
|
||||
:placeholder="t('fromTypePlaceholder')" class="input-width">
|
||||
<el-option :label="t('selectPlaceholder')" value="" />
|
||||
<el-option :label="item.name" :value="key" v-for="(item,key) in fromTypeList" />
|
||||
<el-option :label="item.name" :value="key" v-for="(item, key) in fromTypeList" :key="key"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('createTime')" prop="create_time">
|
||||
<el-date-picker
|
||||
v-model="memberAccountLogTableData.searchParam.create_time"
|
||||
type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')"
|
||||
/>
|
||||
<el-date-picker v-model="memberAccountLogTableData.searchParam.create_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadMemberAccountLogList()">{{ t('search') }}</el-button>
|
||||
@ -81,48 +81,52 @@
|
||||
<template #empty>
|
||||
<span>{{ !memberAccountLogTableData.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
<el-table-column prop="member_id" :label="t('memberId')" min-width="80" :show-overflow-tooltip="true">
|
||||
<el-table-column prop="member_id" :label="t('memberId')" min-width="80" :show-overflow-tooltip="true">
|
||||
<template #default="{ row }">
|
||||
{{ row.member.member_no }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('memberInfo')" min-width="140" :show-overflow-tooltip="true">
|
||||
<el-table-column :label="t('memberInfo')" min-width="140" :show-overflow-tooltip="true">
|
||||
<template #default="{ row }">
|
||||
<div class="flex items-center cursor-pointer" @click="toMember(row.member_id)">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg" :src="img(row.member.headimg)" alt="" >
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/app/assets/images/default_headimg.png" alt="" >
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg"
|
||||
:src="img(row.member.headimg)" alt="">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-else
|
||||
src="@/app/assets/images/default_headimg.png" alt="">
|
||||
<div class="flex flex flex-col">
|
||||
<span class="">{{ row.member.nickname || '' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="mobile" :label="t('mobile')" min-width="90">
|
||||
<template #default="{ row }">
|
||||
{{ row.member.mobile || '' }}
|
||||
<el-table-column prop="mobile" :label="t('mobile')" min-width="90">
|
||||
<template #default="{ row }">
|
||||
{{ row.member.mobile || '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column prop="account_data" :label="t('accountData')" min-width="70" align="right">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.account_data >= 0">+{{ row.account_data }}</span>
|
||||
<span v-else>{{ row.account_data }}</span>
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.account_data >= 0">+{{ row.account_data }}</span>
|
||||
<span v-else>{{ row.account_data }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="account_sum" :label="t('accountSum')" min-width="110" align="right"/>
|
||||
<el-table-column prop="account_type_name" :label="t('balanceType')" min-width="150" align="center" />
|
||||
<el-table-column prop="from_type_name" :label="t('fromType')" min-width="120" align=""/>
|
||||
<el-table-column prop="create_time" :show-overflow-tooltip="true" :label="t('createTime')" min-width="150" />
|
||||
</el-table-column>
|
||||
<el-table-column prop="account_sum" :label="t('accountSum')" min-width="110" align="right" />
|
||||
<el-table-column prop="account_type_name" :label="t('balanceType')" min-width="150" align="center" />
|
||||
<el-table-column prop="from_type_name" :label="t('fromType')" min-width="120" align="" />
|
||||
<el-table-column prop="create_time" :show-overflow-tooltip="true" :label="t('createTime')"
|
||||
min-width="150" />
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right" width="100">
|
||||
<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>
|
||||
<div class="mt-[16px] flex justify-end">
|
||||
<el-pagination v-model:current-page="memberAccountLogTableData.page" v-model:page-size="memberAccountLogTableData.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="memberAccountLogTableData.total"
|
||||
@size-change="loadMemberAccountLogList()" @current-change="loadMemberAccountLogList" />
|
||||
<el-pagination v-model:current-page="memberAccountLogTableData.page"
|
||||
v-model:page-size="memberAccountLogTableData.limit" layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="memberAccountLogTableData.total" @size-change="loadMemberAccountLogList()"
|
||||
@current-change="loadMemberAccountLogList" />
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
@ -134,54 +138,53 @@
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import {
|
||||
getBalanceList,
|
||||
getChangeTypeList,
|
||||
getBalanceSum,
|
||||
getBalanceStatus,
|
||||
getMoneyList,
|
||||
getAccountType,
|
||||
getBalanceList,
|
||||
getChangeTypeList,
|
||||
getBalanceSum,
|
||||
getBalanceStatus,
|
||||
getMoneyList,
|
||||
getAccountType
|
||||
} from '@/app/api/member'
|
||||
import { FormInstance } from 'element-plus'
|
||||
import { img } from '@/utils/common'
|
||||
import balanceInfo from '@/app/views/member/components/member-balance-info.vue'
|
||||
import { useRoute,useRouter } from 'vue-router'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const member_id: number = parseInt(route.query.id || 0)
|
||||
const pageName = route.meta.title;
|
||||
const pageName = route.meta.title
|
||||
|
||||
let memberAccountLogTableData = reactive({
|
||||
const memberAccountLogTableData = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam:{
|
||||
keywords:"",
|
||||
from_type:"",
|
||||
create_time:"",
|
||||
mobile:"",
|
||||
member_id,
|
||||
searchParam: {
|
||||
keywords: '',
|
||||
from_type: '',
|
||||
create_time: '',
|
||||
mobile: '',
|
||||
member_id: member_id
|
||||
|
||||
},
|
||||
balance_type: ""
|
||||
balance_type: ''
|
||||
})
|
||||
|
||||
let fromTypeList = ref([])
|
||||
const fromTypeList = ref([])
|
||||
|
||||
const setFromTypeList = async () => {
|
||||
fromTypeList.value = await (await getChangeTypeList('balance')).data
|
||||
}
|
||||
|
||||
setFromTypeList();
|
||||
setFromTypeList()
|
||||
|
||||
const searchFormRef = ref<FormInstance>()
|
||||
|
||||
|
||||
const resetForm = (formEl: FormInstance | undefined)=>{
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields();
|
||||
loadMemberAccountLogList();
|
||||
formEl.resetFields()
|
||||
loadMemberAccountLogList()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -190,32 +193,31 @@ const resetForm = (formEl: FormInstance | undefined)=>{
|
||||
const loadMemberAccountLogList = (page: number = 1) => {
|
||||
memberAccountLogTableData.loading = true
|
||||
memberAccountLogTableData.page = page
|
||||
if(memberAccountLogTableData.balance_type == "" || memberAccountLogTableData.balance_type == "balance"){
|
||||
getBalanceList({
|
||||
page: memberAccountLogTableData.page,
|
||||
limit: memberAccountLogTableData.limit,
|
||||
...memberAccountLogTableData.searchParam
|
||||
}).then(res => {
|
||||
memberAccountLogTableData.loading = false
|
||||
memberAccountLogTableData.data = res.data.data
|
||||
memberAccountLogTableData.total = res.data.total
|
||||
}).catch(() => {
|
||||
memberAccountLogTableData.loading = false
|
||||
})
|
||||
}else{
|
||||
getMoneyList({
|
||||
page: memberAccountLogTableData.page,
|
||||
limit: memberAccountLogTableData.limit,
|
||||
...memberAccountLogTableData.searchParam
|
||||
}).then(res => {
|
||||
memberAccountLogTableData.loading = false
|
||||
memberAccountLogTableData.data = res.data.data
|
||||
memberAccountLogTableData.total = res.data.total
|
||||
}).catch(() => {
|
||||
memberAccountLogTableData.loading = false
|
||||
})
|
||||
}
|
||||
|
||||
if (memberAccountLogTableData.balance_type == '' || memberAccountLogTableData.balance_type == 'balance') {
|
||||
getBalanceList({
|
||||
page: memberAccountLogTableData.page,
|
||||
limit: memberAccountLogTableData.limit,
|
||||
...memberAccountLogTableData.searchParam
|
||||
}).then(res => {
|
||||
memberAccountLogTableData.loading = false
|
||||
memberAccountLogTableData.data = res.data.data
|
||||
memberAccountLogTableData.total = res.data.total
|
||||
}).catch(() => {
|
||||
memberAccountLogTableData.loading = false
|
||||
})
|
||||
} else {
|
||||
getMoneyList({
|
||||
page: memberAccountLogTableData.page,
|
||||
limit: memberAccountLogTableData.limit,
|
||||
...memberAccountLogTableData.searchParam
|
||||
}).then(res => {
|
||||
memberAccountLogTableData.loading = false
|
||||
memberAccountLogTableData.data = res.data.data
|
||||
memberAccountLogTableData.total = res.data.total
|
||||
}).catch(() => {
|
||||
memberAccountLogTableData.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
loadMemberAccountLogList()
|
||||
|
||||
@ -224,7 +226,7 @@ const balanceDialog: Record<string, any> | null = ref(null)
|
||||
* 查看详情
|
||||
* @param data
|
||||
*/
|
||||
const infoEvent = (data: any) => {
|
||||
const infoEvent = (data: any) => {
|
||||
balanceDialog.value.setFormData(data)
|
||||
balanceDialog.value.showDialog = true
|
||||
}
|
||||
@ -234,7 +236,7 @@ const router = useRouter()
|
||||
/**
|
||||
* 会员详情
|
||||
*/
|
||||
const toMember = (member_id:number) => {
|
||||
const toMember = (member_id: number) => {
|
||||
router.push(`/member/detail?id=${member_id}`)
|
||||
}
|
||||
|
||||
@ -243,37 +245,37 @@ const toMember = (member_id:number) => {
|
||||
*/
|
||||
const balanceStatistics = ref([])
|
||||
const checkBalanceInfo = () => {
|
||||
getBalanceSum({
|
||||
member_id
|
||||
}).then(res => {
|
||||
balanceStatistics.value = res.data;
|
||||
})
|
||||
getBalanceSum({
|
||||
member_id
|
||||
}).then(res => {
|
||||
balanceStatistics.value = res.data
|
||||
})
|
||||
}
|
||||
checkBalanceInfo()
|
||||
|
||||
//获取余额类型
|
||||
// 获取余额类型
|
||||
const balanceStatus = ref([])
|
||||
const checkBalanceStatus = () => {
|
||||
getBalanceStatus().then(res => {
|
||||
for (var i in res.data) {
|
||||
if(i == 'balance' || i == 'money'){
|
||||
balanceStatus.value.push({"name" : res.data[i], "type" : i})
|
||||
}
|
||||
}
|
||||
})
|
||||
getBalanceStatus().then(res => {
|
||||
for (var i in res.data) {
|
||||
if (i == 'balance' || i == 'money') {
|
||||
balanceStatus.value.push({ 'name': res.data[i], 'type': i })
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
checkBalanceStatus()
|
||||
|
||||
const checkAccountType = () => {
|
||||
let account_type = memberAccountLogTableData.balance_type;
|
||||
if(memberAccountLogTableData.balance_type == ""){
|
||||
account_type = "balance"
|
||||
}
|
||||
getAccountType({
|
||||
account_type
|
||||
}).then(res => {
|
||||
fromTypeList.value = res.data;
|
||||
})
|
||||
let account_type = memberAccountLogTableData.balance_type
|
||||
if (memberAccountLogTableData.balance_type == '') {
|
||||
account_type = 'balance'
|
||||
}
|
||||
getAccountType({
|
||||
account_type
|
||||
}).then(res => {
|
||||
fromTypeList.value = res.data
|
||||
})
|
||||
}
|
||||
checkAccountType()
|
||||
|
||||
|
||||
@ -2,72 +2,74 @@
|
||||
<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-[20px]">{{pageName}}</span>
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none base-bg !px-[35px]" shadow="never">
|
||||
<el-row class="flex">
|
||||
<el-col :span="6" class="min-w-[100px]">
|
||||
<el-row class="flex">
|
||||
<el-col :span="6" class="min-w-[100px]">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="commissionStatistics.total_commission ? Number.parseFloat(commissionStatistics.total_commission).toFixed(2) : '0.00'"></el-statistic>
|
||||
<el-statistic
|
||||
:value="commissionStatistics.total_commission ? Number.parseFloat(commissionStatistics.total_commission).toFixed(2) : '0.00'"></el-statistic>
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-[#666]">
|
||||
<span>{{ t('totalCommission') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6" class="min-w-[100px]">
|
||||
</el-col>
|
||||
<el-col :span="6" class="min-w-[100px]">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="commissionStatistics.commission ? Number.parseFloat(commissionStatistics.commission).toFixed(2) : '0.00'"></el-statistic>
|
||||
<el-statistic
|
||||
:value="commissionStatistics.commission ? Number.parseFloat(commissionStatistics.commission).toFixed(2) : '0.00'"></el-statistic>
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-[#666]">
|
||||
<span>{{ t('commission') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6" class="min-w-[100px]">
|
||||
</el-col>
|
||||
<el-col :span="6" class="min-w-[100px]">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="commissionStatistics.withdrawn_commission ? Number.parseFloat(commissionStatistics.withdrawn_commission).toFixed(2) : '0.00'"></el-statistic>
|
||||
<el-statistic
|
||||
:value="commissionStatistics.withdrawn_commission ? Number.parseFloat(commissionStatistics.withdrawn_commission).toFixed(2) : '0.00'"></el-statistic>
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-[#666]">
|
||||
<span>{{ t('withdrawnCommission') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-col>
|
||||
<el-col :span="6" class="min-w-[100px]">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="commissionStatistics.commission_cash_outing ? Number.parseFloat(commissionStatistics.commission_cash_outing).toFixed(2) : '0.00'"></el-statistic>
|
||||
<el-statistic
|
||||
:value="commissionStatistics.commission_cash_outing ? Number.parseFloat(commissionStatistics.commission_cash_outing).toFixed(2) : '0.00'"></el-statistic>
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-[#666]">
|
||||
<span>{{ t('cashOutingCommission') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card !border-none mb-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="memberAccountLogTableData.searchParam" ref="searchFormRef">
|
||||
<el-form-item :label="t('memberInfo')" prop="keywords">
|
||||
<el-input v-model="memberAccountLogTableData.searchParam.keywords" class="w-[240px]" :placeholder="t('memberInfoPlaceholder')" />
|
||||
<el-input v-model="memberAccountLogTableData.searchParam.keywords" class="w-[240px]"
|
||||
:placeholder="t('memberInfoPlaceholder')" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('fromType')" prop="from_type">
|
||||
<el-select v-model="memberAccountLogTableData.searchParam.from_type" clearable :placeholder="t('fromTypePlaceholder')" class="input-width">
|
||||
<el-select v-model="memberAccountLogTableData.searchParam.from_type" clearable
|
||||
:placeholder="t('fromTypePlaceholder')" class="input-width">
|
||||
<el-option :label="t('selectPlaceholder')" value="" />
|
||||
<el-option :label="item.name" :value="key" v-for="(item,key) in fromTypeList" />
|
||||
<el-option :label="item.name" :value="key" v-for="(item, key) in fromTypeList" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('createTime')" prop="create_time">
|
||||
<el-date-picker
|
||||
v-model="memberAccountLogTableData.searchParam.create_time"
|
||||
type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')"
|
||||
/>
|
||||
<el-date-picker v-model="memberAccountLogTableData.searchParam.create_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadMemberAccountLogList()">{{ t('search') }}</el-button>
|
||||
@ -89,45 +91,49 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column :label="t('memberInfo')" min-width="150" :show-overflow-tooltip="true">
|
||||
<el-table-column :label="t('memberInfo')" min-width="150" :show-overflow-tooltip="true">
|
||||
<template #default="{ row }">
|
||||
<div class="flex items-center cursor-pointer" @click="toMember(row.member_id)">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg" :src="img(row.member.headimg)" alt="" >
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/app/assets/images/default_headimg.png" alt="" >
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg"
|
||||
:src="img(row.member.headimg)" alt="">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-else
|
||||
src="@/app/assets/images/default_headimg.png" alt="">
|
||||
<div class="flex flex flex-col">
|
||||
<span class="">{{ row.member.nickname || '' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="mobile" :label="t('mobile')" min-width="100">
|
||||
<template #default="{ row }">
|
||||
{{ row.member.mobile || '' }}
|
||||
<el-table-column prop="mobile" :label="t('mobile')" min-width="100">
|
||||
<template #default="{ row }">
|
||||
{{ row.member.mobile || '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="account_data" :label="t('accountData')" min-width="80" align="right">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.account_data >= 0">+{{ row.account_data }}</span>
|
||||
<span v-else>{{ row.account_data }}</span>
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.account_data >= 0">+{{ row.account_data }}</span>
|
||||
<span v-else>{{ row.account_data }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="account_sum" :label="t('accountSum')" min-width="120" align="right"/>
|
||||
<el-table-column prop="from_type_name" :label="t('fromType')" min-width="180" align="center"/>
|
||||
<el-table-column prop="create_time" :show-overflow-tooltip="true" :label="t('createTime')" min-width="150" />
|
||||
<el-table-column prop="account_sum" :label="t('accountSum')" min-width="120" align="right" />
|
||||
<el-table-column prop="from_type_name" :label="t('fromType')" min-width="180" align="center" />
|
||||
<el-table-column prop="create_time" :show-overflow-tooltip="true" :label="t('createTime')"
|
||||
min-width="150" />
|
||||
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right" width="100">
|
||||
<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>
|
||||
<div class="mt-[16px] flex justify-end">
|
||||
<el-pagination v-model:current-page="memberAccountLogTableData.page" v-model:page-size="memberAccountLogTableData.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="memberAccountLogTableData.total"
|
||||
@size-change="loadMemberAccountLogList()" @current-change="loadMemberAccountLogList" />
|
||||
<el-pagination v-model:current-page="memberAccountLogTableData.page"
|
||||
v-model:page-size="memberAccountLogTableData.limit" layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="memberAccountLogTableData.total" @size-change="loadMemberAccountLogList()"
|
||||
@current-change="loadMemberAccountLogList" />
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
@ -139,58 +145,57 @@
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { FormInstance } from 'element-plus'
|
||||
import { getChangeTypeList,getCommissionList,getCommissionSum } from '@/app/api/member'
|
||||
import { getChangeTypeList, getCommissionList, getCommissionSum } from '@/app/api/member'
|
||||
import { img } from '@/utils/common'
|
||||
import moneyInfo from '@/app/views/member/components/member-commission-info.vue'
|
||||
import { useRouter,useRoute } from 'vue-router'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const member_id: number = parseInt(route.query.id || 0)
|
||||
const pageName = route.meta.title;
|
||||
const pageName = route.meta.title
|
||||
|
||||
let memberAccountLogTableData = reactive({
|
||||
const memberAccountLogTableData = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam:{
|
||||
keywords:"",
|
||||
from_type:"",
|
||||
create_time:"",
|
||||
mobile:"",
|
||||
member_id:member_id
|
||||
searchParam: {
|
||||
keywords: '',
|
||||
from_type: '',
|
||||
create_time: '',
|
||||
mobile: '',
|
||||
member_id: member_id
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
let fromTypeList = ref([])
|
||||
const fromTypeList = ref([])
|
||||
|
||||
const setFromTypeList = async () => {
|
||||
fromTypeList.value = await (await getChangeTypeList('commission')).data
|
||||
}
|
||||
|
||||
setFromTypeList();
|
||||
setFromTypeList()
|
||||
|
||||
/**
|
||||
* 获取佣金总计
|
||||
*/
|
||||
const commissionStatistics = ref([])
|
||||
const commissionStatistics = ref([])
|
||||
const checkCommissionInfo = () => {
|
||||
getCommissionSum({
|
||||
member_id
|
||||
}).then(res => {
|
||||
commissionStatistics.value = res.data;
|
||||
})
|
||||
getCommissionSum({
|
||||
member_id
|
||||
}).then(res => {
|
||||
commissionStatistics.value = res.data
|
||||
})
|
||||
}
|
||||
checkCommissionInfo()
|
||||
|
||||
const searchFormRef = ref<FormInstance>()
|
||||
|
||||
const resetForm = (formEl: FormInstance | undefined)=>{
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields();
|
||||
loadMemberAccountLogList();
|
||||
formEl.resetFields()
|
||||
loadMemberAccountLogList()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -204,7 +209,7 @@ const loadMemberAccountLogList = (page: number = 1) => {
|
||||
getCommissionList({
|
||||
page: memberAccountLogTableData.page,
|
||||
limit: memberAccountLogTableData.limit,
|
||||
...memberAccountLogTableData.searchParam
|
||||
...memberAccountLogTableData.searchParam
|
||||
}).then(res => {
|
||||
memberAccountLogTableData.loading = false
|
||||
memberAccountLogTableData.data = res.data.data
|
||||
@ -221,7 +226,7 @@ const moneyDialog: Record<string, any> | null = ref(null)
|
||||
* 查看详情
|
||||
* @param data
|
||||
*/
|
||||
const infoEvent = (data: any) => {
|
||||
const infoEvent = (data: any) => {
|
||||
moneyDialog.value.setFormData(data)
|
||||
moneyDialog.value.showDialog = true
|
||||
}
|
||||
@ -231,11 +236,10 @@ const router = useRouter()
|
||||
/**
|
||||
* 会员详情
|
||||
*/
|
||||
const toMember = (member_id:number) => {
|
||||
const toMember = (member_id: number) => {
|
||||
router.push(`/member/detail?id=${member_id}`)
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -28,9 +28,9 @@ import { t } from '@/lang'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { addMemberLabel, updateMemberLabel, getMemberLabelInfo } from '@/app/api/member'
|
||||
|
||||
let showDialog = ref(false)
|
||||
const showDialog = ref(false)
|
||||
const loading = ref(false)
|
||||
let popTitle:string = '';
|
||||
let popTitle:string = ''
|
||||
|
||||
/**
|
||||
* 表单数据
|
||||
@ -39,7 +39,7 @@ const initialFormData = {
|
||||
label_id: '',
|
||||
label_name: '',
|
||||
memo: '',
|
||||
sort: 0,
|
||||
sort: 0
|
||||
|
||||
}
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
@ -49,19 +49,19 @@ const formRef = ref<FormInstance>()
|
||||
// 表单验证规则
|
||||
const formRules = computed(() => {
|
||||
return {
|
||||
label_name: [
|
||||
{ required: true, message: t('labelNamePlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
sort:[
|
||||
{ validator: sortVerify, trigger: 'blur' }
|
||||
]
|
||||
label_name: [
|
||||
{ required: true, message: t('labelNamePlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
sort: [
|
||||
{ validator: sortVerify, trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
const sortVerify = (rule: any, value: any, callback: any) => {
|
||||
if (value < 0) {
|
||||
callback(new Error(t('sortVerifyOne')))
|
||||
} else if (value.toString().indexOf(".") != -1) {
|
||||
} else if (value.toString().indexOf('.') != -1) {
|
||||
callback(new Error(t('sortVerifyTwo')))
|
||||
} else {
|
||||
callback()
|
||||
@ -76,19 +76,19 @@ const emit = defineEmits(['complete'])
|
||||
*/
|
||||
const confirm = async (formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
let save = formData.label_id ? updateMemberLabel : addMemberLabel
|
||||
const save = formData.label_id ? updateMemberLabel : addMemberLabel
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
loading.value = true
|
||||
|
||||
let data = formData
|
||||
const data = formData
|
||||
|
||||
save(data).then(res => {
|
||||
loading.value = false
|
||||
showDialog.value = false
|
||||
emit('complete')
|
||||
}).catch(err => {
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
// showDialog.value = false
|
||||
})
|
||||
@ -100,15 +100,16 @@ const setFormData = async (row: any = null) => {
|
||||
loading.value = true
|
||||
Object.assign(formData, initialFormData)
|
||||
popTitle = t('addMemberLabel')
|
||||
if(row){
|
||||
if (row) {
|
||||
popTitle = t('updateMemberLabel')
|
||||
const data = await (await getMemberLabelInfo(row.label_id)).data
|
||||
if (data) Object.keys(formData).forEach((key: string) => {
|
||||
if (data[key] != undefined) formData[key] = data[key]
|
||||
})
|
||||
if (data) {
|
||||
Object.keys(formData).forEach((key: string) => {
|
||||
if (data[key] != undefined) formData[key] = data[key]
|
||||
})
|
||||
}
|
||||
}
|
||||
loading.value = false
|
||||
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
|
||||
@ -13,12 +13,12 @@
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('sex')" v-if="type == 'sex'">
|
||||
<el-select v-model="saveData.sex" clearable :placeholder="t('sexPlaceholder')" class="input-width">
|
||||
<el-option :label="item['name']" :value="item['id']" v-for="item in sexSelectData" />
|
||||
<el-option :label="item['name']" :value="item['id']" v-for="(item,index) in sexSelectData" :key="index" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('memberLabel')" v-if="type == 'member_label'">
|
||||
<el-select v-model="saveData.member_label" multiple collapse-tags :placeholder="t('memberLabelPlaceholder')" class="input-width">
|
||||
<el-option :label="item['label_name']" :value="item['label_id']" v-for="item in labelSelectData" />
|
||||
<el-option :label="item['label_name']" :value="item['label_id']" v-for="(item,index) in labelSelectData" :key="index"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@ -39,11 +39,11 @@ import type { FormInstance } from 'element-plus'
|
||||
import { editMemberDetail, getMemberLabelAll } from '@/app/api/member'
|
||||
|
||||
// 修改类型
|
||||
let type = ref('')
|
||||
let title = ref('')
|
||||
const type = ref('')
|
||||
const title = ref('')
|
||||
// 会员id
|
||||
let memberId = ref('')
|
||||
let showDialog = ref(false)
|
||||
const memberId = ref('')
|
||||
const showDialog = ref(false)
|
||||
const loading = ref(false)
|
||||
const sexSelectData = ref([
|
||||
{
|
||||
@ -58,14 +58,13 @@ const sexSelectData = ref([
|
||||
id: 2,
|
||||
name: t('girlSex')
|
||||
}
|
||||
]);
|
||||
let labelSelectData = ref(null)
|
||||
])
|
||||
const labelSelectData = ref(null)
|
||||
// 获取全部标签
|
||||
const getMemberLabelAllFn = async () => {
|
||||
labelSelectData.value = await (await getMemberLabelAll()).data
|
||||
}
|
||||
getMemberLabelAllFn();
|
||||
|
||||
getMemberLabelAllFn()
|
||||
|
||||
/**
|
||||
* 表单数据
|
||||
@ -79,7 +78,6 @@ const initialFormData = {
|
||||
}
|
||||
const saveData: Record<string, any> = reactive({ ...initialFormData })
|
||||
|
||||
|
||||
const emit = defineEmits(['complete'])
|
||||
|
||||
/**
|
||||
@ -88,7 +86,7 @@ const emit = defineEmits(['complete'])
|
||||
*/
|
||||
const confirm = async (formEl: FormInstance | undefined) => {
|
||||
loading.value = true
|
||||
let data = ref({
|
||||
const data = ref({
|
||||
member_id: memberId.value,
|
||||
field: type.value,
|
||||
value: saveData[type.value]
|
||||
@ -98,25 +96,24 @@ const confirm = async (formEl: FormInstance | undefined) => {
|
||||
loading.value = false
|
||||
showDialog.value = false
|
||||
emit('complete')
|
||||
}).catch(err => {
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
// showDialog.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const setDialogType = async (row: any = null) => {
|
||||
loading.value = true;
|
||||
type.value = row.type;
|
||||
title.value = row.title;
|
||||
memberId.value = row.id;
|
||||
loading.value = true
|
||||
type.value = row.type
|
||||
title.value = row.title
|
||||
memberId.value = row.id
|
||||
saveData[type.value] = row.data[type.value]
|
||||
if (type.value == "member_label" && saveData[type.value]) {
|
||||
saveData[type.value].forEach((item, index) => {
|
||||
saveData[type.value][index] = Number.parseFloat(item);
|
||||
});
|
||||
if (type.value == 'member_label' && saveData[type.value]) {
|
||||
saveData[type.value].forEach((item:any, index:any) => {
|
||||
saveData[type.value][index] = Number.parseFloat(item)
|
||||
})
|
||||
}
|
||||
loading.value = false;
|
||||
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
|
||||
@ -36,7 +36,6 @@
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { img } from '@/utils/common'
|
||||
import { adjustBalance } from '@/app/api/member'
|
||||
|
||||
const showDialog = ref(false)
|
||||
@ -47,11 +46,11 @@ const loading = ref(true)
|
||||
*/
|
||||
const initialFormData = {
|
||||
member_id: 0,
|
||||
balance:'',
|
||||
memo:'',
|
||||
adjust:'',
|
||||
account_data:'',
|
||||
adjust_type:1,
|
||||
balance: '',
|
||||
memo: '',
|
||||
adjust: '',
|
||||
account_data: '',
|
||||
adjust_type: 1
|
||||
}
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
|
||||
@ -64,9 +63,9 @@ const formRules = computed(() => {
|
||||
{ required: true, message: t('adjustBalancePlaceholder'), trigger: 'blur' },
|
||||
{
|
||||
validator: (rule: any, value: string, callback: any) => {
|
||||
let adjust = Math.abs(parseFloat(formData.adjust));
|
||||
const adjust = Math.abs(parseFloat(formData.adjust))
|
||||
|
||||
if(!adjust){
|
||||
if (!adjust) {
|
||||
callback(new Error(t('adjustBalancePlaceholder')))
|
||||
}
|
||||
|
||||
@ -78,7 +77,7 @@ const formRules = computed(() => {
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
@ -86,20 +85,20 @@ const formRules = computed(() => {
|
||||
* 确认
|
||||
* @param formEl
|
||||
*/
|
||||
const confirm = async (formEl: FormInstance | undefined) => {
|
||||
const confirm = async (formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
loading.value = true
|
||||
formData.account_data = Math.abs(parseFloat(formData.adjust)) * formData.adjust_type;
|
||||
let data = formData
|
||||
formData.account_data = Math.abs(parseFloat(formData.adjust)) * formData.adjust_type
|
||||
const data = formData
|
||||
|
||||
adjustBalance(data).then(res => {
|
||||
loading.value = false
|
||||
showDialog.value = false
|
||||
emit('complete')
|
||||
}).catch(err => {
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
// showDialog.value = false
|
||||
})
|
||||
@ -107,7 +106,6 @@ const formRules = computed(() => {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const emit = defineEmits(['complete'])
|
||||
|
||||
const setFormData = async (row: any = null) => {
|
||||
|
||||
@ -61,20 +61,20 @@ const loading = ref(true)
|
||||
*/
|
||||
const initialFormData = {
|
||||
account_data: 0,
|
||||
account_type:'',
|
||||
create_time:'',
|
||||
from_type:'',
|
||||
from_type_name:'',
|
||||
member_id:'',
|
||||
memo:'',
|
||||
related_id:'',
|
||||
member: {
|
||||
headimg:'',
|
||||
mobile:'',
|
||||
member_no: '',
|
||||
username:'',
|
||||
nickname:'',
|
||||
}
|
||||
account_type: '',
|
||||
create_time: '',
|
||||
from_type: '',
|
||||
from_type_name: '',
|
||||
member_id: '',
|
||||
memo: '',
|
||||
related_id: '',
|
||||
member: {
|
||||
headimg: '',
|
||||
mobile: '',
|
||||
member_no: '',
|
||||
username: '',
|
||||
nickname: ''
|
||||
}
|
||||
}
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
|
||||
@ -87,10 +87,10 @@ const formRules = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['complete'])
|
||||
// const emit = defineEmits(['complete'])
|
||||
|
||||
const setFormData = async (row: any = null) => {
|
||||
loading.value = true;
|
||||
loading.value = true
|
||||
Object.assign(formData, initialFormData)
|
||||
|
||||
if (row) {
|
||||
|
||||
@ -1,39 +1,41 @@
|
||||
<template>
|
||||
<el-dialog v-model="showDialog" :title="t('moneyInfo')" width="550px" :destroy-on-close="true">
|
||||
<el-form :model="formData" label-width="110px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
|
||||
<el-form :model="formData" label-width="110px" ref="formRef" :rules="formRules" class="page-form"
|
||||
v-loading="loading">
|
||||
|
||||
<el-form-item :label="t('headimg')" >
|
||||
<el-form-item :label="t('headimg')">
|
||||
<div class="flex items-center">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-if="formData.member.headimg" :src="img(formData.member.headimg)" alt="" >
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/app/assets/images/default_headimg.png" alt="" >
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-if="formData.member.headimg"
|
||||
:src="img(formData.member.headimg)" alt="">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/app/assets/images/default_headimg.png" alt="">
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('memberId')" >
|
||||
<div class="input-width"> {{ formData.member.member_no }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('memberId')">
|
||||
<div class="input-width"> {{ formData.member.member_no }} </div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('nickName')" >
|
||||
<el-form-item :label="t('nickName')">
|
||||
<div class="input-width"> {{ formData.member.nickname }} </div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('mobile')" >
|
||||
<el-form-item :label="t('mobile')">
|
||||
<div class="input-width"> {{ formData.member.mobile }} </div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('accountData')" >
|
||||
<el-form-item :label="t('accountData')">
|
||||
<div class="input-width"> {{ formData.account_data }} </div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('fromType')" >
|
||||
<el-form-item :label="t('fromType')">
|
||||
<div class="input-width"> {{ formData.from_type_name }} </div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('memo')" >
|
||||
<el-form-item :label="t('memo')">
|
||||
<div class="input-width"> {{ formData.memo }} </div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('createTime')" >
|
||||
<el-form-item :label="t('createTime')">
|
||||
<div class="input-width"> {{ formData.create_time }} </div>
|
||||
</el-form-item>
|
||||
|
||||
@ -61,20 +63,20 @@ const loading = ref(true)
|
||||
*/
|
||||
const initialFormData = {
|
||||
account_data: 0,
|
||||
account_type:'',
|
||||
create_time:'',
|
||||
from_type:'',
|
||||
from_type_name:"",
|
||||
member_id:'',
|
||||
memo:'',
|
||||
related_id:'',
|
||||
member: {
|
||||
headimg:'',
|
||||
mobile:'',
|
||||
member_no: '',
|
||||
username:'',
|
||||
nickname:'',
|
||||
}
|
||||
account_type: '',
|
||||
create_time: '',
|
||||
from_type: '',
|
||||
from_type_name: '',
|
||||
member_id: '',
|
||||
memo: '',
|
||||
related_id: '',
|
||||
member: {
|
||||
headimg: '',
|
||||
mobile: '',
|
||||
member_no: '',
|
||||
username: '',
|
||||
nickname: ''
|
||||
}
|
||||
}
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
|
||||
@ -87,10 +89,10 @@ const formRules = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['complete'])
|
||||
// const emit = defineEmits(['complete'])
|
||||
|
||||
const setFormData = async (row: any = null) => {
|
||||
loading.value = true;
|
||||
loading.value = true
|
||||
Object.assign(formData, initialFormData)
|
||||
|
||||
if (row) {
|
||||
|
||||
@ -57,17 +57,17 @@ const loading = ref(true)
|
||||
*/
|
||||
const initialFormData = {
|
||||
account_data: 0,
|
||||
account_type:'',
|
||||
create_time:'',
|
||||
from_type:'',
|
||||
from_type_name:"",
|
||||
headimg:'',
|
||||
member_id:'',
|
||||
memo:'',
|
||||
mobile:'',
|
||||
nickname:'',
|
||||
related_id:'',
|
||||
username:''
|
||||
account_type: '',
|
||||
create_time: '',
|
||||
from_type: '',
|
||||
from_type_name: '',
|
||||
headimg: '',
|
||||
member_id: '',
|
||||
memo: '',
|
||||
mobile: '',
|
||||
nickname: '',
|
||||
related_id: '',
|
||||
username: ''
|
||||
|
||||
}
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
@ -81,10 +81,10 @@ const formRules = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['complete'])
|
||||
// const emit = defineEmits(['complete'])
|
||||
|
||||
const setFormData = async (row: any = null) => {
|
||||
loading.value = true;
|
||||
loading.value = true
|
||||
Object.assign(formData, initialFormData)
|
||||
|
||||
if (row) {
|
||||
|
||||
@ -36,7 +36,6 @@
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { img } from '@/utils/common'
|
||||
import { adjustPoint } from '@/app/api/member'
|
||||
|
||||
const showDialog = ref(false)
|
||||
@ -47,11 +46,11 @@ const loading = ref(true)
|
||||
*/
|
||||
const initialFormData = {
|
||||
member_id: 0,
|
||||
point:'',
|
||||
memo:'',
|
||||
adjust:'',
|
||||
account_data:'',
|
||||
adjust_type:1,
|
||||
point: '',
|
||||
memo: '',
|
||||
adjust: '',
|
||||
account_data: '',
|
||||
adjust_type: 1
|
||||
}
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
|
||||
@ -64,11 +63,11 @@ const formRules = computed(() => {
|
||||
{ required: true, message: t('adjustPointPlaceholder'), trigger: 'blur' },
|
||||
{
|
||||
validator: (rule: any, value: string, callback: any) => {
|
||||
formData.adjust = Math.floor(formData.adjust);
|
||||
formData.adjust = Math.floor(formData.adjust)
|
||||
|
||||
let adjust = Math.abs(parseFloat(formData.adjust));
|
||||
const adjust = Math.abs(parseFloat(formData.adjust))
|
||||
|
||||
if(!adjust){
|
||||
if (!adjust) {
|
||||
callback(new Error(t('adjustPointPlaceholder')))
|
||||
}
|
||||
|
||||
@ -80,7 +79,7 @@ const formRules = computed(() => {
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
@ -88,20 +87,20 @@ const formRules = computed(() => {
|
||||
* 确认
|
||||
* @param formEl
|
||||
*/
|
||||
const confirm = async (formEl: FormInstance | undefined) => {
|
||||
const confirm = async (formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
loading.value = true
|
||||
formData.account_data = Math.abs(parseFloat(formData.adjust)) * formData.adjust_type;
|
||||
let data = formData
|
||||
const data = formData
|
||||
|
||||
adjustPoint(data).then(res => {
|
||||
loading.value = false
|
||||
showDialog.value = false
|
||||
emit('complete')
|
||||
}).catch(err => {
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
// showDialog.value = false
|
||||
})
|
||||
@ -112,7 +111,7 @@ const formRules = computed(() => {
|
||||
const emit = defineEmits(['complete'])
|
||||
|
||||
const setFormData = async (row: any = null) => {
|
||||
loading.value = true;
|
||||
loading.value = true
|
||||
Object.assign(formData, initialFormData)
|
||||
if (row) {
|
||||
Object.keys(formData).forEach((key: string) => {
|
||||
|
||||
@ -61,20 +61,20 @@ const loading = ref(true)
|
||||
*/
|
||||
const initialFormData = {
|
||||
account_data: 0,
|
||||
account_type:'',
|
||||
create_time:'',
|
||||
from_type:'',
|
||||
from_type_name:"",
|
||||
member_id:'',
|
||||
memo:'',
|
||||
related_id:'',
|
||||
member: {
|
||||
headimg:'',
|
||||
mobile:'',
|
||||
member_no: '',
|
||||
username:'',
|
||||
nickname:'',
|
||||
}
|
||||
account_type: '',
|
||||
create_time: '',
|
||||
from_type: '',
|
||||
from_type_name: '',
|
||||
member_id: '',
|
||||
memo: '',
|
||||
related_id: '',
|
||||
member: {
|
||||
headimg: '',
|
||||
mobile: '',
|
||||
member_no: '',
|
||||
username: '',
|
||||
nickname: ''
|
||||
}
|
||||
}
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
|
||||
@ -87,10 +87,10 @@ const formRules = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['complete'])
|
||||
// const emit = defineEmits(['complete'])
|
||||
|
||||
const setFormData = async (row: any = null) => {
|
||||
loading.value = true;
|
||||
loading.value = true
|
||||
Object.assign(formData, initialFormData)
|
||||
if (row) {
|
||||
Object.keys(formData).forEach((key: string) => {
|
||||
|
||||
@ -59,25 +59,25 @@ import EditMemberLabel from '@/app/views/member/components/edit-label.vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title;
|
||||
const pageName = route.meta.title
|
||||
|
||||
let memberLabelTableData = reactive({
|
||||
const memberLabelTableData = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam:{
|
||||
"label_name":""
|
||||
searchParam: {
|
||||
label_name: ''
|
||||
}
|
||||
})
|
||||
|
||||
const searchFormRef = ref<FormInstance>()
|
||||
|
||||
const resetForm = (formEl: FormInstance | undefined)=>{
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields();
|
||||
loadMemberLabelList();
|
||||
formEl.resetFields()
|
||||
loadMemberLabelList()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -3,31 +3,37 @@
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<el-button type="primary" @click="addEvent">{{ t('addMember') }}</el-button>
|
||||
</div>
|
||||
|
||||
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="memberTableData.searchParam" ref="searchFormRef">
|
||||
<el-form-item :label="t('memberInfo')" prop="keyword">
|
||||
<el-input v-model="memberTableData.searchParam.keyword" class="w-[240px]" :placeholder="t('memberInfoPlaceholder')" />
|
||||
<el-input v-model="memberTableData.searchParam.keyword" class="w-[240px]"
|
||||
:placeholder="t('memberInfoPlaceholder')" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('registerChannel')" prop="register_channel">
|
||||
<el-select v-model="memberTableData.searchParam.register_channel" clearable :placeholder="t('channelPlaceholder')" class="input-width">
|
||||
<el-select v-model="memberTableData.searchParam.register_channel" clearable
|
||||
:placeholder="t('channelPlaceholder')" class="input-width">
|
||||
<el-option :label="t('selectPlaceholder')" value="" />
|
||||
<el-option :label="item" :value="key" v-for="(item, key) in channelList" />
|
||||
<el-option :label="item" :value="key" v-for="(item, key) in channelList" :key="key" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('memberLabel')" prop="member_label">
|
||||
<el-select v-model="memberTableData.searchParam.member_label" collapse-tags clearable :placeholder="t('memberLabelPlaceholder')" class="input-width">
|
||||
<el-option :label="t('selectPlaceholder')" value=""/>
|
||||
<el-option :label="item['label_name']" :value="item['label_id']" v-for="item in labelSelectData" />
|
||||
<el-select v-model="memberTableData.searchParam.member_label" collapse-tags clearable
|
||||
:placeholder="t('memberLabelPlaceholder')" class="input-width">
|
||||
<el-option :label="t('selectPlaceholder')" value="" />
|
||||
<el-option :label="item['label_name']" :value="item['label_id']"
|
||||
v-for="(item, index) in labelSelectData" :key="index" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('createTime')" prop="create_time">
|
||||
<el-date-picker v-model="memberTableData.searchParam.create_time" type="datetimerange" value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')" :end-placeholder="t('endDate')" />
|
||||
<el-date-picker v-model="memberTableData.searchParam.create_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadMemberList()">{{ t('search') }}</el-button>
|
||||
@ -46,7 +52,8 @@
|
||||
<template #default="{ row }">
|
||||
<div class="flex items-center">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.headimg" :src="img(row.headimg)" alt="">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/app/assets/images/default_headimg.png" alt="">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-else
|
||||
src="@/app/assets/images/default_headimg.png" alt="">
|
||||
<div class="flex flex flex-col">
|
||||
<span>{{ row.nickname || '' }}</span>
|
||||
</div>
|
||||
@ -63,21 +70,24 @@
|
||||
<el-table-column prop="member_label" :label="t('lable')" min-width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<div class="flex flex-col items-start">
|
||||
<div v-for="(item, key) in row.member_label_array" class="my-[3px]">
|
||||
<el-tag class="ml-[13px]" type="info">{{item.label_name}}</el-tag>
|
||||
<div v-for="(item, key) in row.member_label_array" class="my-[3px]" :key="key">
|
||||
<el-tag class="ml-[13px]" type="info">{{ item.label_name }}</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="register_channel_name" :label="t('registerChannel')" min-width="110" align="center"/>
|
||||
<el-table-column prop="register_channel_name" :label="t('registerChannel')" min-width="110"
|
||||
align="center" />
|
||||
|
||||
<el-table-column prop="member_label" :label="t('status')" min-width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.status == 1" @click="lockMember(row, 0)" class="cursor-pointer">{{t('normal')}}</el-tag>
|
||||
<el-tag type="error" v-else @click="lockMember(row, 1)" class="cursor-pointer">{{t('lock')}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="member_label" :label="t('status')" min-width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.status == 1" @click="lockMember(row, 0)"
|
||||
class="cursor-pointer">{{ t('normal') }}</el-tag>
|
||||
<el-tag type="error" v-else @click="lockMember(row, 1)"
|
||||
class="cursor-pointer">{{ t('lock') }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('createTime')" min-width="150" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.create_time || '' }}
|
||||
@ -117,15 +127,14 @@
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { img } from '@/utils/common'
|
||||
import { addMember, getRegisterChannelType, getMemberList, getMemberLabelAll, editMemberStatus,deleteMember } from '@/app/api/member'
|
||||
import { addMember, getRegisterChannelType, getMemberList, getMemberLabelAll, editMemberStatus, deleteMember } from '@/app/api/member'
|
||||
import { ElMessageBox, FormInstance } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import AddMember from '@/app/views/member/components/add-member.vue'
|
||||
import EditMember from '@/app/views/member/components/edit-member.vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title;
|
||||
const pageName = route.meta.title
|
||||
const memberTableData = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
@ -136,7 +145,7 @@ const memberTableData = reactive({
|
||||
keyword: '',
|
||||
register_type: '',
|
||||
member_label: '',
|
||||
register_channel:'',
|
||||
register_channel: '',
|
||||
create_time: []
|
||||
}
|
||||
})
|
||||
@ -148,21 +157,19 @@ const channelList = ref([])
|
||||
const setChannelList = async () => {
|
||||
channelList.value = await (await getRegisterChannelType({})).data
|
||||
}
|
||||
setChannelList();
|
||||
|
||||
setChannelList()
|
||||
|
||||
// 获取全部标签
|
||||
let labelSelectData = ref([])
|
||||
const labelSelectData = ref([])
|
||||
const getMemberLabelAllFn = async () => {
|
||||
labelSelectData.value = await (await getMemberLabelAll()).data
|
||||
}
|
||||
getMemberLabelAllFn();
|
||||
getMemberLabelAllFn()
|
||||
|
||||
|
||||
const resetForm = (formEl: FormInstance | undefined)=>{
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields();
|
||||
loadMemberList();
|
||||
formEl.resetFields()
|
||||
loadMemberList()
|
||||
}
|
||||
|
||||
// 获取会员列表
|
||||
@ -188,30 +195,29 @@ const router = useRouter()
|
||||
const addMemberDialog: Record<string, any> | null = ref(null)
|
||||
const editMemberDialog: Record<string, any> | null = ref(null)
|
||||
|
||||
|
||||
/**
|
||||
* 获取标签
|
||||
*/
|
||||
function memberLable(res: any) {
|
||||
let data;
|
||||
if (!res.member_label_array) return '';
|
||||
data = res.member_label_array.map((item) => {
|
||||
return item.label_name;
|
||||
});
|
||||
data = data.toString();
|
||||
let data
|
||||
if (!res.member_label_array) return ''
|
||||
data = res.member_label_array.map((item:any) => {
|
||||
return item.label_name
|
||||
})
|
||||
data = data.toString()
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置标签
|
||||
*/
|
||||
function setMemberLable(res: any) {
|
||||
let data = ref({
|
||||
function setMemberLable (res: any) {
|
||||
const data = ref({
|
||||
type: 'member_label',
|
||||
id: res.member_id,
|
||||
title: t('setLable'),
|
||||
data: res
|
||||
});
|
||||
})
|
||||
editMemberDialog.value.setDialogType(data.value)
|
||||
editMemberDialog.value.showDialog = true
|
||||
}
|
||||
@ -220,7 +226,6 @@ function setMemberLable(res: any) {
|
||||
* 删除
|
||||
*/
|
||||
function deleteEvent(res: any) {
|
||||
|
||||
ElMessageBox.confirm(t('memberDeleteTips'), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
@ -229,14 +234,12 @@ function deleteEvent(res: any) {
|
||||
}
|
||||
).then(() => {
|
||||
deleteMember(res.member_id).then(() => {
|
||||
loadMemberList();
|
||||
loadMemberList()
|
||||
}).catch(() => {
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加会员
|
||||
*/
|
||||
@ -261,7 +264,7 @@ const detailEvent = (data: any) => {
|
||||
/**
|
||||
* 变更会员状态
|
||||
*/
|
||||
const lockMember = (res, status) => {
|
||||
const lockMember = (res:any, status:any) => {
|
||||
editMemberStatus({
|
||||
status: status,
|
||||
member_ids: [res.member_id]
|
||||
|
||||
@ -237,16 +237,16 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getMemberInfo } from '@/app/api/member'
|
||||
import { ElMessageBox, FormInstance, ElMessage } from 'element-plus'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { img } from '@/utils/common'
|
||||
import PointEdit from '@/app/views/member/components/member-point-edit.vue'
|
||||
import BalanceEdit from '@/app/views/member/components/member-balance-edit.vue'
|
||||
import EditMember from '@/app/views/member/components/edit-member.vue'
|
||||
import colorGradient from '../../../../uniapp/src/uni_modules/vk-uview-ui/libs/function/colorGradient'
|
||||
// import colorGradient from '../../../../uniapp/src/uni_modules/vk-uview-ui/libs/function/colorGradient'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
|
||||
const route = useRoute()
|
||||
@ -260,34 +260,34 @@ const id: number = parseInt(route.query.id || 0)
|
||||
const formData: any = reactive({ member_label_name: '' })
|
||||
|
||||
const getMemberInfoFn = async () => {
|
||||
loading.value = true
|
||||
if (id) {
|
||||
const data = await (await getMemberInfo(id)).data
|
||||
if (!data || Object.keys(data).length == 0) {
|
||||
ElMessage.error(t('memberNull'))
|
||||
setTimeout(() => {
|
||||
router.go(-1)
|
||||
}, 2000)
|
||||
return false
|
||||
}
|
||||
loading.value = true
|
||||
if (id) {
|
||||
const data = await (await getMemberInfo(id)).data
|
||||
if (!data || Object.keys(data).length == 0) {
|
||||
ElMessage.error(t('memberNull'))
|
||||
setTimeout(() => {
|
||||
router.go(-1)
|
||||
}, 2000)
|
||||
return false
|
||||
}
|
||||
|
||||
Object.keys(data).forEach((item) => {
|
||||
formData[item] = data[item]
|
||||
})
|
||||
Object.keys(data).forEach((item) => {
|
||||
formData[item] = data[item]
|
||||
})
|
||||
|
||||
if (formData?.member_label_array && Object.keys(formData.member_label_array)?.length) {
|
||||
formData.member_label = Object.values(formData.member_label_array).map((item: any, index) => {
|
||||
return item.label_id
|
||||
})
|
||||
if (formData?.member_label_array && Object.keys(formData.member_label_array)?.length) {
|
||||
formData.member_label = Object.values(formData.member_label_array).map((item: any, index) => {
|
||||
return item.label_id
|
||||
})
|
||||
|
||||
formData.member_label_name = Object.values(formData.member_label_array).map((item: any, index) => {
|
||||
return item.label_name
|
||||
})
|
||||
}
|
||||
loading.value = false
|
||||
} else {
|
||||
loading.value = false
|
||||
}
|
||||
formData.member_label_name = Object.values(formData.member_label_array).map((item: any, index) => {
|
||||
return item.label_name
|
||||
})
|
||||
}
|
||||
loading.value = false
|
||||
} else {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
getMemberInfoFn()
|
||||
|
||||
@ -299,29 +299,29 @@ const editMemberDialog: Record<string, any> | null = ref(null)
|
||||
* 修改会员信息
|
||||
*/
|
||||
const editMemberInfo = (type: any) => {
|
||||
const data = ref({
|
||||
type,
|
||||
id,
|
||||
data: formData
|
||||
})
|
||||
editMemberDialog.value.setDialogType(data.value)
|
||||
editMemberDialog.value.showDialog = true
|
||||
const data = ref({
|
||||
type,
|
||||
id,
|
||||
data: formData
|
||||
})
|
||||
editMemberDialog.value.setDialogType(data.value)
|
||||
editMemberDialog.value.showDialog = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 调整积分
|
||||
*/
|
||||
const adjustPoint = (data: any) => {
|
||||
pointDialog.value.setFormData(data)
|
||||
pointDialog.value.showDialog = true
|
||||
pointDialog.value.setFormData(data)
|
||||
pointDialog.value.showDialog = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 调整余额
|
||||
*/
|
||||
const adjustBalance = (data: any) => {
|
||||
balanceDialog.value.setFormData(data)
|
||||
balanceDialog.value.showDialog = true
|
||||
balanceDialog.value.setFormData(data)
|
||||
balanceDialog.value.showDialog = true
|
||||
}
|
||||
|
||||
const router = useRouter()
|
||||
@ -330,21 +330,21 @@ const router = useRouter()
|
||||
* 积分详情
|
||||
*/
|
||||
const infoPoint = () => {
|
||||
router.push(`/member/point?id=${id}`)
|
||||
router.push(`/member/point?id=${id}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 余额详情
|
||||
*/
|
||||
const infoBalance = () => {
|
||||
router.push(`/member/balance?id=${id}`)
|
||||
router.push(`/member/balance?id=${id}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 佣金详情
|
||||
*/
|
||||
const infoCommission = () => {
|
||||
router.push(`/member/commission?id=${id}`)
|
||||
router.push(`/member/commission?id=${id}`)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@ -2,52 +2,52 @@
|
||||
<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-[20x]">{{pageName}}</span>
|
||||
<span class="text-[20x]">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none base-bg !px-[35px]" shadow="never">
|
||||
<el-row class="flex">
|
||||
<el-col :span="12" class="min-w-[100px]">
|
||||
<el-row class="flex">
|
||||
<el-col :span="12" class="min-w-[100px]">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="pointStatistics.point_get ? Number.parseInt(pointStatistics.point_get) : '0'"></el-statistic>
|
||||
<el-statistic
|
||||
:value="pointStatistics.point_get ? Number.parseInt(pointStatistics.point_get) : '0'"></el-statistic>
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-[#666]">
|
||||
<span>{{ t('pointGet') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12" class="min-w-[100px]">
|
||||
</el-col>
|
||||
<el-col :span="12" class="min-w-[100px]">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="pointStatistics.point_use ? Number.parseInt(pointStatistics.point_use) : '0'"></el-statistic>
|
||||
<el-statistic
|
||||
:value="pointStatistics.point_use ? Number.parseInt(pointStatistics.point_use) : '0'"></el-statistic>
|
||||
<div class="statistic-footer">
|
||||
<div class="footer-item text-[14px] text-[#666]">
|
||||
<span>{{ t('pointUse') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<el-card class="box-card !border-none mb-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="memberAccountLogTableData.searchParam" ref="searchFormRef">
|
||||
<el-form-item :label="t('memberInfo')" prop="keywords">
|
||||
<el-input v-model="memberAccountLogTableData.searchParam.keywords" class="w-[240px]" :placeholder="t('memberInfoPlaceholder')" />
|
||||
<el-input v-model="memberAccountLogTableData.searchParam.keywords" class="w-[240px]"
|
||||
:placeholder="t('memberInfoPlaceholder')" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('fromType')" prop="from_type">
|
||||
<el-select v-model="memberAccountLogTableData.searchParam.from_type" clearable :placeholder="t('fromTypePlaceholder')" class="input-width">
|
||||
<el-select v-model="memberAccountLogTableData.searchParam.from_type" clearable
|
||||
:placeholder="t('fromTypePlaceholder')" class="input-width">
|
||||
<el-option :label="t('selectPlaceholder')" value="" />
|
||||
<el-option :label="item.name" :value="key" v-for="(item,key) in fromTypeList" />
|
||||
<el-option :label="item.name" :value="key" v-for="(item, key) in fromTypeList" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('createTime')" prop="create_time">
|
||||
<el-date-picker
|
||||
v-model="memberAccountLogTableData.searchParam.create_time"
|
||||
type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')"
|
||||
/>
|
||||
<el-date-picker v-model="memberAccountLogTableData.searchParam.create_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadMemberAccountLogList()">{{ t('search') }}</el-button>
|
||||
@ -68,46 +68,50 @@
|
||||
{{ row.member.member_no }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('memberInfo')" min-width="150" :show-overflow-tooltip="true">
|
||||
<el-table-column :label="t('memberInfo')" min-width="150" :show-overflow-tooltip="true">
|
||||
<template #default="{ row }">
|
||||
<div class="flex items-center cursor-pointer" @click="toMember(row.member_id)">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg" :src="img(row.member.headimg)" alt="" >
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/app/assets/images/default_headimg.png" alt="" >
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg"
|
||||
:src="img(row.member.headimg)" alt="">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-else
|
||||
src="@/app/assets/images/default_headimg.png" alt="">
|
||||
<div class="flex flex flex-col">
|
||||
<span class="">{{ row.member.nickname || '' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="mobile" :label="t('mobile')" min-width="100">
|
||||
<template #default="{ row }">
|
||||
{{ row.member.mobile || '' }}
|
||||
<el-table-column prop="mobile" :label="t('mobile')" min-width="100">
|
||||
<template #default="{ row }">
|
||||
{{ row.member.mobile || '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="account_data" :label="t('accountData')" min-width="80" align="right">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.account_data >= 0">+{{ row.account_data }}</span>
|
||||
<span v-else>{{ row.account_data }}</span>
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.account_data >= 0">+{{ row.account_data }}</span>
|
||||
<span v-else>{{ row.account_data }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="account_sum" :label="t('accountSum')" min-width="120" align="right"/>
|
||||
<el-table-column prop="account_sum" :label="t('accountSum')" min-width="120" align="right" />
|
||||
|
||||
<el-table-column prop="from_type_name" :label="t('fromType')" min-width="180" align="center"/>
|
||||
<el-table-column prop="create_time" :show-overflow-tooltip="true" :label="t('createTime')" min-width="150" />
|
||||
<el-table-column prop="from_type_name" :label="t('fromType')" min-width="180" align="center" />
|
||||
<el-table-column prop="create_time" :show-overflow-tooltip="true" :label="t('createTime')"
|
||||
min-width="150" />
|
||||
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right" width="100">
|
||||
<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>
|
||||
<div class="mt-[16px] flex justify-end">
|
||||
<el-pagination v-model:current-page="memberAccountLogTableData.page" v-model:page-size="memberAccountLogTableData.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="memberAccountLogTableData.total"
|
||||
@size-change="loadMemberAccountLogList()" @current-change="loadMemberAccountLogList" />
|
||||
<el-pagination v-model:current-page="memberAccountLogTableData.page"
|
||||
v-model:page-size="memberAccountLogTableData.limit" layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="memberAccountLogTableData.total" @size-change="loadMemberAccountLogList()"
|
||||
@current-change="loadMemberAccountLogList" />
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
@ -118,61 +122,60 @@
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getChangeTypeList,getPointList,getPointSum } from '@/app/api/member'
|
||||
import { ElMessageBox, FormInstance } from 'element-plus'
|
||||
import { getChangeTypeList, getPointList, getPointSum } from '@/app/api/member'
|
||||
import { FormInstance } from 'element-plus'
|
||||
import { img } from '@/utils/common'
|
||||
import pointInfo from '@/app/views/member/components/member-point-info.vue'
|
||||
import { useRouter,useRoute } from 'vue-router'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const member_id: number = parseInt(route.query.id || 0)
|
||||
const pageName = route.meta.title;
|
||||
const pageName = route.meta.title
|
||||
|
||||
let memberAccountLogTableData = reactive({
|
||||
const memberAccountLogTableData = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam:{
|
||||
keywords:"",
|
||||
from_type:"",
|
||||
create_time:"",
|
||||
mobile:"",
|
||||
member_id:member_id
|
||||
searchParam: {
|
||||
keywords: '',
|
||||
from_type: '',
|
||||
create_time: '',
|
||||
mobile: '',
|
||||
member_id: member_id
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取积分总计
|
||||
*/
|
||||
const pointStatistics = ref([])
|
||||
const pointStatistics = ref([])
|
||||
const checkPointInfo = () => {
|
||||
getPointSum({
|
||||
member_id
|
||||
}).then(res => {
|
||||
pointStatistics.value = res.data;
|
||||
})
|
||||
getPointSum({
|
||||
member_id
|
||||
}).then(res => {
|
||||
pointStatistics.value = res.data
|
||||
})
|
||||
}
|
||||
checkPointInfo()
|
||||
|
||||
let fromTypeList = ref([])
|
||||
const fromTypeList = ref([])
|
||||
|
||||
const setFromTypeList = async () => {
|
||||
fromTypeList.value = await (await getChangeTypeList('point')).data
|
||||
}
|
||||
|
||||
setFromTypeList();
|
||||
setFromTypeList()
|
||||
|
||||
const searchFormRef = ref<FormInstance>()
|
||||
|
||||
const resetForm = (formEl: FormInstance | undefined)=>{
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
formEl.resetFields();
|
||||
loadMemberAccountLogList();
|
||||
formEl.resetFields()
|
||||
loadMemberAccountLogList()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 获取会员账单表列表
|
||||
@ -184,7 +187,7 @@ const loadMemberAccountLogList = (page: number = 1) => {
|
||||
getPointList({
|
||||
page: memberAccountLogTableData.page,
|
||||
limit: memberAccountLogTableData.limit,
|
||||
...memberAccountLogTableData.searchParam
|
||||
...memberAccountLogTableData.searchParam
|
||||
}).then(res => {
|
||||
memberAccountLogTableData.loading = false
|
||||
memberAccountLogTableData.data = res.data.data
|
||||
@ -201,7 +204,7 @@ const pointDialog: Record<string, any> | null = ref(null)
|
||||
* 查看详情
|
||||
* @param data
|
||||
*/
|
||||
const infoEvent = (data: any) => {
|
||||
const infoEvent = (data: any) => {
|
||||
pointDialog.value.setFormData(data)
|
||||
pointDialog.value.showDialog = true
|
||||
}
|
||||
@ -211,11 +214,10 @@ const router = useRouter()
|
||||
/**
|
||||
* 会员详情
|
||||
*/
|
||||
const toMember = (member_id:number) => {
|
||||
const toMember = (member_id: number) => {
|
||||
router.push(`/member/detail?id=${member_id}`)
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -70,7 +70,7 @@ import type { FormInstance } from 'element-plus'
|
||||
import { getRechargeOrderInfo } from '@/app/api/order'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import useTabbarStore from '@/stores/modules/tabbar'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
// import useAppStore from '@/stores/modules/app'
|
||||
|
||||
const tabbarStore = useTabbarStore()
|
||||
const route = useRoute()
|
||||
|
||||
@ -2,28 +2,30 @@
|
||||
<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-[20px]">{{pageName}}</span>
|
||||
<span class="text-[20px]">{{ 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" class="min-w-[100px]">
|
||||
<el-statistic :value="rechargeStatistics.recharge_money ? Number.parseFloat(rechargeStatistics.recharge_money).toFixed(2) : '0.00'">
|
||||
<template #title>
|
||||
<div class="text-[14px] mb-[9px]">{{ t('totalRechargeMoney') }}</div>
|
||||
</template>
|
||||
</el-statistic>
|
||||
</el-col>
|
||||
<el-col :span="12" class="min-w-[100px]">
|
||||
<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>
|
||||
</el-statistic>
|
||||
</el-col>
|
||||
<el-row class="flex">
|
||||
<el-col :span="12" class="min-w-[100px]">
|
||||
<el-statistic
|
||||
:value="rechargeStatistics.recharge_money ? Number.parseFloat(rechargeStatistics.recharge_money).toFixed(2) : '0.00'">
|
||||
<template #title>
|
||||
<div class="text-[14px] mb-[9px]">{{ t('totalRechargeMoney') }}</div>
|
||||
</template>
|
||||
</el-statistic>
|
||||
</el-col>
|
||||
<el-col :span="12" class="min-w-[100px]">
|
||||
<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>
|
||||
</el-statistic>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card !border-none mb-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="orderTableData.searchParam" ref="searchFormRef">
|
||||
@ -34,35 +36,41 @@
|
||||
<el-form-item :label="t('orderFromName')" prop="order_from">
|
||||
<el-select v-model="orderTableData.searchParam.order_from" clearable class="input-width">
|
||||
<el-option :label="t('selectPlaceholder')" value="" />
|
||||
<el-option :label="item" :value="key" v-for="(item, key) in channelList" />
|
||||
<el-option :label="item" :value="key" v-for="(item, key) in channelList" :key="key"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('orderStatus')" prop="order_status">
|
||||
<el-select v-model="orderTableData.searchParam.order_status" clearable class="input-width">
|
||||
<el-option :label="t('selectPlaceholder')" value="" />
|
||||
<el-option :label="item['name']" :value="item['status']" v-for="item in statusList" />
|
||||
<el-option :label="item['name']" :value="item['status']" v-for="(item,index) in statusList" :key="index"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('createTime')" prop="create_time">
|
||||
<el-date-picker v-model="orderTableData.searchParam.create_time" type="datetimerange" value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')" :end-placeholder="t('endDate')" />
|
||||
<el-date-picker v-model="orderTableData.searchParam.create_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('rechargeMoney')">
|
||||
<div class="region-input">
|
||||
<el-form-item prop="start_money">
|
||||
<input type="text" :placeholder="t('startMoney')" v-model="orderTableData.searchParam.start_money">
|
||||
<input type="text" :placeholder="t('startMoney')"
|
||||
v-model="orderTableData.searchParam.start_money">
|
||||
</el-form-item>
|
||||
<span class="separator">-</span>
|
||||
<el-form-item prop="end_money">
|
||||
<input type="text" :placeholder="t('endMoney')" v-model="orderTableData.searchParam.end_money">
|
||||
<input type="text" :placeholder="t('endMoney')"
|
||||
v-model="orderTableData.searchParam.end_money">
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('payTime')">
|
||||
<el-date-picker v-model="orderTableData.searchParam.pay_time" type="datetimerange" value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')" :end-placeholder="t('endDate')" />
|
||||
<el-date-picker v-model="orderTableData.searchParam.pay_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
@ -81,8 +89,10 @@
|
||||
<el-table-column :show-overflow-tooltip="true" :label="t('member')" 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.member.headimg" :src="img(row.member.headimg)" alt="">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/app/assets/images/default_headimg.png" alt="">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg"
|
||||
:src="img(row.member.headimg)" alt="">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-else
|
||||
src="@/app/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,7 +101,8 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="order_no" :show-overflow-tooltip="true" :label="t('rechargeNo')" align="center" min-width="140" />
|
||||
<el-table-column prop="order_no" :show-overflow-tooltip="true" :label="t('rechargeNo')" align="center"
|
||||
min-width="140" />
|
||||
|
||||
<el-table-column prop="order_money" :label="t('rechargeMoney')" align="center" min-width="140" />
|
||||
|
||||
@ -120,10 +131,13 @@
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="infoEvent(row)">{{ t('info') }}</el-button>
|
||||
|
||||
<el-button v-if="[1, 10].includes(row.order_status_info.status) && row.is_enable_refund && row.refund_status == 0" type="primary" link @click="refundFn(row)">{{ t('refundBtn') }}</el-button>
|
||||
<el-button
|
||||
v-if="[1, 10].includes(row.order_status_info.status) && row.is_enable_refund && row.refund_status == 0"
|
||||
type="primary" link @click="refundFn(row)">{{ t('refundBtn') }}</el-button>
|
||||
|
||||
<template v-for="(item, index) in row.order_status_info.action">
|
||||
<el-button type="primary" link @click="orderEvent(row, item.class)">{{ item.name }}</el-button>
|
||||
<template v-for="(item, index) in row.order_status_info.action" :key="index">
|
||||
<el-button type="primary" link @click="orderEvent(row, item.class)">{{ item.name
|
||||
}}</el-button>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -158,7 +172,7 @@ import { getChannelType } from '@/app/api/sys'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { AnyObject } from '@/types/global'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
|
||||
import { img } from '@/utils/common'
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageName = route.meta.title
|
||||
@ -203,7 +217,7 @@ const statusList = ref([])
|
||||
const searchFormRef = ref<FormInstance>()
|
||||
|
||||
const setCategoryList = async () => {
|
||||
statusList.value = await (await getRechargeOrderStatusList({})).data
|
||||
statusList.value = await (await getRechargeOrderStatusList()).data
|
||||
}
|
||||
setCategoryList()
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@
|
||||
<el-form-item :label="t('refundStatus')" prop="status">
|
||||
<el-select v-model="refundTableData.searchParam.status" clearable class="input-width">
|
||||
<el-option :label="t('selectPlaceholder')" value="" />
|
||||
<el-option :label="item.name" :value="key" v-for="(item, key) in refundList" />
|
||||
<el-option :label="item.name" :value="key" v-for="(item, key) in refundList" :key="key" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('refundTime')" prop="create_time">
|
||||
@ -152,85 +152,85 @@ const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
const searchFormRef = ref<FormInstance>()
|
||||
const refundTableData = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam: {
|
||||
refund_no: '',
|
||||
// member_id,
|
||||
create_time: [],
|
||||
status: '',
|
||||
keywords: '',
|
||||
order_no: ''
|
||||
}
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam: {
|
||||
refund_no: '',
|
||||
// member_id,
|
||||
create_time: [],
|
||||
status: '',
|
||||
keywords: '',
|
||||
order_no: ''
|
||||
}
|
||||
})
|
||||
|
||||
const resetForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
if (!formEl) return
|
||||
|
||||
formEl.resetFields()
|
||||
loadRefundList()
|
||||
formEl.resetFields()
|
||||
loadRefundList()
|
||||
}
|
||||
/**
|
||||
* 获取退款列表
|
||||
*/
|
||||
const loadRefundList = (page: number = 1) => {
|
||||
refundTableData.loading = true
|
||||
refundTableData.page = page
|
||||
refundTableData.loading = true
|
||||
refundTableData.page = page
|
||||
|
||||
getRechargeRefund({
|
||||
page: refundTableData.page,
|
||||
limit: refundTableData.limit,
|
||||
...refundTableData.searchParam
|
||||
}).then(res => {
|
||||
refundTableData.loading = false
|
||||
refundTableData.data = res.data.data
|
||||
refundTableData.total = res.data.total
|
||||
}).catch(() => {
|
||||
refundTableData.loading = false
|
||||
})
|
||||
getRechargeRefund({
|
||||
page: refundTableData.page,
|
||||
limit: refundTableData.limit,
|
||||
...refundTableData.searchParam
|
||||
}).then(res => {
|
||||
refundTableData.loading = false
|
||||
refundTableData.data = res.data.data
|
||||
refundTableData.total = res.data.total
|
||||
}).catch(() => {
|
||||
refundTableData.loading = false
|
||||
})
|
||||
}
|
||||
loadRefundList()
|
||||
|
||||
const refundList = ref([])
|
||||
const checkRefundList = () => {
|
||||
getRechargeRefundStatus().then(res => {
|
||||
refundList.value = res.data
|
||||
})
|
||||
getRechargeRefundStatus().then(res => {
|
||||
refundList.value = res.data
|
||||
})
|
||||
}
|
||||
checkRefundList()
|
||||
|
||||
const refundStat = reactive({
|
||||
refund_all_money: 0.00,
|
||||
refund_have_money: 0.00,
|
||||
refund_Success_money: 0.00,
|
||||
refund_fail_moey: 0.00
|
||||
refund_all_money: 0.00,
|
||||
refund_have_money: 0.00,
|
||||
refund_Success_money: 0.00,
|
||||
refund_fail_moey: 0.00
|
||||
})
|
||||
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
|
||||
})
|
||||
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 infoEvent = (info) => {
|
||||
refundInfo.value = info
|
||||
refundInfoShowDialog.value = true
|
||||
const infoEvent = (info:any) => {
|
||||
refundInfo.value = info
|
||||
refundInfoShowDialog.value = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员详情
|
||||
*/
|
||||
const toMember = (memberId: number) => {
|
||||
router.push(`/member/detail?id=${memberId}`)
|
||||
router.push(`/member/detail?id=${memberId}`)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
</div>
|
||||
|
||||
<el-form :model="formData" label-width="150px" ref="ruleFormRef" :rules="formRules" class="page-form" v-loading="loading">
|
||||
<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 !text-sm">{{ t('admin') }}</h3>
|
||||
@ -45,29 +45,29 @@
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getConfigLogin, setConfigLogin } from '@/app/api/sys'
|
||||
import { FormRules, FormInstance } from 'element-plus'
|
||||
import { getConfigLogin, setConfigLogin } from '@/app/api/sys'
|
||||
import { FormInstance } from 'element-plus'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const loading = ref(true),
|
||||
ruleFormRef = ref<FormInstance>(),
|
||||
formData = reactive<Record<string, number | string>>({
|
||||
const loading = ref(true)
|
||||
const ruleFormRef = ref<FormInstance>()
|
||||
const formData = reactive<Record<string, number | string>>({
|
||||
is_captcha: 0,
|
||||
is_site_captcha: 0,
|
||||
bg: '',
|
||||
site_bg: ''
|
||||
});
|
||||
})
|
||||
|
||||
const getFormData = async (id: number = 0) => {
|
||||
const data = await (await getConfigLogin()).data
|
||||
Object.keys(formData).forEach((key: string) => {
|
||||
if (['is_captcha','is_site_captcha'].includes(key)) formData[key] = Boolean(Number(data[key]));
|
||||
else formData[key] = data[key];
|
||||
if (['is_captcha', 'is_site_captcha'].includes(key)) formData[key] = Boolean(Number(data[key]))
|
||||
else formData[key] = data[key]
|
||||
})
|
||||
loading.value = false;
|
||||
loading.value = false
|
||||
}
|
||||
getFormData()
|
||||
|
||||
@ -75,9 +75,9 @@ const onSave = async (formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
await formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
let save = JSON.parse(JSON.stringify(formData));
|
||||
Object.keys(save).forEach((key)=>{
|
||||
if (['is_captcha','is_site_captcha'].includes(key)) save[key] = Number(save[key]);
|
||||
const save = JSON.parse(JSON.stringify(formData))
|
||||
Object.keys(save).forEach((key) => {
|
||||
if (['is_captcha', 'is_site_captcha'].includes(key)) save[key] = Number(save[key])
|
||||
})
|
||||
|
||||
setConfigLogin(save).then(() => {
|
||||
|
||||
@ -38,14 +38,14 @@
|
||||
import { reactive } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getAgreementList } from '@/app/api/sys'
|
||||
import { useRouter,useRoute } from 'vue-router'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title;
|
||||
const pageName = route.meta.title
|
||||
|
||||
let agreementTableData = reactive({
|
||||
const agreementTableData = reactive({
|
||||
loading: true,
|
||||
data: [],
|
||||
data: []
|
||||
})
|
||||
|
||||
/**
|
||||
@ -53,10 +53,10 @@ let agreementTableData = reactive({
|
||||
*/
|
||||
const loadAgreementList = () => {
|
||||
agreementTableData.loading = true
|
||||
agreementTableData.data = [];
|
||||
agreementTableData.data = []
|
||||
getAgreementList().then(res => {
|
||||
Object.keys(res.data).forEach((key) => {
|
||||
return agreementTableData.data.push(res.data[key]);
|
||||
return agreementTableData.data.push(res.data[key])
|
||||
})
|
||||
agreementTableData.loading = false
|
||||
}).catch(() => {
|
||||
|
||||
@ -37,9 +37,9 @@ import type { FormInstance } from 'element-plus'
|
||||
import { getAgreementInfo, editAgreement } from '@/app/api/sys'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import useTabbarStore from '@/stores/modules/tabbar'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
// import useAppStore from '@/stores/modules/app'
|
||||
|
||||
const appStore = useAppStore()
|
||||
// const appStore = useAppStore()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const agreement_key: string = route.query.key || ''
|
||||
@ -65,11 +65,10 @@ const setFormData = async (agreement_key: string = '') => {
|
||||
Object.keys(formData).forEach((key: string) => {
|
||||
if (data[key] != undefined) formData[key] = data[key]
|
||||
})
|
||||
loading.value = false;
|
||||
loading.value = false
|
||||
}
|
||||
if (agreement_key) setFormData(agreement_key)
|
||||
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
// 表单验证规则
|
||||
@ -87,10 +86,10 @@ const onSave = async (formEl: FormInstance | undefined) => {
|
||||
if (valid) {
|
||||
loading.value = true
|
||||
const data = formData
|
||||
data.key = formData.agreement_key;
|
||||
data.key = formData.agreement_key
|
||||
editAgreement(data).then(res => {
|
||||
loading.value = false
|
||||
back();
|
||||
back()
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
@ -57,69 +57,66 @@ import { useRoute } from 'vue-router'
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
|
||||
const loading = ref(true),
|
||||
ruleFormRef = ref<FormInstance>(),
|
||||
formData = reactive<Record<string, string | boolean | Array<string> >>({
|
||||
is_auto_transfer: "0",
|
||||
is_auto_verify: "0",
|
||||
is_open: "0",
|
||||
min: "0.01",
|
||||
rate: "0",
|
||||
transfer_type: []
|
||||
});
|
||||
const loading = ref(true)
|
||||
const ruleFormRef = ref<FormInstance>()
|
||||
const formData = reactive<Record<string, string | boolean | Array<string> >>({
|
||||
is_auto_transfer: '0',
|
||||
is_auto_verify: '0',
|
||||
is_open: '0',
|
||||
min: '0.01',
|
||||
rate: '0',
|
||||
transfer_type: []
|
||||
})
|
||||
const Transfertype = ref<Array<Object>>([])
|
||||
|
||||
// 获取会员转账方式
|
||||
const getTransfertypeFn = async()=>{
|
||||
const getTransfertypeFn = async () => {
|
||||
Transfertype.value = await (await getTransfertype()).data
|
||||
}
|
||||
getTransfertypeFn()
|
||||
|
||||
|
||||
// 获取会员的配置信息
|
||||
const setFormData = async (id: number = 0) => {
|
||||
const data = await (await getCashOutConfig()).data
|
||||
Object.keys(formData).forEach((key: string) => {
|
||||
if (data[key] != undefined) formData[key] = data[key];
|
||||
if (data[key] != undefined) formData[key] = data[key]
|
||||
})
|
||||
formData.is_open = Boolean(Number(formData.is_open));
|
||||
loading.value = false;
|
||||
formData.is_open = Boolean(Number(formData.is_open))
|
||||
loading.value = false
|
||||
}
|
||||
setFormData()
|
||||
|
||||
|
||||
|
||||
const minRules = (rule: any, value: any, callback: any) => {
|
||||
if (Number(value) < 0.01) {
|
||||
callback(new Error(t('cashWithdrawalAmountHint')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
if (Number(value) < 0.01) {
|
||||
callback(new Error(t('cashWithdrawalAmountHint')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
const rateRules = (rule: any, value: any, callback: any) => {
|
||||
if (Number(value) > 100 || Number(value) < 0) {
|
||||
callback(new Error(t('commissionRatioHint')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
if (Number(value) > 100 || Number(value) < 0) {
|
||||
callback(new Error(t('commissionRatioHint')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
const rules = reactive<FormRules>({
|
||||
min: [
|
||||
{ validator: minRules, trigger: 'blur' }
|
||||
],
|
||||
rate: [
|
||||
{ validator: rateRules, trigger: 'blur' }
|
||||
]
|
||||
min: [
|
||||
{ validator: minRules, trigger: 'blur' }
|
||||
],
|
||||
rate: [
|
||||
{ validator: rateRules, trigger: 'blur' }
|
||||
]
|
||||
})
|
||||
|
||||
const onSave = async (formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
await formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
let save = {...formData};
|
||||
save.is_open = Number(save.is_open).toString();
|
||||
const save = { ...formData }
|
||||
save.is_open = Number(save.is_open).toString()
|
||||
|
||||
setCashOutConfig(save).then(() => {
|
||||
loading.value = false
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<el-dialog v-model="showDialog" :title="t('cronInfo')" width="550px" :destroy-on-close="true">
|
||||
<el-form :model="formData" label-width="110px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
|
||||
|
||||
|
||||
<el-form-item :label="t('title')" >
|
||||
<div class="input-width"> {{ formData.title }} </div>
|
||||
</el-form-item>
|
||||
@ -18,7 +18,7 @@
|
||||
<el-form-item :label="t('count')" >
|
||||
<div class="input-width"> {{ formData.count }} </div>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
<el-form-item :label="t('task')" >
|
||||
<div class="input-width"> {{ formData.task }} </div>
|
||||
</el-form-item>
|
||||
@ -66,19 +66,19 @@ const loading = ref(true)
|
||||
*/
|
||||
const initialFormData = {
|
||||
count: 0,
|
||||
create_time:'',
|
||||
crond_length:'',
|
||||
crond_type:'',
|
||||
crond_type_name:'',
|
||||
data:'',
|
||||
delete_time:'',
|
||||
last_time:'',
|
||||
next_time:'',
|
||||
status_desc:'',
|
||||
title:'',
|
||||
type:'',
|
||||
type_name:'',
|
||||
update_time:''
|
||||
create_time: '',
|
||||
crond_length: '',
|
||||
crond_type: '',
|
||||
crond_type_name: '',
|
||||
data: '',
|
||||
delete_time: '',
|
||||
last_time: '',
|
||||
next_time: '',
|
||||
status_desc: '',
|
||||
title: '',
|
||||
type: '',
|
||||
type_name: '',
|
||||
update_time: ''
|
||||
}
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
|
||||
@ -91,7 +91,7 @@ const formRules = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['complete'])
|
||||
// const emit = defineEmits(['complete'])
|
||||
|
||||
const setFormData = async (row: any = null) => {
|
||||
loading.value = true
|
||||
@ -101,7 +101,6 @@ const setFormData = async (row: any = null) => {
|
||||
if (row[key] != undefined) formData[key] = row[key]
|
||||
})
|
||||
}
|
||||
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { editNoticeStatus } from '@/app/api/notice'
|
||||
// import { editNoticeStatus } from '@/app/api/notice'
|
||||
|
||||
const showDialog = ref(false)
|
||||
const loading = ref(true)
|
||||
@ -57,7 +57,7 @@ const initialFormData = {
|
||||
message_type: '',
|
||||
name: '',
|
||||
nickname: '',
|
||||
receiver: '',
|
||||
receiver: ''
|
||||
}
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
|
||||
@ -70,10 +70,10 @@ const formRules = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['complete'])
|
||||
// const emit = defineEmits(['complete'])
|
||||
|
||||
const setFormData = async (row: any = null) => {
|
||||
loading.value = true;
|
||||
loading.value = true
|
||||
Object.assign(formData, initialFormData)
|
||||
|
||||
if (row) {
|
||||
|
||||
@ -55,7 +55,7 @@ const initialFormData = {
|
||||
title: '',
|
||||
type: '',
|
||||
sms_id: '',
|
||||
content: ''
|
||||
content: ''
|
||||
}
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
|
||||
@ -66,7 +66,7 @@ const formRules = computed(() => {
|
||||
return {
|
||||
sms_id: [
|
||||
{ required: true, message: t('smsIdPlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
@ -84,7 +84,7 @@ const confirm = async (formEl: FormInstance | undefined) => {
|
||||
loading.value = true
|
||||
|
||||
const data = formData
|
||||
data.status = data.is_sms;
|
||||
data.status = data.is_sms
|
||||
|
||||
editNotice(data).then(res => {
|
||||
loading.value = false
|
||||
@ -99,13 +99,13 @@ const confirm = async (formEl: FormInstance | undefined) => {
|
||||
}
|
||||
|
||||
const setFormData = async (row: any = null) => {
|
||||
loading.value = true;
|
||||
loading.value = true
|
||||
Object.assign(formData, initialFormData)
|
||||
|
||||
if (row) {
|
||||
Object.keys(formData).forEach((key: string) => {
|
||||
if (row[key] != undefined) formData[key] = row[key];
|
||||
if (row.sms && row.sms[key] != undefined) formData[key] = row.sms[key]
|
||||
if (row[key] != undefined) formData[key] = row[key]
|
||||
if (row.sms && row.sms[key] != undefined) formData[key] = row.sms[key]
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user