修复bug ,底部导航,装修优化
This commit is contained in:
parent
a1fc2fed1c
commit
cf99b35b79
|
|
@ -30,6 +30,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@rushstack/eslint-patch": "^1.1.0",
|
||||
"@tailwindcss/line-clamp": "^0.4.2",
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"@types/node": "^16.11.41",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,11 @@ export function setDecoratePages(params: any) {
|
|||
return request.post({ url: '/decorate/pages/save', params })
|
||||
}
|
||||
|
||||
// 获取首页文章数据
|
||||
export function getDecorateArticle(params?: any) {
|
||||
return request.get({ url: '/decorate/data/article', params })
|
||||
}
|
||||
|
||||
// 底部导航详情
|
||||
export function getDecorateTabbar(params?: any) {
|
||||
return request.get({ url: '/decorate/tabbar/detail', params })
|
||||
|
|
|
|||
|
|
@ -1,11 +1,5 @@
|
|||
<template>
|
||||
<el-image :style="styles" v-bind="props">
|
||||
<template v-slot:error>
|
||||
<div class="text-tx-secondary flex items-center justify-center bg-white h-full">
|
||||
<icon name="el-icon-Picture" :size="30" />
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
<el-image :style="styles" v-bind="props"> </el-image>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
自定义链接
|
||||
<div class="ml-4 flex-1 min-w-[100px]">
|
||||
<el-input
|
||||
:model-value="modelValue.path"
|
||||
:model-value="modelValue.query?.url"
|
||||
placeholder="请输入链接地址"
|
||||
@input="handleInput"
|
||||
/>
|
||||
|
|
@ -32,7 +32,10 @@ const emit = defineEmits<{
|
|||
|
||||
const handleInput = (value: string) => {
|
||||
emit('update:modelValue', {
|
||||
path: value,
|
||||
path: '/pages/webview/webview',
|
||||
query: {
|
||||
url: value
|
||||
},
|
||||
type: LinkTypeEnum.CUSTOM_LINK
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,16 +10,8 @@
|
|||
</el-menu-item>
|
||||
</el-menu>
|
||||
<div class="flex-1 pl-4">
|
||||
<shop-pages
|
||||
v-model="activeLink"
|
||||
v-if="LinkTypeEnum.SHOP_PAGES == activeMenu"
|
||||
@update:model-value="updateLink"
|
||||
/>
|
||||
<custom-link
|
||||
v-model="activeLink"
|
||||
v-if="LinkTypeEnum.CUSTOM_LINK == activeMenu"
|
||||
@update:model-value="updateLink"
|
||||
/>
|
||||
<shop-pages v-model="activeLink" v-if="LinkTypeEnum.SHOP_PAGES == activeMenu" />
|
||||
<custom-link v-model="activeLink" v-if="LinkTypeEnum.CUSTOM_LINK == activeMenu" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -72,9 +64,10 @@ const handleSelect = (index: string) => {
|
|||
activeMenu.value = index
|
||||
}
|
||||
|
||||
const updateLink = (value: any) => {
|
||||
watch(activeLink, (value) => {
|
||||
if (!value.type) return
|
||||
emit('update:modelValue', value)
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
<template>
|
||||
<div class="link-picker flex-1" @click="!disabled && popupRef?.open()">
|
||||
<el-input
|
||||
:model-value="modelValue?.name ?? modelValue?.path"
|
||||
placeholder="请选择链接"
|
||||
readonly
|
||||
:disabled="disabled"
|
||||
>
|
||||
<el-input :model-value="getLink" placeholder="请选择链接" readonly :disabled="disabled">
|
||||
<template #suffix>
|
||||
<icon v-if="!modelValue?.path" name="el-icon-ArrowRight" />
|
||||
<icon
|
||||
|
|
@ -43,6 +38,17 @@ const activeLink = ref<Link>({ path: '', type: LinkTypeEnum.SHOP_PAGES })
|
|||
const handleConfirm = () => {
|
||||
emit('update:modelValue', activeLink.value)
|
||||
}
|
||||
|
||||
const getLink = computed(() => {
|
||||
switch (props.modelValue?.type) {
|
||||
case LinkTypeEnum.SHOP_PAGES:
|
||||
return props.modelValue.name
|
||||
case LinkTypeEnum.CUSTOM_LINK:
|
||||
return props.modelValue.query?.url
|
||||
default:
|
||||
return props.modelValue?.name
|
||||
}
|
||||
})
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(value) => {
|
||||
|
|
|
|||
|
|
@ -86,8 +86,6 @@ export function findFirstValidRoute(routes: RouteRecordRaw[]): string | undefine
|
|||
}
|
||||
|
||||
export function getRoutePath(perms: string) {
|
||||
console.log(router.getRoutes())
|
||||
console.log(router.getRoutes().find((item) => item.meta?.perms == perms)?.path)
|
||||
return router.getRoutes().find((item) => item.meta?.perms == perms)?.path || ''
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,14 +64,13 @@ export class Axios {
|
|||
return response
|
||||
},
|
||||
(err: AxiosError) => {
|
||||
let cancelUrl = err.config?.url
|
||||
if (isFunction(responseInterceptorsCatchHook)) {
|
||||
responseInterceptorsCatchHook(err)
|
||||
}
|
||||
if (err.code == AxiosError.ERR_CANCELED) {
|
||||
cancelUrl = err.message
|
||||
if (err.code != AxiosError.ERR_CANCELED) {
|
||||
this.removeCancelToken(err.config?.url!)
|
||||
}
|
||||
this.removeCancelToken(cancelUrl!)
|
||||
|
||||
if (err.code == AxiosError.ECONNABORTED) {
|
||||
setTimeout(() => {
|
||||
console.log(err)
|
||||
|
|
|
|||
|
|
@ -149,3 +149,14 @@ export const timeFormat = (dateTime: number, fmt = 'yyyy-mm-dd') => {
|
|||
}
|
||||
return fmt
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取不重复的id
|
||||
* @param length { Number } id的长度
|
||||
* @return { String } id
|
||||
*/
|
||||
export const getNonDuplicateID = (length = 8) => {
|
||||
let idStr = Date.now().toString(36)
|
||||
idStr += Math.random().toString(36).substring(3, length)
|
||||
return idStr
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,21 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-card class="!border-none" shadow="never">
|
||||
<el-alert type="warning" title="温馨提示:用于管理网站的分类,只可添加到一级" :closable="false" show-icon />
|
||||
<el-alert
|
||||
type="warning"
|
||||
title="温馨提示:用于管理网站的分类,只可添加到一级"
|
||||
:closable="false"
|
||||
show-icon
|
||||
/>
|
||||
</el-card>
|
||||
<el-card class="!border-none mt-4" shadow="never" v-loading="pager.loading">
|
||||
<div>
|
||||
<el-button class="mb-4" v-perms="['article:cate:add']" type="primary" @click="handleAdd()">
|
||||
<el-button
|
||||
class="mb-4"
|
||||
v-perms="['article:cate:add']"
|
||||
type="primary"
|
||||
@click="handleAdd()"
|
||||
>
|
||||
<template #icon>
|
||||
<icon name="el-icon-Plus" />
|
||||
</template>
|
||||
|
|
@ -17,17 +27,32 @@
|
|||
<el-table-column label="文章数" prop="number" min-width="120" />
|
||||
<el-table-column label="状态" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-switch v-perms="['article:cate:change']" v-model="row.isShow" :active-value="1"
|
||||
:inactive-value="0" @change="changeStatus(row.id)" />
|
||||
<el-switch
|
||||
v-perms="['article:cate:change']"
|
||||
v-model="row.isShow"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
@change="changeStatus(row.id)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="排序" prop="sort" min-width="120" />
|
||||
<el-table-column label="操作" width="120" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button v-perms="['article:cate:edit']" type="primary" link @click="handleEdit(row)">
|
||||
<el-button
|
||||
v-perms="['article:cate:edit']"
|
||||
type="primary"
|
||||
link
|
||||
@click="handleEdit(row)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button v-perms="['article:cate:del']" type="danger" link @click="handleDelete(row.id)">
|
||||
<el-button
|
||||
v-perms="['article:cate:del']"
|
||||
type="danger"
|
||||
link
|
||||
@click="handleDelete(row.id)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@
|
|||
:src="row.image"
|
||||
class="w-[60px] h-[45px]"
|
||||
:preview-src-list="[row.image]"
|
||||
preview-teleported
|
||||
fit="contain"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
<template>
|
||||
<el-image :style="styles" v-bind="props" :src="getImageUrl(src)">
|
||||
<template #placeholder>
|
||||
<div class="image-slot"></div>
|
||||
</template>
|
||||
<template #error>
|
||||
<div class="image-slot">
|
||||
<icon name="el-icon-Picture" :size="30" />
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
import type { CSSProperties } from 'vue'
|
||||
import { addUnit } from '@/utils/util'
|
||||
import { imageProps } from 'element-plus'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
const props = defineProps({
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: 'auto'
|
||||
},
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: 'auto'
|
||||
},
|
||||
radius: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
...imageProps
|
||||
})
|
||||
|
||||
const { getImageUrl } = useAppStore()
|
||||
const styles = computed<CSSProperties>(() => {
|
||||
return {
|
||||
width: addUnit(props.width),
|
||||
height: addUnit(props.height),
|
||||
borderRadius: addUnit(props.radius)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-image {
|
||||
display: block;
|
||||
.image-slot {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #fafafa;
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,31 +1,32 @@
|
|||
<template>
|
||||
<div class="shadow mx-[30px] pages-preview">
|
||||
<div
|
||||
v-for="(widget, index) in pageData"
|
||||
:key="widget"
|
||||
class="relative"
|
||||
:class="{
|
||||
'cursor-pointer': !widget?.disabled
|
||||
}"
|
||||
@click="handleClick(widget, index)"
|
||||
>
|
||||
<el-scrollbar>
|
||||
<div
|
||||
class="absolute w-full h-full z-[100] border-dashed"
|
||||
v-for="(widget, index) in pageData"
|
||||
:key="widget.id"
|
||||
class="relative"
|
||||
:class="{
|
||||
select: index == modelValue,
|
||||
'border-br border-2': !widget?.disabled
|
||||
'cursor-pointer': !widget?.disabled
|
||||
}"
|
||||
></div>
|
||||
<slot>
|
||||
<keep-alive>
|
||||
@click="handleClick(widget, index)"
|
||||
>
|
||||
<div
|
||||
class="absolute w-full h-full z-[100] border-dashed"
|
||||
:class="{
|
||||
select: index == modelValue,
|
||||
'border-[#dcdfe6] border-2': !widget?.disabled
|
||||
}"
|
||||
></div>
|
||||
<slot>
|
||||
<component
|
||||
:is="widgets[widget?.name]?.content"
|
||||
:content="widget.content"
|
||||
:styles="widget.styles"
|
||||
:key="widget.id"
|
||||
/>
|
||||
</keep-alive>
|
||||
</slot>
|
||||
</div>
|
||||
</slot>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<div class="banner">
|
||||
<div class="banner-image">
|
||||
<image-contain width="100%" height="170px" :src="getImageUrl(getImage)" fit="contain" />
|
||||
<decoration-img width="100%" height="170px" :src="getImage" fit="contain" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
import type { PropType } from 'vue'
|
||||
import type options from './options'
|
||||
import DecorationImg from '../../decoration-img.vue'
|
||||
type OptionsType = ReturnType<typeof options>
|
||||
const props = defineProps({
|
||||
content: {
|
||||
|
|
@ -20,7 +20,7 @@ const props = defineProps({
|
|||
default: () => ({})
|
||||
}
|
||||
})
|
||||
const { getImageUrl } = useAppStore()
|
||||
|
||||
const getImage = computed(() => {
|
||||
const { data } = props.content
|
||||
if (Array.isArray(data)) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="customer-service">
|
||||
<image-contain width="140px" height="140px" :src="getImageUrl(content.qrcode)" alt="" />
|
||||
<decoration-img width="140px" height="140px" :src="content.qrcode" alt="" />
|
||||
<div class="text-[15px] mt-[7px] font-medium">{{ content.title }}</div>
|
||||
<div class="text-[#666] mt-[20px]">服务时间:{{ content.time }}</div>
|
||||
<div class="text-[#666] mt-[7px]">客服电话:{{ content.mobile }}</div>
|
||||
|
|
@ -12,9 +12,9 @@
|
|||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
import type { PropType } from 'vue'
|
||||
import type options from './options'
|
||||
import DecorationImg from '../../decoration-img.vue'
|
||||
type OptionsType = ReturnType<typeof options>
|
||||
defineProps({
|
||||
content: {
|
||||
|
|
@ -26,7 +26,6 @@ defineProps({
|
|||
default: () => ({})
|
||||
}
|
||||
})
|
||||
const { getImageUrl } = useAppStore()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
:key="index"
|
||||
class="flex flex-col items-center w-1/4 mb-[15px]"
|
||||
>
|
||||
<image-contain width="26px" height="26px" :src="getImageUrl(item.image)" alt="" />
|
||||
<decoration-img width="26px" height="26px" :src="item.image" alt="" />
|
||||
<div class="mt-[7px]">{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
:key="index"
|
||||
class="flex items-center border-b border-[#e5e5e5] h-[50px] px-[12px]"
|
||||
>
|
||||
<image-contain width="24px" height="24px" :src="getImageUrl(item.image)" alt="" />
|
||||
<decoration-img width="24px" height="24px" :src="item.image" alt="" />
|
||||
<div class="ml-[10px] flex-1">{{ item.name }}</div>
|
||||
<div>
|
||||
<icon name="el-icon-ArrowRight" />
|
||||
|
|
@ -29,9 +29,9 @@
|
|||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
import type { PropType } from 'vue'
|
||||
import type options from './options'
|
||||
import DecorationImg from '../../decoration-img.vue'
|
||||
type OptionsType = ReturnType<typeof options>
|
||||
defineProps({
|
||||
content: {
|
||||
|
|
@ -43,7 +43,6 @@ defineProps({
|
|||
default: () => ({})
|
||||
}
|
||||
})
|
||||
const { getImageUrl } = useAppStore()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
<template>
|
||||
<div class="nav pt-[15px] pb-[8px]">
|
||||
<div class="nav bg-white pt-[15px] pb-[8px]">
|
||||
<div class="flex flex-wrap">
|
||||
<div
|
||||
v-for="(item, index) in content.data"
|
||||
:key="index"
|
||||
class="flex flex-col items-center w-1/5 mb-[15px]"
|
||||
>
|
||||
<image-contain width="41px" height="41px" :src="getImageUrl(item.image)" alt="" />
|
||||
<decoration-img width="41px" height="41px" :src="item.image" alt="" />
|
||||
<div class="mt-[7px]">{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
import type { PropType } from 'vue'
|
||||
import type options from './options'
|
||||
import DecorationImg from '../../decoration-img.vue'
|
||||
type OptionsType = ReturnType<typeof options>
|
||||
const props = defineProps({
|
||||
content: {
|
||||
|
|
@ -27,11 +27,6 @@ const props = defineProps({
|
|||
default: () => ({})
|
||||
}
|
||||
})
|
||||
const { getImageUrl } = useAppStore()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.nav {
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from 'vue'
|
||||
import type options from './options'
|
||||
type OptionsType = ReturnType<typeof options>
|
||||
defineProps({
|
||||
content: {
|
||||
type: Object as PropType<OptionsType['content']>,
|
||||
default: () => ({})
|
||||
},
|
||||
styles: {
|
||||
type: Object as PropType<OptionsType['styles']>,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
<template>
|
||||
<div class="news">
|
||||
<div class="flex items-center news-title mx-[10px] my-[15px] text-[17px] font-medium">
|
||||
最新资讯
|
||||
</div>
|
||||
<div
|
||||
v-for="item in newsList"
|
||||
:key="item.id"
|
||||
class="news-card flex bg-white px-[10px] py-[16px] text-[#333] border-[#f2f2f2] border-b"
|
||||
>
|
||||
<div class="mr-[10px]" v-if="item.image">
|
||||
<img :src="item.image" class="w-[120px] h-[90px]" />
|
||||
</div>
|
||||
<div class="flex flex-col justify-between flex-1">
|
||||
<div class="text-[15px] font-medium line-clamp-2">{{ item.title }}</div>
|
||||
<div class="line-clamp-1 text-sm mt-[8px]">
|
||||
{{ item.intro }}
|
||||
</div>
|
||||
|
||||
<div class="text-[#999] text-xs w-full flex justify-between mt-[8px]">
|
||||
<div>{{ item.createTime }}</div>
|
||||
<div class="flex items-center">
|
||||
<icon name="el-icon-View" />
|
||||
<div class="ml-[5px]">{{ item.visit }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from 'vue'
|
||||
import { getDecorateArticle } from '@/api/decoration'
|
||||
import type options from './options'
|
||||
type OptionsType = ReturnType<typeof options>
|
||||
const props = defineProps({
|
||||
content: {
|
||||
type: Object as PropType<OptionsType['content']>,
|
||||
default: () => ({})
|
||||
},
|
||||
styles: {
|
||||
type: Object as PropType<OptionsType['styles']>,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
const newsList = ref<any[]>([])
|
||||
const getData = async () => {
|
||||
const data = await getDecorateArticle({
|
||||
limit: 10
|
||||
})
|
||||
newsList.value = data
|
||||
}
|
||||
getData()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.news {
|
||||
.news-title {
|
||||
&::before {
|
||||
content: '';
|
||||
width: 4px;
|
||||
height: 17px;
|
||||
display: block;
|
||||
margin-right: 5px;
|
||||
background: #4173ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import attr from './attr.vue'
|
||||
import content from './content.vue'
|
||||
import options from './options'
|
||||
export default {
|
||||
attr,
|
||||
content,
|
||||
options
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
export default () => ({
|
||||
title: '资讯',
|
||||
name: 'news',
|
||||
disabled: 1,
|
||||
content: {},
|
||||
styles: {}
|
||||
})
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<div class="banner mx-[10px] mt-[10px]">
|
||||
<div class="banner-image">
|
||||
<image-contain width="100%" height="100px" :src="getImageUrl(getImage)" fit="contain" />
|
||||
<decoration-img width="100%" height="100px" :src="getImage" fit="contain" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
import type { PropType } from 'vue'
|
||||
import type options from './options'
|
||||
import DecorationImg from '../../decoration-img.vue'
|
||||
type OptionsType = ReturnType<typeof options>
|
||||
const props = defineProps({
|
||||
content: {
|
||||
|
|
@ -20,7 +20,6 @@ const props = defineProps({
|
|||
default: () => ({})
|
||||
}
|
||||
})
|
||||
const { getImageUrl } = useAppStore()
|
||||
const getImage = computed(() => {
|
||||
const { data } = props.content
|
||||
if (Array.isArray(data)) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="decoration-pages min-w-[1100px]">
|
||||
<el-card shadow="never" class="!border-none flex-1" :body-style="{ height: '100%' }">
|
||||
<el-card shadow="never" class="!border-none flex-1 flex" :body-style="{ flex: 1 }">
|
||||
<div class="flex h-full items-start">
|
||||
<Menu v-model="activeMenu" :menus="menus" />
|
||||
<preview v-model="selectWidgetIndex" :pageData="getPageData" />
|
||||
|
|
@ -19,6 +19,7 @@ import AttrSetting from '../component/pages/attr-setting.vue'
|
|||
import widgets from '../component/widgets'
|
||||
import { getDecoratePages, setDecoratePages } from '@/api/decoration'
|
||||
import feedback from '@/utils/feedback'
|
||||
import { getNonDuplicateID } from '@/utils/util'
|
||||
enum pagesTypeEnum {
|
||||
HOME = '1',
|
||||
USER = '2',
|
||||
|
|
@ -26,7 +27,13 @@ enum pagesTypeEnum {
|
|||
}
|
||||
|
||||
const generatePageData = (widgetNames: string[]) => {
|
||||
return widgetNames.map((widgetName) => widgets[widgetName]?.options() || {})
|
||||
return widgetNames.map((widgetName) => {
|
||||
const options = {
|
||||
id: getNonDuplicateID(),
|
||||
...(widgets[widgetName]?.options() || {})
|
||||
}
|
||||
return options
|
||||
})
|
||||
}
|
||||
|
||||
const menus: Record<
|
||||
|
|
@ -41,7 +48,7 @@ const menus: Record<
|
|||
id: 1,
|
||||
pageType: 1,
|
||||
name: '商城首页',
|
||||
pageData: generatePageData(['search', 'banner', 'nav'])
|
||||
pageData: generatePageData(['search', 'banner', 'nav', 'news'])
|
||||
},
|
||||
[pagesTypeEnum.USER]: {
|
||||
id: 2,
|
||||
|
|
@ -70,6 +77,7 @@ const getData = async () => {
|
|||
const data = await getDecoratePages({ id: activeMenu.value })
|
||||
menus[String(data.id)].pageData = JSON.parse(data.pageData)
|
||||
}
|
||||
|
||||
const setData = async () => {
|
||||
await setDecoratePages({
|
||||
...menus[activeMenu.value],
|
||||
|
|
|
|||
|
|
@ -60,5 +60,7 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
|
||||
plugins: []
|
||||
plugins: [
|
||||
require('@tailwindcss/line-clamp') // 引入插件
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -426,6 +426,11 @@
|
|||
resolved "https://registry.npmmirror.com/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz#0c8b74c50f29ee44f423f7416829c0bf8bb5eb27"
|
||||
integrity sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==
|
||||
|
||||
"@tailwindcss/line-clamp@^0.4.2":
|
||||
version "0.4.2"
|
||||
resolved "https://registry.npmmirror.com/@tailwindcss/line-clamp/-/line-clamp-0.4.2.tgz#f353c5a8ab2c939c6267ac5b907f012e5ee130f9"
|
||||
integrity sha512-HFzAQuqYCjyy/SX9sLGB1lroPzmcnWv1FHkIpmypte10hptf4oPUfucryMKovZh2u0uiS9U5Ty3GghWfEJGwVw==
|
||||
|
||||
"@transloadit/prettier-bytes@0.0.7":
|
||||
version "0.0.7"
|
||||
resolved "https://registry.npmmirror.com/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz#cdb5399f445fdd606ed833872fa0cabdbc51686b"
|
||||
|
|
|
|||
|
|
@ -1,21 +1,30 @@
|
|||
<template>
|
||||
<u-tabbar v-bind="tabbarStyle" :list="tabbarList" @change="handleChange"></u-tabbar>
|
||||
<u-tabbar
|
||||
v-model="current"
|
||||
v-bind="tabbarStyle"
|
||||
:list="tabbarList"
|
||||
@change="handleChange"
|
||||
:hide-tab-bar="false"
|
||||
></u-tabbar>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import { currentPage, navigateTo } from '@/utils/util'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { navigateTo } from '@/utils/util'
|
||||
import { computed, ref } from 'vue'
|
||||
const current = ref()
|
||||
const appStore = useAppStore()
|
||||
const tabbarList = computed(() => {
|
||||
return appStore.getTabbarConfig.map((item: any) => ({
|
||||
iconPath: item.unselected,
|
||||
selectedIconPath: item.selected,
|
||||
text: item.name,
|
||||
link: JSON.parse(item.link),
|
||||
pagePath: JSON.parse(item.link).path
|
||||
}))
|
||||
return appStore.getTabbarConfig.map((item: any) => {
|
||||
const link = JSON.parse(item.link)
|
||||
return {
|
||||
iconPath: item.unselected,
|
||||
selectedIconPath: item.selected,
|
||||
text: item.name,
|
||||
link,
|
||||
pagePath: link.path
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const tabbarStyle = computed(() => ({
|
||||
|
|
@ -26,8 +35,4 @@ const handleChange = (index: number) => {
|
|||
const selectTab = tabbarList.value[index]
|
||||
navigateTo(selectTab.link, 'reLaunch')
|
||||
}
|
||||
// onMounted(() => {
|
||||
// const page = currentPage()
|
||||
// console.log(page)
|
||||
// })
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -238,16 +238,20 @@ export default {
|
|||
},
|
||||
// 切换tab
|
||||
switchTab(index) {
|
||||
// 发出事件和修改v-model绑定的值
|
||||
this.$emit("change", index);
|
||||
|
||||
let pagePath = this.list[index].pagePath;
|
||||
// 如果有配置pagePath属性,使用uni.switchTab进行跳转
|
||||
if (this.list[index].pagePath) {
|
||||
if (pagePath) {
|
||||
if(pagePath == this.pageUrl || pagePath == "/" + this.pageUrl) return
|
||||
// 发出事件和修改v-model绑定的值
|
||||
this.$emit("change", index);
|
||||
uni.switchTab({
|
||||
url: this.list[index].pagePath
|
||||
url: pagePath
|
||||
});
|
||||
} else {
|
||||
// 如果配置了papgePath属性,将不会双向绑定v-model传入的value值
|
||||
// 因为这个模式下,不再需要v-model绑定的value值了,而是通过getCurrentPages()适配
|
||||
this.$emit("change", index);
|
||||
this.$emit("input", index);
|
||||
this.$emit("update:modelValue", index);
|
||||
}
|
||||
|
|
@ -370,4 +374,4 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -53,15 +53,8 @@ export enum LinkTypeEnum {
|
|||
}
|
||||
|
||||
export function navigateTo(link: Link, navigateType: 'navigateTo' | 'reLaunch' = 'navigateTo') {
|
||||
let url: string
|
||||
switch (link.type) {
|
||||
case LinkTypeEnum.SHOP_PAGES:
|
||||
url = link.query ? `${link.path}?${objectToQuery(link.query)}` : link.path
|
||||
uni[navigateType]({ url })
|
||||
break
|
||||
case LinkTypeEnum.CUSTOM_LINK:
|
||||
uni[navigateType]({ url: `/pages/webview/webview?url=${link.path}` })
|
||||
}
|
||||
const url = link.query ? `${link.path}?${objectToQuery(link.query)}` : link.path
|
||||
uni[navigateType]({ url })
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue