This commit is contained in:
CQ 2025-08-23 17:06:12 +08:00
parent 1edbfb2a1f
commit fd7f31e40a
54 changed files with 4004 additions and 3282 deletions

View File

@ -9,6 +9,7 @@ declare module '@vue/runtime-core' {
export interface GlobalComponents {
Attachment: typeof import('./src/components/upload-attachment/attachment.vue')['default']
DiyLink: typeof import('./src/components/diy-link/index.vue')['default']
DiyPage: typeof import('./src/components/diy-page/index.vue')['default']
Editor: typeof import('./src/components/editor/index.vue')['default']
ElAlert: typeof import('element-plus/es')['ElAlert']
ElAside: typeof import('element-plus/es')['ElAside']
@ -91,6 +92,7 @@ declare module '@vue/runtime-core' {
SelectIcon: typeof import('./src/components/select-icon/index.vue')['default']
SpreadPopup: typeof import('./src/components/spread-popup/index.vue')['default']
UploadAttachment: typeof import('./src/components/upload-attachment/index.vue')['default']
UploadAudio: typeof import('./src/components/upload-audio/index.vue')['default']
UploadFile: typeof import('./src/components/upload-file/index.vue')['default']
UploadImage: typeof import('./src/components/upload-image/index.vue')['default']
UploadVideo: typeof import('./src/components/upload-video/index.vue')['default']

View File

@ -157,7 +157,7 @@ UE.I18N['zh-cn'] = {
'elementPathTip': "元素路径",
'wordCountTip': "字数统计",
'wordCountMsg': '{#count} / {#leave}',
'wordOverFlowMsg': '<span style="color:red;">字数超出最大允许值,服务器可能拒绝保存</span>',
'wordOverFlowMsg': '<span style="color:red;">字数超出最大允许值</span>',
'ok': "确认",
'cancel': "取消",
'closeDialog': "关闭对话框",

View File

@ -13,6 +13,7 @@ import useAppStore from '@/stores/modules/app'
import { useDark, useToggle } from '@vueuse/core'
import { setThemeColor } from '@/utils/common'
import { useRoute } from 'vue-router'
import { getSiteAllowChange} from '@/app/api/site'
const route = useRoute()
@ -24,7 +25,14 @@ systemStore.getWebsiteInfo()
systemStore.getWebsiteLayout()
const toggleDark = useToggle(useDark())
const getSiteAllowChangeFn = ()=>{
getSiteAllowChange().then(({data})=>{
let isAllowChange = data.is_allow ? true : false
localStorage.setItem('isAllowChange',isAllowChange.toString())
})
}
getSiteAllowChangeFn()
watch(route, () => {
useAppStore().$patch(state => {
state.route = route
@ -39,3 +47,9 @@ onMounted(() => {
</script>
<style lang="scss" scoped></style>
<style>
.el-page-header__header .el-page-header__left .el-page-header__content{
font-size: 14px !important;
font-weight: 500 !important;
}
</style>

View File

@ -103,3 +103,6 @@ export function getAppIndex() {
return request.get('app/index')
}
export function getAdvList() {
return request.get('index/adv_list')
}

View File

@ -199,6 +199,12 @@ export function copyDiy(params: Record<string, any>) {
return request.post(`diy/copy`, params, { showSuccessMessage: true })
}
/**
*
*/
export function getPageLink(params: Record<string, any>) {
return request.get(`diy/page_link`, { params })
}
/***************************************************** 主题风格 ****************************************************/

View File

@ -113,3 +113,7 @@ export function getPreviewPoster(params: Record<string, any>) {
export function getPosterGenerate(params: Record<string, any>) {
return request.get(`sys/poster/generate`, { params, showErrorMessage: false })
}
// 判断是否安装imagemagick扩展
export function checkImagick() {
return request.get(`sys/check_imagick`, { showErrorMessage: false })
}

View File

@ -21,6 +21,23 @@ export function getVerifyDetail(verifyCode: string) {
return request.get(`verify/verify/${ verifyCode }`)
}
/**
*
* @param verifyCode
* @returns
*/
export function getVerifyDetailInfo(verifyCode: string) {
return request.get(`verify/detail/${ verifyCode }`)
}
/**
*
* @param verifyCode
* @returns
*/
export function verify(verifyCode: string, params: Record<string, any>) {
return request.post(`verify/verify/${ verifyCode }`,params,{ showSuccessMessage: true})
}
/***************************************************** 核销员 ****************************************************/
/**

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

View File

@ -13,7 +13,7 @@
<div class="flex flex-wrap plug-list pb-10 plug-large">
<div class="cursor-pointer mt-[20px] mr-4 bg-[#f7f7f7]" v-for="(childItem,childIndex) in item.list" :key="childIndex" @click="toLink(childItem)">
<div class="w-[264px] flex py-[20px] px-[17px] app-item relative">
<el-image class="w-[40px] h-[40px] mr-[10px]" :src="img(childItem.icon)" fit="contain">
<el-image class="w-[40px] h-[40px] mr-[10px] rounded-[6px] overflow-hidden" :src="img(childItem.icon)" fit="contain">
<template #error>
<div class="image-slot">
<img class="w-[40px] h-[40px]" src="@/app/assets/images/index/app_default.png" />
@ -65,7 +65,13 @@ getMarketingList()
const toLink = (item: any) => {
if (item.url) {
router.push(item.url)
// is_target=true
if (item.url.indexOf('is_target=true') != -1) {
const url = router.resolve(item.url)
window.open(url.href)
} else {
router.push(item.url)
}
} else {
addonIndexRoute[item.key] && router.push({ name: addonIndexRoute[item.key] })
}

View File

@ -7,7 +7,7 @@
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('selectStyle')" class="flex">
<span class="text-primary flex-1 cursor-pointer" @click="showTitleStyle">{{ diyStore.editComponent.titleStyle.title }}</span>
<el-icon>
<el-icon @click="showTitleStyle" class="cursor-pointer">
<ArrowRight />
</el-icon>
</el-form-item>
@ -57,7 +57,7 @@
<el-form-item :label="t('selectStyle')" class="flex">
<span class="text-primary flex-1 cursor-pointer"
@click="showBlockStyle">{{ diyStore.editComponent.blockStyle.title }}</span>
<el-icon>
<el-icon @click="showBlockStyle" class="cursor-pointer">
<ArrowRight />
</el-icon>
</el-form-item>

View File

@ -29,7 +29,7 @@
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('selectStyle')" class="flex">
<span class="text-primary flex-1 cursor-pointer" @click="showSearchStyle">{{ diyStore.editComponent.search.styleName }}</span>
<el-icon>
<el-icon @click="showSearchStyle" class="cursor-pointer">
<ArrowRight />
</el-icon>
</el-form-item>

View File

@ -7,7 +7,7 @@
<el-form-item :label="t('selectStyle')" class="flex">
<span class="text-primary flex-1 cursor-pointer"
@click="showStyle">{{ diyStore.editComponent.styleName }}</span>
<el-icon>
<el-icon @click="showStyle" class="cursor-pointer">
<ArrowRight />
</el-icon>
</el-form-item>

View File

@ -74,7 +74,7 @@
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue'
import { ref, computed, watch } from 'vue'
import { t } from '@/lang'
import useDiyStore from '@/stores/modules/diy'
import { img } from '@/utils/common'
@ -330,6 +330,10 @@ const handleHeight = (isCalcHeight: boolean = false) => {
})
}
watch(() => diyStore.editComponent.list, () => {
handleHeight(true)
}, { deep: true })
defineExpose({})
</script>

View File

@ -7,7 +7,7 @@
<el-form-item :label="t('selectStyle')" class="flex">
<span class="text-primary flex-1 cursor-pointer"
@click="showStyle">{{ diyStore.editComponent.styleName }}</span>
<el-icon>
<el-icon @click="showStyle" class="cursor-pointer">
<ArrowRight />
</el-icon>
</el-form-item>

View File

@ -510,12 +510,12 @@ const spreadPopupRef = ref(null)
const spreadEvent = (data: any) => {
const pagePath = '/app/pages/index/diy_form'
const columnName = 'form_id'
const columnValue = data.form_id
const paramsArr = [
{ name: 'form_id', value: data.form_id },
];
const title = '表单推广'
const folder = 'diy_form'
spreadPopupRef.value?.show(pagePath, columnName, columnValue, title, folder)
spreadPopupRef.value?.show(pagePath, paramsArr, title, folder);
}
//

View File

@ -1,5 +1,5 @@
<template>
<el-drawer v-model="showDialog" title="退款详情" direction="rtl" :before-close="handleClose" class="member-detail-drawer">
<el-drawer v-model="showDialog" title="退款详情" direction="rtl" :before-close="handleClose" size="1300px">
<div class="main-container" v-loading="loading">
<div class="relative" v-if="formData">
<div class="flex mb-[20px] justify-between text-[15px]">
@ -152,8 +152,4 @@ defineExpose({
setFormData
})
</script>
<style lang="scss">
.member-detail-drawer{
width: 1300px !important;
}
</style>
<style lang="scss" scoped></style>

View File

@ -3,11 +3,16 @@
<!-- <div class="flex justify-between items-center">
<layoutHeader></layoutHeader>
</div> -->
<div class="flex justify-between items-center py-[24px] pl-[62px] pr-[64px] home-head">
<div class="flex items-center" v-if="webConfig">
<img class="w-[32x] h-[32px] rounded-full" v-if="webConfig.icon" :src="img(webConfig.icon)" alt="">
<img class="w-[32x] h-[32px] rounded-full" v-else src="@/app/assets/images/icon-addon.png" alt="">
<span class="ml-[10px] text-[16px] font-bold">{{webConfig.site_name}}</span>
<div class="flex justify-between items-center py-[24px] pr-[64px] home-head">
<div class="flex items-center w-[219px] justify-center" v-if="webConfig">
<div class="max-w-[82px] h-[40px] overflow-hidden">
<el-image class="h-[40px]" :src="img(webConfig.icon)" fit="contain">
<template #error>
<div class="flex justify-center items-center w-full h-full"><img class="max-w-[70px]" src="@/app/assets/images/logo.default.png" alt="" object-fit="contain"></div>
</template>
</el-image>
</div>
<span class="ml-[10px] max-w-[120px] text-[16px] font-bold truncate">{{webConfig.site_name}}</span>
</div>
<div class="flex items-center">
<div v-if="userStore.userInfo.is_super_admin" class="border-primary border-[1px] h-[30px] px-[15px] flex items-center rounded-[6px] mr-[10px] cursor-pointer" @click="toHome">

View File

@ -12,7 +12,7 @@
<div class="flex h-[156px]">
<div class="w-full h-full ">
<el-carousel :interval="3000" height="156px" class="rounded-[6px]">
<el-carousel-item >
<!-- <el-carousel-item >
<div class="h-full index-carousel" @click="toApplication">
<img :src="img('static/resource/images/banner_1.png')" alt="" class="w-full h-full cursor-pointer">
</div>
@ -21,7 +21,14 @@
<div class="h-full index-carousel" @click="toApplication">
<img :src="img('static/resource/images/banner_2.png')" alt="" class="w-full h-full cursor-pointer">
</div>
</el-carousel-item> -->
<el-carousel-item v-for="(item, index) in bannerlistr" :key="index">
<div class="h-full index-carousel" @click="toApplicationurl(item)">
<img :src="item.image" alt="" class="w-full h-full cursor-pointer">
</div>
</el-carousel-item>
</el-carousel>
</div>
</div>
@ -248,7 +255,7 @@
import { ref, watch ,onMounted} from 'vue'
import { t } from '@/lang'
import { getStatInfo } from '@/app/api/stat'
import { getAppIndex } from '@/app/api/addon'
import { getAppIndex ,getAdvList} from '@/app/api/addon'
import * as echarts from 'echarts'
import { getFrameworkNewVersion } from '@/app/api/module'
import { getWebCopyright } from '@/app/api/sys'
@ -302,12 +309,20 @@ const appList = ref<any>([])
const getAppIndexFn = () => {
loading.value = true
getAppIndex().then((res) => {
appList.value = res.data.data
console.log(res)
appList.value = res.data
loading.value = false
})
}
getAppIndexFn()
const bannerlistr = ref<any>([])
const getAdvListFn = () => {
getAdvList().then((res) => {
console.log(res.data)
bannerlistr.value = res.data
})
}
getAdvListFn()
const getInfoFn = () => {
if (copyright.value.copyright_desc) {
dialogVisible.value = true
@ -442,6 +457,9 @@ const toTypeLink = (url: any,type: any) => {
const toApplication = () => {
window.open('https://www.niucloud.com/app')
}
const toApplicationurl = (item: any) => {
window.open(item.url)
}
const toApplicationDetail = (item: any) => {
window.open(`https://www.niucloud.com/app/detail?id=${item.app_id}`)
}

View File

@ -56,7 +56,7 @@
<el-image class="w-[54px] h-[54px]" :src="row.icon" fit="contain">
<template #error>
<div class="flex items-center w-full h-full">
<img class="max-w-full max-h-full" src="@/app/assets/images/icon-addon.png" alt="" />
<img class="max-w-full max-h-full" src="@/app/assets/images/icon-addon-one.png" alt="" />
</div>
</template>
</el-image>

View File

@ -1,5 +1,5 @@
<template>
<el-drawer v-model="showDialog" title="核销记录详情" direction="rtl" :before-close="handleClose" class="member-detail-drawer">
<el-drawer v-model="showDialog" title="核销记录详情" direction="rtl" :before-close="handleClose" size="1300px">
<div class="main-container" v-loading="loading">
<el-tabs v-model="activeName" class="pb-[10px]" @tab-change="handleClick">
<el-tab-pane label="核销信息" name="verifyInfo" />
@ -28,7 +28,7 @@
<div class="flex items-center mt-[15px]">
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('核销人员') }}</span>
<span class="text-[14px] text-[#666666]">
{{ verifyData.member ? verifyData.member.nickname : '--' }}
{{ (verifyData.is_admin == 1 ? '后台核销' : verifyData.member?.nickname) || '--' }}
</span>
</div>
</el-col>
@ -156,8 +156,4 @@ defineExpose({
})
</script>
<style lang="scss">
.member-detail-drawer{
width: 1300px !important;
}
</style>
<style lang="scss" scoped></style>

View File

@ -39,15 +39,17 @@
<template #empty>
<span>{{ !recordTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="code" :show-overflow-tooltip="true" :label="t('verifyCode')" align="left" min-width="150" />
<el-table-column prop="type_name" :label="t('verifyType')" align="left" min-width="150" />
<el-table-column :label="t('verifyTime')" min-width="180" align="center" :show-overflow-tooltip="true">
<el-table-column :label="t('verifyTime')" min-width="180" align="left" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.create_time || '' }}
</template>
</el-table-column>
<el-table-column prop="member.nickname" :label="t('verifyer')" min-width="180" align="center">
<el-table-column prop="type_name" :label="t('verifyType')" align="left" min-width="150" />
<el-table-column prop="code" :show-overflow-tooltip="true" :label="t('verifyCode')" align="left" min-width="150" />
<el-table-column :label="t('verifyer')" min-width="180" align="center">
<template #default="{ row }">
{{ row.is_admin == 1 ? '后台核销' : row.member?.nickname }}
</template>
</el-table-column>
<el-table-column :label="t('operation')" align="right" fixed="right" width="100">
<template #default="{ row }">
@ -89,7 +91,7 @@ const recordTable = reactive({
data: [],
searchParam: {
code: '',
type: '',
type: route.query.type || '',
verifier_member_id: '',
create_time: []
}

View File

@ -0,0 +1,130 @@
<template>
<div class="main-container min-h-[300px]">
<div class="">
<el-card class="box-card mt-[10px]!border-none table-search-wrap" shadow="never">
<div class="flex p-[10px] items-end">
<div class="flex items-center w-[500px] h-[45px] border-[2px] border-primary rounded-l-lg">
<span class="h-[15px] ml-[10px] pr-[10px] border-r-[1px] border-[#DEE1E7] leading-[1]">
<img class="w-[15px]" src="@/app/assets/images/write.png" />
</span>
<input class="w-[400px] h-[40px] outline-none pl-[10px] text-[18px] bg-transparent"
v-model="verifycode" />
</div>
<div class="bg-primary h-[45px] flex items-center px-[20px] rounded-[10px] ml-[10px] text-[#fff] cursor-pointer"
@click="handelVerify">
<span>{{ t("核销") }}</span>
</div>
<div class="bg-primary h-[45px] flex items-center px-[20px] rounded-[10px] ml-[10px] text-[#fff] cursor-pointer"
@click="router.push('/marketing/verify')">
<span>{{ t("核销记录") }}</span>
</div>
</div>
</el-card>
</div>
<el-dialog v-model="showDialog" :title="t('核销')" width="500px" :destroy-on-close="true">
<div>
<h3 class="panel-title !text-sm">{{ t('核销信息') }}</h3>
<div class="flex items-center mt-[15px]">
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('核销码') }}</span>
<span class="text-[14px] text-[#666666]">
{{verifycode}}
</span>
</div>
<div class="flex items-center mt-[15px]">
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ t('核销类型') }}</span>
<span class="text-[14px] text-[#666666]">
{{ verifyInfo.type_name }}
</span>
</div>
<div class="flex items-center mt-[15px]" v-for="(item,index) in verifyInfo.fixed" :key="index">
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ item.title }}</span>
<span class="text-[14px] text-[#666666]">
{{ item.value }}
</span>
</div>
<div class="box-card mt-[15px] !border-none" shadow="never" v-for="(item,index) in verifyContentData.diy" :key="index">
<h3 class="panel-title !text-sm">{{ item.title }}</h3>
<div class="flex items-center mt-[15px]" v-for="(subItem,subIndex) in item.list" :key="subIndex">
<span class="text-[14px] w-[130px] text-right mr-[20px]">{{ subItem.title }}</span>
<span class="text-[14px] text-[#666666]">
{{ subItem.value }}
</span>
</div>
</div>
<div class="mt-[15px]">
<h3 class="panel-title !text-sm">{{ t('商品信息') }}</h3>
<el-table :data="verifyGoodsList" size="large">
<el-table-column :label="t('商品名称')" align="left" width="300">
<template #default="{ row }">
<div class="flex">
<div class="flex items-center shrink-0">
<el-image v-if="row.cover" class="w-[50px] h-[50px] mr-[10rpx]" :src="img(row.cover)" fit="contain">
<template #error>
<div class="image-slot">
<img class="w-[50px] h-[50px] mr-[10rpx]" src="@/app/assets/images/goods_default.png" />
</div>
</template>
</el-image>
<img v-else class="w-[50px] h-[50px] mr-[10rpx]" src="@/app/assets/images/goods_default.png" fit="contain" />
</div>
<div class="flex flex-col">
<p class="multi-hidden text-[14px]">{{ row.name }}</p>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="num" :label="t('数量')" min-width="50" align="right" />
</el-table>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="verifyCode">{{ t("confirm") }}</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang='ts' setup>
import { ref } from 'vue'
import { t } from '@/lang'
import {img} from '@/utils/common'
import { useRouter } from 'vue-router'
import { getVerifyDetailInfo ,verify} from '@/app/api/verify'
const router = useRouter()
const loading = ref(false)
const verifycode = ref('')
const verifyInfo = ref<any>([])
const verifyContentData: any = ref({})
const verifyGoodsList: any = ref([])
const showDialog = ref(false)
const handelVerify = () => {
if (verifycode.value == '') return
getVerifyDetailInfo(verifycode.value).then((res) => {
showDialog.value = true
verifyInfo.value = res.data
verifyContentData.value = res.data.value.content || {}
verifyGoodsList.value = res.data.value.list || []
loading.value = false
})
}
const isSubmit = ref(false)
const verifyCode = () => {
if (verifycode.value == '') return
if (isSubmit.value) return
isSubmit.value = true
verify(verifycode.value).then(() => {
showDialog.value = false
isSubmit.value = false
}).catch(() => {
isSubmit.value = false
})
}
</script>
<style></style>

View File

@ -1,5 +1,5 @@
<template>
<el-drawer v-model="showDialog" :title="popTitle" direction="rtl" :before-close="handleClose" class="member-detail-drawer">
<el-drawer v-model="showDialog" :title="popTitle" direction="rtl" :before-close="handleClose" class="member-detail-drawer" size="1300px">
<div class="main-container" v-loading="loading">
<div class="bg-page py-[20px] pr-[30px] relative flex">
<div class="member-info w-[250px]">
@ -375,17 +375,20 @@ const getMemberInfoFn = async (bool=false) => {
Object.keys(data).forEach((item) => {
formData[item] = data[item]
})
if(!data.member_label_array){
formData.member_label_array =[]
formData.member_label_name=''
}
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
loading.value = false
} else {
loading.value = false
}
@ -406,8 +409,4 @@ defineExpose({
})
</script>
<style lang="scss">
.member-detail-drawer{
width: 1300px !important;
}
</style>
<style lang="scss" scoped></style>

View File

@ -28,7 +28,7 @@ const componentStyle = computed(() => {
if (prop.value.weight) {
style += 'font-weight: bold;'
}
if (!prop.value.fontFamily || prop.value.fontFamily == 'static/font/SourceHanSansCN-Regular.ttf') {
if (!prop.value.fontFamily || prop.value.fontFamily == 'static/font/PingFang-Medium.ttf') {
style += 'font-family: poster_default_font;'
}
const box: any = document.getElementById(prop.value.id)

View File

@ -28,7 +28,7 @@ const componentStyle = computed(() => {
if (prop.value.weight) {
style += 'font-weight: bold;'
}
if (!prop.value.fontFamily || prop.value.fontFamily == 'static/font/SourceHanSansCN-Regular.ttf') {
if (!prop.value.fontFamily || prop.value.fontFamily == 'static/font/PingFang-Medium.ttf') {
style += 'font-family: poster_default_font;'
}
const box: any = document.getElementById(prop.value.id)

View File

@ -28,7 +28,7 @@ const componentStyle = computed(() => {
if (prop.value.weight) {
style += 'font-weight: bold;'
}
if (!prop.value.fontFamily || prop.value.fontFamily == 'static/font/SourceHanSansCN-Regular.ttf') {
if (!prop.value.fontFamily || prop.value.fontFamily == 'static/font/PingFang-Medium.ttf') {
style += 'font-family: poster_default_font;'
}
const box: any = document.getElementById(prop.value.id)

View File

@ -28,7 +28,7 @@ const componentStyle = computed(() => {
if (prop.value.weight) {
style += `font-weight: bold;`;
}
if (!prop.value.fontFamily || prop.value.fontFamily == 'static/font/SourceHanSansCN-Regular.ttf') {
if (!prop.value.fontFamily || prop.value.fontFamily == 'static/font/PingFang-Medium.ttf') {
style += `font-family: poster_default_font;`;
}
let box: any = document.getElementById(prop.value.id)

View File

@ -6,7 +6,13 @@
<span class="text-page-title">{{ pageName }}</span>
<el-button type="primary" class="w-[100px]" @click="dialogVisible = true">{{ t('添加海报') }}</el-button>
</div>
<div class="mt-[20px]" v-if="!isImagick">
<el-alert type="warning" show-icon :closable="false">
<template #title>
<span class="!text-[14px]">检测到PHP未安装ImageMagick扩展需安装后才能使用海报功能</span>
</template>
</el-alert>
</div>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="posterTableData.searchParam" ref="searchFormDiyPosterRef">
<el-form-item :label="t('posterName')" prop="name">
@ -103,7 +109,7 @@ import { reactive, ref, computed } from 'vue'
import { t } from '@/lang'
import { ElMessageBox, FormInstance } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import { getPosterPageList, getPosterType, modifyPosterStatus, modifyPosterDefault, deletePoster, getPreviewPoster } from '@/app/api/poster'
import { getPosterPageList, getPosterType, modifyPosterStatus, modifyPosterDefault, deletePoster, getPreviewPoster ,checkImagick} from '@/app/api/poster'
import { img, setTablePageStorage, getTablePageStorage } from '@/utils/common'
const router = useRouter()
@ -281,6 +287,16 @@ const resetForm = (formEl: FormInstance | undefined) => {
formEl.resetFields()
loadPosterPageList()
}
const isImagick = ref(false)
// imagemagick
const checkImagickFn = () => {
checkImagick().then((res:any) => {
console.log(res)
isImagick.value = res.data
})
}
checkImagickFn()
</script>

View File

@ -25,7 +25,11 @@
<el-form-item :label="t('createTime')">
<div class="input-width"> {{ formData.create_time }} </div>
</el-form-item>
<el-form-item :label="t('发送结果')">
<div class="input-width" v-if="formData.status == 'sending'"> 发送失败 </div>
<div class="input-width" v-if="formData.status == 'success'"> 发送成功 </div>
<div class="input-width" v-if="formData.status == 'fail'"> {{ formData.result }} </div>
</el-form-item>
</el-form>
<template #footer>
@ -55,7 +59,9 @@ const initialFormData = {
name: '',
nickname: '',
mobile: '',
sms_type_name: ''
sms_type_name: '',
status:'',
result:''
}
const formData: Record<string, any> = reactive({ ...initialFormData })

View File

@ -18,7 +18,7 @@
<el-image class="w-[40px] h-[40px] rounded-md overflow-hidden" :src="row.icon" fit="contain">
<template #error>
<div class="flex items-center w-full h-full">
<img class="w-full h-full" src="@/app/assets/images/icon-addon.png" alt="">
<img class="w-full h-full" src="@/app/assets/images/icon-addon-one.png" alt="">
</div>
</template>
</el-image>

View File

@ -13,7 +13,7 @@
<h3 class="panel-title !text-sm">{{ payItems.name }}</h3>
<div>
<div class="flex items-center justify-between p-[10px] table-item-border bg">
<div class="flex items-center justify-between px-[10px] table-item-border bg h-[50px]">
<span class="text-base w-[230px]">{{ t('payType') }}</span>
<span class="text-base w-[110px] text-center">{{ t('onState') }}</span>
<span class="text-base w-[80px] text-center" v-if="isEdit">{{ t('templateName') }}</span>
@ -52,7 +52,6 @@
<el-button type="primary" :loading="loading" @click="saveFn(formRef)">{{ t('save') }}</el-button>
</div>
</div>
<template v-for="(item, index) in payTypeList">
<component :is="item.setting_component" :ref="(el) => setPayTypeRefs(el, item.key)" v-if="item.setting_component" @complete="setConfigInfo"/>
</template>
@ -210,6 +209,6 @@ const cancelFn = () => {
<style lang="scss" scoped>
.table-item-border {
@apply border-b border-[var(--el-border-color)];
@apply border-b border-[var(--el-border-color-lighter)];
}
</style>

View File

@ -77,8 +77,80 @@
</div>
</el-card>
<div class="mt-[20px]">
<el-table :data="siteTableData.data" size="large" v-loading="siteTableData.loading">
<template #empty>
<span>{{ !siteTableData.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="site_id" :label="t('siteId')" width="100" :show-overflow-tooltip="true" />
<el-table-column :label="t('siteInfo')" width="300" align="left">
<template #default="{ row }">
<div class="flex items-center">
<img class="w-[54px] h-[54px] mr-[10px] rounded-[4px]" v-if="row.logo" :src="img(row.logo)" alt="">
<img class="w-[54px] h-[54px] mr-[10px] rounded-[4px]" v-else src="@/app/assets/images/site_default.png" alt="">
<div class="flex flex-col">
<span>{{ row.site_name || '' }}</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column :label="t('manager')" width="150" align="left">
<template #default="{ row }">
<div class="flex items-center">
<div class="flex flex-col">
<span>{{ row.admin.username || '' }}</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="group_name" :label="t('groupId')" width="150" :show-overflow-tooltip="true" />
<el-table-column prop="site_domain" :label="t('siteDomain')" width="250" :show-overflow-tooltip="true" />
<el-table-column prop="create_time" :label="t('createTime')" width="200" :show-overflow-tooltip="true" />
<el-table-column prop="expire_time" :label="t('expireTime')" width="200" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-if="row.expire_time == 0">永久</div>
<div v-else>{{ row.expire_time }}</div>
</template>
</el-table-column>
<el-table-column :label="t('status')" width="100" align="center">
<template #default="{ row }">
<el-tag class="ml-2" type="success" v-if="row.status == 1">{{ row.status_name }}</el-tag>
<el-tag class="ml-2" type="error" v-else-if="row.status == 3">
{{ row.status_name }}
</el-tag>
<el-tag class="ml-2" type="error" v-else>
{{ row.status_name }}
</el-tag>
</template>
</el-table-column>
<el-table-column :label="t('operation')" min-width="250" align="right" fixed="right">
<template #default="{ row }">
<div class="operation-buttons">
<div class="button-row">
<el-button type="primary" link @click="toSiteLink(row.site_id)">{{ t('toSite') }}</el-button>
<el-button type="primary" link @click="openClose(row.status, row.site_id)" v-if="row.status == 1 || row.status == 3">{{ row.status == 1 ? t('closeTxt') : t('openTxt') }}</el-button>
<el-button type="primary" link @click="infoEvent(row)">{{ t('info') }}</el-button>
</div>
<div class="button-row">
<el-button type="primary" link @click="initSiteEvent(row)">{{ t('站点初始化') }}</el-button>
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
<el-button type="primary" link @click="deleteEvent(row)">{{ t('delete') }}</el-button>
</div>
</div>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="siteTableData.page" v-model:page-size="siteTableData.limit"
layout="total, sizes, prev, pager, next, jumper" :total="siteTableData.total"
@size-change="loadSiteList()" @current-change="loadSiteList" />
</div>
</div>
<!-- <div class="mt-[20px]">
<div class="el-table--fit el-table--default el-table overflow-x-auto w-full" style="width: 100%;" v-loading="siteTableData.loading">
<div class="el-table__inner-wrapper">
@ -169,7 +241,7 @@
layout="total, sizes, prev, pager, next, jumper" :total="siteTableData.total"
@size-change="loadSiteList()" @current-change="loadSiteList" />
</div>
</div>
</div> -->
</el-card>
<edit-site ref="addSiteDialog" @complete="loadSiteList()" />
@ -404,8 +476,6 @@ const infoEvent = (data: any) => {
router.push({ path: '/admin/site/info', query: { id: data.site_id } })
}
/**
* 编辑站点详情
* @param data
@ -687,8 +757,8 @@ const confirmInit = () => {
:deep(.setting-card .el-card__body){
padding: 0 !important;
}
:deep(.el-scrollbar__view){
margin-bottom: 53px !important;
}
// :deep(.el-scrollbar__view){
// margin-bottom: 53px !important;
// }
</style>

View File

@ -67,16 +67,53 @@
</div>
</div>
</el-card>
<el-dialog v-model="dialogVisible" class="dialog-visible" width="70%" title="代码预览">
<div class="flex h-[50vh]" v-loading="codeLoading">
<el-scrollbar class="h-[100%] w-[270px]">
<div class="w-[600px]">
<el-tree v-if="treeData.length && treeKey != ''" :data="treeData" :props="{ label: 'name', value: 'key' }"
node-key="key" :current-node-key="treeKey" :expand-on-click-node="false" highlight-current
default-expand-all ref="treeRef" @node-click="nodeClick">
<template #default="{ node, data }">
<div class="flex items-center">
<el-icon v-if="data.children">
<Folder v-if="!node.expanded" />
<FolderOpened v-else />
</el-icon>
<el-icon v-else>
<Document />
</el-icon>
<span class="pl-[5px]">{{ data.name }}</span>
</div>
</template>
</el-tree>
</div>
</el-scrollbar>
<div class="ml-[20px] relative" style="width: calc(100% - 285px);">
<el-scrollbar class="h-[100%] w-[100%]">
<highlightjs autodetect class="h-[100%]" :code="code" />
</el-scrollbar>
<div class="absolute top-0 right-[15px] z-5 cursor-pointer hover:text-primary" @click="copyCode">
<el-tooltip content="点击复制" placement="top" >
<icon name="iconfont icondingdanzhongxinPC-3"/>
</el-tooltip>
</div>
</div>
</div>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { reactive, ref, watch } from 'vue'
import { img, setTablePageStorage } from '@/utils/common'
import { t } from '@/lang'
import { getGenerateTableList, deleteGenerateTable, generateCreate, generatePreview, generatorCheckFile, getAddonDevelop } from '@/app/api/tools'
import { ElMessage, ElMessageBox, FormInstance } from 'element-plus'
import { useRouter, useRoute } from 'vue-router'
import { useClipboard } from '@vueuse/core'
const router = useRouter()
const route = useRoute()
@ -251,6 +288,27 @@ const listToTree = (arr:any) => {
}
return ret
}
const { copy, isSupported, copied } = useClipboard()
const copyCode = () => {
if (!isSupported.value) {
ElMessage({
message: t('notSupportCopy'),
type: 'warning'
})
return
}
copy(code.value)
}
watch(copied, () => {
if (copied.value) {
ElMessage({
message: t('copySuccess'),
type: 'success'
})
}
})
</script>
<style lang="scss" scoped>

View File

@ -26,13 +26,13 @@
<div class="flex justify-between">
<el-form :inline="true" :model="cronTableData.searchParam" ref="searchFormRef">
<el-form-item :label="t('title')" prop="key">
<el-select v-model="cronTableData.searchParam.key" placeholder="全部" filterable remote clearable :remote-method="loadCronList(1)">
<el-select v-model="cronTableData.searchParam.key" placeholder="全部" filterable remote clearable>
<el-option label="全部" value="all" />
<el-option v-for="item in templateList" :key="item.key" :label="item.name" :value="item.key" />
</el-select>
</el-form-item>
<el-form-item :label="t('status')" prop="status">
<el-select v-model="cronTableData.searchParam.status" placeholder="全部" filterable remote clearable :remote-method="loadCronList(1)">
<el-select v-model="cronTableData.searchParam.status" placeholder="全部" clearable>
<el-option label="全部" value="all" />
<el-option label="启用" value="1" />
<el-option label="关闭" value="0" />

View File

@ -0,0 +1,202 @@
<template>
<div>
<div @click="show">
<slot>
<el-input v-model="selectData.title" :placeholder="t('请选择跳转页面')" readonly class="link-input">
<template #suffix>
<div @click.stop="clear">
<el-icon v-if="selectData.name">
<Close />
</el-icon>
<el-icon v-else>
<ArrowRight />
</el-icon>
</div>
</template>
</el-input>
</slot>
</div>
<el-dialog v-model="showDialog" :title="t('页面选择')" width="850px" :destroy-on-close="true" :close-on-click-modal="false">
<el-table :data="tableData.data" size="large" v-loading="tableData.loading" ref="timeListTableRef" max-height="400">
<template #empty>
<span>{{ !tableData.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column min-width="7%">
<template #default="{ row }">
<el-checkbox v-model="row.checked" @change="handleCheckChange($event,row)" />
</template>
</el-table-column>
<el-table-column prop="page_title" :label="t('页面名称')" min-width="25%" />
<el-table-column prop="type_name" :label="t('页面类型')" min-width="25%" />
<el-table-column prop="url" :label="t('页面路径')" min-width="25%" />
</el-table>
<div class="mt-[16px] flex">
<el-pagination v-model:current-page="tableData.page" v-model:page-size="tableData.limit"
layout="total, sizes, prev, pager, next, jumper" :total="tableData.total"
@size-change="loadList()" @current-change="loadList" />
</div>
<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>
</div>
</template>
<script lang="ts" setup>
import { t } from '@/lang'
import { ref, reactive, nextTick,computed } from 'vue'
import { FormInstance, ElMessage } from "element-plus";
import { getPageLink } from '@/app/api/diy'
const prop = defineProps({
modelValue: {
type: Object,
default: () => {
return {
id: 0,
name: '',
parent: '',
title: '',
url: ''
}
}
},
ignore: {
type: Array,
default: []
}
})
const clear = () => {
selectData.value = {
id: 0,
name: '',
parent: '',
title: '',
url: ''
}
}
const emit = defineEmits(['update:modelValue', 'confirm', 'success'])
const selectData: any = computed({
get() {
return prop.modelValue
},
set(value) {
emit('update:modelValue', value)
}
})
const searchFormRef = ref<FormInstance>()
const tableData = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
name: '',
}
})
const timeListTableRef = ref()
const showDialog = ref(false)
const show = () => {
showDialog.value = true
loadList()
}
/**
* 获取商品列表
*/
const loadList = (page: number = 1) => {
tableData.loading = true
tableData.page = page
getPageLink({
page: tableData.page,
limit: tableData.limit,
...tableData.searchParam
}).then(res => {
tableData.loading = false
tableData.data = res.data.data
tableData.data.forEach((item: any) => {
item.checked = item.id == selectData.value.id
})
tableData.total = res.data.total
setTimesSelected();
}).catch(() => {
tableData.loading = false
})
}
loadList()
const handleCheckChange = (isSelect: any, row: any) => {
if (isSelect) {
selectData.value.id = row.id
} else {
selectData.value.id = 0 //
}
setTimesSelected()
}
// //
const setTimesSelected = () => {
nextTick(() => {
for (let i = 0; i < tableData.data.length; i++) {
tableData.data[i].checked = false
if (selectData.value.id == tableData.data[i].id) {
tableData.data[i].checked = true
Object.assign(selectData.value, tableData.data[i])
}
}
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadList()
}
const save = () => {
if (selectData.value.id == 0) {
ElMessage({
type: 'warning',
message: `${ t('请选择页面') }`
})
return;
}
selectData.value ={
id:selectData.value.id,
name:selectData.value.name,
parent:selectData.value.parent,
title:selectData.value.title,
url:selectData.value.url
}
showDialog.value = false;
}
defineExpose({
show,
showDialog,
})
</script>
<style lang="scss" scoped>
.form-item-wrap {
margin-right: 10px !important;
margin-bottom: 10px !important;
&.last-child {
margin-right: 0 !important;
}
}
</style>

View File

@ -50,15 +50,19 @@ import { img } from '@/utils/common'
const showDialog = ref(false)
const channel = ref('h5')
// H5
const wapUrl = ref('')
const wapDomain = ref('')
const wapImage = ref('')
const wapPreview = ref('')
const pageName = ref('')
//
const weappData = reactive({
path: ''
})
//
getUrl().then((res: any) => {
wapUrl.value = res.data.wap_url
@ -66,42 +70,53 @@ getUrl().then((res: any) => {
if (import.meta.env.MODE == 'production') return
wapDomain.value = res.data.wap_domain
// envwap
if (wapDomain.value) {
wapUrl.value = wapDomain.value + '/wap'
}
const wapDomainStorage = storage.get('wap_domain')
if (wapDomainStorage) {
wapUrl.value = wapDomainStorage
}
})
// **H5**
// H5
const generateH5QRCode = () => {
wapPreview.value = `${ wapUrl.value }${ pageName.value }`
QRCode.toDataURL(wapPreview.value, { errorCorrectionLevel: 'L', margin: 0, width: 120 }).then(url => {
// URL
const queryStr = params.value
.map(item => `${encodeURIComponent(item.name)}=${encodeURIComponent(item.value)}`)
.join('&')
// H5
wapPreview.value = `${wapUrl.value}${pagePath.value}${queryStr ? '?' + queryStr : ''}`
//
QRCode.toDataURL(wapPreview.value, {
errorCorrectionLevel: 'L',
margin: 0,
width: 120
}).then(url => {
wapImage.value = url
})
}
// ****
//
const fetchWeAppQRCode = () => {
// page '/'
if (pagePath.value.startsWith('/')) {
pagePath.value = pagePath.value.slice(1);
// '/'
let page = pagePath.value
if (page.startsWith('/')) {
page = page.slice(1)
}
//
getQrcode({
page: pagePath.value, //
folder: folder.value, //
params: [
{
column_name: columnName.value,
column_value: columnValue.value
}
]
page: page,
folder: folder.value,
// { column_name, column_value }
params: params.value.map(item => ({
column_name: item.name,
column_value: item.value
}))
}).then((res: any) => {
if (res.data) {
weappData.path = res.data.weapp_path
@ -109,24 +124,30 @@ const fetchWeAppQRCode = () => {
})
}
//
const pagePath = ref("")
const columnName = ref("")
const columnValue = ref("")
const titleName = ref("")
const folder: any = ref("")
//
const pagePath = ref("") // "/addon/pintuan/pages/goods/detail"
const params = ref<Array<{name: string; value: string | number}>>([]) //
const titleName = ref("") //
const folder: any = ref("") //
// ****
const show = (page: string, column: string, value: string, title: string, dir: string) => {
//
const show = (
page: string,
paramsArr: Array<{name: string; value: string | number}>,
title: string,
dir: string
) => {
//
pagePath.value = page
columnName.value = column
columnValue.value = value
params.value = paramsArr
titleName.value = title
folder.value = dir
pageName.value = `${ pagePath.value }?${ columnName.value }=${ columnValue.value }`
//
generateH5QRCode()
fetchWeAppQRCode()
//
showDialog.value = true
}
@ -156,3 +177,4 @@ defineExpose({
show
})
</script>

View File

@ -1,5 +1,5 @@
<template>
<div class="flex border-t border-b main-wrap border-color w-full attachment-wrap" :class="scene == 'select' ? 'h-[40vh]' : 'h-full'">
<div class="flex border-t border-b main-wrap border-color w-full attachment-wrap" :class="scene == 'select' ? 'h-[546px]' : 'h-full'">
<!-- 分组 -->
<div class="group-wrap w-[180px] p-[15px] h-full border-r border-color flex flex-col">
@ -82,7 +82,7 @@
<div class="flex items-center">
<el-tooltip placement="top">
<template #content>{{ item.real_name }}</template>
<div class="truncate my-[10px] cursor-pointer text-base flex-1 text-center">{{ item.real_name }}</div>
<div class="truncate my-[10px] cursor-pointer text-base flex-1 text-center h-[20px] leading-[20px]">{{ item.real_name }}</div>
</el-tooltip>
<!-- 图片操作 -->
<el-dropdown :hide-on-click="false" v-if="scene == 'attachment'" class="attachment-action hidden ">
@ -232,12 +232,12 @@ const attachment: Record<string, any> = reactive({
loading: true,
page: 1,
total: 0,
limit: prop.scene == 'select' ? 10 : 20,
limit: prop.scene == 'select' ? 18 : 20,
data: []
})
if (prop.scene == 'select') {
attachment.limit = 10
attachment.limit = 18
if (prop.type == 'icon') {
attachment.limit = 20
}

View File

@ -2,7 +2,7 @@
<span @click="openDialog" class="cursor-pointer">
<slot></slot>
</span>
<el-dialog v-model="showDialog" :title="t('upload.select' + type)" width="60%" class="attachment-dialog" :destroy-on-close="true">
<el-dialog v-model="showDialog" :title="t('upload.select' + type)" width="920px" class="attachment-dialog" :destroy-on-close="true">
<attachment :limit="limit" :type="type" ref="attachmentRef" />

View File

@ -0,0 +1,74 @@
<template>
<el-upload v-bind="upload" class="upload-file">
<slot>
<el-button type="primary">{{ t('上传音频') }}</el-button>
</slot>
</el-upload>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { t } from '@/lang'
import { getToken } from '@/utils/common'
import { UploadFile, ElMessage } from 'element-plus'
import storage from '@/utils/storage'
const prop = defineProps({
modelValue: {
type: String,
default: ''
},
api: {
type: String,
default: 'sys/audio'
}
})
const emit = defineEmits(['update:modelValue'])
const value = computed({
get () {
return prop.modelValue
},
set (value) {
emit('update:modelValue', value)
}
})
const upload: Record<string, any> = {
action: `${import.meta.env.VITE_APP_BASE_URL}/${prop.api}`,
showFileList: false,
headers: {},
accept: 'audio/*,.mp3,.wav,.ogg,.m4a,.flac,.aac,.wma',
beforeUpload: (file: File) => {
const audioTypes = ['audio/mp3', 'audio/wav', 'audio/ogg', 'audio/m4a', 'audio/flac', 'audio/aac', 'audio/wma', 'audio/mpeg']
const audioExtensions = ['.mp3', '.wav', '.ogg', '.m4a', '.flac', '.aac', '.wma']
const isAudio = audioTypes.includes(file.type) || audioExtensions.some(ext => file.name.toLowerCase().endsWith(ext))
if (!isAudio) {
ElMessage({ message: t('请上传音频文件'), type: 'error' })
return false
}
return true
},
onSuccess: (response: any, uploadFile: UploadFile) => {
if (response.code != undefined && response.code != 1) {
ElMessage({ message: response.msg, type: 'error' })
return
}
value.value = response.data.url
ElMessage({ message: t('upload.success'), type: 'success' })
}
}
upload.headers[import.meta.env.VITE_REQUEST_HEADER_TOKEN_KEY] = getToken()
upload.headers[import.meta.env.VITE_REQUEST_HEADER_SITEID_KEY] = storage.get('siteId') || 0
</script>
<style lang="scss">
.upload-file .el-upload {
width: 100%;
}
</style>

View File

@ -6,7 +6,7 @@
<div class="logo flex items-center m-auto h-[64px]" v-if="!systemStore.menuIsCollapse">
<el-image style="width: 40px; height: 40px" :src="img(logoUrl)" fit="contain">
<template #error>
<div class="flex justify-center items-center w-full h-[40px]"><img class="max-w-[40px]" src="@/app/assets/images/icon-addon.png" alt="" object-fit="contain"></div>
<div class="flex justify-center items-center w-full h-[40px]"><img class="max-w-[40px]" src="@/app/assets/images/icon-addon-one.png" alt="" object-fit="contain"></div>
</template>
</el-image>
</div>

View File

@ -4,7 +4,7 @@
<div class="logo flex items-center m-auto h-[64px]" v-if="!systemStore.menuIsCollapse">
<el-image style="width: 40px; height: 40px" :src="img(logoUrl)" fit="contain">
<template #error>
<div class="flex justify-center items-center w-full h-[40px]"><img class="max-w-[40px]" src="@/app/assets/images/icon-addon.png" alt="" object-fit="contain"></div>
<div class="flex justify-center items-center w-full h-[40px]"><img class="max-w-[40px]" src="@/app/assets/images/icon-addon-one.png" alt="" object-fit="contain"></div>
</template>
</el-image>
</div>

View File

@ -4,7 +4,7 @@
<div class="logo flex items-center m-auto h-[64px]" v-if="!systemStore.menuIsCollapse">
<el-image style="width: 40px; height: 40px" :src="img(logoUrl)" fit="contain">
<template #error>
<div class="flex justify-center items-center w-full h-[40px]"><img class="max-w-[40px]" src="@/app/assets/images/icon-addon.png" alt="" object-fit="contain"></div>
<div class="flex justify-center items-center w-full h-[40px]"><img class="max-w-[40px]" src="@/app/assets/images/icon-addon-one.png" alt="" object-fit="contain"></div>
</template>
</el-image>
</div>

View File

@ -15,7 +15,8 @@
<!-- 面包屑导航 -->
<div class="flex items-center h-full pl-[10px]">
<el-breadcrumb separator="/">
<el-breadcrumb-item v-for="(route, index) in breadcrumb" :to="route.path" class="inter" :key="index">{{route.meta.title }}</el-breadcrumb-item>
<!-- :to="route.path" class="inter" 这种修改方式导致部分跳转不对需要重新调整菜单才可以 -->
<el-breadcrumb-item v-for="(route, index) in breadcrumb" :key="index">{{route.meta.title }}</el-breadcrumb-item>
</el-breadcrumb>
</div>
</div>

View File

@ -1,13 +1,13 @@
<template>
<el-container class="w-100 h-screen">
<el-main class="flex p-0">
<div class="one-menu w-[124px] h-screen px-[8px] bg-[#282c34]">
<div class="one-menu w-[124px] h-screen px-[8px] bg-[#1c2233]">
<el-header class="logo-wrap">
<div class="logo flex items-center m-auto h-[64px]" v-if="!systemStore.menuIsCollapse">
<el-image style="width: 40px; height: 40px" :src="img(logoUrl)" fit="contain">
<template #error>
<div class="flex justify-center items-center w-full h-[40px]">
<img class="max-w-[40px]" src="@/app/assets/images/icon-addon.png" alt="" object-fit="contain">
<img class="max-w-[40px]" src="@/app/assets/images/icon-addon-one.png" alt="" object-fit="contain">
</div>
</template>
</el-image>
@ -38,8 +38,8 @@
</el-scrollbar>
</div>
<el-scrollbar v-if="twoMenuData.length" class="two-menu w-[140px]">
<div class="w-[140px] h-[64px] flex items-center justify-center text-[16px] border-b-[1px] border-solid border-[var(--el-border-color-lighter)]">
<el-scrollbar v-if="twoMenuData.length" class="two-menu w-[132px]">
<div class="w-[132px] h-[64px] flex items-center justify-center text-[16px] border-b-[1px] border-solid border-[var(--el-border-color-lighter)]">
{{ route.matched[1].meta.title }}
</div>
@ -161,6 +161,18 @@ onMounted(async () => {
await getMarketingList()
})
//
const menuOption = ref([])
const secondMenuShowWayFn = () => {
menuOption.value = []
if (oneMenuActive.value !== 'active' && oneMenuActive.value !== 'addon' && twoMenuData.value && Object.values(twoMenuData.value).length) {
const data = cloneDeep(twoMenuData.value)
for (const key in data) {
menuOption.value.push(data[key].name)
}
}
}
watchEffect(() => {
// if (!appList.value || loading.value) return; //
const addonKeys = appList.value?.addon?.list?.map(item => item.key) ?? []
@ -199,10 +211,10 @@ watchEffect(() => {
}
}
}
secondMenuShowWayFn()
})
// watch(route, () => {
// console.log(route.matched);
// if (route.meta.attr != '') {
// oneMenuActive.value = route.matched[2].name
@ -230,18 +242,6 @@ watchEffect(() => {
// }
// }
// }, { immediate: true })
//
const menuOption = ref([])
watch(twoMenuData.value, () => {
menuOption.value = []
if (twoMenuData.value && Object.values(twoMenuData.value).length) {
const data = cloneDeep(twoMenuData.value)
for (const key in data) {
menuOption.value.push(data[key].name)
}
}
}, { immediate: true })
</script>
<style lang="scss">
@ -259,8 +259,8 @@ watch(twoMenuData.value, () => {
border-radius: 2px;
&:hover {
color: var(--el-color-primary);
background-color: transparent;
color: #ffffff;
background-color: var(--el-color-primary);
}
&.is-active {
@ -287,14 +287,14 @@ watch(twoMenuData.value, () => {
.two-menu {
.aside-menu:not(.el-menu--collapse) {
width: 140px;
width: 132px;
padding-top: 16px;
border: 0;
.el-menu-item {
height: 36px;
margin: 0 8px 4px;
padding: 0 8px !important;
margin: 0 12px 4px;
padding: 0 !important;
border-radius: 2px;
span {
@ -318,7 +318,7 @@ watch(twoMenuData.value, () => {
.el-sub-menu__title {
height: 36px;
margin: 0 8px 4px;
padding-left: 8px;
padding-left: 0;
border-radius: 2px;
span {
@ -339,6 +339,9 @@ watch(twoMenuData.value, () => {
.el-menu-item {
padding-left: 20px !important;
span{
margin-left: 0 !important;
}
}
}
}

View File

@ -15,7 +15,8 @@
<!-- 面包屑导航 -->
<div class="flex items-center h-full pl-[10px] hidden-xs-only">
<el-breadcrumb separator="/">
<el-breadcrumb-item v-for="(route, index) in breadcrumb" :key="index" :to="route.path" class="inter">{{route.meta.title }}</el-breadcrumb-item>
<!-- :to="route.path" class="inter" 这种修改方式导致部分跳转不对需要重新调整菜单才可以 -->
<el-breadcrumb-item v-for="(route, index) in breadcrumb" :key="index">{{route.meta.title }}</el-breadcrumb-item>
</el-breadcrumb>
</div>
</div>
@ -238,7 +239,7 @@ const refreshRouter = () => {
//
const breadcrumb = computed(() => {
console.log(route.matched)
// console.log(route.matched)
const matched = route.matched.filter(item => { return item.meta.title })
if (matched[0] && matched[0].path == '/') matched.splice(0, 1)
return matched

View File

@ -67,7 +67,7 @@ const usePosterStore = defineStore('poster', {
height: 60,
minWidth: 120,
minHeight: 44,
fontFamily: 'static/font/SourceHanSansCN-Regular.ttf',
fontFamily: 'static/font/PingFang-Medium.ttf',
fontSize: 40,
weight: false,
lineHeight: 10,

View File

@ -19,12 +19,12 @@ html, body {
// 海报价格字体
@font-face {
font-family: 'poster_price_font';
src: url('./font/price.ttf') format('truetype');
src: url('./font/OPLUSSANS3-REGULAR.ttf') format('truetype');
}
// 海报价格字体
@font-face {
font-family: 'poster_default_font';
src: url('./font/SourceHanSansCN-Regular.ttf') format('truetype');
src: url('./font/PingFang-Medium.ttf') format('truetype');
}
// 以下最新请勿改动 2024.5.25

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -83,7 +83,7 @@ class Request {
}
/**
* get请求
* post请求
* @param url
* @param data
* @param config
@ -94,7 +94,7 @@ class Request {
}
/**
* get请求
* put请求
* @param url
* @param data
* @param config
@ -105,7 +105,7 @@ class Request {
}
/**
* get请求
* delete请求
* @param url
* @param config
* @returns