Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
605f9060
authored
Dec 09, 2023
by
芋道源码
Committed by
Gitee
Dec 09, 2023
Browse files
Options
Browse Files
Download
Plain Diff
!344 商城装修
Merge pull request !344 from 疯狂的世界/dev
parents
ce79dd68
59ff6b13
Show whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
312 additions
and
380 deletions
+312
-380
.env.base
+0
-19
.env.dev
+15
-9
.env.local-dev
+10
-10
.env.prod
+5
-2
.env.stage
+4
-1
.env.test
+5
-2
package.json
+7
-8
src/components/DiyEditor/components/ComponentLibrary.vue
+3
-1
src/components/DiyEditor/components/mobile/Carousel/property.vue
+9
-45
src/components/DiyEditor/components/mobile/MenuGrid/property.vue
+5
-36
src/components/DiyEditor/components/mobile/MenuList/property.vue
+3
-33
src/components/DiyEditor/components/mobile/MenuSwiper/property.vue
+5
-35
src/components/DiyEditor/components/mobile/NoticeBar/config.ts
+9
-2
src/components/DiyEditor/components/mobile/NoticeBar/property.vue
+13
-43
src/components/DiyEditor/components/mobile/SearchBar/property.vue
+7
-33
src/components/DiyEditor/components/mobile/TabBar/index.vue
+9
-2
src/components/DiyEditor/components/mobile/TabBar/property.vue
+8
-53
src/components/DiyEditor/index.vue
+37
-16
src/components/DiyEditor/util.ts
+2
-0
src/components/Draggable/index.vue
+77
-0
src/layout/components/AppView.vue
+12
-1
src/views/Home/Index.vue
+24
-21
src/views/mall/home/components/ShortcutCard.vue
+4
-1
src/views/mall/promotion/diy/page/decorate.vue
+0
-3
src/views/mall/promotion/diy/template/decorate.vue
+39
-4
No files found.
.env.base
deleted
100644 → 0
View file @
ce79dd68
# 本地开发环境
NODE_ENV=development
VITE_DEV=true
# 请求路径
VITE_BASE_URL='http://127.0.0.1:48080'
# 上传路径
VITE_UPLOAD_URL='http://127.0.0.1:48080/admin-api/infra/file/upload'
# 接口前缀
VITE_API_BASEPATH=/dev-api
# 接口地址
VITE_API_URL=/admin-api
# 打包路径
VITE_BASE_PATH=/
.env.dev
View file @
605f9060
# 开发环境
# 开发环境
:本地只启动前端项目,依赖开发环境(后端、APP)
NODE_ENV=development
VITE_DEV=
fals
e
VITE_DEV=
tru
e
# 请求路径
VITE_BASE_URL='http://
localhost:48080
'
VITE_BASE_URL='http://
api-dashboard.yudao.iocoder.cn
'
# 上传路径
VITE_UPLOAD_URL='http://
localhost:48080
/admin-api/infra/file/upload'
VITE_UPLOAD_URL='http://
api-dashboard.yudao.iocoder.cn
/admin-api/infra/file/upload'
# 接口前缀
VITE_API_BASEPATH=/dev-api
...
...
@@ -15,17 +15,23 @@ VITE_API_BASEPATH=/dev-api
# 接口地址
VITE_API_URL=/admin-api
# 打包路径
VITE_BASE_PATH=/
# 是否删除debugger
VITE_DROP_DEBUGGER=
tru
e
VITE_DROP_DEBUGGER=
fals
e
# 是否删除console.log
VITE_DROP_CONSOLE=false
# 是否sourcemap
VITE_SOURCEMAP=false
VITE_SOURCEMAP=true
# 打包路径
VITE_BASE_PATH=/
# 输出路径
VITE_OUT_DIR=dist
# 商城H5会员端域名
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
# 验证码的开关
VITE_APP_CAPTCHA_ENABLE=false
.env.
front
→
.env.
local-dev
View file @
605f9060
# 本地开发环境
# 本地开发环境
:本地启动所有项目(前端、后端、APP)时使用,不依赖外部环境
NODE_ENV=development
VITE_DEV=true
# 请求路径
VITE_BASE_URL='http://
api-dashboard.yudao.iocoder.cn
'
VITE_BASE_URL='http://
localhost:48080
'
# 上传路径
VITE_UPLOAD_URL='http://
api-dashboard.yudao.iocoder.cn
/admin-api/infra/file/upload'
VITE_UPLOAD_URL='http://
localhost:48080
/admin-api/infra/file/upload'
# 接口前缀
VITE_API_BASEPATH=/dev-api
...
...
@@ -15,12 +15,6 @@ VITE_API_BASEPATH=/dev-api
# 接口地址
VITE_API_URL=/admin-api
# 打包路径
VITE_BASE_PATH=/
# 项目本地运行端口号, 与.vscode/launch.json配合
VITE_PORT=80
# 是否删除debugger
VITE_DROP_DEBUGGER=false
...
...
@@ -28,7 +22,13 @@ VITE_DROP_DEBUGGER=false
VITE_DROP_CONSOLE=false
# 是否sourcemap
VITE_SOURCEMAP=true
VITE_SOURCEMAP=false
# 打包路径
VITE_BASE_PATH=/
# 商城H5会员端域名
VITE_MALL_H5_DOMAIN='http://localhost:3000'
# 验证码的开关
VITE_APP_CAPTCHA_ENABLE=false
.env.pro
→
.env.pro
d
View file @
605f9060
# 生产环境
# 生产环境
:只在打包时使用
NODE_ENV=production
VITE_DEV=false
...
...
@@ -28,4 +28,7 @@ VITE_SOURCEMAP=false
VITE_BASE_PATH=/
# 输出路径
VITE_OUT_DIR
=
dist
-
pro
VITE_OUT_DIR=dist-prod
# 商城H5会员端域名
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
.env.stage
View file @
605f9060
#
生产环境
#
预发布环境:只在打包时使用
NODE_ENV=production
VITE_DEV=false
...
...
@@ -29,3 +29,6 @@ VITE_BASE_PATH='http://static-vue3.yudao.iocoder.cn/'
# 输出路径
VITE_OUT_DIR=dist-stage
# 商城H5会员端域名
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
.env.
static
→
.env.
test
View file @
605f9060
#
开发环境
#
测试环境:只在打包时使用
NODE_ENV
=
production
VITE_DEV
=
false
...
...
@@ -28,4 +28,7 @@ VITE_SOURCEMAP=false
VITE_BASE_PATH
=/
admin
-
ui
-
vue3
/
# 输出路径
VITE_OUT_DIR=dist-dev
VITE_OUT_DIR
=
dist
-
test
# 商城H5会员端域名
VITE_MALL_H5_DOMAIN
=
'http://mall.yudao.iocoder.cn'
package.json
View file @
605f9060
...
...
@@ -6,18 +6,17 @@
"private"
:
false
,
"scripts"
:
{
"i"
:
"pnpm install"
,
"
dev"
:
"vite --mode base
"
,
"
front"
:
"vite --mode front
"
,
"
local-dev"
:
"vite --mode local-dev
"
,
"
dev"
:
"vite --mode dev
"
,
"ts:check"
:
"vue-tsc --noEmit"
,
"build:
pro"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode pro
"
,
"build:
local-dev"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode local-dev
"
,
"build:dev"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode dev"
,
"build:
base"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode base
"
,
"build:
test"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode test
"
,
"build:stage"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode stage"
,
"build:static"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode static"
,
"build:front"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode front"
,
"serve:pro"
:
"vite preview --mode pro"
,
"build:prod"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode prod"
,
"serve:dev"
:
"vite preview --mode dev"
,
"preview"
:
"pnpm build:base && vite preview"
,
"serve:prod"
:
"vite preview --mode prod"
,
"preview"
:
"pnpm build:local-dev && vite preview"
,
"clean"
:
"npx rimraf node_modules"
,
"clean:cache"
:
"npx rimraf node_modules/.cache"
,
"lint:eslint"
:
"eslint --fix --ext .js,.ts,.vue ./src"
,
...
...
src/components/DiyEditor/components/ComponentLibrary.vue
View file @
605f9060
...
...
@@ -82,7 +82,9 @@ watch(
// 克隆组件
const
handleCloneComponent
=
(
component
:
DiyComponent
<
any
>
)
=>
{
return
cloneDeep
(
component
)
const
instance
=
cloneDeep
(
component
)
instance
.
uid
=
new
Date
().
getTime
()
return
instance
}
</
script
>
...
...
src/components/DiyEditor/components/mobile/Carousel/property.vue
View file @
605f9060
...
...
@@ -39,30 +39,9 @@
</el-form-item>
</el-card>
<el-card
header=
"内容设置"
class=
"property-group"
shadow=
"never"
>
<el-text
type=
"info"
size=
"small"
>
拖动左上角的小圆点可对其排序
</el-text>
<template
v-if=
"formData.items[0]"
>
<draggable
:list=
"formData.items"
:force-fallback=
"true"
:animation=
"200"
handle=
".drag-icon"
class=
"m-t-8px"
item-key=
"index"
>
<template
#
item=
"
{ element, index }">
<div
class=
"content mb-4px flex flex-col gap-4px rounded bg-gray-50 p-8px"
>
<div
class=
"m--8px m-b-8px flex flex-row items-center justify-between bg-gray-100 p-8px"
>
<Icon
icon=
"ic:round-drag-indicator"
class=
"drag-icon cursor-move"
/>
<Icon
icon=
"ep:delete"
class=
"cursor-pointer text-red-5"
@
click=
"handleDeleteImage(index)"
v-if=
"formData.items.length > 1"
/>
</div>
<el-form-item
label=
"类型"
prop=
"type"
class=
"m-b-8px!"
label-width=
"50px"
>
<Draggable
v-model=
"formData.items"
:empty-item=
"
{ type: 'img' }">
<template
#
default=
"
{ element }">
<el-form-item
label=
"类型"
prop=
"type"
class=
"m-b-8px!"
label-width=
"40px"
>
<el-radio-group
v-model=
"element.type"
>
<el-radio
label=
"img"
>
图片
</el-radio>
<el-radio
label=
"video"
>
视频
</el-radio>
...
...
@@ -71,7 +50,7 @@
<el-form-item
label=
"图片"
class=
"m-b-8px!"
label-width=
"5
0px"
label-width=
"4
0px"
v-if=
"element.type === 'img'"
>
<UploadImg
...
...
@@ -83,7 +62,7 @@
/>
</el-form-item>
<template
v-else
>
<el-form-item
label=
"封面"
class=
"m-b-8px!"
label-width=
"5
0px"
>
<el-form-item
label=
"封面"
class=
"m-b-8px!"
label-width=
"4
0px"
>
<UploadImg
v-model=
"element.imgUrl"
draggable=
"false"
...
...
@@ -92,7 +71,7 @@
class=
"min-w-80px"
/>
</el-form-item>
<el-form-item
label=
"视频"
class=
"m-b-8px!"
label-width=
"5
0px"
>
<el-form-item
label=
"视频"
class=
"m-b-8px!"
label-width=
"4
0px"
>
<UploadFile
v-model=
"element.videoUrl"
:file-type=
"['mp4']"
...
...
@@ -102,24 +81,18 @@
/>
</el-form-item>
</
template
>
<el-form-item
label=
"链接"
class=
"m-b-8px!"
label-width=
"5
0px"
>
<el-form-item
label=
"链接"
class=
"m-b-8px!"
label-width=
"4
0px"
>
<AppLinkInput
v-model=
"element.url"
/>
</el-form-item>
</div>
</template>
</draggable>
</template>
<el-button
@
click=
"handleAddImage"
type=
"primary"
plain
class=
"w-full"
>
添加图片
</el-button>
</Draggable>
</el-card>
</el-form>
</ComponentContainerProperty>
</template>
<
script
setup
lang=
"ts"
>
import
draggable
from
'vuedraggable'
//拖拽组件
import
{
CarouselItemProperty
,
CarouselProperty
}
from
'./config'
import
{
CarouselProperty
}
from
'./config'
import
{
usePropertyForm
}
from
'@/components/DiyEditor/util'
// 轮播图属性面板
...
...
@@ -128,15 +101,6 @@ defineOptions({ name: 'CarouselProperty' })
const
props
=
defineProps
<
{
modelValue
:
CarouselProperty
}
>
()
const
emit
=
defineEmits
([
'update:modelValue'
])
const
{
formData
}
=
usePropertyForm
(
props
.
modelValue
,
emit
)
// 添加图片
const
handleAddImage
=
()
=>
{
formData
.
value
.
items
.
push
({}
as
CarouselItemProperty
)
}
// 删除图片
const
handleDeleteImage
=
(
index
:
number
)
=>
{
formData
.
value
.
items
.
splice
(
index
,
1
)
}
</
script
>
<
style
scoped
lang=
"scss"
></
style
>
src/components/DiyEditor/components/mobile/MenuGrid/property.vue
View file @
605f9060
...
...
@@ -9,23 +9,9 @@
</el-radio-group>
</el-form-item>
<el-text
tag=
"p"
>
菜单设置
</el-text>
<el-text
type=
"info"
size=
"small"
>
拖动左侧的小圆点可以调整顺序
</el-text>
<template
v-if=
"formData.list.length"
>
<VueDraggable
class=
"m-t-8px"
:list=
"formData.list"
item-key=
"index"
handle=
".drag-icon"
:forceFallback=
"true"
:animation=
"200"
>
<template
#
item=
"
{ element, index }">
<div
class=
"mb-4px flex flex-col gap-4px rounded bg-gray-100 p-8px"
>
<div
class=
"flex flex-row justify-between"
>
<Icon
icon=
"ic:round-drag-indicator"
class=
"drag-icon cursor-move"
/>
<Icon
icon=
"ep:delete"
class=
"text-red-500"
@
click=
"handleDeleteMenu(index)"
/>
</div>
<el-card
header=
"菜单设置"
class=
"property-group"
shadow=
"never"
>
<Draggable
v-model=
"formData.list"
:empty-item=
"EMPTY_MENU_GRID_ITEM_PROPERTY"
>
<template
#
default=
"
{ element }">
<el-form-item
label=
"图标"
prop=
"iconUrl"
>
<UploadImg
v-model=
"element.iconUrl"
height=
"80px"
width=
"80px"
>
<template
#
tip
>
建议尺寸:44 * 44
</
template
>
...
...
@@ -54,27 +40,19 @@
<ColorInput
v-model=
"element.badge.bgColor"
/>
</el-form-item>
</
template
>
</div>
</template>
</VueDraggable>
</template>
<el-form-item
label-width=
"0"
>
<el-button
@
click=
"handleAddMenu"
type=
"primary"
plain
class=
"m-t-8px w-full"
>
<Icon
icon=
"ep:plus"
class=
"mr-5px"
/>
添加菜单
</el-button>
</el-form-item>
</Draggable>
</el-card>
</el-form>
</ComponentContainerProperty>
</template>
<
script
setup
lang=
"ts"
>
import
VueDraggable
from
'vuedraggable'
import
{
usePropertyForm
}
from
'@/components/DiyEditor/util'
import
{
EMPTY_MENU_GRID_ITEM_PROPERTY
,
MenuGridProperty
}
from
'@/components/DiyEditor/components/mobile/MenuGrid/config'
import
{
cloneDeep
}
from
'lodash-es'
/** 宫格导航属性面板 */
defineOptions
({
name
:
'MenuGridProperty'
})
...
...
@@ -82,15 +60,6 @@ defineOptions({ name: 'MenuGridProperty' })
const
props
=
defineProps
<
{
modelValue
:
MenuGridProperty
}
>
()
const
emit
=
defineEmits
([
'update:modelValue'
])
const
{
formData
}
=
usePropertyForm
(
props
.
modelValue
,
emit
)
/* 添加菜单 */
const
handleAddMenu
=
()
=>
{
formData
.
value
.
list
.
push
(
cloneDeep
(
EMPTY_MENU_GRID_ITEM_PROPERTY
))
}
/* 删除菜单 */
const
handleDeleteMenu
=
(
index
:
number
)
=>
{
formData
.
value
.
list
.
splice
(
index
,
1
)
}
</
script
>
<
style
scoped
lang=
"scss"
></
style
>
src/components/DiyEditor/components/mobile/MenuList/property.vue
View file @
605f9060
...
...
@@ -5,20 +5,8 @@
<!-- 表单 -->
<el-form
label-width=
"60px"
:model=
"formData"
class=
"m-t-8px"
>
<div
v-if=
"formData.list.length"
>
<VueDraggable
:list=
"formData.list"
item-key=
"index"
handle=
".drag-icon"
:forceFallback=
"true"
:animation=
"200"
>
<template
#
item=
"
{ element, index }">
<div
class=
"mb-4px flex flex-col gap-4px rounded bg-gray-100 p-8px"
>
<div
class=
"flex flex-row justify-between"
>
<Icon
icon=
"ic:round-drag-indicator"
class=
"drag-icon cursor-move"
/>
<Icon
icon=
"ep:delete"
class=
"text-red-500"
@
click=
"handleDeleteMenu(index)"
/>
</div>
<Draggable
v-model=
"formData.list"
:empty-item=
"EMPTY_MENU_LIST_ITEM_PROPERTY"
>
<template
#
default=
"
{ element }">
<el-form-item
label=
"图标"
prop=
"iconUrl"
>
<UploadImg
v-model=
"element.iconUrl"
height=
"80px"
width=
"80px"
>
<template
#
tip
>
建议尺寸:44 * 44
</
template
>
...
...
@@ -33,27 +21,18 @@
<el-form-item
label=
"链接"
prop=
"url"
>
<AppLinkInput
v-model=
"element.url"
/>
</el-form-item>
</div>
</template>
</VueDraggable>
</div>
<el-form-item
label-width=
"0"
>
<el-button
@
click=
"handleAddMenu"
type=
"primary"
plain
class=
"m-t-8px w-full"
>
<Icon
icon=
"ep:plus"
class=
"mr-5px"
/>
添加菜单
</el-button>
</el-form-item>
</Draggable>
</el-form>
</ComponentContainerProperty>
</template>
<
script
setup
lang=
"ts"
>
import
VueDraggable
from
'vuedraggable'
import
{
usePropertyForm
}
from
'@/components/DiyEditor/util'
import
{
EMPTY_MENU_LIST_ITEM_PROPERTY
,
MenuListProperty
}
from
'@/components/DiyEditor/components/mobile/MenuList/config'
import
{
cloneDeep
}
from
'lodash-es'
/** 列表导航属性面板 */
defineOptions
({
name
:
'MenuListProperty'
})
...
...
@@ -61,15 +40,6 @@ defineOptions({ name: 'MenuListProperty' })
const
props
=
defineProps
<
{
modelValue
:
MenuListProperty
}
>
()
const
emit
=
defineEmits
([
'update:modelValue'
])
const
{
formData
}
=
usePropertyForm
(
props
.
modelValue
,
emit
)
/* 添加菜单 */
const
handleAddMenu
=
()
=>
{
formData
.
value
.
list
.
push
(
cloneDeep
(
EMPTY_MENU_LIST_ITEM_PROPERTY
))
}
/* 删除菜单 */
const
handleDeleteMenu
=
(
index
:
number
)
=>
{
formData
.
value
.
list
.
splice
(
index
,
1
)
}
</
script
>
<
style
scoped
lang=
"scss"
></
style
>
src/components/DiyEditor/components/mobile/MenuSwiper/property.vue
View file @
605f9060
...
...
@@ -22,23 +22,9 @@
</el-radio-group>
</el-form-item>
<el-text
tag=
"p"
>
菜单设置
</el-text>
<el-text
type=
"info"
size=
"small"
>
拖动左侧的小圆点可以调整顺序
</el-text>
<template
v-if=
"formData.list.length"
>
<VueDraggable
class=
"m-t-8px"
:list=
"formData.list"
item-key=
"index"
handle=
".drag-icon"
:forceFallback=
"true"
:animation=
"200"
>
<template
#
item=
"
{ element, index }">
<div
class=
"mb-4px flex flex-col gap-4px rounded bg-gray-100 p-8px"
>
<div
class=
"flex flex-row justify-between"
>
<Icon
icon=
"ic:round-drag-indicator"
class=
"drag-icon cursor-move"
/>
<Icon
icon=
"ep:delete"
class=
"text-red-500"
@
click=
"handleDeleteMenu(index)"
/>
</div>
<el-card
header=
"菜单设置"
class=
"property-group"
shadow=
"never"
>
<Draggable
v-model=
"formData.list"
:empty-item=
"cloneDeep(EMPTY_MENU_SWIPER_ITEM_PROPERTY"
>
<template
#
default=
"
{ element }">
<el-form-item
label=
"图标"
prop=
"iconUrl"
>
<UploadImg
v-model=
"element.iconUrl"
height=
"80px"
width=
"80px"
>
<template
#
tip
>
建议尺寸:98 * 98
</
template
>
...
...
@@ -64,21 +50,14 @@
<ColorInput
v-model=
"element.badge.bgColor"
/>
</el-form-item>
</
template
>
</div>
</template>
</VueDraggable>
</template>
<el-form-item
label-width=
"0"
>
<el-button
@
click=
"handleAddMenu"
type=
"primary"
plain
class=
"m-t-8px w-full"
>
<Icon
icon=
"ep:plus"
class=
"mr-5px"
/>
添加菜单
</el-button>
</el-form-item>
</Draggable>
</el-card>
</el-form>
</ComponentContainerProperty>
</template>
<
script
setup
lang=
"ts"
>
import
VueDraggable
from
'vuedraggable'
import
{
usePropertyForm
}
from
'@/components/DiyEditor/util'
import
{
EMPTY_MENU_SWIPER_ITEM_PROPERTY
,
...
...
@@ -92,15 +71,6 @@ defineOptions({ name: 'MenuSwiperProperty' })
const
props
=
defineProps
<
{
modelValue
:
MenuSwiperProperty
}
>
()
const
emit
=
defineEmits
([
'update:modelValue'
])
const
{
formData
}
=
usePropertyForm
(
props
.
modelValue
,
emit
)
/* 添加菜单 */
const
handleAddMenu
=
()
=>
{
formData
.
value
.
list
.
push
(
cloneDeep
(
EMPTY_MENU_SWIPER_ITEM_PROPERTY
))
}
/* 删除菜单 */
const
handleDeleteMenu
=
(
index
:
number
)
=>
{
formData
.
value
.
list
.
splice
(
index
,
1
)
}
</
script
>
<
style
scoped
lang=
"scss"
></
style
>
src/components/DiyEditor/components/mobile/NoticeBar/config.ts
View file @
605f9060
import
{
DiyComponent
}
from
'@/components/DiyEditor/util'
import
{
ComponentStyle
,
DiyComponent
}
from
'@/components/DiyEditor/util'
/** 公告栏属性 */
export
interface
NoticeBarProperty
{
...
...
@@ -10,6 +10,8 @@ export interface NoticeBarProperty {
backgroundColor
:
string
// 文字颜色
textColor
:
string
// 组件样式
style
:
ComponentStyle
}
/** 内容属性 */
...
...
@@ -34,6 +36,11 @@ export const component = {
}
],
backgroundColor
:
'#fff'
,
textColor
:
'#333'
textColor
:
'#333'
,
style
:
{
bgType
:
'color'
,
bgColor
:
'#fff'
,
marginBottom
:
8
}
as
ComponentStyle
}
}
as
DiyComponent
<
NoticeBarProperty
>
src/components/DiyEditor/components/mobile/NoticeBar/property.vue
View file @
605f9060
<
template
>
<ComponentContainerProperty
v-model=
"formData.style"
>
<el-form
label-width=
"80px"
:model=
"formData"
:rules=
"rules"
>
<el-form-item
label=
"公告图标"
prop=
"iconUrl"
>
<UploadImg
v-model=
"formData.iconUrl"
height=
"48px"
>
...
...
@@ -11,48 +12,26 @@
<el-form-item
label=
"文字颜色"
prop=
"文字颜色"
>
<ColorInput
v-model=
"formData.textColor"
/>
</el-form-item>
<el-text
tag=
"p"
>
公告内容
</el-text>
<el-text
type=
"info"
size=
"small"
>
拖动左上角的小圆点可以调整热词顺序
</el-text>
<
template
v-if=
"formData.contents.length"
>
<VueDraggable
:list=
"formData.contents"
item-key=
"index"
handle=
".drag-icon"
:forceFallback=
"true"
:animation=
"200"
class=
"m-t-8px"
>
<template
#
item=
"
{ element, index }">
<div
class=
"mb-4px flex flex-row gap-4px rounded bg-gray-100 p-8px"
>
<div
class=
"flex flex-col items-start justify-between"
>
<Icon
icon=
"ic:round-drag-indicator"
class=
"drag-icon cursor-move"
/>
<Icon
icon=
"ep:delete"
class=
"cursor-pointer text-red-5"
@
click=
"handleDeleteContent(index)"
v-if=
"formData.contents.length > 1"
/>
</div>
<div
class=
"w-full flex flex-col gap-8px"
>
<el-card
header=
"公告内容"
class=
"property-group"
shadow=
"never"
>
<Draggable
v-model=
"formData.contents"
>
<
template
#
default=
"{ element }"
>
<el-form-item
label=
"公告"
prop=
"text"
label-width=
"40px"
>
<el-input
v-model=
"element.text"
placeholder=
"请输入公告"
/>
</el-form-item>
<el-form-item
label=
"链接"
prop=
"url"
label-width=
"40px"
>
<AppLinkInput
v-model=
"element.url"
/>
</div>
</div>
</
template
>
</VueDraggable>
</template>
<el-form-item
label-width=
"0"
>
<el-button
@
click=
"handleAddContent"
type=
"primary"
plain
class=
"m-t-8px w-full"
>
添加内容
</el-button>
</el-form-item>
</
template
>
</Draggable>
</el-card>
</el-form>
</ComponentContainerProperty>
</template>
<
script
setup
lang=
"ts"
>
import
{
NoticeBarProperty
,
NoticeContentProperty
}
from
'./config'
import
{
NoticeBarProperty
}
from
'./config'
import
{
usePropertyForm
}
from
'@/components/DiyEditor/util'
import
VueDraggable
from
'vuedraggable'
// 通知栏属性面板
defineOptions
({
name
:
'NoticeBarProperty'
})
// 表单校验
...
...
@@ -63,15 +42,6 @@ const rules = {
const
props
=
defineProps
<
{
modelValue
:
NoticeBarProperty
}
>
()
const
emit
=
defineEmits
([
'update:modelValue'
])
const
{
formData
}
=
usePropertyForm
(
props
.
modelValue
,
emit
)
/* 添加公告 */
const
handleAddContent
=
()
=>
{
formData
.
value
.
contents
.
push
({}
as
NoticeContentProperty
)
}
/* 删除公告 */
const
handleDeleteContent
=
(
index
:
number
)
=>
{
formData
.
value
.
contents
.
splice
(
index
,
1
)
}
</
script
>
<
style
scoped
lang=
"scss"
></
style
>
src/components/DiyEditor/components/mobile/SearchBar/property.vue
View file @
605f9060
<
template
>
<ComponentContainerProperty
v-model=
"formData.style"
>
<el-text
tag=
"p"
>
搜索热词
</el-text>
<el-text
type=
"info"
size=
"small"
>
拖动左侧的小圆点可以调整热词顺序
</el-text>
<!-- 表单 -->
<el-form
label-width=
"80px"
:model=
"formData"
class=
"m-t-8px"
>
<div
v-if=
"formData.hotKeywords.length"
>
<VueDraggable
:list=
"formData.hotKeywords"
item-key=
"index"
handle=
".drag-icon"
:forceFallback=
"true"
:animation=
"200"
>
<template
#
item=
"
{ index }">
<div
class=
"mb-4px flex flex-row items-center gap-4px rounded bg-gray-100 p-8px"
>
<Icon
icon=
"ic:round-drag-indicator"
class=
"drag-icon cursor-move"
/>
<el-card
header=
"搜索热词"
class=
"property-group"
shadow=
"never"
>
<Draggable
v-model=
"formData.hotKeywords"
:empty-item=
"''"
>
<template
#
default=
"
{ index }">
<el-input
v-model=
"formData.hotKeywords[index]"
placeholder=
"请输入热词"
/>
<Icon
icon=
"ep:delete"
class=
"text-red-500"
@
click=
"deleteHotWord(index)"
/>
</div>
</
template
>
</VueDraggable>
</div>
<el-form-item
label-width=
"0"
>
<el-button
@
click=
"handleAddHotWord"
type=
"primary"
plain
class=
"m-t-8px w-full"
>
添加热词
</el-button>
</el-form-item>
</Draggable>
</el-card>
<el-card
header=
"搜索样式"
class=
"property-group"
shadow=
"never"
>
<el-form-item
label=
"框体样式"
>
<el-radio-group
v-model=
"formData!.borderRadius"
>
<el-tooltip
content=
"方形"
placement=
"top"
>
...
...
@@ -70,12 +53,12 @@
<el-form-item
class=
"lef"
label=
"文本颜色"
prop=
"textColor"
>
<ColorInput
v-model=
"formData.textColor"
/>
</el-form-item>
</el-card>
</el-form>
</ComponentContainerProperty>
</template>
<
script
setup
lang=
"ts"
>
import
VueDraggable
from
'vuedraggable'
import
{
usePropertyForm
}
from
'@/components/DiyEditor/util'
import
{
SearchProperty
}
from
'@/components/DiyEditor/components/mobile/SearchBar/config'
...
...
@@ -85,15 +68,6 @@ defineOptions({ name: 'SearchProperty' })
const
props
=
defineProps
<
{
modelValue
:
SearchProperty
}
>
()
const
emit
=
defineEmits
([
'update:modelValue'
])
const
{
formData
}
=
usePropertyForm
(
props
.
modelValue
,
emit
)
/* 添加热词 */
const
handleAddHotWord
=
()
=>
{
formData
.
value
.
hotKeywords
.
push
(
''
)
}
/* 删除热词 */
const
deleteHotWord
=
(
index
:
number
)
=>
{
formData
.
value
.
hotKeywords
.
splice
(
index
,
1
)
}
</
script
>
<
style
scoped
lang=
"scss"
></
style
>
src/components/DiyEditor/components/mobile/TabBar/index.vue
View file @
605f9060
...
...
@@ -12,7 +12,13 @@
}"
>
<div
v-for=
"(item, index) in property.items"
:key=
"index"
class=
"tab-bar-item"
>
<img
:src=
"index === 0 ? item.activeIconUrl : item.iconUrl"
alt=
""
/>
<el-image
:src=
"index === 0 ? item.activeIconUrl : item.iconUrl"
>
<template
#
error
>
<div
class=
"h-full w-full flex items-center justify-center"
>
<Icon
icon=
"ep:picture"
/>
</div>
</
template
>
</el-image>
<span
:style=
"{ color: index === 0 ? property.style.activeColor : property.style.color }"
>
{{ item.text }}
</span>
...
...
@@ -48,7 +54,8 @@ defineProps<{ property: TabBarProperty }>()
align-items
:
center
;
justify-content
:
center
;
img
{
:deep(img),
.el-icon
{
width
:
26px
;
height
:
26px
;
border-radius
:
4px
;
...
...
src/components/DiyEditor/components/mobile/TabBar/property.vue
View file @
605f9060
...
...
@@ -42,26 +42,8 @@
<el-text
tag=
"p"
>
图标设置
</el-text>
<el-text
type=
"info"
size=
"small"
>
拖动左上角的小圆点可对其排序, 图标建议尺寸 44*44
</el-text>
<draggable
:list=
"formData!.items"
item-key=
"index"
:forceFallback=
"true"
:animation=
"200"
handle=
".drag-icon"
class=
"m-t-8px"
>
<
template
#
item=
"{ element, index }"
>
<div
class=
"mb-4px flex flex-row gap-4px rounded bg-gray-100 p-8px"
>
<div
class=
"flex flex-col items-start justify-between"
>
<Icon
icon=
"ic:round-drag-indicator"
class=
"drag-icon cursor-move"
/>
<Icon
icon=
"ep:delete"
class=
"cursor-pointer text-red-5"
@
click=
"handleDeleteItem(index)"
v-if=
"formData.items.length > 1"
/>
</div>
<div
class=
"w-full flex flex-col"
>
<Draggable
v-model=
"formData.items"
:limit=
"5"
>
<
template
#
default=
"{ element }"
>
<div
class=
"m-b-8px flex items-center justify-around"
>
<div
class=
"flex flex-col items-center justify-between"
>
<UploadImg
...
...
@@ -71,7 +53,7 @@
:show-delete=
"false"
:show-btn-text=
"false"
/>
<el-text
size=
"small"
>
默认图片
</el-text>
<el-text
size=
"small"
>
未选中
</el-text>
</div>
<div>
<UploadImg
...
...
@@ -81,41 +63,23 @@
:show-delete=
"false"
:show-btn-text=
"false"
/>
<el-text>
选中图片
</el-text>
<el-text>
已选中
</el-text>
</div>
</div>
<el-form-item
prop=
"text"
label-width=
"0
"
class=
"m-b-8px!"
>
<el-form-item
prop=
"text"
label=
"文字"
label-width=
"48px
"
class=
"m-b-8px!"
>
<el-input
v-model=
"element.text"
placeholder=
"请输入文字"
/>
</el-form-item>
<el-form-item
prop=
"url"
label-width=
"0
"
class=
"m-b-0!"
>
<el-form-item
prop=
"url"
label=
"链接"
label-width=
"48px
"
class=
"m-b-0!"
>
<AppLinkInput
v-model=
"element.url"
/>
</el-form-item>
</div>
</div>
</
template
>
</draggable>
<el-form-item
label-width=
"0"
>
<!-- 添加导航按钮 -->
<el-tooltip
content=
"最多添加5个"
>
<el-button
@
click=
"handleAddItem"
class=
"m-b-16px w-full"
type=
"primary"
plain
:disabled=
"formData!.items.length >= 5"
>
添加导航
</el-button>
</el-tooltip>
</el-form-item>
</Draggable>
</el-form>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
draggable
from
'vuedraggable'
//拖拽组件
import
{
TabBarItemProperty
,
TabBarProperty
,
THEME_LIST
}
from
'./config'
import
{
TabBarProperty
,
THEME_LIST
}
from
'./config'
import
{
usePropertyForm
}
from
'@/components/DiyEditor/util'
// 底部导航栏
defineOptions
({
name
:
'TabBarProperty'
})
...
...
@@ -124,15 +88,6 @@ const props = defineProps<{ modelValue: TabBarProperty }>()
const
emit
=
defineEmits
([
'update:modelValue'
])
const
{
formData
}
=
usePropertyForm
(
props
.
modelValue
,
emit
)
/** 添加导航项 */
const
handleAddItem
=
()
=>
{
formData
?.
value
?.
items
?.
push
({}
as
TabBarItemProperty
)
}
/** 删除导航项 */
const
handleDeleteItem
=
(
index
:
number
)
=>
{
formData
?.
value
?.
items
?.
splice
(
index
,
1
)
}
// 要的主题
const
handleThemeChange
=
()
=>
{
const
theme
=
THEME_LIST
.
find
((
theme
)
=>
theme
.
id
===
formData
.
value
.
theme
)
...
...
src/components/DiyEditor/index.vue
View file @
605f9060
...
...
@@ -15,7 +15,7 @@
<Icon
icon=
"system-uicons:reset-alt"
:size=
"24"
/>
</el-button>
</el-tooltip>
<el-tooltip
content=
"预览"
>
<el-tooltip
content=
"预览"
v-if=
"previewUrl"
>
<el-button
@
click=
"handlePreview"
>
<Icon
icon=
"ep:view"
:size=
"24"
/>
</el-button>
...
...
@@ -102,8 +102,8 @@
<!-- 组件名称 -->
<
template
#
header
>
<div
class=
"flex items-center gap-8px"
>
<Icon
:icon=
"selectedComponent.icon"
color=
"gray"
/>
<span>
{{
selectedComponent
.
name
}}
</span>
<Icon
:icon=
"selectedComponent
?
.icon"
color=
"gray"
/>
<span>
{{
selectedComponent
?
.
name
}}
</span>
</div>
</
template
>
<el-scrollbar
...
...
@@ -111,7 +111,8 @@
view-class=
"p-[var(--el-card-padding)] p-b-[calc(var(--el-card-padding)+var(--el-card-padding))] property"
>
<component
:is=
"selectedComponent.id + 'Property'"
:key=
"selectedComponent?.uid || selectedComponent?.id"
:is=
"selectedComponent?.id + 'Property'"
v-model=
"selectedComponent.property"
/>
</el-scrollbar>
...
...
@@ -119,6 +120,19 @@
</el-aside>
</el-container>
</el-container>
<!-- 预览弹框 -->
<Dialog
v-model=
"previewDialogVisible"
title=
"预览"
width=
"700"
>
<div
class=
"flex justify-around"
>
<IFrame
class=
"w-375px border-4px border-rounded-8px border-solid p-2px h-667px!"
:src=
"previewUrl"
/>
<div
class=
"flex flex-col"
>
<el-text>
手机扫码预览
</el-text>
<Qrcode
:text=
"previewUrl"
logo=
"/logo.gif"
/>
</div>
</div>
</Dialog>
</template>
<
script
lang=
"ts"
>
// 注册所有的组件
...
...
@@ -137,12 +151,12 @@ import { component as TAB_BAR_COMPONENT } from './components/mobile/TabBar/confi
import
{
isString
}
from
'@/utils/is'
import
{
DiyComponent
,
DiyComponentLibrary
,
PageConfig
}
from
'@/components/DiyEditor/util'
import
{
componentConfigs
}
from
'@/components/DiyEditor/components/mobile'
import
{
array
,
oneOfType
}
from
'vue-types'
import
{
propTypes
}
from
'@/utils/propTypes'
/** 页面装修详情页 */
defineOptions
({
name
:
'DiyPageDetail'
})
// 消息弹窗
const
message
=
useMessage
()
// 左侧组件库
const
componentLibrary
=
ref
()
// 页面设置组件
...
...
@@ -159,20 +173,22 @@ const selectedComponentIndex = ref<number>(-1)
// 组件列表
const
pageComponents
=
ref
<
DiyComponent
<
any
>
[]
>
([])
// 定义属性
const
props
=
defineProps
<
{
const
props
=
defineProps
(
{
// 页面配置,支持Json字符串
modelValue
:
string
|
PageConfig
modelValue
:
oneOfType
<
string
|
PageConfig
>
([
String
,
Object
]).
isRequired
,
// 标题
title
:
string
title
:
propTypes
.
string
.
def
(
''
),
// 组件库
libs
:
DiyComponentLibrary
[]
libs
:
array
<
DiyComponentLibrary
>
(),
// 是否显示顶部导航栏
showNavigationBar
:
boolean
showNavigationBar
:
propTypes
.
bool
.
def
(
true
),
// 是否显示底部导航菜单
showTabBar
:
boolean
showTabBar
:
propTypes
.
bool
.
def
(
false
),
// 是否显示页面配置
showPageConfig
:
boolean
}
>
()
showPageConfig
:
propTypes
.
bool
.
def
(
true
),
// 预览地址:提供了预览地址,才会显示预览按钮
previewUrl
:
propTypes
.
string
.
def
(
''
)
})
// 监听传入的页面配置
watch
(
...
...
@@ -281,6 +297,7 @@ const handleMoveComponent = (index: number, direction: number) => {
/** 复制组件 */
const
handleCopyComponent
=
(
index
:
number
)
=>
{
const
component
=
cloneDeep
(
pageComponents
.
value
[
index
])
component
.
uid
=
new
Date
().
getTime
()
pageComponents
.
value
.
splice
(
index
+
1
,
0
,
component
)
}
/**
...
...
@@ -306,14 +323,18 @@ const handleDeleteComponent = (index: number) => {
// 工具栏操作
const
emits
=
defineEmits
([
'reset'
,
'preview'
,
'save'
,
'update:modelValue'
])
// 注入无感刷新页面函数
const
reload
=
inject
<
()
=>
void
>
(
'reload'
)
// 重置
const
handleReset
=
()
=>
{
message
.
warning
(
'开发中~'
)
if
(
reload
)
reload
(
)
emits
(
'reset'
)
}
// 预览
const
previewDialogVisible
=
ref
(
false
)
const
handlePreview
=
()
=>
{
message
.
warning
(
'开发中~'
)
previewDialogVisible
.
value
=
true
emits
(
'preview'
)
}
...
...
src/components/DiyEditor/util.ts
View file @
605f9060
...
...
@@ -5,6 +5,8 @@ import { TabBarProperty } from '@/components/DiyEditor/components/mobile/TabBar/
// 页面装修组件
export
interface
DiyComponent
<
T
>
{
// 用于区分同一种组件的不同实例
uid
:
number
// 组件唯一标识
id
:
string
// 组件名称
...
...
src/components/Draggable/index.vue
0 → 100644
View file @
605f9060
<
template
>
<el-text
type=
"info"
size=
"small"
>
拖动左上角的小圆点可对其排序
</el-text>
<VueDraggable
:list=
"formData"
:force-fallback=
"true"
:animation=
"200"
handle=
".drag-icon"
class=
"m-t-8px"
item-key=
"index"
>
<template
#
item=
"
{ element, index }">
<div
class=
"mb-4px flex flex-col gap-4px border border-gray-2 border-rounded rounded border-solid p-8px"
>
<!-- 操作按钮区 -->
<div
class=
"m--8px m-b-4px flex flex-row items-center justify-between bg-gray-1 p-8px"
>
<el-tooltip
content=
"拖动排序"
>
<Icon
icon=
"ic:round-drag-indicator"
class=
"drag-icon cursor-move"
/>
</el-tooltip>
<el-tooltip
content=
"删除"
>
<Icon
icon=
"ep:delete"
class=
"cursor-pointer text-red-5"
v-if=
"formData.length > 1"
@
click=
"handleDelete(index)"
/>
</el-tooltip>
</div>
<!-- 内容区 -->
<slot
:element=
"element"
:index=
"index"
></slot>
</div>
</
template
>
</VueDraggable>
<el-tooltip
:disabled=
"limit < 1"
:content=
"`最多添加${limit}个`"
>
<el-button
type=
"primary"
plain
class=
"m-t-4px w-full"
:disabled=
"limit > 0 && formData.length >= limit"
@
click=
"handleAdd"
>
<Icon
icon=
"ep:plus"
/><span>
添加
</span>
</el-button>
</el-tooltip>
</template>
<
script
setup
lang=
"ts"
>
// 拖拽组件
import
VueDraggable
from
'vuedraggable'
import
{
usePropertyForm
}
from
'@/components/DiyEditor/util'
import
{
any
,
array
}
from
'vue-types'
import
{
propTypes
}
from
'@/utils/propTypes'
import
{
cloneDeep
}
from
'lodash-es'
// 拖拽组件封装
defineOptions
({
name
:
'Draggable'
})
// 定义属性
const
props
=
defineProps
({
// 绑定值
modelValue
:
array
<
any
>
().
isRequired
,
// 空的元素:点击添加按钮时,创建元素并添加到列表;默认为空对象
emptyItem
:
any
<
unknown
>
().
def
({}),
// 数量限制:默认为0,表示不限制
limit
:
propTypes
.
number
.
def
(
0
)
})
// 定义事件
const
emit
=
defineEmits
([
'update:modelValue'
])
const
{
formData
}
=
usePropertyForm
(
props
.
modelValue
,
emit
)
// 处理添加
const
handleAdd
=
()
=>
formData
.
value
.
push
(
cloneDeep
(
props
.
emptyItem
||
{}))
// 处理删除
const
handleDelete
=
(
index
:
number
)
=>
formData
.
value
.
splice
(
index
,
1
)
</
script
>
<
style
scoped
lang=
"scss"
></
style
>
src/layout/components/AppView.vue
View file @
605f9060
...
...
@@ -20,6 +20,17 @@ const getCaches = computed((): string[] => {
})
const
tagsView
=
computed
(()
=>
appStore
.
getTagsView
)
//region 无感刷新
const
routerAlive
=
ref
(
true
)
// 无感刷新,防止出现页面闪烁白屏
const
reload
=
()
=>
{
routerAlive
.
value
=
false
nextTick
(()
=>
(
routerAlive
.
value
=
true
))
}
// 为组件后代提供刷新方法
provide
(
'reload'
,
reload
)
//endregion
</
script
>
<
template
>
...
...
@@ -49,7 +60,7 @@ const tagsView = computed(() => appStore.getTagsView)
}
]"
>
<router-view>
<router-view
v-if=
"routerAlive"
>
<template
#
default=
"
{ Component, route }">
<keep-alive
:include=
"getCaches"
>
<component
:is=
"Component"
:key=
"route.fullPath"
/>
...
...
src/views/Home/Index.vue
View file @
605f9060
...
...
@@ -2,10 +2,12 @@
<div>
<el-card
shadow=
"never"
>
<el-skeleton
:loading=
"loading"
animated
>
<el-row
:gutter=
"
20
"
justify=
"space-between"
>
<el-row
:gutter=
"
16
"
justify=
"space-between"
>
<el-col
:xl=
"12"
:lg=
"12"
:md=
"12"
:sm=
"24"
:xs=
"24"
>
<div
class=
"flex items-center"
>
<img
:src=
"avatar"
alt=
""
class=
"mr-20px h-70px w-70px rounded-[50%]"
/>
<el-avatar
:src=
"avatar"
:size=
"70"
class=
"mr-16px"
>
<img
src=
"@/assets/imgs/avatar.gif"
alt=
""
/>
</el-avatar>
<div>
<div
class=
"text-20px"
>
{{
t
(
'workplace.welcome'
)
}}
{{
username
}}
{{
t
(
'workplace.happyDay'
)
}}
...
...
@@ -19,7 +21,7 @@
<el-col
:xl=
"12"
:lg=
"12"
:md=
"12"
:sm=
"24"
:xs=
"24"
>
<div
class=
"h-70px flex items-center justify-end lt-sm:mt-10px"
>
<div
class=
"px-8px text-right"
>
<div
class=
"mb-
20
px text-14px text-gray-400"
>
{{
t
(
'workplace.project'
)
}}
</div>
<div
class=
"mb-
16
px text-14px text-gray-400"
>
{{
t
(
'workplace.project'
)
}}
</div>
<CountTo
class=
"text-20px"
:start-val=
"0"
...
...
@@ -29,7 +31,7 @@
</div>
<el-divider
direction=
"vertical"
/>
<div
class=
"px-8px text-right"
>
<div
class=
"mb-
20
px text-14px text-gray-400"
>
{{
t
(
'workplace.toDo'
)
}}
</div>
<div
class=
"mb-
16
px text-14px text-gray-400"
>
{{
t
(
'workplace.toDo'
)
}}
</div>
<CountTo
class=
"text-20px"
:start-val=
"0"
...
...
@@ -39,7 +41,7 @@
</div>
<el-divider
direction=
"vertical"
border-style=
"dashed"
/>
<div
class=
"px-8px text-right"
>
<div
class=
"mb-
20
px text-14px text-gray-400"
>
{{
t
(
'workplace.access'
)
}}
</div>
<div
class=
"mb-
16
px text-14px text-gray-400"
>
{{
t
(
'workplace.access'
)
}}
</div>
<CountTo
class=
"text-20px"
:start-val=
"0"
...
...
@@ -54,8 +56,8 @@
</el-card>
</div>
<el-row
class=
"mt-
5px"
:gutter=
"20
"
justify=
"space-between"
>
<el-col
:xl=
"16"
:lg=
"16"
:md=
"24"
:sm=
"24"
:xs=
"24"
class=
"mb-
10
px"
>
<el-row
class=
"mt-
8px"
:gutter=
"8
"
justify=
"space-between"
>
<el-col
:xl=
"16"
:lg=
"16"
:md=
"24"
:sm=
"24"
:xs=
"24"
class=
"mb-
8
px"
>
<el-card
shadow=
"never"
>
<template
#
header
>
<div
class=
"h-3 flex justify-between"
>
...
...
@@ -76,11 +78,11 @@
>
<el-card
shadow=
"hover"
>
<div
class=
"flex items-center"
>
<Icon
:icon=
"item.icon"
:size=
"25"
class=
"mr-
10
px"
/>
<Icon
:icon=
"item.icon"
:size=
"25"
class=
"mr-
8
px"
/>
<span
class=
"text-16px"
>
{{ item.name }}
</span>
</div>
<div
class=
"mt-1
5
px text-14px text-gray-400"
>
{{ t(item.message) }}
</div>
<div
class=
"mt-
20
px flex justify-between text-12px text-gray-400"
>
<div
class=
"mt-1
6
px text-14px text-gray-400"
>
{{ t(item.message) }}
</div>
<div
class=
"mt-
16
px flex justify-between text-12px text-gray-400"
>
<span>
{{ item.personal }}
</span>
<span>
{{ formatTime(item.time, 'yyyy-MM-dd') }}
</span>
</div>
...
...
@@ -90,18 +92,18 @@
</el-skeleton>
</el-card>
<el-card
shadow=
"never"
class=
"mt-
5
px"
>
<el-card
shadow=
"never"
class=
"mt-
8
px"
>
<el-skeleton
:loading=
"loading"
animated
>
<el-row
:gutter=
"20"
justify=
"space-between"
>
<el-col
:xl=
"10"
:lg=
"10"
:md=
"24"
:sm=
"24"
:xs=
"24"
>
<el-card
shadow=
"hover"
class=
"mb-
10
px"
>
<el-card
shadow=
"hover"
class=
"mb-
8
px"
>
<el-skeleton
:loading=
"loading"
animated
>
<Echart
:options=
"pieOptionsData"
:height=
"280"
/>
</el-skeleton>
</el-card>
</el-col>
<el-col
:xl=
"14"
:lg=
"14"
:md=
"24"
:sm=
"24"
:xs=
"24"
>
<el-card
shadow=
"hover"
class=
"mb-
10
px"
>
<el-card
shadow=
"hover"
class=
"mb-
8
px"
>
<el-skeleton
:loading=
"loading"
animated
>
<Echart
:options=
"barOptionsData"
:height=
"280"
/>
</el-skeleton>
...
...
@@ -111,7 +113,7 @@
</el-skeleton>
</el-card>
</el-col>
<el-col
:xl=
"8"
:lg=
"8"
:md=
"24"
:sm=
"24"
:xs=
"24"
class=
"mb-
10
px"
>
<el-col
:xl=
"8"
:lg=
"8"
:md=
"24"
:sm=
"24"
:xs=
"24"
class=
"mb-
8
px"
>
<el-card
shadow=
"never"
>
<
template
#
header
>
<div
class=
"h-3 flex justify-between"
>
...
...
@@ -120,9 +122,9 @@
</
template
>
<el-skeleton
:loading=
"loading"
animated
>
<el-row>
<el-col
v-for=
"item in shortcut"
:key=
"`team-${item.name}`"
:span=
"8"
class=
"mb-
10
px"
>
<el-col
v-for=
"item in shortcut"
:key=
"`team-${item.name}`"
:span=
"8"
class=
"mb-
8
px"
>
<div
class=
"flex items-center"
>
<Icon
:icon=
"item.icon"
class=
"mr-
10
px"
/>
<Icon
:icon=
"item.icon"
class=
"mr-
8
px"
/>
<el-link
type=
"default"
:underline=
"false"
@
click=
"setWatermark(item.name)"
>
{{ item.name }}
</el-link>
...
...
@@ -131,7 +133,7 @@
</el-row>
</el-skeleton>
</el-card>
<el-card
shadow=
"never"
class=
"mt-
10
px"
>
<el-card
shadow=
"never"
class=
"mt-
8
px"
>
<
template
#
header
>
<div
class=
"h-3 flex justify-between"
>
<span>
{{
t
(
'workplace.notice'
)
}}
</span>
...
...
@@ -141,14 +143,16 @@
<el-skeleton
:loading=
"loading"
animated
>
<div
v-for=
"(item, index) in notice"
:key=
"`dynamics-${index}`"
>
<div
class=
"flex items-center"
>
<img
:src=
"avatar"
alt=
""
class=
"mr-20px h-35px w-35px rounded-[50%]"
/>
<el-avatar
:src=
"avatar"
:size=
"35"
class=
"mr-16px"
>
<img
src=
"@/assets/imgs/avatar.gif"
alt=
""
/>
</el-avatar>
<div>
<div
class=
"text-14px"
>
<Highlight
:keys=
"item.keys.map((v) => t(v))"
>
{{ item.type }} : {{ item.title }}
</Highlight>
</div>
<div
class=
"mt-1
5
px text-12px text-gray-400"
>
<div
class=
"mt-1
6
px text-12px text-gray-400"
>
{{ formatTime(item.date, 'yyyy-MM-dd') }}
</div>
</div>
...
...
@@ -167,7 +171,6 @@ import { formatTime } from '@/utils'
import
{
useUserStore
}
from
'@/store/modules/user'
import
{
useWatermark
}
from
'@/hooks/web/useWatermark'
import
avatarImg
from
'@/assets/imgs/avatar.gif'
import
type
{
WorkplaceTotal
,
Project
,
Notice
,
Shortcut
}
from
'./types'
import
{
pieOptions
,
barOptions
}
from
'./echarts-data'
...
...
@@ -177,7 +180,7 @@ const { t } = useI18n()
const
userStore
=
useUserStore
()
const
{
setWatermark
}
=
useWatermark
()
const
loading
=
ref
(
true
)
const
avatar
=
userStore
.
getUser
.
avatar
?
userStore
.
getUser
.
avatar
:
avatarImg
const
avatar
=
userStore
.
getUser
.
avatar
const
username
=
userStore
.
getUser
.
nickname
const
pieOptionsData
=
reactive
<
EChartsOption
>
(
pieOptions
)
as
EChartsOption
// 获取统计数
...
...
src/views/mall/home/components/ShortcutCard.vue
View file @
605f9060
...
...
@@ -10,7 +10,10 @@
class=
"h-20 w-20% flex flex-col cursor-pointer items-center justify-center gap-2"
@
click=
"handleMenuClick(menu.routerName)"
>
<div
:class=
"menu.bgColor"
class=
"rounded p-3 text-white"
>
<div
:class=
"menu.bgColor"
class=
"h-48px w-48px flex items-center justify-center rounded text-white"
>
<Icon
:icon=
"menu.icon"
class=
"text-7.5!"
/>
</div>
<span>
{{ menu.name }}
</span>
...
...
src/views/mall/promotion/diy/page/decorate.vue
View file @
605f9060
...
...
@@ -4,9 +4,6 @@
v-model=
"formData.property"
:title=
"formData.name"
:libs=
"PAGE_LIBS"
:show-page-config=
"true"
:show-navigation-bar=
"true"
:show-tab-bar=
"false"
@
save=
"submitForm"
/>
</
template
>
...
...
src/views/mall/promotion/diy/template/decorate.vue
View file @
605f9060
...
...
@@ -7,7 +7,9 @@
:show-page-config=
"selectedTemplateItem !== 0"
:show-tab-bar=
"selectedTemplateItem === 0"
:show-navigation-bar=
"selectedTemplateItem !== 0"
:preview-url=
"previewUrl"
@
save=
"submitForm"
@
reset=
"handleEditorReset"
>
<template
#
toolBarLeft
>
<el-radio-group
...
...
@@ -29,6 +31,7 @@ import * as DiyTemplateApi from '@/api/mall/promotion/diy/template'
import
*
as
DiyPageApi
from
'@/api/mall/promotion/diy/page'
import
{
useTagsViewStore
}
from
'@/store/modules/tagsView'
import
{
DiyComponentLibrary
,
PAGE_LIBS
}
from
'@/components/DiyEditor/util'
import
{
toNumber
}
from
'lodash-es'
/** 装修模板表单 */
defineOptions
({
name
:
'DiyTemplateDecorate'
})
...
...
@@ -48,6 +51,8 @@ const formData = ref<DiyTemplateApi.DiyTemplatePropertyVO>()
const
formRef
=
ref
()
// 表单 Ref
// 当前编辑的属性
const
currentFormData
=
ref
<
DiyTemplateApi
.
DiyTemplatePropertyVO
|
DiyPageApi
.
DiyPageVO
>
()
// 商城H5预览地址
const
previewUrl
=
ref
(
''
)
// 获取详情
const
getPageDetail
=
async
(
id
:
any
)
=>
{
...
...
@@ -55,6 +60,10 @@ const getPageDetail = async (id: any) => {
try
{
formData
.
value
=
await
DiyTemplateApi
.
getDiyTemplateProperty
(
id
)
currentFormData
.
value
=
formData
.
value
// 拼接手机预览链接
const
domain
=
import
.
meta
.
env
.
VITE_MALL_H5_DOMAIN
previewUrl
.
value
=
`
${
domain
}
/#/pages/index/index?templateId=
${
formData
.
value
.
id
}
`
}
finally
{
formLoading
.
value
=
false
}
...
...
@@ -115,17 +124,43 @@ const resetForm = () => {
formRef
.
value
?.
resetFields
()
}
// 重置时记录当前编辑的页面
const
handleEditorReset
=
()
=>
storePageIndex
()
//#region 无感刷新
// 记录标识
const
DIY_PAGE_INDEX_KEY
=
'diy_page_index'
// 1. 记录
const
storePageIndex
=
()
=>
sessionStorage
.
setItem
(
DIY_PAGE_INDEX_KEY
,
`
${
selectedTemplateItem
.
value
}
`
)
// 2. 恢复
const
recoverPageIndex
=
()
=>
{
// 恢复重置前的页面,默认是第一个页面
const
pageIndex
=
toNumber
(
sessionStorage
.
getItem
(
DIY_PAGE_INDEX_KEY
))
||
0
// 移除标记
sessionStorage
.
removeItem
(
DIY_PAGE_INDEX_KEY
)
// 切换页面
if
(
pageIndex
!==
selectedTemplateItem
.
value
)
{
selectedTemplateItem
.
value
=
pageIndex
handleTemplateItemChange
()
}
}
//#endregion
/** 初始化 **/
const
{
currentRoute
}
=
useRouter
()
// 路由
const
{
delView
}
=
useTagsViewStore
()
// 视图操作
const
route
=
useRoute
()
onMounted
(()
=>
{
onMounted
(
async
()
=>
{
resetForm
()
if
(
!
rout
e
.
params
.
id
)
{
if
(
!
currentRoute
.
valu
e
.
params
.
id
)
{
message
.
warning
(
'参数错误,页面编号不能为空!'
)
delView
(
unref
(
currentRoute
))
return
}
getPageDetail
(
route
.
params
.
id
)
// 查询详情
await
getPageDetail
(
currentRoute
.
value
.
params
.
id
)
// 恢复重置前的页面
recoverPageIndex
()
})
</
script
>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment