Merge branch 'master' of http://101.43.112.107:3000/root/allLikeMall into khy-two
This commit is contained in:
commit
ef3ea85b66
@ -1,29 +1,20 @@
|
||||
kind: pipeline # 定义对象类型,还有secret和signature两种类型
|
||||
|
||||
type: docker # 定义流水线类型,还有kubernetes、exec、ssh等类型
|
||||
|
||||
name: filesystem-drone # 定义流水线名称
|
||||
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
steps: # 定义流水线执行步骤,这些步骤将顺序执行
|
||||
|
||||
- name: build-java
|
||||
image: appleboy/drone-ssh # SSH工具镜像
|
||||
|
||||
settings:
|
||||
|
||||
host: 1.14.205.126 # 远程连接地址
|
||||
|
||||
username: root # 远程连接账号
|
||||
|
||||
password:
|
||||
|
||||
password:
|
||||
from_secret: ssh_password # 从Secret中读取SSH密码
|
||||
|
||||
port: 22 # 远程连接端口
|
||||
|
||||
command_timeout: 30m # 远程执行命令超时时间
|
||||
|
||||
script:
|
||||
- echo "build-java......"
|
||||
- cd /root/allLikeMall
|
||||
@ -34,4 +25,3 @@ steps: # 定义流水线执行步骤,这些步骤将顺序执行
|
||||
- cd yudao-server
|
||||
- chmod +x all.sh
|
||||
- ./all.sh
|
||||
|
||||
|
@ -56,3 +56,32 @@ export const getDiyTemplateProperty = async (id: number) => {
|
||||
export const updateDiyTemplateProperty = async (data: DiyTemplateVO) => {
|
||||
return await request.put({ url: `/promotion/diy-template/update-property`, data })
|
||||
}
|
||||
|
||||
|
||||
// 设置商品分类接口
|
||||
export const setDiyProjuctClass = async (id) => {
|
||||
return await request.get({
|
||||
url: `/system/dict-data/diy-template-goods?id=` + id
|
||||
})
|
||||
}
|
||||
|
||||
// 获取商品分类接口
|
||||
export const getDiyProjuctClass = async () => {
|
||||
return await request.get({
|
||||
url: `/system/dict-data/getGoods`
|
||||
})
|
||||
}
|
||||
|
||||
// 设置主题风格
|
||||
export const setDiyZtClass = async (id) => {
|
||||
return await request.get({
|
||||
url: `/system/dict-data/diy-template-theme?id=` + id
|
||||
})
|
||||
}
|
||||
|
||||
// 获取主题风格
|
||||
export const getDiyZtClass = async () => {
|
||||
return await request.get({
|
||||
url: `/system/dict-data/getTheme`
|
||||
})
|
||||
}
|
@ -20,6 +20,7 @@ export interface UserVO {
|
||||
point: number | undefined | null
|
||||
totalPoint: number | undefined | null
|
||||
experience: number | null | undefined
|
||||
groupName: string
|
||||
}
|
||||
|
||||
// 查询会员用户列表
|
||||
@ -51,3 +52,8 @@ export const updateUserPoint = async (data: any) => {
|
||||
export const updateUserBalance = async (data: any) => {
|
||||
return await request.put({ url: `/member/user/update-balance`, data })
|
||||
}
|
||||
|
||||
// 客服查询用户详情
|
||||
export const getUserInfo = async (id: number) => {
|
||||
return await request.get({ url: `/member/user/getUserInfo?id=` + id })
|
||||
}
|
||||
|
56
yudao-admin-vue3/src/api/pay/wallet/recharge/index.ts
Normal file
56
yudao-admin-vue3/src/api/pay/wallet/recharge/index.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 钱包充值 VO
|
||||
export interface WalletRechargeVO {
|
||||
id: number // id
|
||||
walletId: number // 钱包编号
|
||||
totalPrice: number // 充值实际到账
|
||||
payPrice: number // 实际支付金额
|
||||
bonusPrice: number // 钱包赠送金额
|
||||
packageId: number // 充值套餐编号
|
||||
payStatus: boolean // 是否支付
|
||||
payOrderId: number // 支付订单编号
|
||||
payChannelCode: string // 支付成功的支付渠道
|
||||
payTime: Date // 订单支付时间
|
||||
payRefundId: number // 支付退款单编号
|
||||
refundTotalPrice: number // 退款金额(包含赠送金额)
|
||||
refundPayPrice: number // 退款支付金额
|
||||
refundBonusPrice: number // 退款钱包赠送金额
|
||||
refundTime: Date // 退款时间
|
||||
refundStatus: number // 退款状态
|
||||
name : string
|
||||
avatar: string
|
||||
}
|
||||
|
||||
// 钱包充值 API
|
||||
export const WalletRechargeApi = {
|
||||
// 查询钱包充值分页
|
||||
getWalletRechargePage: async (params: any) => {
|
||||
return await request.get({ url: `/pay/wallet-recharge/page`, params })
|
||||
},
|
||||
|
||||
// 查询钱包充值详情
|
||||
getWalletRecharge: async (id: number) => {
|
||||
return await request.get({ url: `/pay/wallet-recharge/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增钱包充值
|
||||
createWalletRecharge: async (data: WalletRechargeVO) => {
|
||||
return await request.post({ url: `/pay/wallet-recharge/create`, data })
|
||||
},
|
||||
|
||||
// 修改钱包充值
|
||||
updateWalletRecharge: async (data: WalletRechargeVO) => {
|
||||
return await request.put({ url: `/pay/wallet-recharge/update`, data })
|
||||
},
|
||||
|
||||
// 删除钱包充值
|
||||
deleteWalletRecharge: async (id: number) => {
|
||||
return await request.delete({ url: `/pay/wallet-recharge/delete?id=` + id })
|
||||
},
|
||||
|
||||
// 导出钱包充值 Excel
|
||||
exportWalletRecharge: async (params) => {
|
||||
return await request.download({ url: `/pay/wallet-recharge/export-excel`, params })
|
||||
}
|
||||
}
|
BIN
yudao-admin-vue3/src/assets/imgs/liebiao.png
Normal file
BIN
yudao-admin-vue3/src/assets/imgs/liebiao.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
BIN
yudao-admin-vue3/src/assets/imgs/tubiao.png
Normal file
BIN
yudao-admin-vue3/src/assets/imgs/tubiao.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
@ -24,7 +24,7 @@
|
||||
:content="appLink.path" placement="bottom" :show-after="300">
|
||||
|
||||
<el-button class="m-b-8px m-r-8px m-l-0px!"
|
||||
:type="isSameLink(appLink.path, activeAppLink.path) ? 'primary' : 'default'"
|
||||
:type="appLink.path == activeAppLink.path ? 'primary' : 'default'"
|
||||
@click="handleAppLinkSelected(appLink)">
|
||||
{{ appLink.name }}
|
||||
</el-button>
|
||||
@ -109,9 +109,14 @@
|
||||
|
||||
// 处理 APP 链接选中
|
||||
const handleAppLinkSelected = (appLink : AppLink) => {
|
||||
if (!isSameLink(appLink.path, activeAppLink.value.path)) {
|
||||
activeAppLink.value = appLink
|
||||
console.log(activeAppLink.value,activeAppLink.value.path,"activeAppLink.value")
|
||||
if(!appLink.path.includes('/pages/index/page')){
|
||||
if (!isSameLink(appLink.path, activeAppLink.value.path)) {
|
||||
activeAppLink.value = appLink
|
||||
// console.log(activeAppLink.value,activeAppLink.value.path,"activeAppLink.value")
|
||||
}
|
||||
}else{
|
||||
activeAppLink.value.path = appLink.path
|
||||
console.log(activeAppLink.value.path,"activeAppLink.value.path")
|
||||
}
|
||||
switch (appLink.type) {
|
||||
case APP_LINK_TYPE_ENUM.PRODUCT_CATEGORY_LIST:
|
||||
|
@ -65,11 +65,11 @@ export const APP_LINK_GROUP_LIST = [
|
||||
name: '商品搜索',
|
||||
path: '/pages/index/search'
|
||||
},
|
||||
{
|
||||
name: '自定义页面',
|
||||
path: '/pages/index/page',
|
||||
type: APP_LINK_TYPE_ENUM.DIY_PAGE_DETAIL
|
||||
},
|
||||
// {
|
||||
// name: '自定义页面',
|
||||
// path: '/pages/index/page',
|
||||
// type: APP_LINK_TYPE_ENUM.DIY_PAGE_DETAIL
|
||||
// },
|
||||
{
|
||||
name: '客服',
|
||||
path: '/pages/chat/index'
|
||||
@ -78,13 +78,25 @@ export const APP_LINK_GROUP_LIST = [
|
||||
name: '系统设置',
|
||||
path: '/pages/public/setting'
|
||||
},
|
||||
{
|
||||
name: '常见问题',
|
||||
path: '/pages/public/faq'
|
||||
},
|
||||
// {
|
||||
// name: '常见问题',
|
||||
// path: '/pages/public/faq'
|
||||
// },
|
||||
{
|
||||
name: '积分商城',
|
||||
path: '/pages/public/faq'
|
||||
path: '/pages/index/page?id=3'
|
||||
},
|
||||
{
|
||||
name:'我的积分',
|
||||
path:'/pages/user/wallet/score'
|
||||
},
|
||||
{
|
||||
name:'兑换记录',
|
||||
path:'/pages/activity/point/exchange_list'
|
||||
},
|
||||
{
|
||||
name:'积分商品列表',
|
||||
path:'/pages/activity/point/exchange_listall?id=3'
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -111,11 +123,11 @@ export const APP_LINK_GROUP_LIST = [
|
||||
path: '/pages/goods/seckill',
|
||||
type: APP_LINK_TYPE_ENUM.PRODUCT_DETAIL_SECKILL
|
||||
},
|
||||
{
|
||||
name: '促销列表',
|
||||
path: '/pages/goods/sales',
|
||||
type: APP_LINK_TYPE_ENUM.PRODUCT_DETAIL_SECKILL
|
||||
},
|
||||
// {
|
||||
// name: '促销列表',
|
||||
// path: '/pages/goods/sales',
|
||||
// type: APP_LINK_TYPE_ENUM.PRODUCT_DETAIL_SECKILL
|
||||
// },
|
||||
{
|
||||
name: '门店管理',
|
||||
path: '/pages/user/goods_details_store/index',
|
||||
@ -195,11 +207,12 @@ export const APP_LINK_GROUP_LIST = [
|
||||
{
|
||||
name: '充值记录',
|
||||
path: '/pages/pay/recharge-log'
|
||||
},
|
||||
{
|
||||
name: '核销记录',
|
||||
path: '/pages/pay/recharge-log'
|
||||
}
|
||||
// ,
|
||||
// {
|
||||
// name: '核销记录',
|
||||
// path: '/pages/pay/recharge-log'
|
||||
// }
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -248,7 +261,19 @@ export const APP_LINK_GROUP_LIST = [
|
||||
{
|
||||
name: '会员中心',
|
||||
path: '/pages/user/user_vip/index'
|
||||
}
|
||||
},
|
||||
{
|
||||
name:'付费会员',
|
||||
path:'/pages/user/user_vip/list'
|
||||
},
|
||||
{
|
||||
name:'预约中心',
|
||||
path:'/pages/subscribe/subscribe'
|
||||
},
|
||||
{
|
||||
name:'预约记录',
|
||||
path:'pages/reservation_record/reservation_record'
|
||||
}
|
||||
]
|
||||
}
|
||||
// ,
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<el-scrollbar class="z-1 min-h-30px" wrap-class="w-full" ref="containerRef">
|
||||
<div
|
||||
class="new-class flex flex-row text-12px"
|
||||
class="new-class flex-row text-12px"
|
||||
:style="{
|
||||
gap: `${property.space}px`,
|
||||
width: scrollbarWidth
|
||||
@ -13,11 +13,13 @@
|
||||
background: property.bgImg
|
||||
? `url(${property.bgImg}) 100% center / 100% 100% no-repeat`
|
||||
: '#fff',
|
||||
width: `${couponWidth}px`,
|
||||
width: `150px`,
|
||||
padding: `10px 10px`,
|
||||
color: property.textColor
|
||||
}"
|
||||
v-for="(coupon, index) in couponList"
|
||||
:key="index"
|
||||
style="padding-left: 0px;padding-right: 4px;"
|
||||
>
|
||||
<!-- 布局1:1列-->
|
||||
<!-- <div v-if="property.columns === 1" class="m-l-16px flex flex-row justify-between p-8px">
|
||||
@ -41,16 +43,17 @@
|
||||
<!-- 布局2:2列-->
|
||||
<!-- v-else-if="property.columns === 2"s -->
|
||||
<div
|
||||
class="m-l-16px flex flex-row justify-between"
|
||||
class="flex flex-row justify-between"
|
||||
style=""
|
||||
>
|
||||
<div class="flex flex-col justify-evenly gap-4px">
|
||||
<div class="flex flex-col justify-evenly gap-4px" style="flex:1;">
|
||||
<!-- 优惠值 -->
|
||||
<CouponDiscount :coupon="coupon" />
|
||||
<div>{{ coupon.name }}</div>
|
||||
<CouponDiscount :coupon="coupon" style="text-align:center;" />
|
||||
<div style="text-align:center;">{{ coupon.name }}</div>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col" style="writing-mode: vertical-rl;">
|
||||
<div
|
||||
class="h-full w-20px rounded-20px p-x-2px p-y-8px text-center"
|
||||
class="h-full w-20px rounded-20px text-center"
|
||||
:style="{
|
||||
color: property.button.color,
|
||||
background: property.button.bgColor
|
||||
@ -138,8 +141,11 @@ onMounted(() => {
|
||||
<style scoped lang="scss">
|
||||
.new-class{
|
||||
margin-left: 10px;
|
||||
overflow-x:scroll;
|
||||
white-space: nowrap;
|
||||
.box-content{
|
||||
margin-right:10px;
|
||||
display:inline-block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<div
|
||||
v-for="(item, index) in property.list"
|
||||
:key="index"
|
||||
class="relative flex flex-col items-center p-b-14px p-t-20px"
|
||||
class="relative flex flex-col items-center"
|
||||
:style="{ width: `${100 * (1 / property.column)}%` }"
|
||||
>
|
||||
<!-- 右上角角标 -->
|
||||
@ -14,11 +14,11 @@
|
||||
>
|
||||
{{ item.badge.text }}
|
||||
</span>
|
||||
<el-image v-if="item.iconUrl" class="h-28px w-28px" :src="item.iconUrl" />
|
||||
<el-image v-if="item.iconUrl" class="h-40px w-40px" :src="item.iconUrl" />
|
||||
<span class="m-t-8px h-16px text-12px leading-16px" :style="{ color: item.titleColor }">
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<span class="m-t-6px h-12px text-10px leading-12px" :style="{ color: item.subtitleColor }">
|
||||
<span v-if="item.subtitle" class="m-t-6px h-12px text-10px leading-12px" :style="{ color: item.subtitleColor }">
|
||||
{{ item.subtitle }}
|
||||
</span>
|
||||
</div>
|
||||
@ -32,4 +32,9 @@ defineOptions({ name: 'MenuGrid' })
|
||||
defineProps<{ property: MenuGridProperty }>()
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
<style scoped lang="scss">
|
||||
|
||||
.items-center{
|
||||
margin:5px 0;
|
||||
}
|
||||
</style>
|
||||
|
@ -0,0 +1,80 @@
|
||||
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
/** 宫格导航属性 */
|
||||
export interface MenuGridProperty {
|
||||
// 列数
|
||||
column: number
|
||||
// 导航菜单列表
|
||||
list: MenuGridItemProperty[]
|
||||
// 组件样式
|
||||
style: ComponentStyle
|
||||
}
|
||||
|
||||
/** 宫格导航项目属性 */
|
||||
export interface MenuGridItemProperty {
|
||||
// 图标链接
|
||||
iconUrl: string
|
||||
// 标题
|
||||
title: string
|
||||
// 标题颜色
|
||||
titleColor: string
|
||||
// 副标题
|
||||
subtitle: string
|
||||
// 副标题颜色
|
||||
subtitleColor: string
|
||||
// 链接
|
||||
url: string
|
||||
// 角标
|
||||
badge: {
|
||||
// 是否显示
|
||||
show: boolean
|
||||
// 角标文字
|
||||
text: string
|
||||
// 角标文字颜色
|
||||
textColor: string
|
||||
// 角标背景颜色
|
||||
bgColor: string
|
||||
}
|
||||
}
|
||||
|
||||
export const EMPTY_MENU_GRID_ITEM_PROPERTY = {
|
||||
title: '标题',
|
||||
titleColor: '#333',
|
||||
subtitle: '副标题',
|
||||
subtitleColor: '#bbb',
|
||||
badge: {
|
||||
show: false,
|
||||
textColor: '#fff',
|
||||
bgColor: '#FF6000'
|
||||
}
|
||||
} as MenuGridItemProperty
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-04.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'MenuGridTow',
|
||||
name: '魔方',
|
||||
// icon: 'bi:grid-3x3-gap',
|
||||
icon: logo,
|
||||
property: {
|
||||
column: 3,
|
||||
list: [cloneDeep(EMPTY_MENU_GRID_ITEM_PROPERTY)],
|
||||
style: {
|
||||
bgType: 'color',
|
||||
bgColor: '#fff',
|
||||
marginBottom: 8,
|
||||
marginLeft: 8,
|
||||
marginRight: 8,
|
||||
padding: 8,
|
||||
paddingTop: 8,
|
||||
paddingRight: 8,
|
||||
paddingBottom: 8,
|
||||
paddingLeft: 8,
|
||||
borderRadius: 8,
|
||||
borderTopLeftRadius: 8,
|
||||
borderTopRightRadius: 8,
|
||||
borderBottomRightRadius: 8,
|
||||
borderBottomLeftRadius: 8
|
||||
} as ComponentStyle
|
||||
}
|
||||
} as DiyComponent<MenuGridProperty>
|
@ -0,0 +1,201 @@
|
||||
<template>
|
||||
<div class='new_czbk'>
|
||||
<div class="t">
|
||||
<text class="left-font">超值爆款</text>
|
||||
<div class="sub">美好生活由此开始</div>
|
||||
</div>
|
||||
<div class="new-list">
|
||||
<!-- <div class="item" @click="sheep.$router.go('/pages/goods/sales', {
|
||||
activityType: 'recommendBest',
|
||||
});"> -->
|
||||
<div class="item" >
|
||||
<div class="nei">
|
||||
<div class="l">
|
||||
<div class="t">今日推荐</div>
|
||||
<div class="c">店主诚意推荐品质商品</div>
|
||||
<div class="b">
|
||||
<!-- GO! -->
|
||||
<img src="https://zysc.fjptzykj.com:3000/shangcheng/40a7582be7aeb5a6047415ab3a6728439a2798a4752ffcc1c063d66a534aa630.png"
|
||||
class="img"/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="r">
|
||||
<img
|
||||
src="https://zysc.fjptzykj.com:3000/shangcheng/c80faeeeb2d6dadcdbe7e6d1a4caa06869b94301612cdf157414a10559b38267.png"
|
||||
class="img"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="item" @click="sheep.$router.go('/pages/goods/sales', {
|
||||
activityType: 'recommendHot',
|
||||
});"> -->
|
||||
<div class="item">
|
||||
<div class="nei">
|
||||
<div class="l">
|
||||
<div class="t">热门榜单</div>
|
||||
<div class="c">店主诚意推荐品质商品</div>
|
||||
<div class="b">
|
||||
<!-- GO! -->
|
||||
<img
|
||||
src="https://zysc.fjptzykj.com:3000/shangcheng/5c72fc99989bf0a7e59b57f519c76c9a98cb20478384e20b1b934aa8f80cc598.png"
|
||||
class="img"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="r">
|
||||
<img
|
||||
src="https://zysc.fjptzykj.com:3000/shangcheng/904fd4848fde8025ccc17693662efd5b7bf5ec3f2656ecc7de407c8c46f910b2.png"
|
||||
class="img"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="item" @click="sheep.$router.go('/pages/goods/sales', {
|
||||
activityType: 'recommendNew',
|
||||
});"> -->
|
||||
<div class="item">
|
||||
<div class="nei">
|
||||
<div class="l">
|
||||
<div class="t">首发新品</div>
|
||||
<div class="c">新品上架等 你来拿</div>
|
||||
<div class="b">
|
||||
<!-- GO! -->
|
||||
<img
|
||||
src="https://zysc.fjptzykj.com:3000/shangcheng/ebb2fc0512d1bd6a6d21a2c07f6603bfd2ea6f7e23377eb4cd8118d89d666589.png"
|
||||
class="img"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="r">
|
||||
<img
|
||||
src="https://zysc.fjptzykj.com:3000/shangcheng/7c71cbf2c757418302ea9ef2952893c24e1d46c4cc35a821f56be0f315bcabb0.png"
|
||||
class="img"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="item" @click="sheep.$router.go('/pages/goods/sales', {
|
||||
activityType: 'recommendGood',
|
||||
});"> -->
|
||||
<div class="item">
|
||||
<div class="nei">
|
||||
<div class="l">
|
||||
<div class="t">促销单品</div>
|
||||
<div class="c">综合评选好 产品</div>
|
||||
<div class="b">
|
||||
<!-- GO! -->
|
||||
<img
|
||||
src="https://zysc.fjptzykj.com:3000/shangcheng/aac8baa7a6feb9ee3459d1cf75ba9a7e8bacb5d93c88ac95c1b0ecd29b847f96.png"
|
||||
class="img"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="r">
|
||||
<img
|
||||
src="https://zysc.fjptzykj.com:3000/shangcheng/8a61c35d82702c61f97ef3db43a8d6755b2eca3d78a22dbaa55851e815e96a23.png"
|
||||
class="img" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="clear:both;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { MenuGridProperty } from './config'
|
||||
/** 宫格导航 */
|
||||
defineOptions({ name: 'MenuGridTow' })
|
||||
defineProps<{ property: MenuGridProperty }>()
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.new_czbk {
|
||||
width: 100%;
|
||||
background: rgba(255, 229, 227);
|
||||
border-radius: 5px;
|
||||
margin: 0 auto;
|
||||
padding: 5px 0;
|
||||
// margin-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
padding-top: 10px;
|
||||
&>.t {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding:0 10px;
|
||||
.left-font {
|
||||
color: rgba(252, 60, 62);
|
||||
font-size: 17px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.sub {
|
||||
background: rgba(248, 79, 43);
|
||||
color: white;
|
||||
border-radius: 20px 0px 20px 0px;
|
||||
padding: 0 13px;
|
||||
margin-left: 10px;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.new-list {
|
||||
// width: 100%;
|
||||
margin-right:10px;
|
||||
.item {
|
||||
float: left;
|
||||
width: 50%;
|
||||
|
||||
.nei {
|
||||
margin: 10px;
|
||||
margin-right:0;
|
||||
margin-bottom: 0;
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
padding: 8px 10px;
|
||||
display: flex;
|
||||
|
||||
.l {
|
||||
width: 50%;
|
||||
|
||||
.t {
|
||||
// font-size: 17px;
|
||||
}
|
||||
|
||||
.c {
|
||||
color: rgba(153, 153, 153);
|
||||
font-size: 12px;
|
||||
margin: 3px 0;
|
||||
}
|
||||
|
||||
.b {
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
// justify-content: space-around;
|
||||
// background: #329cff;
|
||||
// margin: 0 3px;
|
||||
// border-radius: 15px;
|
||||
// color: white;
|
||||
// font-weight: 700;
|
||||
// padding: 0px 9px;
|
||||
// font-style: oblique;
|
||||
|
||||
.img {
|
||||
width: 76%;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.r {
|
||||
width: 49%;
|
||||
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</style>
|
@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<ComponentContainerProperty v-model="formData.style">
|
||||
<!-- 表单 -->
|
||||
<el-form label-width="80px" :model="formData" class="m-t-8px">
|
||||
<el-form-item label="每行数量" prop="column">
|
||||
<el-radio-group v-model="formData.column">
|
||||
<el-radio :label="3">3个</el-radio>
|
||||
<el-radio :label="4">4个</el-radio>
|
||||
<el-radio :label="5">5个</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<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>
|
||||
</UploadImg>
|
||||
</el-form-item>
|
||||
<el-form-item label="标题" prop="title">
|
||||
<InputWithColor v-model="element.title" v-model:color="element.titleColor" />
|
||||
</el-form-item>
|
||||
<el-form-item label="副标题" prop="subtitle">
|
||||
<InputWithColor v-model="element.subtitle" v-model:color="element.subtitleColor" />
|
||||
</el-form-item>
|
||||
<el-form-item label="链接" prop="url">
|
||||
<AppLinkInput v-model="element.url" />
|
||||
</el-form-item>
|
||||
<el-form-item label="显示角标" prop="badge.show">
|
||||
<el-switch v-model="element.badge.show" />
|
||||
</el-form-item>
|
||||
<template v-if="element.badge.show">
|
||||
<el-form-item label="角标内容" prop="badge.text">
|
||||
<InputWithColor
|
||||
v-model="element.badge.text"
|
||||
v-model:color="element.badge.textColor"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="背景颜色" prop="badge.bgColor">
|
||||
<ColorInput v-model="element.badge.bgColor" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</template>
|
||||
</Draggable>
|
||||
</el-card>
|
||||
</el-form>
|
||||
</ComponentContainerProperty>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import {
|
||||
EMPTY_MENU_GRID_ITEM_PROPERTY,
|
||||
MenuGridProperty
|
||||
} from '@/components/DiyEditor/components/mobile/MenuGrid/config'
|
||||
|
||||
/** 宫格导航属性面板 */
|
||||
defineOptions({ name: 'MenuGridProperty' })
|
||||
|
||||
const props = defineProps<{ modelValue: MenuGridProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
@ -10,7 +10,7 @@
|
||||
<div class="h-24px truncate leading-24px">{{ item.text }}</div>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
<Icon icon="ep:arrow-right" />
|
||||
<!-- <Icon icon="ep:arrow-right" /> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -1,5 +1,23 @@
|
||||
<template>
|
||||
<div :class="`box-content min-h-30px w-full flex flex-row flex-wrap`" ref="containerRef">
|
||||
<view class="new-fenlei">
|
||||
<view class="list on">
|
||||
<view class="t">首页新品</view>
|
||||
<view class="b">最新出炉</view>
|
||||
</view>
|
||||
<view class="list">
|
||||
<view class="t">精品推荐</view>
|
||||
<view class="b">猜你喜欢</view>
|
||||
</view>
|
||||
<view class="list">
|
||||
<view class="t">热门榜单</view>
|
||||
<view class="b">好评如云</view>
|
||||
</view>
|
||||
<view class="list">
|
||||
<view class="t">促销单品</view>
|
||||
<view class="b">多买多销</view>
|
||||
</view>
|
||||
</view>
|
||||
<div
|
||||
class="relative box-content flex flex-row flex-wrap overflow-hidden bg-white"
|
||||
:style="{
|
||||
@ -164,4 +182,44 @@ const calculateWidth = () => {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
<style scoped lang="scss">
|
||||
|
||||
.new-fenlei {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
margin:10px 0;
|
||||
justify-content: space-around;
|
||||
.list {
|
||||
width: 100%;
|
||||
display:flex;
|
||||
flex-wrap:wrap;
|
||||
&.on{
|
||||
.t {
|
||||
color: #e93422;
|
||||
}
|
||||
|
||||
.b {
|
||||
background: #e93422;
|
||||
color:white;
|
||||
}
|
||||
}
|
||||
.t {
|
||||
width:100%;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.b {
|
||||
// background: rgba(255, 102, 7);
|
||||
text-align: center;
|
||||
color: rgba(153,153,153);
|
||||
border-radius: 15px;
|
||||
width: 63%;
|
||||
margin: 0 auto;
|
||||
font-size: 12px;
|
||||
margin-top:5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -27,8 +27,8 @@
|
||||
:style="{
|
||||
gridGap: `${property.space}px`,
|
||||
gridTemplateColumns,
|
||||
width: scrollbarWidth
|
||||
}"
|
||||
style="padding:0 10px;padding-bottom: 8px;"
|
||||
>
|
||||
<!-- 商品 -->
|
||||
<div
|
||||
@ -53,7 +53,7 @@
|
||||
<el-image fit="cover" :src="spu.picUrl" :style="{ width: imageSize, height: imageSize }" />
|
||||
<div
|
||||
:class="[
|
||||
'flex flex-col gap-8px p-8px box-border',
|
||||
'flex flex-col p-8px box-border',
|
||||
{
|
||||
'w-[calc(100%-64px)]': columns === 2,
|
||||
'w-full': columns === 3
|
||||
@ -79,6 +79,7 @@
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<view class="sss">参与拼团</view>
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
@ -145,9 +146,18 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.sss {
|
||||
width: 100%;
|
||||
// margin-top: 10px;
|
||||
padding: 3px;
|
||||
font-size: 13px;
|
||||
background: #e93422;
|
||||
text-align: center;
|
||||
color: white;
|
||||
border-radius: 0px 0px 5px 5px;
|
||||
}
|
||||
.new-class{
|
||||
padding: 10px;
|
||||
padding:0 0;
|
||||
// width:42%;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,12 @@
|
||||
src="https://zysc.fjptzykj.com:3000/shangcheng/cb995c399d784c08e27d8f56b0a63ace2d13af3a1ee6aba5a2da71868dc4cf00.png" />
|
||||
<span class="new-text">限时秒杀</span>
|
||||
</div>
|
||||
<span class="text-16px" style="color: rgb(187, 187, 187);">已有99人购买</span>
|
||||
<div style="color: rgba(255, 51, 35, 1); font-size:15px;" class="title-text">
|
||||
<span class="time">05</span>:
|
||||
<span class="time">00</span>:
|
||||
<span class="time">00</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-center flex flex-row justify-center gap-4px">
|
||||
<span class="text-12px" style="color: rgb(187, 187, 187);">查看更多</span>
|
||||
@ -23,10 +28,8 @@
|
||||
<!-- 商品网格 -->
|
||||
<!-- gridGap: `${property.space}px`, -->
|
||||
<div class="new-main" :style="{
|
||||
|
||||
gridTemplateColumns,
|
||||
width: scrollbarWidth
|
||||
}">
|
||||
gridTemplateColumns,
|
||||
}" style="padding:0 10px;">
|
||||
<!-- 商品 -->
|
||||
<!--
|
||||
:style="{
|
||||
@ -44,19 +47,14 @@
|
||||
</div>
|
||||
<!-- 商品封面图 -->
|
||||
<el-image fit="cover" :src="spu.picUrl" :style="{ width: imageSize, height: imageSize }" />
|
||||
<div :class="[
|
||||
'flex flex-col gap-8px p-8px box-border',
|
||||
{
|
||||
'w-[calc(100%-64px)]': columns === 2,
|
||||
'w-full': columns === 3
|
||||
}
|
||||
]">
|
||||
<div>
|
||||
<!-- 商品名称 -->
|
||||
<div v-if="property.fields.name.show" class="truncate text-12px"
|
||||
:style="{ color: property.fields.name.color }">
|
||||
:style="{ color: property.fields.name.color }" style="margin: 5px 0;">
|
||||
{{ spu.name }}
|
||||
</div>
|
||||
<div>
|
||||
<div style="display: flex;">
|
||||
<div class="fff">抢</div>
|
||||
<!-- 商品价格 -->
|
||||
<span v-if="property.fields.price.show" class="text-12px"
|
||||
:style="{ color: property.fields.price.color }">
|
||||
@ -129,6 +127,24 @@
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.fff {
|
||||
padding: 1px 3px;
|
||||
font-size: 8px;
|
||||
background: #e93422;
|
||||
color: white;
|
||||
border-radius: 2px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.time {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: rgba(255, 237, 238, 1);
|
||||
color: rgba(255, 51, 35, 1);
|
||||
text-align: center;
|
||||
padding: 0 3px;
|
||||
}
|
||||
|
||||
:deep(.el-scrollbar__view) {
|
||||
background-color: white;
|
||||
border-radius: 12px;
|
||||
@ -136,28 +152,36 @@
|
||||
|
||||
.new-class {
|
||||
width: 33%;
|
||||
padding: 10px;
|
||||
border-radius: 8px 8px 8px 0px;
|
||||
padding-bottom: 10px;
|
||||
// padding: 10px;
|
||||
// width:42%;
|
||||
}
|
||||
|
||||
.new-main {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
grid-template-columns: repeat(3, auto);
|
||||
padding: 0px 10px 8px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
:deep(.el-image) {
|
||||
width: 100% !important;
|
||||
}
|
||||
// :deep(.el-image) {
|
||||
// width: 100% !important;
|
||||
// }
|
||||
|
||||
.wh {
|
||||
position: relative;
|
||||
padding-right: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.new-text1{
|
||||
width:30px;
|
||||
|
||||
.new-text1 {
|
||||
width: 30px;
|
||||
}
|
||||
.new-text{
|
||||
font-weight: 700;
|
||||
|
||||
.new-text {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,10 +69,10 @@
|
||||
</draggable>
|
||||
</el-scrollbar>
|
||||
<!-- 手机底部导航 -->
|
||||
<div v-if="showTabBar" :class="['editor-design-bottom', 'component', 'cursor-pointer!']">
|
||||
<!-- <div v-if="showTabBar" :class="['editor-design-bottom', 'component', 'cursor-pointer!']">
|
||||
<ComponentContainer :component="tabBarComponent" :show-toolbar="false"
|
||||
:active="selectedComponent?.id === tabBarComponent.id" @click="handleTabBarSelected" />
|
||||
</div>
|
||||
</div> -->
|
||||
<!-- 固定布局的组件 操作按钮区 -->
|
||||
<div class="fixed-component-action-group">
|
||||
<el-tag v-if="showPageConfig" size="large"
|
||||
|
@ -118,7 +118,8 @@ export const PAGE_LIBS = [
|
||||
'MenuGrid',
|
||||
'MenuList',
|
||||
'Popover',
|
||||
'FloatingActionButton'
|
||||
'FloatingActionButton',
|
||||
"MenuGridTow"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -54,7 +54,7 @@ export default defineComponent({
|
||||
onClick={handleClickOutside}
|
||||
></div>
|
||||
) : undefined}
|
||||
|
||||
|
||||
{renderLayout()}
|
||||
|
||||
<Backtop></Backtop>
|
||||
|
@ -35,88 +35,120 @@ const mobile = computed(() => appStore.getMobile)
|
||||
// 固定菜单
|
||||
const fixedMenu = computed(() => appStore.getFixedMenu)
|
||||
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
export const useRenderLayout = () => {
|
||||
const renderClassic = () => {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
class={[
|
||||
'absolute top-0 left-0 h-full layout-border__right',
|
||||
{ '!fixed z-3000': mobile.value }
|
||||
]}
|
||||
>
|
||||
{logo.value ? (
|
||||
<Logo
|
||||
class={[
|
||||
'bg-[var(--left-menu-bg-color)] relative',
|
||||
{
|
||||
'!pl-0': mobile.value && collapse.value,
|
||||
'w-[var(--left-menu-min-width)]': appStore.getCollapse,
|
||||
'w-[var(--left-menu-max-width)]': !appStore.getCollapse
|
||||
}
|
||||
]}
|
||||
style="transition: all var(--transition-time-02);"
|
||||
></Logo>
|
||||
) : undefined}
|
||||
<Menu class={[{ '!h-[calc(100%-var(--logo-height))]': logo.value }]}></Menu>
|
||||
</div>
|
||||
<div
|
||||
class={[
|
||||
`${prefixCls}-content`,
|
||||
'absolute top-0 h-[100%]',
|
||||
{
|
||||
'w-[calc(100%-var(--left-menu-min-width))] left-[var(--left-menu-min-width)]':
|
||||
collapse.value && !mobile.value && !mobile.value,
|
||||
'w-[calc(100%-var(--left-menu-max-width))] left-[var(--left-menu-max-width)]':
|
||||
!collapse.value && !mobile.value && !mobile.value,
|
||||
'fixed !w-full !left-0': mobile.value
|
||||
}
|
||||
]}
|
||||
style="transition: all var(--transition-time-02);"
|
||||
>
|
||||
<ElScrollbar
|
||||
v-loading={pageLoading.value}
|
||||
class={[
|
||||
`${prefixCls}-content-scrollbar`,
|
||||
{
|
||||
'!h-[calc(100%-var(--top-tool-height)-var(--tags-view-height))] mt-[calc(var(--top-tool-height)+var(--tags-view-height))]':
|
||||
fixedHeader.value
|
||||
}
|
||||
]}
|
||||
>
|
||||
<div
|
||||
class={[
|
||||
{
|
||||
'fixed top-0 left-0 z-10': fixedHeader.value,
|
||||
'w-[calc(100%-var(--left-menu-min-width))] !left-[var(--left-menu-min-width)]':
|
||||
collapse.value && fixedHeader.value && !mobile.value,
|
||||
'w-[calc(100%-var(--left-menu-max-width))] !left-[var(--left-menu-max-width)]':
|
||||
!collapse.value && fixedHeader.value && !mobile.value,
|
||||
'!w-full !left-0': mobile.value
|
||||
}
|
||||
]}
|
||||
style="transition: all var(--transition-time-02);"
|
||||
>
|
||||
<ToolHeader
|
||||
class={[
|
||||
'bg-[var(--top-header-bg-color)]',
|
||||
{
|
||||
'layout-border__bottom': !tagsView.value
|
||||
}
|
||||
]}
|
||||
></ToolHeader>
|
||||
|
||||
{tagsView.value ? (
|
||||
<TagsView class="layout-border__top layout-border__bottom"></TagsView>
|
||||
) : undefined}
|
||||
</div>
|
||||
|
||||
<AppView></AppView>
|
||||
</ElScrollbar>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
const route = useRoute()
|
||||
let renderClassic = null;
|
||||
if(route.path == "/kefu/kefu"){
|
||||
renderClassic = () => {
|
||||
return (
|
||||
<>
|
||||
|
||||
<div
|
||||
|
||||
style="transition: all var(--transition-time-02);width:85%;margin:0 auto;"
|
||||
>
|
||||
<ElScrollbar
|
||||
v-loading={pageLoading.value}
|
||||
class={[
|
||||
`${prefixCls}-content-scrollbar`,
|
||||
{
|
||||
|
||||
}
|
||||
]}
|
||||
>
|
||||
|
||||
|
||||
<AppView></AppView>
|
||||
</ElScrollbar>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}else {
|
||||
renderClassic = () => {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
class={[
|
||||
'absolute top-0 left-0 h-full layout-border__right',
|
||||
{ '!fixed z-3000': mobile.value }
|
||||
]}
|
||||
>
|
||||
{logo.value ? (
|
||||
<Logo
|
||||
class={[
|
||||
'bg-[var(--left-menu-bg-color)] relative',
|
||||
{
|
||||
'!pl-0': mobile.value && collapse.value,
|
||||
'w-[var(--left-menu-min-width)]': appStore.getCollapse,
|
||||
'w-[var(--left-menu-max-width)]': !appStore.getCollapse
|
||||
}
|
||||
]}
|
||||
style="transition: all var(--transition-time-02);"
|
||||
></Logo>
|
||||
) : undefined}
|
||||
<Menu class={[{ '!h-[calc(100%-var(--logo-height))]': logo.value }]}></Menu>
|
||||
</div>
|
||||
<div
|
||||
class={[
|
||||
`${prefixCls}-content`,
|
||||
'absolute top-0 h-[100%]',
|
||||
{
|
||||
'w-[calc(100%-var(--left-menu-min-width))] left-[var(--left-menu-min-width)]':
|
||||
collapse.value && !mobile.value && !mobile.value,
|
||||
'w-[calc(100%-var(--left-menu-max-width))] left-[var(--left-menu-max-width)]':
|
||||
!collapse.value && !mobile.value && !mobile.value,
|
||||
'fixed !w-full !left-0': mobile.value
|
||||
}
|
||||
]}
|
||||
style="transition: all var(--transition-time-02);"
|
||||
>
|
||||
<ElScrollbar
|
||||
v-loading={pageLoading.value}
|
||||
class={[
|
||||
`${prefixCls}-content-scrollbar`,
|
||||
{
|
||||
'!h-[calc(100%-var(--top-tool-height)-var(--tags-view-height))] mt-[calc(var(--top-tool-height)+var(--tags-view-height))]':
|
||||
fixedHeader.value
|
||||
}
|
||||
]}
|
||||
>
|
||||
<div
|
||||
class={[
|
||||
{
|
||||
'fixed top-0 left-0 z-10': fixedHeader.value,
|
||||
'w-[calc(100%-var(--left-menu-min-width))] !left-[var(--left-menu-min-width)]':
|
||||
collapse.value && fixedHeader.value && !mobile.value,
|
||||
'w-[calc(100%-var(--left-menu-max-width))] !left-[var(--left-menu-max-width)]':
|
||||
!collapse.value && fixedHeader.value && !mobile.value,
|
||||
'!w-full !left-0': mobile.value
|
||||
}
|
||||
]}
|
||||
style="transition: all var(--transition-time-02);"
|
||||
>
|
||||
<ToolHeader
|
||||
class={[
|
||||
'bg-[var(--top-header-bg-color)]',
|
||||
{
|
||||
'layout-border__bottom': !tagsView.value
|
||||
}
|
||||
]}
|
||||
></ToolHeader>
|
||||
|
||||
{tagsView.value ? (
|
||||
<TagsView class="layout-border__top layout-border__bottom"></TagsView>
|
||||
) : undefined}
|
||||
</div>
|
||||
|
||||
<AppView></AppView>
|
||||
</ElScrollbar>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const renderTopLeft = () => {
|
||||
return (
|
||||
|
@ -126,6 +126,8 @@ export enum DICT_TYPE {
|
||||
|
||||
INFRA_FILE_TYPE = 'infra_file_type',
|
||||
|
||||
PAY_WALLET_RECHARGE_PAY_STATUS = 'pay_wallet_recharge_pay_status',
|
||||
|
||||
//预约:项目
|
||||
SUBSCRIBE_PROJECT_STATUS = 'subscribe_project_status',
|
||||
|
||||
|
@ -1,376 +1,420 @@
|
||||
<template>
|
||||
<doc-alert title="上传下载" url="https://doc.iocoder.cn/file/" />
|
||||
<doc-alert title="上传下载" url="https://doc.iocoder.cn/file/" />
|
||||
|
||||
<div class="flex-container">
|
||||
<!-- 菜单区域 -->
|
||||
<div class="menu-area">
|
||||
<div class="flex-container">
|
||||
<!-- 菜单区域 -->
|
||||
<div class="menu-area">
|
||||
|
||||
<el-button type="primary" plain @click="createType" style="width: 90;font-size: 12px;">
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增分类
|
||||
</el-button>
|
||||
<el-button type="primary" plain @click="createType" style="width: 90;font-size: 12px;">
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增分类
|
||||
</el-button>
|
||||
|
||||
<el-menu :default-active="targetMenuId" style="width:182px">
|
||||
<el-menu-item :index="targetMenuId" :key="targetMenuId" @click="clickMenu(targetMenuId)">
|
||||
全部类型
|
||||
</el-menu-item>
|
||||
<el-menu-item v-for="item in typeMenu" :index="item.value" :key="item.value"
|
||||
@click="clickMenu(item.value)">
|
||||
{{ item.label }}
|
||||
<el-icon style="margin-left: 60px;width: 10px;" @mouseover="showActions = item.value"
|
||||
@mouseleave="showActions = null">
|
||||
<MoreFilled />
|
||||
<div v-if="showActions === item.value" class="action-buttons">
|
||||
<el-button size="small" @click.stop="editItem(item.id,item.label)">编辑</el-button>
|
||||
<br />
|
||||
<el-button size="small" @click.stop="deleteItem(item.id)">删除</el-button>
|
||||
</div>
|
||||
</el-icon>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
<el-menu :default-active="targetMenuId" style="width:182px">
|
||||
<el-menu-item :index="targetMenuId" :key="targetMenuId" @click="clickMenu(targetMenuId)">
|
||||
全部类型
|
||||
</el-menu-item>
|
||||
<el-menu-item v-for="item in typeMenu" :index="item.value" :key="item.value"
|
||||
@click="clickMenu(item.value)">
|
||||
{{ item.label }}
|
||||
<el-icon style="margin-left: 60px;width: 10px;" @mouseover="showActions = item.value"
|
||||
@mouseleave="showActions = null">
|
||||
<MoreFilled />
|
||||
<div v-if="showActions === item.value" class="action-buttons">
|
||||
<el-button size="small" @click.stop="editItem(item.id,item.label)">编辑</el-button>
|
||||
<br />
|
||||
<el-button size="small" @click.stop="deleteItem(item.id)">删除</el-button>
|
||||
</div>
|
||||
</el-icon>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<div class="content-wrap">
|
||||
<ContentWrap>
|
||||
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||
<!-- <el-form-item label="文件路径" prop="path">
|
||||
<el-input
|
||||
v-model="queryParams.path"
|
||||
placeholder="请输入文件路径"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="文件类型" prop="type" width="80">
|
||||
<el-input v-model="queryParams.type" placeholder="请输入文件类型" clearable
|
||||
@keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<!-- 内容区域 -->
|
||||
<div class="content-wrap">
|
||||
<ContentWrap>
|
||||
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||
<el-form-item label="文件类型" prop="type" width="80">
|
||||
<el-input v-model="queryParams.type" placeholder="请输入文件类型" clearable
|
||||
@keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange" start-placeholder="开始日期" end-placeholder="结束日期"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery">
|
||||
<Icon icon="ep:search" class="mr-5px" /> 搜索
|
||||
</el-button>
|
||||
<el-button @click="resetQuery">
|
||||
<Icon icon="ep:refresh" class="mr-5px" /> 重置
|
||||
</el-button>
|
||||
<el-button type="primary" plain @click="openForm">
|
||||
<Icon icon="ep:upload" class="mr-5px" /> 上传文件
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange" start-placeholder="开始日期" end-placeholder="结束日期"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery">
|
||||
<Icon icon="ep:search" class="mr-5px" /> 搜索
|
||||
</el-button>
|
||||
<el-button @click="resetQuery">
|
||||
<Icon icon="ep:refresh" class="mr-5px" /> 重置
|
||||
</el-button>
|
||||
<el-button type="primary" plain @click="openForm">
|
||||
<Icon icon="ep:upload" class="mr-5px" /> 上传文件
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<span><img @click="liebiao" style="cursor: pointer;" class="mr-10px h-30px w-30px" src="@/assets/imgs/liebiao.png" /></span>
|
||||
<span><img @click="tubiao" style="cursor: pointer;" class="mr-10px h-30px w-30px" src="@/assets/imgs/tubiao.png" /></span>
|
||||
</el-form>
|
||||
|
||||
</ContentWrap>
|
||||
|
||||
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="文件内容" align="center" prop="url" width="110px">
|
||||
<template #default="{ row }">
|
||||
<el-image v-if="row.type.includes('image')" class="h-80px w-80px" lazy :src="row.url"
|
||||
:preview-src-list="[row.url]" preview-teleported fit="cover" />
|
||||
<el-link v-else-if="row.type.includes('pdf')" type="primary" :href="row.url"
|
||||
:underline="false" target="_blank">预览</el-link>
|
||||
<el-link v-else type="primary" download :href="row.url" :underline="false"
|
||||
target="_blank">下载</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="文件名" align="center" prop="name" :show-overflow-tooltip="true" />
|
||||
<!-- <el-table-column label="文件路径" align="center" prop="path" :show-overflow-tooltip="true" /> -->
|
||||
<el-table-column label="URL" align="center" prop="url" :show-overflow-tooltip="true" />
|
||||
<!-- <el-table-column label="文件大小" align="center" prop="size" width="120"
|
||||
:formatter="fileSizeFormatter" /> -->
|
||||
<!-- <el-table-column label="文件类型" align="center" prop="type" width="180px" />
|
||||
<el-table-column label="图片分类" align="center" prop="picType">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.INFRA_FILE_TYPE" :value="scope.row.picType" />
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
|
||||
<el-table-column label="上传时间" align="center" prop="createTime" width="180"
|
||||
:formatter="dateFormatter" />
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary"
|
||||
@click="updateForm('update', scope.row.id , scope.row.picType)">
|
||||
更改类型
|
||||
</el-button>
|
||||
<el-button link type="danger" @click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['infra:file:delete']">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</ContentWrap>
|
||||
<!-- 分页 -->
|
||||
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList" />
|
||||
<el-table v-loading="loading" :data="list" v-show="panduan == '1'">
|
||||
<el-table-column label="文件内容" align="center" prop="url" width="110px">
|
||||
<template #default="{ row }">
|
||||
<el-image v-if="row.type.includes('image')" class="h-80px w-80px" lazy :src="row.url"
|
||||
:preview-src-list="[row.url]" preview-teleported fit="cover" />
|
||||
<el-link v-else-if="row.type.includes('pdf')" type="primary" :href="row.url"
|
||||
:underline="false" target="_blank">预览</el-link>
|
||||
<el-link v-else type="primary" download :href="row.url" :underline="false"
|
||||
target="_blank">下载</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="文件名" align="center" prop="name" :show-overflow-tooltip="true" />
|
||||
<!-- <el-table-column label="文件路径" align="center" prop="path" :show-overflow-tooltip="true" /> -->
|
||||
<el-table-column label="URL" align="center" prop="url" :show-overflow-tooltip="true" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<FileForm ref="formRef" @success="getList" />
|
||||
<el-table-column label="上传时间" align="center" prop="createTime" width="180"
|
||||
:formatter="dateFormatter" />
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary"
|
||||
@click="updateForm('update', scope.row.id , scope.row.picType)">
|
||||
更改类型
|
||||
</el-button>
|
||||
<el-button link type="danger" @click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['infra:file:delete']">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<UpdateForm ref="forRef" @success="getList" />
|
||||
<div v-show="panduan == '2'">
|
||||
<!-- 图片展示区域 -->
|
||||
<div class="image-container">
|
||||
<div v-for="item in tubiaoData" :key="item.id" class="image-item">
|
||||
<img :src="item.url" alt="图表" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Dialog v-model="dialogVisibles" :title="dialogTitles">
|
||||
<el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px">
|
||||
|
||||
<el-form-item label="数据标签" prop="label">
|
||||
<el-input v-model="formData.label" placeholder="请输入数据标签" />
|
||||
</el-form-item>
|
||||
<el-form-item label="显示排序" prop="sort">
|
||||
<el-input-number v-model="formData.sort" :min="0" controls-position="right" />
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisibles = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
<!-- 分页 -->
|
||||
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList" />
|
||||
|
||||
<Dialog v-model="dialogVisible" :title="dialogTitle">
|
||||
<el-form ref="formRef" v-loading="formLoading" :model="formData" label-width="80px">
|
||||
<el-form-item label="数据标签" prop="label">
|
||||
<el-input v-model="updateLabel" placeholder="请输入数据标签" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForms">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<FileForm ref="formRef" @success="getList" />
|
||||
|
||||
<UpdateForm ref="forRef" @success="getList" />
|
||||
|
||||
<Dialog v-model="dialogVisibles" :title="dialogTitles">
|
||||
<el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" label-width="80px">
|
||||
|
||||
<el-form-item label="数据标签" prop="label">
|
||||
<el-input v-model="formData.label" placeholder="请输入数据标签" />
|
||||
</el-form-item>
|
||||
<el-form-item label="显示排序" prop="sort">
|
||||
<el-input-number v-model="formData.sort" :min="0" controls-position="right" />
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisibles = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
|
||||
<Dialog v-model="dialogVisible" :title="dialogTitle">
|
||||
<el-form ref="formRef" v-loading="formLoading" :model="formData" label-width="80px">
|
||||
<el-form-item label="数据标签" prop="label">
|
||||
<el-input v-model="updateLabel" placeholder="请输入数据标签" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForms">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import { fileSizeFormatter } from '@/utils'
|
||||
import { Search, MoreFilled } from '@element-plus/icons-vue';
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
// import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||
import * as FileApi from '@/api/infra/file'
|
||||
import FileForm from './FileForm.vue'
|
||||
import UpdateForm from './updateForm.vue'
|
||||
import * as DictDataApi from '@/api/system/dict/dict.data'
|
||||
const typeMenu = ref<DictDataApi.DictDataVO[]>([]) //
|
||||
const targetMenuId = ref('0')
|
||||
defineOptions({ name: 'InfraFile' })
|
||||
const showActions = ref(null);
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const dialogVisibles = ref(false) // 弹窗的是否展示
|
||||
const dialogTitles = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
sort: undefined,
|
||||
label: '',
|
||||
value: '',
|
||||
dictType: '',
|
||||
// status: CommonStatusEnum.ENABLE,
|
||||
colorType: '',
|
||||
cssClass: '',
|
||||
remark: ''
|
||||
})
|
||||
const formRules = reactive({
|
||||
label: [{ required: true, message: '数据标签不能为空', trigger: 'blur' }],
|
||||
sort: [{ required: true, message: '数据顺序不能为空', trigger: 'blur' }],
|
||||
})
|
||||
const updateLabel = ref('')
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import { fileSizeFormatter } from '@/utils'
|
||||
import { Search, MoreFilled } from '@element-plus/icons-vue';
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
// import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||
import * as FileApi from '@/api/infra/file'
|
||||
import FileForm from './FileForm.vue'
|
||||
import UpdateForm from './updateForm.vue'
|
||||
import * as DictDataApi from '@/api/system/dict/dict.data'
|
||||
const typeMenu = ref<DictDataApi.DictDataVO[]>([]) //
|
||||
const targetMenuId = ref('0')
|
||||
defineOptions({ name: 'InfraFile' })
|
||||
const showActions = ref(null);
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const dialogVisibles = ref(false) // 弹窗的是否展示
|
||||
const dialogTitles = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const panduan = ref('1')
|
||||
const tubiaoData = ref<FileDataVO[]>([]);
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
sort: undefined,
|
||||
label: '',
|
||||
value: '',
|
||||
dictType: '',
|
||||
// status: CommonStatusEnum.ENABLE,
|
||||
colorType: '',
|
||||
cssClass: '',
|
||||
remark: ''
|
||||
})
|
||||
const formRules = reactive({
|
||||
label: [{ required: true, message: '数据标签不能为空', trigger: 'blur' }],
|
||||
sort: [{ required: true, message: '数据顺序不能为空', trigger: 'blur' }],
|
||||
})
|
||||
const updateLabel = ref('')
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref([]) // 列表的
|
||||
const menuId = ref()
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref([]) // 列表的
|
||||
const menuId = ref()
|
||||
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: undefined,
|
||||
type: undefined,
|
||||
picType: '',
|
||||
path: undefined,
|
||||
createTime: [],
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: undefined,
|
||||
type: undefined,
|
||||
picType: '',
|
||||
path: undefined,
|
||||
createTime: [],
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await FileApi.getFilePage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await FileApi.getFilePage(queryParams)
|
||||
list.value = data.list
|
||||
tubiaoData.value = data.list
|
||||
console.log('111111',tubiaoData)
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
interface FileDataVO {
|
||||
id: string
|
||||
configId: string
|
||||
path: string
|
||||
name: string
|
||||
url: string
|
||||
type: string
|
||||
picType: string
|
||||
size: string
|
||||
createTime: Date
|
||||
}
|
||||
|
||||
//新增分类
|
||||
const createType = () => {
|
||||
dialogVisibles.value = true
|
||||
dialogTitles.value = '新增分类'
|
||||
const tubiao = () => {
|
||||
panduan.value = '2'
|
||||
}
|
||||
|
||||
}
|
||||
const liebiao = () => {
|
||||
panduan.value = '1'
|
||||
}
|
||||
|
||||
/** 添加分类菜单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as DictDataApi.DictDataVO
|
||||
await DictDataApi.createPicType(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
dialogVisibles.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
getTypeList()
|
||||
//新增分类
|
||||
const createType = () => {
|
||||
dialogVisibles.value = true
|
||||
dialogTitles.value = '新增分类'
|
||||
}
|
||||
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
/** 添加分类菜单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as DictDataApi.DictDataVO
|
||||
await DictDataApi.createPicType(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
dialogVisibles.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
getTypeList()
|
||||
|
||||
//修改分类菜单
|
||||
const submitForms = async () => {
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
await DictDataApi.updateMenu(menuId.value, updateLabel.value)
|
||||
message.success(t('common.createSuccess'))
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
getTypeList()
|
||||
//修改分类菜单
|
||||
const submitForms = async () => {
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
await DictDataApi.updateMenu(menuId.value, updateLabel.value)
|
||||
message.success(t('common.createSuccess'))
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
getTypeList()
|
||||
|
||||
//分类菜单修改按钮
|
||||
const editItem = (id : number | undefined, lable : string) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '菜单编辑'
|
||||
menuId.value = id
|
||||
updateLabel.value = lable
|
||||
// 处理编辑事件
|
||||
console.log('编辑:',);
|
||||
};
|
||||
//分类菜单删除按钮
|
||||
const deleteItem = async (id : number | undefined) => {
|
||||
// 处理删除事件
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
await DictDataApi.deleteMenu(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
getTypeList()
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
//图片素材管理分类菜单
|
||||
const getTypeList = async () => {
|
||||
const data = await DictDataApi.getTypeList()
|
||||
typeMenu.value = data
|
||||
console.log('1111111111', typeMenu)
|
||||
}
|
||||
//分类菜单修改按钮
|
||||
const editItem = (id : number | undefined, lable : string) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '菜单编辑'
|
||||
menuId.value = id
|
||||
updateLabel.value = lable
|
||||
// 处理编辑事件
|
||||
console.log('编辑:',);
|
||||
};
|
||||
//分类菜单删除按钮
|
||||
const deleteItem = async (id : number | undefined) => {
|
||||
// 处理删除事件
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
await DictDataApi.deleteMenu(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
getTypeList()
|
||||
|
||||
};
|
||||
//图片素材管理分类菜单
|
||||
const getTypeList = async () => {
|
||||
const data = await DictDataApi.getTypeList()
|
||||
typeMenu.value = data
|
||||
}
|
||||
|
||||
|
||||
/** */
|
||||
const clickMenu = (id : string) => {
|
||||
queryParams.picType = id
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
/** */
|
||||
const clickMenu = (id : string) => {
|
||||
queryParams.picType = id
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
|
||||
const formRef = ref()
|
||||
const openForm = () => {
|
||||
formRef.value.open()
|
||||
}
|
||||
const formRef = ref()
|
||||
const openForm = () => {
|
||||
formRef.value.open()
|
||||
}
|
||||
|
||||
const forRef = ref()
|
||||
/** 修改操作 */
|
||||
const updateForm = (type : string, id : number, picType : number) => {
|
||||
forRef.value.open(type, id, picType)
|
||||
}
|
||||
const forRef = ref()
|
||||
/** 修改操作 */
|
||||
const updateForm = (type : string, id : number, picType : number) => {
|
||||
forRef.value.open(type, id, picType)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id : number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await FileApi.deleteFile(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch { }
|
||||
}
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id : number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await FileApi.deleteFile(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch { }
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
queryParams.picType = targetMenuId.value
|
||||
getTypeList()
|
||||
getList()
|
||||
})
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
queryParams.picType = targetMenuId.value
|
||||
getTypeList()
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
.flex-container {
|
||||
height: 100vh;
|
||||
/* 使容器填满视口高度 */
|
||||
display: flex;
|
||||
}
|
||||
.flex-container {
|
||||
height: 100vh;
|
||||
/* 使容器填满视口高度 */
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.menu-area {
|
||||
padding: 25px;
|
||||
background-color: white;
|
||||
width: 180px;
|
||||
height: 1000px;
|
||||
/* 固定高度 */
|
||||
overflow-y: hidden;
|
||||
/* 禁止滚动 */
|
||||
border-right: 1px solid #e0e0e0;
|
||||
/* 可选:添加分隔线 */
|
||||
}
|
||||
.menu-area {
|
||||
padding: 25px;
|
||||
background-color: white;
|
||||
width: 180px;
|
||||
height: 1000px;
|
||||
/* 固定高度 */
|
||||
overflow-y: hidden;
|
||||
/* 禁止滚动 */
|
||||
border-right: 1px solid #e0e0e0;
|
||||
/* 可选:添加分隔线 */
|
||||
}
|
||||
|
||||
.content-wrap {
|
||||
flex-grow: 1;
|
||||
/* 使内容区域占据剩余空间 */
|
||||
overflow-y: auto;
|
||||
/* 允许内容区域滚动 */
|
||||
}
|
||||
</style>
|
||||
.content-wrap {
|
||||
flex-grow: 1;
|
||||
/* 使内容区域占据剩余空间 */
|
||||
overflow-y: auto;
|
||||
/* 允许内容区域滚动 */
|
||||
}
|
||||
|
||||
|
||||
/* 图片容器样式 */
|
||||
.image-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px; /* 设置图片之间的间距 */
|
||||
justify-content: flex-start; /* 如果图片少于5张,会平均分布 */
|
||||
max-width: 1000px; /* 设置外部容器的最大宽度 */
|
||||
margin: 0 auto; /* 居中显示 */
|
||||
}
|
||||
|
||||
/* 每张图片占用的宽度,使每行显示5张 */
|
||||
.image-item {
|
||||
width: calc(20% - 8px); /* 宽度设为容器的20%,减去间距 */
|
||||
}
|
||||
|
||||
/* 设置图片的最大宽度 */
|
||||
.image-item img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 8px; /* 图片边缘圆角(可选) */
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
@ -67,9 +67,9 @@
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['promotion:auto-response:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增自动恢复
|
||||
</el-button>
|
||||
<el-button
|
||||
<!-- <el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
@ -77,7 +77,7 @@
|
||||
v-hasPermi="['promotion:auto-response:export']"
|
||||
>
|
||||
<Icon icon="ep:download" class="mr-5px" /> 导出
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
@ -0,0 +1,124 @@
|
||||
<template>
|
||||
<div class="main">
|
||||
<div class="mainTop">
|
||||
<div>商品分类</div>
|
||||
<div class="right">
|
||||
<div class="save" @click="save">保存</div>
|
||||
<div class="cz" @click="cz">重置</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mainBottom">
|
||||
<div class='item' :class="currItem == 1 ? 'on': ''" @click="clickItem(1)">
|
||||
<img class="img" src="https://zysc.fjptzykj.com:3000/shangcheng/a7d0409cbf5335a2780409756914c530fc7c88bec85fc81302b53760d9be4a03.jpg" />
|
||||
<div class="text">样式1</div>
|
||||
</div>
|
||||
<div class='item' :class="currItem == 2 ? 'on': ''" @click="clickItem(2)">
|
||||
<img class="img" src="https://zysc.fjptzykj.com:3000/shangcheng/9096b2c04a6e46ea562999a93a1b975100c6b4557e680dcb31de6d3555407841.png" />
|
||||
<div class="text">样式2</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
// TODO @疯狂:要不要建个 decorate 目录,然后挪进去,改成 index.vue,这样可以更明确看到是个独立界面哈,更好找
|
||||
import * as DiyTemplateApi from '@/api/mall/promotion/diy/template'
|
||||
import { useTagsdivStore } from '@/store/modules/tagsdiv'
|
||||
import { DiyComponentLibrary, PAGE_LIBS } from '@/components/DiyEditor/util' // 商城的 DIY 组件,在 DiyEditor 目录下
|
||||
import { toNumber } from 'lodash-es'
|
||||
const message = useMessage() // 消息弹窗
|
||||
const currItem = ref();
|
||||
|
||||
function clickItem (val){
|
||||
currItem.value = val;
|
||||
}
|
||||
|
||||
function cz (val){
|
||||
currItem.value = 1;
|
||||
}
|
||||
|
||||
function save (){
|
||||
setProjuctClass(currItem.value);
|
||||
// console.log("请求接口还没有写啊!!!!快让后端提供啊")
|
||||
}
|
||||
|
||||
// 设置商品分类
|
||||
const setProjuctClass = async (id) => {
|
||||
const res = await DiyTemplateApi.setDiyProjuctClass(id);
|
||||
console.log(res, "sssss");
|
||||
if(res){
|
||||
message.success('保存成功')
|
||||
}
|
||||
}
|
||||
|
||||
// 获取商品分类
|
||||
const getProjuctClass = async () => {
|
||||
const res = await DiyTemplateApi.getDiyProjuctClass();
|
||||
currItem.value = res
|
||||
}
|
||||
getProjuctClass()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.main{
|
||||
display:flex;
|
||||
flex-wrap:wrap;
|
||||
.mainTop{
|
||||
width:100%;
|
||||
margin:10px 10px;
|
||||
background:white;
|
||||
padding:10px 20px;
|
||||
font-weight:700;
|
||||
display:flex;
|
||||
justify-content:space-between;
|
||||
align-items: center;
|
||||
.right{
|
||||
display:flex;
|
||||
div{
|
||||
padding:5px 15px;
|
||||
font-weight:400;
|
||||
font-size: 14px;
|
||||
}
|
||||
.save{
|
||||
background:#0256FF;
|
||||
margin-right:10px;
|
||||
color:white;
|
||||
cursor: pointer;
|
||||
}
|
||||
.cz{
|
||||
border:1px solid #cccccc;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
.mainBottom{
|
||||
width:100%;
|
||||
margin:10px 10px;
|
||||
background:white;
|
||||
padding:30px 30px;
|
||||
display:flex;
|
||||
.item{
|
||||
margin-right:20px;
|
||||
text-align: center;
|
||||
border-radius: 12px;
|
||||
cursor: pointer;
|
||||
&.on{
|
||||
.text{
|
||||
color:#0256ff;
|
||||
}
|
||||
.img{
|
||||
border:2px solid #0256ff;
|
||||
}
|
||||
}
|
||||
.img{
|
||||
width:260px;
|
||||
border-radius: 12px;
|
||||
border:2px solid white;
|
||||
}
|
||||
.text{
|
||||
margin-top:10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,195 @@
|
||||
<template>
|
||||
<div class="main">
|
||||
<div class="mainTop">
|
||||
<div>主题风格</div>
|
||||
<div class="right">
|
||||
<div class="save" @click="save">保存</div>
|
||||
<!-- <div class="cz" @click="cz">重置</div> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ztfg">
|
||||
<div class='top'>
|
||||
<div class="item" :class="currItem== '' ? 'on': ''" @click="clickItem('')">
|
||||
<div class="le" style="background: rgb(233, 52, 34);"></div>
|
||||
<div class="ri">红色</div>
|
||||
</div>
|
||||
<div class="item" :class="currItem== 'blue' ? 'on': ''" @click="clickItem('blue')">
|
||||
<div class="le"></div>
|
||||
<div class="ri">天空蓝</div>
|
||||
</div>
|
||||
<div class="item" :class="currItem== 'lv' ? 'on': ''" @click="clickItem('lv')">
|
||||
<div class="le" style="background:rgb(66, 202, 77);"></div>
|
||||
<div class="ri">生鲜绿</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mainBottom">
|
||||
<div class='item' v-show="currItem== ''">
|
||||
<img class="img"
|
||||
src="https://zysc.fjptzykj.com:3000/shangcheng/667bbed3e719df73217b10d743eb880c1719cb294b6f50a81f78f597fdbcf351.png" style="width:300px;" />
|
||||
</div>
|
||||
|
||||
<div class='item' v-show="currItem== 'blue'">
|
||||
<img class="img"
|
||||
src="https://zysc.fjptzykj.com:3000/shangcheng/4bffe9f0cee9605262a579ee45156c9e37a16e2a24035a0e49b8a4433075f793.jpg" />
|
||||
</div>
|
||||
<div class='item' v-show="currItem== 'lv'">
|
||||
<img class="img"
|
||||
src="https://zysc.fjptzykj.com:3000/shangcheng/0d0a7ab210afb5cee674e402ca3ec197a30523687acbec2e8e5f16fb52075e9b.jpg" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
// TODO @疯狂:要不要建个 decorate 目录,然后挪进去,改成 index.vue,这样可以更明确看到是个独立界面哈,更好找
|
||||
import * as DiyTemplateApi from '@/api/mall/promotion/diy/template'
|
||||
import * as DiyPageApi from '@/api/mall/promotion/diy/page'
|
||||
import { useTagsdivStore } from '@/store/modules/tagsdiv'
|
||||
import { DiyComponentLibrary, PAGE_LIBS } from '@/components/DiyEditor/util' // 商城的 DIY 组件,在 DiyEditor 目录下
|
||||
import { toNumber } from 'lodash-es'
|
||||
const message = useMessage() // 消息弹窗
|
||||
const currItem = ref('blue');
|
||||
|
||||
function clickItem(val) {
|
||||
currItem.value = val;
|
||||
}
|
||||
|
||||
function cz(val) {
|
||||
currItem.value = 'blue';
|
||||
}
|
||||
|
||||
function save() {
|
||||
const val = '';
|
||||
// currItem.value = val;
|
||||
if(currItem.value == 'lv'){
|
||||
setZtClass('lv')
|
||||
}else if(currItem.value == 'blue'){
|
||||
setZtClass('blue')
|
||||
}else{
|
||||
setZtClass('')
|
||||
}
|
||||
// console.log("请求接口还没有写啊!!!!快让后端提供啊")
|
||||
}
|
||||
|
||||
// 设置主题风格
|
||||
const setZtClass = async (id) => {
|
||||
const res = await DiyTemplateApi.setDiyZtClass(id);
|
||||
console.log(res, "sssss");
|
||||
if(res || res == ''){
|
||||
message.success('保存成功')
|
||||
}
|
||||
}
|
||||
|
||||
// 获取商品分类
|
||||
const getZtClass = async () => {
|
||||
const res = await DiyTemplateApi.getDiyZtClass();
|
||||
currItem.value = res
|
||||
}
|
||||
getZtClass()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.main {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.mainTop {
|
||||
width: 100%;
|
||||
margin: 10px 10px;
|
||||
background: white;
|
||||
padding: 10px 20px;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
|
||||
div {
|
||||
padding: 5px 15px;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.save {
|
||||
background: #0256FF;
|
||||
margin-right: 10px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cz {
|
||||
border: 1px solid #cccccc;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ztfg {
|
||||
width: 100%;
|
||||
margin: 10px 10px;
|
||||
background: white;
|
||||
padding: 30px 30px;
|
||||
.top{
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
.item{
|
||||
padding:10px 15px;
|
||||
border:1px solid #cccccc;
|
||||
border-radius:6px;
|
||||
margin-right:10px;
|
||||
display:flex;
|
||||
align-items:center;
|
||||
cursor: pointer;
|
||||
&.on{
|
||||
border:1px solid #0256ff;
|
||||
}
|
||||
.le{
|
||||
margin-right:10px;
|
||||
border-radius:6px;
|
||||
width:25px;
|
||||
height:25px;
|
||||
background:rgb(28, 165, 233);
|
||||
}
|
||||
.ti{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.mainBottom {
|
||||
|
||||
display: flex;
|
||||
|
||||
.item {
|
||||
margin-right: 20px;
|
||||
text-align: center;
|
||||
border-radius: 12px;
|
||||
|
||||
// &.on {
|
||||
// .text {
|
||||
// color: #0256ff;
|
||||
// }
|
||||
|
||||
// .img {
|
||||
// border: 2px solid #0256ff;
|
||||
// }
|
||||
// }
|
||||
|
||||
.img {
|
||||
width: 800px;
|
||||
border-radius: 12px;
|
||||
border: 2px solid white;
|
||||
}
|
||||
|
||||
.text {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="kefu">
|
||||
|
||||
<div
|
||||
v-for="item in conversationList"
|
||||
:key="item.id"
|
||||
@ -9,7 +10,7 @@
|
||||
@contextmenu.prevent="rightClick($event as PointerEvent, item)"
|
||||
>
|
||||
<div class="flex justify-center items-center w-100%">
|
||||
<div class="flex justify-center items-center w-50px h-50px">
|
||||
<div class="flex justify-center items-center w-40px h-40px">
|
||||
<!-- 头像 + 未读 -->
|
||||
<el-badge
|
||||
:hidden="item.adminUnreadMessageCount === 0"
|
||||
@ -19,10 +20,10 @@
|
||||
<el-avatar :src="item.userAvatar" alt="avatar" />
|
||||
</el-badge>
|
||||
</div>
|
||||
<div class="ml-10px w-100%">
|
||||
<div class="flex justify-between items-center w-100%">
|
||||
<div class="ml-3px w-full">
|
||||
<div class="flex justify-between items-center w-full">
|
||||
<span class="username">{{ item.userNickname }}</span>
|
||||
<span class="color-[var(--left-menu-text-color)]" style="font-size: 13px">
|
||||
<span class="color-[var(--left-menu-text-color)]" style="font-size: 12px">
|
||||
{{ formatPast(item.lastMessageTime, 'YYYY-MM-DD') }}
|
||||
</span>
|
||||
</div>
|
||||
@ -182,12 +183,13 @@ watch(showRightMenu, (val) => {
|
||||
<style lang="scss" scoped>
|
||||
.kefu {
|
||||
&-conversation {
|
||||
height: 60px;
|
||||
padding: 10px;
|
||||
height: 55px;
|
||||
padding: 8px;
|
||||
//background-color: #fff;
|
||||
transition: border-left 0.05s ease-in-out; /* 设置过渡效果 */
|
||||
|
||||
.username {
|
||||
font-size: 20%;
|
||||
min-width: 0;
|
||||
max-width: 60%;
|
||||
overflow: hidden;
|
||||
@ -198,7 +200,7 @@ watch(showRightMenu, (val) => {
|
||||
}
|
||||
|
||||
.last-message {
|
||||
font-size: 13px;
|
||||
font-size: 15px;
|
||||
width: 200px;
|
||||
overflow: hidden; // 隐藏超出的文本
|
||||
white-space: nowrap; // 禁止换行
|
||||
|
@ -1,17 +1,18 @@
|
||||
<template>
|
||||
<el-container v-if="showKeFuMessageList" class="kefu">
|
||||
<el-header>
|
||||
<!-- <el-header>
|
||||
<div class="kefu-title">{{ conversation.userNickname }}</div>
|
||||
</el-header>
|
||||
</el-header> -->
|
||||
<el-main class="kefu-content overflow-visible">
|
||||
<el-scrollbar ref="scrollbarRef" always height="calc(100vh - 495px)" @scroll="handleScroll">
|
||||
<el-scrollbar ref="scrollbarRef" always height="calc(100vh - 390px)" @scroll="handleScroll">
|
||||
<div v-if="refreshContent" ref="innerRef" class="w-[100%] pb-3px">
|
||||
|
||||
|
||||
<!-- 消息列表 -->
|
||||
<div v-for="(item, index) in getMessageList0" :key="item.id" class="w-[100%]">
|
||||
<div class="flex justify-center items-center mb-20px">
|
||||
<!-- 日期 -->
|
||||
<div
|
||||
v-if="
|
||||
<div v-if="
|
||||
item.contentType !== KeFuMessageContentTypeEnum.SYSTEM && showTime(item, index)
|
||||
" class="date-message">
|
||||
{{ formatDate(item.createTime) }}
|
||||
@ -21,19 +22,18 @@ v-if="
|
||||
{{ item.content }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
:class="[
|
||||
|
||||
|
||||
<div :class="[
|
||||
item.senderType === UserTypeEnum.MEMBER
|
||||
? `ss-row-left`
|
||||
: item.senderType === UserTypeEnum.ADMIN
|
||||
? `ss-row-right`
|
||||
: ''
|
||||
]" class="flex mb-20px w-[100%]">
|
||||
<el-avatar
|
||||
v-if="item.senderType === UserTypeEnum.MEMBER" :src="conversation.userAvatar"
|
||||
<el-avatar v-if="item.senderType === UserTypeEnum.MEMBER" :src="conversation.userAvatar"
|
||||
alt="avatar" class="w-60px h-60px" />
|
||||
<div
|
||||
:class="{ 'kefu-message': KeFuMessageContentTypeEnum.TEXT === item.contentType }"
|
||||
<div :class="{ 'kefu-message': KeFuMessageContentTypeEnum.TEXT === item.contentType }"
|
||||
class="p-10px">
|
||||
<!-- 文本消息 -->
|
||||
<MessageItem :message="item">
|
||||
@ -44,15 +44,13 @@ v-if="item.senderType === UserTypeEnum.MEMBER" :src="conversation.userAvatar"
|
||||
</MessageItem>
|
||||
<!-- 图片消息 -->
|
||||
<MessageItem :message="item">
|
||||
<el-image
|
||||
v-if="KeFuMessageContentTypeEnum.IMAGE === item.contentType"
|
||||
<el-image v-if="KeFuMessageContentTypeEnum.IMAGE === item.contentType"
|
||||
:initial-index="0" :preview-src-list="[item.content]" :src="item.content"
|
||||
class="w-200px" fit="contain" preview-teleported />
|
||||
</MessageItem>
|
||||
<!-- 商品消息 -->
|
||||
<MessageItem :message="item">
|
||||
<ProductItem
|
||||
v-if="KeFuMessageContentTypeEnum.PRODUCT === item.contentType"
|
||||
<ProductItem v-if="KeFuMessageContentTypeEnum.PRODUCT === item.contentType"
|
||||
:spuId="getMessageContent(item).spuId" :picUrl="getMessageContent(item).picUrl"
|
||||
:price="getMessageContent(item).price"
|
||||
:skuText="getMessageContent(item).introduction"
|
||||
@ -61,50 +59,53 @@ v-if="KeFuMessageContentTypeEnum.PRODUCT === item.contentType"
|
||||
</MessageItem>
|
||||
<!-- 订单消息 -->
|
||||
<MessageItem :message="item">
|
||||
<OrderItem
|
||||
v-if="KeFuMessageContentTypeEnum.ORDER === item.contentType"
|
||||
<OrderItem v-if="KeFuMessageContentTypeEnum.ORDER === item.contentType"
|
||||
:message="item" class="max-w-100%" />
|
||||
</MessageItem>
|
||||
</div>
|
||||
<el-avatar
|
||||
v-if="item.senderType === UserTypeEnum.ADMIN" :src="item.senderAvatar"
|
||||
<el-avatar v-if="item.senderType === UserTypeEnum.ADMIN" :src="item.senderAvatar"
|
||||
alt="avatar" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<div
|
||||
v-show="showNewMessageTip" class="newMessageTip flex items-center cursor-pointer"
|
||||
<div v-show="showNewMessageTip" class="newMessageTip flex items-center cursor-pointer"
|
||||
@click="handleToNewMessage">
|
||||
<span>有新消息</span>
|
||||
<Icon class="ml-5px" icon="ep:bottom" />
|
||||
</div>
|
||||
</el-main>
|
||||
<el-footer height="230px">
|
||||
|
||||
<el-divider style="margin: 4px 0;" />
|
||||
|
||||
<el-footer height="185px">
|
||||
<div class="h-[100%]">
|
||||
<div class="chat-tools flex items-center">
|
||||
<div class="flex items-center">
|
||||
<EmojiSelectPopover @select-emoji="handleEmojiSelect" />
|
||||
<PictureSelectUpload class="ml-15px mt-3px cursor-pointer" @send-picture="handleSendPicture" />
|
||||
<!-- <VerbalTrick class="ml-11px mt-5px cursor-pointer" /> -->
|
||||
<!-- 话术库 -->
|
||||
<div style="margin-left: 9px; margin-top:5px;cursor: pointer;">
|
||||
<img :src="Picture" class="w-32px h-32px" @click="huashu" />
|
||||
<div style="margin-left: 15px; margin-top:4px;cursor: pointer;">
|
||||
<img :src="xiaoxi" class="w-22px h-22px" @click="huashu" />
|
||||
</div>
|
||||
<!-- 转接按钮 -->
|
||||
<el-dropdown placement="top" style="margin-left: auto;margin-right: 15px; margin-top:5px;margin-top:5px;cursor: pointer;" ref="dropdown1" trigger="contextmenu">
|
||||
<el-dropdown placement="top"
|
||||
style="margin-left: auto;margin-right: 15px;cursor: pointer;"
|
||||
ref="dropdown1" trigger="contextmenu">
|
||||
<div>
|
||||
<img :src="Picture2" class="w-27px h-27px" @click="getOnlineStaffList" title="转接"/>
|
||||
<img :src="Picture2" class="w-62px h-20px" @click="getOnlineStaffList" title="转接" />
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-item v-for="staff in onlineStaffList" :key="staff.id" :disabled="staff.id===getStaffToken()" @click="transferConversion(staff.id)">
|
||||
<el-dropdown-item v-for="staff in onlineStaffList" :key="staff.id"
|
||||
:disabled="staff.id===getStaffToken()" @click="transferConversion(staff.id)">
|
||||
{{ staff.name }}
|
||||
</el-dropdown-item>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
|
||||
|
||||
</div>
|
||||
<el-input v-model="message" :rows="6" style="border-style: none" type="textarea" />
|
||||
<br/>
|
||||
<textarea style="border: none; outline: none;" v-model="message" placeholder="请输入文字内容" rows="5" cols="75"></textarea>
|
||||
<div class="h-45px flex justify-end">
|
||||
<el-button class="mt-10px" type="primary" @click="handleSendMessage">发送</el-button>
|
||||
</div>
|
||||
@ -120,12 +121,15 @@ v-show="showNewMessageTip" class="newMessageTip flex items-center cursor-pointer
|
||||
<!-- 左边占 30% -->
|
||||
<div style="flex: 0 0 20%; padding: 10px;">
|
||||
<el-menu :default-active="targetMenuId">
|
||||
<el-menu-item v-for="item in huashuType" :index="item.value" :key="item.value" @click="clickMenu(item.value)">{{item.label}}</el-menu-item>
|
||||
<el-menu-item v-for="item in huashuType" :index="item.value" :key="item.value"
|
||||
@click="clickMenu(item.value)">{{item.label}}</el-menu-item>
|
||||
</el-menu>
|
||||
</div>
|
||||
<!-- 右边占 70% -->
|
||||
<div style="flex: 1; padding: 5px; overflow-y: auto; max-height: 400px;">
|
||||
<p v-for="item in verbalTrickList" :key="item.id" style="font-size: 12px;cursor: pointer;transition: background-color 0.3s;" class="hover-shadow" @click="huashuClick(item.details)">
|
||||
<p v-for="item in verbalTrickList" :key="item.id"
|
||||
style="font-size: 12px;cursor: pointer;transition: background-color 0.3s;" class="hover-shadow"
|
||||
@click="huashuClick(item.details)">
|
||||
{{item.details}}
|
||||
</p>
|
||||
</div>
|
||||
@ -143,7 +147,8 @@ v-show="showNewMessageTip" class="newMessageTip flex items-center cursor-pointer
|
||||
import PictureSelectUpload from './tools/PictureSelectUpload.vue'
|
||||
// import VerbalTrick from './tools/VerbalTrick.vue'
|
||||
import Picture from '@/views/mall/promotion/kefu/components/asserts/huashu.png'
|
||||
import Picture2 from '@/views/mall/promotion/kefu/components/asserts/zhuanjie.png'
|
||||
import xiaoxi from '@/views/mall/promotion/kefu/components/asserts/xiaoxi.png'
|
||||
import Picture2 from '@/views/mall/promotion/kefu/components/asserts/zj.png'
|
||||
import ProductItem from './message/ProductItem.vue'
|
||||
import OrderItem from './message/OrderItem.vue'
|
||||
import { Emoji, useEmoji } from './tools/emoji'
|
||||
@ -155,11 +160,11 @@ v-show="showNewMessageTip" class="newMessageTip flex items-center cursor-pointer
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import { debounce } from 'lodash-es'
|
||||
import { jsonParse } from '@/utils'
|
||||
import { getStaffToken, setStaffToken} from '@/utils/auth'
|
||||
import { getStaffToken, setStaffToken } from '@/utils/auth'
|
||||
import type { DropdownInstance } from 'element-plus'
|
||||
import { ref } from 'vue'
|
||||
|
||||
|
||||
|
||||
|
||||
import * as DictDataApi from '@/api/system/dict/dict.data'
|
||||
const huashuType = ref<DictDataApi.DictDataVO[]>([]) //
|
||||
const targetMenuId = ref('0')
|
||||
@ -170,7 +175,7 @@ v-show="showNewMessageTip" class="newMessageTip flex items-center cursor-pointer
|
||||
let dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('客服话术') // 客服话术库弹窗标题
|
||||
// 话术库的数据
|
||||
const verbalTrickList = ref<VerbalTrickVO[]>([])
|
||||
const verbalTrickList = ref<VerbalTrickVO[]>([])
|
||||
const message = ref('') // 消息弹窗
|
||||
const { replaceEmoji } = useEmoji()
|
||||
const messageTool = useMessage()
|
||||
@ -178,10 +183,12 @@ v-show="showNewMessageTip" class="newMessageTip flex items-center cursor-pointer
|
||||
const conversation = ref<KeFuConversationRespVO>({} as KeFuConversationRespVO) // 用户会话
|
||||
const showNewMessageTip = ref(false) // 显示有新消息提示
|
||||
import { SupportStaffApi, SupportStaffVO } from '@/api/mall/promotion/supportstaff' // 客服列表接口
|
||||
import { KeFuConversationApi} from '@/api/mall/promotion/kefu/conversation'
|
||||
import { KeFuConversationApi } from '@/api/mall/promotion/kefu/conversation'
|
||||
import { number } from 'vue-types'
|
||||
const onlineStaffList = ref<SupportStaffVO[]>([]) // 在线客服列表的数据
|
||||
|
||||
const messages = useMessage() // 消息弹窗
|
||||
const kefuName = ref('')
|
||||
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
@ -253,6 +260,7 @@ v-show="showNewMessageTip" class="newMessageTip flex items-center cursor-pointer
|
||||
/** 获得新会话的消息列表 */
|
||||
// TODO @puhui999:可优化:可以考虑本地做每个会话的消息 list 缓存;然后点击切换时,读取缓存;然后异步获取新消息,merge 下;
|
||||
const getNewMessageList = async (val : KeFuConversationRespVO) => {
|
||||
// console.log('22222222',val)
|
||||
// 会话切换,重置相关参数
|
||||
queryParams.pageNo = 1
|
||||
messageList.value = []
|
||||
@ -297,25 +305,24 @@ v-show="showNewMessageTip" class="newMessageTip flex items-center cursor-pointer
|
||||
//话术分类菜单
|
||||
const getHuaShuTypeList = async () => {
|
||||
const data = await DictDataApi.getHuaShuTypeList()
|
||||
huashuType.value = data
|
||||
huashuType.value = data
|
||||
}
|
||||
//话术内容
|
||||
const getVerbalTrickList = async (id: string) => {
|
||||
const getVerbalTrickList = async (id : string) => {
|
||||
const response = await VerbalTrickApi.getVerbalTrickList(id);
|
||||
verbalTrickList.value = response; // 将数据部分赋值给 verbalTrickList
|
||||
}
|
||||
|
||||
|
||||
verbalTrickList.value = response; // 将数据部分赋值给 verbalTrickList
|
||||
}
|
||||
|
||||
|
||||
/*选择话术库内容*/
|
||||
const huashuClick = (content: string) => {
|
||||
const huashuClick = (content : string) => {
|
||||
message.value = content;
|
||||
dialogVisible.value = false;
|
||||
}
|
||||
const clickMenu = (id: string) => {
|
||||
console.log('1111111111',id)
|
||||
const clickMenu = (id : string) => {
|
||||
getVerbalTrickList(id)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** 发送文本消息 */
|
||||
const handleSendMessage = async () => {
|
||||
@ -420,14 +427,26 @@ v-show="showNewMessageTip" class="newMessageTip flex items-center cursor-pointer
|
||||
status: 1,
|
||||
})
|
||||
onlineStaffList.value = data.list
|
||||
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** 转接客服人员列表 id:会话id kefuId:客服人员id */
|
||||
const transferConversion = async (kefuId: number) => {
|
||||
const transferConversion = async (kefuId : number) => {
|
||||
try {
|
||||
await KeFuConversationApi.transferConversion(queryParams.conversationId, kefuId)
|
||||
const re = await KeFuConversationApi.transferConversion(queryParams.conversationId, kefuId)
|
||||
kefuName.value = re
|
||||
// 2. 组织发送消息
|
||||
const msg = {
|
||||
conversationId: conversation.value.id,
|
||||
contentType: KeFuMessageContentTypeEnum.SYSTEM,
|
||||
content: '已为您转接至' + re,
|
||||
}
|
||||
await sendMessage(msg)
|
||||
messages.success('转接成功')
|
||||
|
||||
conversation.value = null
|
||||
} finally {
|
||||
// todo 刷新会话列表
|
||||
}
|
||||
@ -435,15 +454,20 @@ v-show="showNewMessageTip" class="newMessageTip flex items-center cursor-pointer
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getHuaShuTypeList()
|
||||
getVerbalTrickList(targetMenuId.value)
|
||||
getVerbalTrickList(targetMenuId.value)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
|
||||
|
||||
.hover-shadow:hover {
|
||||
background-color: lightgray; /* 可根据需要调整颜色 */
|
||||
background-color: lightgray;
|
||||
|
||||
/* 可根据需要调整颜色 */
|
||||
}
|
||||
|
||||
.kefu {
|
||||
&-title {
|
||||
border-bottom: #e4e0e0 solid 1px;
|
||||
@ -472,6 +496,7 @@ v-show="showNewMessageTip" class="newMessageTip flex items-center cursor-pointer
|
||||
.kefu-message {
|
||||
margin-left: 20px;
|
||||
position: relative;
|
||||
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
@ -487,8 +512,8 @@ v-show="showNewMessageTip" class="newMessageTip flex items-center cursor-pointer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.ss-row-right {
|
||||
justify-content: flex-end;
|
||||
@ -514,7 +539,7 @@ v-show="showNewMessageTip" class="newMessageTip flex items-center cursor-pointer
|
||||
|
||||
// 消息气泡
|
||||
.kefu-message {
|
||||
color: #a9a9a9;
|
||||
color: #101010;
|
||||
border-radius: 5px;
|
||||
box-shadow: 3px 3px 5px rgba(220, 220, 220, 0.1);
|
||||
padding: 5px 10px;
|
||||
|
@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div style="height: 522px ;" ref="userInfoRef" >
|
||||
<div>
|
||||
<span style="display: flex;">
|
||||
<el-avatar
|
||||
style="border: 1px solid #f8f9ee;"
|
||||
src="https://zysc.fjptzykj.com:3000/shangcheng/29e07b7973621a1a9679744e18f2b4efd1fd50d857fe594879e813d67be3e2db.png"
|
||||
/>
|
||||
<span style="margin-left:5px;margin-top: 9px;">Marvin</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;" />
|
||||
<div>
|
||||
<span style="color: #5d5d59;font-size: 13px ;">手机号</span><span style="margin-left: 47px;font-size: 14px ;">暂无</span>
|
||||
</div>
|
||||
<div style="margin-top: 5px;">
|
||||
<span style="color: #5d5d59;font-size: 13px ;">分组</span><span style="margin-left: 60px;font-size: 14px ;">D类客户</span>
|
||||
</div>
|
||||
<div style="margin-top: 5px;">
|
||||
<span style="color: #5d5d59;font-size: 13px ;">用户标签</span><span style="margin-left: 33px;font-size: 14px ;">小客户</span>
|
||||
</div>
|
||||
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;" />
|
||||
|
||||
<div>
|
||||
<span style="color: #5d5d59;font-size: 13px ;">用户等级</span><span style="margin-left: 35px;font-size: 14px ;">暂无</span>
|
||||
</div>
|
||||
<div style="margin-top: 5px;">
|
||||
<span style="color: #5d5d59;font-size: 13px ;">推荐人</span><span style="margin-left: 47px;font-size: 14px ;">客户</span>
|
||||
</div>
|
||||
<div style="margin-top: 5px;">
|
||||
<span style="color: #5d5d59;font-size: 13px ;">用户类型</span><span style="margin-left: 33px;font-size: 14px ;">小客户</span>
|
||||
</div>
|
||||
<div>
|
||||
<span style="color: #5d5d59;font-size: 13px ;">余额</span><span style="margin-left: 60px;font-size: 14px ;">暂无</span>
|
||||
</div>
|
||||
<div style="margin-top: 5px;">
|
||||
<span style="color: #5d5d59;font-size: 13px ;">推广员</span><span style="margin-left: 47px;font-size: 14px ;">客户</span>
|
||||
</div>
|
||||
<div style="margin-top: 5px;">
|
||||
<span style="color: #5d5d59;font-size: 13px ;">生日</span><span style="margin-left: 60px;font-size: 14px ;">小客户</span>
|
||||
</div>
|
||||
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script >
|
||||
import * as UserApi from '@/api/member/user'
|
||||
|
||||
|
||||
// const user = ref<UserApi.UserVO>({} as UserApi.UserVO)
|
||||
|
||||
|
||||
// const getUserId = async (id: string) => {
|
||||
// user.value = await UserApi.getUserInfo(id)
|
||||
// }
|
||||
// defineExpose({ getUserId })
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
Binary file not shown.
After Width: | Height: | Size: 994 B |
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
@ -1,7 +1,7 @@
|
||||
<!-- 目录是不是叫 member 好点。然后这个组件是 MemberInfo,里面有浏览足迹 -->
|
||||
<template>
|
||||
<div v-show="!isEmpty(conversation)" class="kefu">
|
||||
<div class="header-title h-60px flex justify-center items-center">他的足迹</div>
|
||||
<!-- <div class="header-title h-60px flex justify-center items-center">他的足迹</div> -->
|
||||
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
|
||||
<el-tab-pane label="最近浏览" name="a" />
|
||||
<el-tab-pane label="订单列表" name="b" />
|
||||
|
@ -1,5 +1,6 @@
|
||||
import KeFuConversationList from './KeFuConversationList.vue'
|
||||
import KeFuMessageList from './KeFuMessageList.vue'
|
||||
import MemberBrowsingHistory from './history/MemberBrowsingHistory.vue'
|
||||
import UserInfo from './UserInfo.vue'
|
||||
|
||||
export { KeFuConversationList, KeFuMessageList, MemberBrowsingHistory }
|
||||
export { KeFuConversationList, KeFuMessageList, MemberBrowsingHistory ,UserInfo}
|
||||
|
@ -2,7 +2,8 @@
|
||||
<template>
|
||||
<el-popover :width="500" placement="top" trigger="click">
|
||||
<template #reference>
|
||||
<Icon :size="30" class="ml-10px cursor-pointer" icon="twemoji:grinning-face" />
|
||||
<!-- <Icon :size="30" class="ml-10px cursor-pointer" icon="twemoji:grinning-face" /> -->
|
||||
<img :src="biaoqing" class="w-23px h-25px" />
|
||||
</template>
|
||||
<ElScrollbar height="300px">
|
||||
<ul class="ml-2 flex flex-wrap px-2">
|
||||
@ -26,8 +27,10 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineOptions({ name: 'EmojiSelectPopover' })
|
||||
import biaoqing from '@/views/mall/promotion/kefu/components/asserts/biaoqing.png'
|
||||
import { Emoji, useEmoji } from './emoji'
|
||||
|
||||
|
||||
const { getEmojiList } = useEmoji()
|
||||
const emojiList = computed(() => getEmojiList())
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
<!-- 图片选择 -->
|
||||
<template>
|
||||
<div>
|
||||
<img :src="Picture" class="w-35px h-35px" @click="selectAndUpload" />
|
||||
<img :src="tupian" class="w-23px h-23px" @click="selectAndUpload" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Picture from '@/views/mall/promotion/kefu/components/asserts/picture.svg'
|
||||
import tupian from '@/views/mall/promotion/kefu/components/asserts/tupian.png'
|
||||
import * as FileApi from '@/api/infra/file'
|
||||
|
||||
defineOptions({ name: 'PictureSelectUpload' })
|
||||
|
@ -1,53 +1,206 @@
|
||||
<template>
|
||||
<el-row :gutter="10" style="display: flex; justify-content: center;">
|
||||
<!-- 会话列表 -->
|
||||
<el-col :span="5" >
|
||||
<ContentWrap>
|
||||
<KeFuConversationList ref="keFuConversationRef" @change="handleChange" />
|
||||
</ContentWrap>
|
||||
</el-col>
|
||||
<!-- 会话详情(选中会话的消息列表) -->
|
||||
<el-col :span="10">
|
||||
<ContentWrap>
|
||||
<KeFuMessageList ref="keFuChatBoxRef" @change="getConversationList" />
|
||||
</ContentWrap>
|
||||
</el-col>
|
||||
<!-- 会员足迹(选中会话的会员足迹) -->
|
||||
<el-col :span="5">
|
||||
<ContentWrap>
|
||||
<MemberBrowsingHistory ref="memberBrowsingHistoryRef" />
|
||||
</ContentWrap>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div>
|
||||
<!-- 新区域,放在头部 -->
|
||||
<el-row style="display: flex; justify-content: center;">
|
||||
|
||||
<el-col :span="24">
|
||||
<div style="width:100%;height:70px;background-color:#3c80ff;">
|
||||
<el-row>
|
||||
<el-col :span="6">
|
||||
<el-input
|
||||
style="width: 80%;margin-top: 20px;margin-left:10px;"
|
||||
:suffix-icon="Search"
|
||||
/>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="6">
|
||||
<span style="display: flex; margin-top: 15px;">
|
||||
<el-avatar
|
||||
:src="pic"
|
||||
/>
|
||||
<span style="margin-left:5px;margin-top: 9px;">{{name}}</span>
|
||||
<!-- <el-switch
|
||||
style="margin-top: 4px;--el-switch-on-color: #13ce66; --el-switch-off-color: #b6bac1;"
|
||||
v-model="value6"
|
||||
class="ml-2"
|
||||
width="60"
|
||||
inline-prompt
|
||||
active-text="在线"
|
||||
inactive-text="下线"
|
||||
/> -->
|
||||
</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-button @click="out" size="small" round style="margin-top:23px;margin-left:75%">退出</el-button>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="6">
|
||||
<el-menu
|
||||
background-color="#3c80ff"
|
||||
text-color="white"
|
||||
active-text-color="white"
|
||||
style="width:100%;display: flex;"
|
||||
>
|
||||
<el-menu-item @click="userInfo" style="width:33%;height:70px" index="1">客户信息</el-menu-item>
|
||||
<el-menu-item @click="zuoji" style="width:33%;height:70px" index="2">他的足迹</el-menu-item>
|
||||
<!-- <el-menu-item style="width:34%;height:70px" index="3">商品信息</el-menu-item> -->
|
||||
</el-menu>
|
||||
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 原有的三个区域 -->
|
||||
<el-row style="display: flex; justify-content: center;">
|
||||
<!-- 会话列表 -->
|
||||
<el-col :span="6">
|
||||
<ContentWrap>
|
||||
<KeFuConversationList ref="keFuConversationRef" @change="handleChange"/>
|
||||
</ContentWrap>
|
||||
</el-col>
|
||||
|
||||
<!-- 会话详情(选中会话的消息列表) -->
|
||||
<el-col :span="12">
|
||||
<ContentWrap>
|
||||
<KeFuMessageList ref="keFuChatBoxRef" @change="getConversationList"/>
|
||||
</ContentWrap>
|
||||
</el-col>
|
||||
|
||||
<!-- 会员足迹(选中会话的会员足迹) -->
|
||||
<el-col :span="6">
|
||||
<ContentWrap v-show="chick == '2'">
|
||||
<MemberBrowsingHistory ref="memberBrowsingHistoryRef"/>
|
||||
</ContentWrap>
|
||||
|
||||
<ContentWrap v-show = "chick == '1'">
|
||||
<div style="height: 522px ;" >
|
||||
<div>
|
||||
<span style="display: flex;">
|
||||
<el-avatar
|
||||
style="border: 1px solid #f8f9ee;"
|
||||
:src="user.avatar"
|
||||
/>
|
||||
<span style="margin-left:5px;margin-top: 9px;">{{user.nickname}}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;" />
|
||||
<div>
|
||||
<span style="color: #5d5d59;font-size: 13px ;">手机号</span><span style="margin-left: 47px;font-size: 14px ;">{{user.mobile}}</span>
|
||||
</div>
|
||||
<div style="margin-top: 5px;">
|
||||
<span style="color: #5d5d59;font-size: 13px ;">分组</span><span style="margin-left: 60px;font-size: 14px ;">{{user.groupName}}</span>
|
||||
</div>
|
||||
<div style="margin-top: 5px;">
|
||||
<span style="color: #5d5d59;font-size: 13px ;">用户标签</span><span style="margin-left: 33px;font-size: 14px ;">小客户</span>
|
||||
</div>
|
||||
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;" />
|
||||
|
||||
<div>
|
||||
<span style="color: #5d5d59;font-size: 13px ;">用户等级</span><span style="margin-left: 35px;font-size: 14px ;">{{user.levelName}}</span>
|
||||
</div>
|
||||
<div style="margin-top: 5px;">
|
||||
<span style="color: #5d5d59;font-size: 13px ;">推荐人</span><span style="margin-left: 47px;font-size: 14px ;">客户</span>
|
||||
</div>
|
||||
<div style="margin-top: 5px;">
|
||||
<span style="color: #5d5d59;font-size: 13px ;">用户类型</span><span style="margin-left: 33px;font-size: 14px ;">小客户</span>
|
||||
</div>
|
||||
<div style="margin-top: 5px;">
|
||||
<span style="color: #5d5d59;font-size: 13px ;">积分</span><span style="margin-left: 60px;font-size: 14px ;">{{user.point}}</span>
|
||||
</div>
|
||||
<div style="margin-top: 5px;">
|
||||
<span style="color: #5d5d59;font-size: 13px ;">推广员</span><span style="margin-left: 47px;font-size: 14px ;">客户</span>
|
||||
</div>
|
||||
<div style="margin-top: 5px;">
|
||||
<span style="color: #5d5d59;font-size: 13px ;">生日</span><span style="margin-left: 60px;font-size: 14px ;">{{user.birthday}}</span>
|
||||
</div>
|
||||
<el-divider style="border-color: #f5f5f5;margin-top: 15px;margin-bottom:15px;" />
|
||||
</div>
|
||||
</ContentWrap>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { KeFuConversationList, KeFuMessageList, MemberBrowsingHistory } from './components'
|
||||
import { WebSocketMessageTypeConstants } from './components/tools/constants'
|
||||
import { KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation'
|
||||
import { getRefreshToken, getAccessToken } from '@/utils/auth'
|
||||
import { useWebSocket } from '@vueuse/core'
|
||||
import { KeFuConversationList, KeFuMessageList,MemberBrowsingHistory,UserInfo } from './components'
|
||||
import {WebSocketMessageTypeConstants} from './components/tools/constants'
|
||||
import {KeFuConversationRespVO} from '@/api/mall/promotion/kefu/conversation'
|
||||
import {getRefreshToken, getAccessToken} from '@/utils/auth'
|
||||
import {useWebSocket} from '@vueuse/core'
|
||||
import {Search} from '@element-plus/icons-vue'
|
||||
import * as UserApi from '@/api/member/user'
|
||||
|
||||
defineOptions({ name: 'KeFu' })
|
||||
|
||||
|
||||
defineOptions({name: 'KeFu'})
|
||||
|
||||
const value6 = ref(true)
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const name = params.get('name');
|
||||
const pic = params.get('pic');
|
||||
const conversations = ref<KeFuConversationRespVO[]>([])
|
||||
// const userInfoRef = ref<InstanceType<typeof UserInfo>>()
|
||||
const user = ref<UserApi.UserVO>({} as UserApi.UserVO)
|
||||
const userId = ref(0)
|
||||
|
||||
|
||||
// ======================= WebSocket start =======================
|
||||
const server = ref(
|
||||
(import.meta.env.VITE_BASE_URL + '/infra/ws').replace('http', 'ws') +
|
||||
'?token=' +
|
||||
getRefreshToken() // 使用 getRefreshToken() 方法,而不使用 getAccessToken() 方法的原因:WebSocket 无法方便的刷新访问令牌
|
||||
) // WebSocket 服务地址
|
||||
const server = ref(
|
||||
(import.meta.env.VITE_BASE_URL + '/infra/ws').replace('http', 'ws') +
|
||||
'?token=' +
|
||||
getRefreshToken()
|
||||
// 使用 getRefreshToken() 方法,而不使用 getAccessToken() 方法的原因:WebSocket 无法方便的刷新访问令牌
|
||||
) // WebSocket 服务地址
|
||||
|
||||
/** 发起 WebSocket 连接 */
|
||||
const { data, close, open } = useWebSocket(server.value, {
|
||||
autoReconnect: false,
|
||||
heartbeat: true
|
||||
})
|
||||
|
||||
let a = 0;
|
||||
|
||||
const {status, data, send, open, close} = useWebSocket(server.value, {
|
||||
onConnected: function (ws) {
|
||||
console.log('websocket 连接成功!', ws);
|
||||
},
|
||||
onDisconnected: function (ws, event) {
|
||||
console.log('WebSocket 连接断开', event);
|
||||
},
|
||||
onError: function (ws, event) {
|
||||
console.error('WebSocket 连接错误:', event);
|
||||
if (event instanceof ErrorEvent) {
|
||||
console.error('详细错误信息:', event.message);
|
||||
} else {
|
||||
console.error('非标准错误:', event);
|
||||
}
|
||||
},
|
||||
onMessage: function (ws, event) {
|
||||
console.log('收到的 WebSocket 消息:', event.data);
|
||||
|
||||
|
||||
a = a + 1 ;
|
||||
if(a == 2){
|
||||
getConversationList()
|
||||
keFuChatBoxRef.value?.refreshMessageList()
|
||||
a = 0;
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
autoReconnect: false, // 开启自动重连
|
||||
heartbeat: true
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
/** 监听 WebSocket 数据 */
|
||||
watchEffect(() => {
|
||||
console.log('连接服务器得到消息:',data.value)
|
||||
if (!data.value) {
|
||||
return
|
||||
}
|
||||
@ -56,10 +209,12 @@
|
||||
if (data.value === 'pong') {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// 2.1 解析 type 消息类型
|
||||
const jsonMessage = JSON.parse(data.value)
|
||||
const type = jsonMessage.type
|
||||
console.log('来自用户发送的消息:',data.value)
|
||||
|
||||
if (!type) {
|
||||
message.error('未知的消息类型:' + data.value)
|
||||
return
|
||||
@ -83,6 +238,8 @@
|
||||
console.error(error)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// ======================= WebSocket end =======================
|
||||
/** 加载会话列表 */
|
||||
const keFuConversationRef = ref<InstanceType<typeof KeFuConversationList>>()
|
||||
@ -94,21 +251,43 @@
|
||||
const keFuChatBoxRef = ref<InstanceType<typeof KeFuMessageList>>()
|
||||
const memberBrowsingHistoryRef = ref<InstanceType<typeof MemberBrowsingHistory>>()
|
||||
const handleChange = (conversation: KeFuConversationRespVO) => {
|
||||
conversations.value = conversation
|
||||
chick.value = '2'
|
||||
userId.value = conversation.userId
|
||||
keFuChatBoxRef.value?.getNewMessageList(conversation)
|
||||
memberBrowsingHistoryRef.value?.initHistory(conversation)
|
||||
}
|
||||
|
||||
const out = () =>{
|
||||
window.close();
|
||||
// window.location.href = '/kefu/support-staff';
|
||||
}
|
||||
|
||||
|
||||
const chick = ref('2')
|
||||
const userInfo = async () =>{
|
||||
chick.value = '1'
|
||||
user.value = await UserApi.getUserInfo(userId.value)
|
||||
}
|
||||
const zuoji = () =>{
|
||||
chick.value = '2'
|
||||
// keFuChatBoxRef.value?.getNewMessageList(conversations.value)
|
||||
memberBrowsingHistoryRef.value?.initHistory(conversations.value)
|
||||
}
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(() => {
|
||||
getConversationList()
|
||||
// 打开 websocket 连接
|
||||
open()
|
||||
console.log('WebSocket 已初始化');
|
||||
})
|
||||
|
||||
/** 销毁 */
|
||||
onBeforeUnmount(() => {
|
||||
// 关闭 websocket 连接
|
||||
close()
|
||||
console.log('WebSocket 已关闭');
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -116,6 +295,7 @@
|
||||
.kefu {
|
||||
height: calc(100vh - 165px);
|
||||
overflow: auto; /* 确保内容可滚动 */
|
||||
|
||||
}
|
||||
|
||||
/* 定义滚动条样式 */
|
||||
@ -133,8 +313,10 @@
|
||||
|
||||
/* 定义滑块 内阴影+圆角 */
|
||||
::-webkit-scrollbar-thumb {
|
||||
|
||||
border-radius: 10px;
|
||||
box-shadow: inset 0 0 0 rgba(240, 240, 240, 0.5);
|
||||
background-color: rgba(240, 240, 240, 0.5);
|
||||
|
||||
}
|
||||
</style>
|
||||
|
@ -26,7 +26,7 @@
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="登录账号" prop="account">
|
||||
<!-- <el-form-item label="登录账号" prop="account">
|
||||
<el-input
|
||||
v-model="queryParams.account"
|
||||
placeholder="请输入登录账号"
|
||||
@ -34,15 +34,6 @@
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="登录密码" prop="password">
|
||||
<el-input
|
||||
v-model="queryParams.password"
|
||||
placeholder="请输入登录密码"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="客服状态" prop="status">
|
||||
<el-select
|
||||
@ -59,36 +50,6 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="手机订单管理" prop="orderManage">
|
||||
<el-select
|
||||
v-model="queryParams.orderManage"
|
||||
placeholder="请选择手机订单管理"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.KEFU_SUPPORT_STAFF_ORDER_MANAGE)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<!-- <el-form-item label="订单通知" prop="orderInform">
|
||||
<el-select
|
||||
v-model="queryParams.orderInform"
|
||||
placeholder="请选择订单通知"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.KEFU_SUPPORT_STAFF_ORDER_INFORM)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
@ -109,7 +70,7 @@
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['promotion:support-staff:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增客服
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
@ -143,22 +104,11 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="手机号码" align="center" prop="phone" />
|
||||
<el-table-column label="登录账号" align="center" prop="account" />
|
||||
<!-- <el-table-column label="登录密码" align="center" prop="password" /> -->
|
||||
<el-table-column label="客服状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.KEFU_SUPPORT_STAFF_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="手机订单管理" align="center" prop="orderManage">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.KEFU_SUPPORT_STAFF_ORDER_MANAGE" :value="scope.row.orderManage" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="订单通知" align="center" prop="orderInform">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.KEFU_SUPPORT_STAFF_ORDER_INFORM" :value="scope.row.orderInform" />
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
@ -188,7 +138,7 @@
|
||||
v-if="scope.row.status == 1"
|
||||
link
|
||||
type="success"
|
||||
@click="handleEnterConsole(scope.row.id)"
|
||||
@click="handleEnterConsole(scope.row.id,scope.row.name,scope.row.pic)"
|
||||
>
|
||||
进入工作台
|
||||
</el-button>
|
||||
@ -206,6 +156,9 @@
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<SupportStaffForm ref="formRef" @success="getList" />
|
||||
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@ -215,6 +168,7 @@ import download from '@/utils/download'
|
||||
import { SupportStaffApi, SupportStaffVO } from '@/api/mall/promotion/supportstaff'
|
||||
import SupportStaffForm from './SupportStaffForm.vue'
|
||||
import { setStaffToken} from '@/utils/auth'
|
||||
import { createImageViewer } from '@/components/ImageViewer'
|
||||
/** 客服人员 列表 */
|
||||
defineOptions({ name: 'SupportStaff' })
|
||||
|
||||
@ -271,6 +225,13 @@ const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
const imagePreview = (imgUrl: string) => {
|
||||
createImageViewer({
|
||||
zIndex: 9999999,
|
||||
urlList: [imgUrl]
|
||||
})
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
@ -284,9 +245,10 @@ const handleDelete = async (id: number) => {
|
||||
} catch {}
|
||||
}
|
||||
/** 客服进入工作台 */
|
||||
const handleEnterConsole = async (id: number) => {
|
||||
const handleEnterConsole = async (id: number,name: string,pic: string) => {
|
||||
setStaffToken(id);
|
||||
window.open(`${window.location.origin}/kefu/kefu`, '_blank');
|
||||
const url = `${window.location.origin}/kefu/kefu?name=${encodeURIComponent(name)}&pic=${encodeURIComponent(pic)}`;
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
|
@ -25,7 +25,7 @@
|
||||
:key="dict.value" :label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="标题" prop="title">
|
||||
<!-- <el-form-item label="标题" prop="title">
|
||||
<el-input v-model="queryParams.title" placeholder="请输入标题" clearable @keyup.enter="handleQuery"
|
||||
class="!w-240px" />
|
||||
</el-form-item>
|
||||
@ -33,22 +33,22 @@
|
||||
<el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange" start-placeholder="开始日期" end-placeholder="结束日期"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-240px" />
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery">
|
||||
<!-- <el-button @click="handleQuery">
|
||||
<Icon icon="ep:search" class="mr-5px" /> 搜索
|
||||
</el-button>
|
||||
<el-button @click="resetQuery">
|
||||
<Icon icon="ep:refresh" class="mr-5px" /> 重置
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
<el-button type="primary" plain @click="openForm('create')"
|
||||
v-hasPermi="['promotion:verbal-trick:create']">
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 添加话术
|
||||
</el-button>
|
||||
<el-button type="success" plain @click="handleExport" :loading="exportLoading"
|
||||
<!-- <el-button type="success" plain @click="handleExport" :loading="exportLoading"
|
||||
v-hasPermi="['promotion:verbal-trick:export']">
|
||||
<Icon icon="ep:download" class="mr-5px" /> 导出
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="100px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<el-form-item label="钱包编号" prop="walletId">
|
||||
<el-input v-model="formData.walletId" placeholder="请输入钱包编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="充值实际到账" prop="totalPrice">
|
||||
<el-input v-model="formData.totalPrice" placeholder="请输入充值实际到账" />
|
||||
</el-form-item>
|
||||
<el-form-item label="实际支付金额" prop="payPrice">
|
||||
<el-input v-model="formData.payPrice" placeholder="请输入实际支付金额" />
|
||||
</el-form-item>
|
||||
<el-form-item label="钱包赠送金额" prop="bonusPrice">
|
||||
<el-input v-model="formData.bonusPrice" placeholder="请输入钱包赠送金额" />
|
||||
</el-form-item>
|
||||
<el-form-item label="充值套餐编号" prop="packageId">
|
||||
<el-input v-model="formData.packageId" placeholder="请输入充值套餐编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="是否支付" prop="payStatus">
|
||||
<el-select v-model="formData.payStatus" placeholder="请选择是否支付">
|
||||
<el-option
|
||||
v-for="dict in getBoolDictOptions(DICT_TYPE.PAY_WALLET_RECHARGE_PAY_STATUS)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="支付订单编号" prop="payOrderId">
|
||||
<el-input v-model="formData.payOrderId" placeholder="请输入支付订单编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="支付成功的支付渠道" prop="payChannelCode">
|
||||
<el-input v-model="formData.payChannelCode" placeholder="请输入支付成功的支付渠道" />
|
||||
</el-form-item>
|
||||
<el-form-item label="订单支付时间" prop="payTime">
|
||||
<el-date-picker
|
||||
v-model="formData.payTime"
|
||||
type="date"
|
||||
value-format="x"
|
||||
placeholder="选择订单支付时间"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="支付退款单编号" prop="payRefundId">
|
||||
<el-input v-model="formData.payRefundId" placeholder="请输入支付退款单编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="退款金额(包含赠送金额)" prop="refundTotalPrice">
|
||||
<el-input v-model="formData.refundTotalPrice" placeholder="请输入退款金额(包含赠送金额)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="退款支付金额" prop="refundPayPrice">
|
||||
<el-input v-model="formData.refundPayPrice" placeholder="请输入退款支付金额" />
|
||||
</el-form-item>
|
||||
<el-form-item label="退款钱包赠送金额" prop="refundBonusPrice">
|
||||
<el-input v-model="formData.refundBonusPrice" placeholder="请输入退款钱包赠送金额" />
|
||||
</el-form-item>
|
||||
<el-form-item label="退款时间" prop="refundTime">
|
||||
<el-date-picker
|
||||
v-model="formData.refundTime"
|
||||
type="date"
|
||||
value-format="x"
|
||||
placeholder="选择退款时间"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="退款状态" prop="refundStatus">
|
||||
<el-radio-group v-model="formData.refundStatus">
|
||||
<el-radio label="1">请选择字典生成</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import { WalletRechargeApi, WalletRechargeVO } from '@/api/pay/wallet/recharge'
|
||||
|
||||
/** 钱包充值 表单 */
|
||||
defineOptions({ name: 'WalletRechargeForm' })
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
walletId: undefined,
|
||||
totalPrice: undefined,
|
||||
payPrice: undefined,
|
||||
bonusPrice: undefined,
|
||||
packageId: undefined,
|
||||
payStatus: undefined,
|
||||
payOrderId: undefined,
|
||||
payChannelCode: undefined,
|
||||
payTime: undefined,
|
||||
payRefundId: undefined,
|
||||
refundTotalPrice: undefined,
|
||||
refundPayPrice: undefined,
|
||||
refundBonusPrice: undefined,
|
||||
refundTime: undefined,
|
||||
refundStatus: undefined
|
||||
})
|
||||
const formRules = reactive({
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await WalletRechargeApi.getWalletRecharge(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
await formRef.value.validate()
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown as WalletRechargeVO
|
||||
if (formType.value === 'create') {
|
||||
await WalletRechargeApi.createWalletRecharge(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await WalletRechargeApi.updateWalletRecharge(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
walletId: undefined,
|
||||
totalPrice: undefined,
|
||||
payPrice: undefined,
|
||||
bonusPrice: undefined,
|
||||
packageId: undefined,
|
||||
payStatus: undefined,
|
||||
payOrderId: undefined,
|
||||
payChannelCode: undefined,
|
||||
payTime: undefined,
|
||||
payRefundId: undefined,
|
||||
refundTotalPrice: undefined,
|
||||
refundPayPrice: undefined,
|
||||
refundBonusPrice: undefined,
|
||||
refundTime: undefined,
|
||||
refundStatus: undefined
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
280
yudao-admin-vue3/src/views/pay/wallet/recharge/index.vue
Normal file
280
yudao-admin-vue3/src/views/pay/wallet/recharge/index.vue
Normal file
@ -0,0 +1,280 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="100px"
|
||||
>
|
||||
|
||||
<el-form-item label="是否支付" prop="payStatus">
|
||||
<el-select
|
||||
v-model="queryParams.payStatus"
|
||||
placeholder="请选择是否支付"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getBoolDictOptions(DICT_TYPE.PAY_WALLET_RECHARGE_PAY_STATUS)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="支付渠道" prop="payChannelCode">
|
||||
<el-input
|
||||
v-model="queryParams.payChannelCode"
|
||||
placeholder="请输入支付渠道"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="订单支付时间" prop="payTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.payTime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<!-- <el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['pay:wallet-recharge:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
:loading="exportLoading"
|
||||
v-hasPermi="['pay:wallet-recharge:export']"
|
||||
>
|
||||
<Icon icon="ep:download" class="mr-5px" /> 导出
|
||||
</el-button> -->
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="ID" align="center" prop="id" />
|
||||
<el-table-column label="用户昵称" align="center" prop="name" />
|
||||
<!-- <el-table-column label="用户头像" align="center" prop="avatar" /> -->
|
||||
<el-table-column label="用户头像" align="center" prop="avatar" >
|
||||
<template #default="{ row }">
|
||||
<div class="flex justify-center items-center">
|
||||
<el-image
|
||||
fit="cover"
|
||||
:src="row.avatar"
|
||||
class="flex-none w-50px h-50px"
|
||||
@click="imagePreview(row.avatar)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付订单编号" align="center" prop="payOrderId" />
|
||||
<el-table-column label="支付金额" align="center" prop="payPrice" />
|
||||
<el-table-column label="支付渠道" align="center" prop="payChannelCode" />
|
||||
|
||||
<!-- <el-table-column label="钱包赠送金额" align="center" prop="bonusPrice" />
|
||||
<el-table-column label="充值套餐编号" align="center" prop="packageId" /> -->
|
||||
<el-table-column label="是否支付" align="center" prop="payStatus">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.PAY_WALLET_RECHARGE_PAY_STATUS" :value="scope.row.payStatus" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="订单支付时间"
|
||||
align="center"
|
||||
prop="payTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<!-- <el-table-column label="支付退款单编号" align="center" prop="payRefundId" />
|
||||
<el-table-column label="退款金额(包含赠送金额)" align="center" prop="refundTotalPrice" />
|
||||
<el-table-column label="退款支付金额" align="center" prop="refundPayPrice" />
|
||||
<el-table-column label="退款钱包赠送金额" align="center" prop="refundBonusPrice" />
|
||||
<el-table-column
|
||||
label="退款时间"
|
||||
align="center"
|
||||
prop="refundTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="退款状态" align="center" prop="refundStatus" /> -->
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<!-- <el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['pay:wallet-recharge:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button> -->
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['pay:wallet-recharge:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<WalletRechargeForm ref="formRef" @success="getList" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import { WalletRechargeApi, WalletRechargeVO } from '@/api/pay/wallet/recharge'
|
||||
import WalletRechargeForm from './WalletRechargeForm.vue'
|
||||
import { createImageViewer } from "@/components/ImageViewer"
|
||||
|
||||
/** 钱包充值 列表 */
|
||||
defineOptions({ name: 'WalletRecharge' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const list = ref<WalletRechargeVO[]>([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
walletId: undefined,
|
||||
totalPrice: undefined,
|
||||
payPrice: undefined,
|
||||
bonusPrice: undefined,
|
||||
packageId: undefined,
|
||||
payStatus: undefined,
|
||||
payOrderId: undefined,
|
||||
payChannelCode: undefined,
|
||||
payTime: [],
|
||||
payRefundId: undefined,
|
||||
refundTotalPrice: undefined,
|
||||
refundPayPrice: undefined,
|
||||
refundBonusPrice: undefined,
|
||||
refundTime: [],
|
||||
refundStatus: undefined,
|
||||
createTime: []
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await WalletRechargeApi.getWalletRechargePage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
const imagePreview = (imgUrl : string) => {
|
||||
createImageViewer({
|
||||
urlList: [imgUrl]
|
||||
})
|
||||
}
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await WalletRechargeApi.deleteWalletRecharge(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await WalletRechargeApi.exportWalletRecharge(queryParams)
|
||||
download.excel(data, '钱包充值.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
@ -29,6 +29,6 @@ public class WebSocketProperties {
|
||||
* 可选值:local、redis、rocketmq、kafka、rabbitmq
|
||||
*/
|
||||
@NotNull(message = "WebSocket 的消息发送者不能为空")
|
||||
private String senderType = "local";
|
||||
private String senderType = "redis";
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate;
|
||||
import cn.iocoder.yudao.framework.websocket.core.handler.JsonWebSocketMessageHandler;
|
||||
import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListener;
|
||||
import cn.iocoder.yudao.framework.websocket.core.security.LoginUserHandshakeInterceptor;
|
||||
import cn.iocoder.yudao.framework.websocket.core.security.WebSocketAuthorizeRequestsCustomizer;
|
||||
import cn.iocoder.yudao.framework.websocket.core.sender.kafka.KafkaWebSocketMessageConsumer;
|
||||
import cn.iocoder.yudao.framework.websocket.core.sender.kafka.KafkaWebSocketMessageSender;
|
||||
import cn.iocoder.yudao.framework.websocket.core.sender.local.LocalWebSocketMessageSender;
|
||||
@ -76,10 +77,15 @@ public class YudaoWebSocketAutoConfiguration {
|
||||
return new WebSocketSessionManagerImpl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebSocketAuthorizeRequestsCustomizer webSocketAuthorizeRequestsCustomizer(WebSocketProperties webSocketProperties) {
|
||||
return new WebSocketAuthorizeRequestsCustomizer(webSocketProperties);
|
||||
}
|
||||
|
||||
// ==================== Sender 相关 ====================
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "local", matchIfMissing = true)
|
||||
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "local")
|
||||
public class LocalWebSocketMessageSenderConfiguration {
|
||||
|
||||
@Bean
|
||||
@ -90,7 +96,7 @@ public class YudaoWebSocketAutoConfiguration {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "redis", matchIfMissing = true)
|
||||
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "redis")
|
||||
public class RedisWebSocketMessageSenderConfiguration {
|
||||
|
||||
@Bean
|
||||
@ -108,7 +114,7 @@ public class YudaoWebSocketAutoConfiguration {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "rocketmq", matchIfMissing = true)
|
||||
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "rocketmq")
|
||||
public class RocketMQWebSocketMessageSenderConfiguration {
|
||||
|
||||
@Bean
|
||||
@ -127,7 +133,7 @@ public class YudaoWebSocketAutoConfiguration {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "rabbitmq", matchIfMissing = true)
|
||||
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "rabbitmq")
|
||||
public class RabbitMQWebSocketMessageSenderConfiguration {
|
||||
|
||||
@Bean
|
||||
@ -156,7 +162,7 @@ public class YudaoWebSocketAutoConfiguration {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "kafka", matchIfMissing = true)
|
||||
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "kafka")
|
||||
public class KafkaWebSocketMessageSenderConfiguration {
|
||||
|
||||
@Bean
|
||||
|
@ -21,4 +21,4 @@ public class WebSocketAuthorizeRequestsCustomizer extends AuthorizeRequestsCusto
|
||||
registry.antMatchers(webSocketProperties.getPath()).permitAll();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -43,7 +43,7 @@ public interface WebSocketSenderApi {
|
||||
send(userType, userId, messageType, JsonUtils.toJsonString(messageContent));
|
||||
}
|
||||
|
||||
default void sendObject(Integer userType, String messageType, Object messageContent) {
|
||||
default void sendObject(Integer userType, String messageType, Object messageContent) { //用户发送消息
|
||||
send(userType, messageType, JsonUtils.toJsonString(messageContent));
|
||||
}
|
||||
|
||||
|
@ -79,6 +79,12 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-system-biz</artifactId>
|
||||
<version>2.1.0-jdk8-snapshot</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -84,9 +84,9 @@ public class KeFuConversationController {
|
||||
}
|
||||
@Operation(summary = "转接会话给指定客服")
|
||||
@GetMapping("/transfer/{id}/{kefuId}")
|
||||
public CommonResult<Boolean> transferConversation(@PathVariable("id") Long id, @PathVariable("kefuId") Long kefuId) {
|
||||
conversationService.transferConversation(id, kefuId);
|
||||
public CommonResult<String> transferConversation(@PathVariable("id") Long id, @PathVariable("kefuId") Long kefuId) {
|
||||
String name = conversationService.transferConversation(id, kefuId);
|
||||
// 处理逻辑
|
||||
return success(true);
|
||||
return success(name);
|
||||
}
|
||||
}
|
@ -28,4 +28,8 @@ public class AppDiyTemplatePropertyRespVO {
|
||||
@JsonRawValue
|
||||
private String user;
|
||||
|
||||
private String goodsType;
|
||||
|
||||
private String themeType;
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessagePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessageSendReqVO;
|
||||
@ -31,6 +33,10 @@ public class AppKeFuMessageController {
|
||||
@Resource
|
||||
private KeFuMessageService kefuMessageService;
|
||||
|
||||
@Resource
|
||||
private MemberUserApi memberUserApi;
|
||||
|
||||
|
||||
@PostMapping("/send")
|
||||
@Operation(summary = "发送客服消息")
|
||||
@PreAuthenticated
|
||||
@ -53,6 +59,19 @@ public class AppKeFuMessageController {
|
||||
@PreAuthenticated
|
||||
public CommonResult<PageResult<KeFuMessageRespVO>> getKefuMessagePage(@Valid AppKeFuMessagePageReqVO pageReqVO) {
|
||||
PageResult<KeFuMessageDO> pageResult = kefuMessageService.getKeFuMessagePage(pageReqVO, getLoginUserId());
|
||||
for (int i = 0; i < pageResult.getList().size(); i++) {
|
||||
KeFuMessageDO keFuMessageDO = pageResult.getList().get(i);
|
||||
if (keFuMessageDO.getSenderType() == 1){
|
||||
MemberUserRespDTO user = memberUserApi.getUser(keFuMessageDO.getSenderId());
|
||||
keFuMessageDO.setSenderAvatar(user.getAvatar());
|
||||
}
|
||||
|
||||
if (keFuMessageDO.getSenderType() == 2){
|
||||
String systemUserAvatar = kefuMessageService.findSystemUserAvatar(keFuMessageDO.getSenderId());
|
||||
keFuMessageDO.setSenderAvatar(systemUserAvatar);
|
||||
}
|
||||
|
||||
}
|
||||
return success(BeanUtils.toBean(pageResult, KeFuMessageRespVO.class));
|
||||
}
|
||||
|
||||
|
@ -61,4 +61,11 @@ public class DiyTemplateDO extends BaseDO {
|
||||
*/
|
||||
private String property;
|
||||
|
||||
|
||||
@TableField(exist = false)
|
||||
private String goodsType;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String themeType;
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.kefu.KeFuMessageContentTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
@ -78,4 +79,7 @@ public class KeFuMessageDO extends BaseDO {
|
||||
*/
|
||||
private Boolean readStatus;
|
||||
|
||||
|
||||
@TableField(exist = false)
|
||||
private String senderAvatar;
|
||||
}
|
||||
|
@ -19,13 +19,13 @@ public interface KeFuConversationMapper extends BaseMapperX<KeFuConversationDO>
|
||||
default List<KeFuConversationDO> selectConversationList() {
|
||||
return selectList(new LambdaQueryWrapperX<KeFuConversationDO>()
|
||||
.eq(KeFuConversationDO::getAdminDeleted, Boolean.FALSE)
|
||||
.orderByDesc(KeFuConversationDO::getCreateTime));
|
||||
.orderByDesc(KeFuConversationDO::getLastMessageTime));
|
||||
}
|
||||
default List<KeFuConversationDO> selectConversationList(Long kefuId) {
|
||||
return selectList(new LambdaQueryWrapperX<KeFuConversationDO>()
|
||||
.eq(KeFuConversationDO::getAdminDeleted, Boolean.FALSE)
|
||||
.eqIfPresent(KeFuConversationDO::getKefuId, kefuId)
|
||||
.orderByDesc(KeFuConversationDO::getCreateTime));
|
||||
.orderByDesc(KeFuConversationDO::getLastMessageTime));
|
||||
}
|
||||
|
||||
default void updateAdminUnreadMessageCountIncrement(Long id) {
|
||||
|
@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@ -46,4 +47,8 @@ public interface KeFuMessageMapper extends BaseMapperX<KeFuMessageDO> {
|
||||
.orderByDesc(KeFuMessageDO::getCreateTime));
|
||||
}
|
||||
|
||||
|
||||
@Select(" SELECT avatar FROM system_users where id = #{id} ")
|
||||
String findSystemUserAvatar(Long id);
|
||||
|
||||
}
|
@ -26,7 +26,7 @@ public interface SupportStaffMapper extends BaseMapperX<SupportStaffDO> {
|
||||
.eqIfPresent(SupportStaffDO::getOrderManage, reqVO.getOrderManage())
|
||||
.eqIfPresent(SupportStaffDO::getOrderInform, reqVO.getOrderInform())
|
||||
.betweenIfPresent(SupportStaffDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(SupportStaffDO::getId));
|
||||
.orderByAsc(SupportStaffDO::getId));
|
||||
}
|
||||
|
||||
}
|
@ -11,12 +11,15 @@ import cn.iocoder.yudao.module.promotion.convert.diy.DiyPageConvert;
|
||||
import cn.iocoder.yudao.module.promotion.convert.diy.DiyTemplateConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.diy.DiyTemplateDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.diy.DiyTemplateMapper;
|
||||
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
|
||||
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
||||
@ -36,6 +39,9 @@ public class DiyTemplateServiceImpl implements DiyTemplateService {
|
||||
@Resource
|
||||
private DiyPageService diyPageService;
|
||||
|
||||
@Resource
|
||||
private DictDataApi dictDataApi;
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public Long createDiyTemplate(DiyTemplateCreateReqVO createReqVO) {
|
||||
@ -165,7 +171,17 @@ public class DiyTemplateServiceImpl implements DiyTemplateService {
|
||||
|
||||
@Override
|
||||
public DiyTemplateDO getUsedDiyTemplate() {
|
||||
return diyTemplateMapper.selectByUsed(true);
|
||||
DiyTemplateDO diyTemplateDO = diyTemplateMapper.selectByUsed(true);
|
||||
|
||||
List<DictDataRespDTO> dictDataList = dictDataApi.getDictDataList("diy-template-theme");
|
||||
DictDataRespDTO dictDataRespDTO = dictDataList.get(0);
|
||||
diyTemplateDO.setThemeType(dictDataRespDTO.getValue());
|
||||
|
||||
List<DictDataRespDTO> dictDataList1 = dictDataApi.getDictDataList("diy-template-goods");
|
||||
DictDataRespDTO dictDataRespDTO1 = dictDataList1.get(0);
|
||||
diyTemplateDO.setGoodsType(dictDataRespDTO1.getValue());
|
||||
|
||||
return diyTemplateDO;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -102,5 +102,5 @@ public interface KeFuConversationService {
|
||||
* @param kefuId 客服id
|
||||
* @return void
|
||||
*/
|
||||
void transferConversation(Long id, Long kefuId);
|
||||
String transferConversation(Long id, Long kefuId);
|
||||
}
|
@ -5,7 +5,9 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.conversation.KeFuConversationUpdatePinnedReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuConversationDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.supportstaff.SupportStaffDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.kefu.KeFuConversationMapper;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.supportstaff.SupportStaffMapper;
|
||||
import cn.iocoder.yudao.module.promotion.enums.kefu.KeFuMessageContentTypeEnum;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -30,6 +32,9 @@ public class KeFuConversationServiceImpl implements KeFuConversationService {
|
||||
@Resource
|
||||
private KeFuConversationMapper conversationMapper;
|
||||
|
||||
@Resource
|
||||
private SupportStaffMapper supportStaffMapper;
|
||||
|
||||
@Override
|
||||
public void deleteKefuConversation(Long id) {
|
||||
// 校验存在
|
||||
@ -126,11 +131,13 @@ public class KeFuConversationServiceImpl implements KeFuConversationService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferConversation(Long id, Long kefuId) {
|
||||
public String transferConversation(Long id, Long kefuId) {
|
||||
KeFuConversationDO keFuConversationDO = new KeFuConversationDO();
|
||||
keFuConversationDO.setId(id);
|
||||
keFuConversationDO.setKefuId(kefuId);
|
||||
conversationMapper.updateById(keFuConversationDO);
|
||||
SupportStaffDO supportStaffDO = supportStaffMapper.selectById(kefuId);
|
||||
return supportStaffDO.getName();
|
||||
}
|
||||
|
||||
}
|
@ -31,6 +31,8 @@ public interface KeFuMessageService {
|
||||
* @return 编号
|
||||
*/
|
||||
Long sendKefuMessage(AppKeFuMessageSendReqVO sendReqVO);
|
||||
|
||||
|
||||
String sendKefuMessageTest(String s);
|
||||
|
||||
/**
|
||||
@ -59,4 +61,6 @@ public interface KeFuMessageService {
|
||||
*/
|
||||
PageResult<KeFuMessageDO> getKeFuMessagePage(AppKeFuMessagePageReqVO pageReqVO, Long userId);
|
||||
|
||||
String findSystemUserAvatar(Long id);
|
||||
|
||||
}
|
@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessagePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuMessagePageReqVO;
|
||||
@ -16,7 +17,10 @@ import cn.iocoder.yudao.module.promotion.controller.app.kefu.vo.message.AppKeFuM
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuConversationDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.kefu.KeFuMessageMapper;
|
||||
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyMessageDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.notify.NotifyMessageMapper;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -51,9 +55,12 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
||||
@Resource
|
||||
private WebSocketSenderApi webSocketSenderApi;
|
||||
|
||||
@Resource
|
||||
private NotifyMessageMapper notifyMessageMapper;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long sendKefuMessage(KeFuMessageSendReqVO sendReqVO) {
|
||||
public Long sendKefuMessage(KeFuMessageSendReqVO sendReqVO) { //客服发消息
|
||||
// 1.1 校验会话是否存在
|
||||
KeFuConversationDO conversation = conversationService.validateKefuConversationExists(sendReqVO.getConversationId());
|
||||
// 1.2 校验接收人是否存在
|
||||
@ -74,20 +81,39 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long sendKefuMessage(AppKeFuMessageSendReqVO sendReqVO) {
|
||||
public Long sendKefuMessage(AppKeFuMessageSendReqVO sendReqVO) { //用户发消息
|
||||
// 1.1 设置会话编号
|
||||
KeFuMessageDO kefuMessage = BeanUtils.toBean(sendReqVO, KeFuMessageDO.class);
|
||||
KeFuConversationDO conversation = conversationService.getOrCreateConversation(sendReqVO.getSenderId());
|
||||
kefuMessage.setConversationId(conversation.getId());
|
||||
// 1.2 保存消息
|
||||
kefuMessage.setReceiverId(conversation.getKefuId()).setReceiverType(UserTypeEnum.ADMIN.getValue()); // 设置接收人
|
||||
keFuMessageMapper.insert(kefuMessage);
|
||||
|
||||
// 2. 更新会话消息冗余
|
||||
conversationService.updateConversationLastMessage(kefuMessage);
|
||||
|
||||
getSelf().sendAsyncMessageToMembers(conversation.getKefuId(), KEFU_MESSAGE_TYPE, kefuMessage);
|
||||
|
||||
// 3. 通知所有管理员更新对话
|
||||
getSelf().sendAsyncMessageToAdmin(KEFU_MESSAGE_TYPE, kefuMessage);
|
||||
getSelf().sendAsyncMessageToAdmins(KEFU_MESSAGE_TYPE, kefuMessage);
|
||||
return kefuMessage.getId();
|
||||
}
|
||||
//添加站内信
|
||||
// MemberUserRespDTO user = memberUserApi.getUser(sendReqVO.getSenderId());
|
||||
// NotifyMessageDO notifyMessageDO = new NotifyMessageDO()
|
||||
// .setUserId(sendReqVO.getSenderId())
|
||||
// .setUserType(sendReqVO.getSenderType())
|
||||
// .setTemplateId((long)1)
|
||||
// .setTemplateCode()
|
||||
// .setTemplateNickname(user.getNickname())
|
||||
// .setTemplateContent("客户发来消息")
|
||||
// .setTemplateType(2)
|
||||
// .setTemplateParams()
|
||||
// .setReadStatus(2);
|
||||
// notifyMessageMapper.insert(notifyMessageDO);
|
||||
|
||||
|
||||
@Override
|
||||
public String sendKefuMessageTest(String s){
|
||||
webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), 1L, "1", s);;
|
||||
@ -137,11 +163,21 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
||||
webSocketSenderApi.sendObject(UserTypeEnum.MEMBER.getValue(), userId, messageType, content);
|
||||
}
|
||||
|
||||
@Async
|
||||
public void sendAsyncMessageToMembers(Long userId, String messageType, Object content) {
|
||||
webSocketSenderApi.sendObject(UserTypeEnum.MEMBER.getValue(), userId, messageType, content);
|
||||
}
|
||||
|
||||
@Async
|
||||
public void sendAsyncMessageToAdmin(String messageType, Object content) {
|
||||
webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), messageType, content);
|
||||
}
|
||||
|
||||
@Async
|
||||
public void sendAsyncMessageToAdmins(String messageType, Object content) {
|
||||
webSocketSenderApi.sendObject(UserTypeEnum.MEMBER.getValue(), messageType, content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<KeFuMessageDO> getKeFuMessagePage(KeFuMessagePageReqVO pageReqVO) {
|
||||
return keFuMessageMapper.selectPage(pageReqVO);
|
||||
@ -159,6 +195,11 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
||||
return keFuMessageMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String findSystemUserAvatar(Long id) {
|
||||
return keFuMessageMapper.findSystemUserAvatar(id);
|
||||
}
|
||||
|
||||
private KeFuMessageServiceImpl getSelf() {
|
||||
return SpringUtil.getBean(getClass());
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
|
||||
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
|
||||
import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleService;
|
||||
|
@ -17,7 +17,10 @@ import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.memberCode.MemberCodeDo;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.tag.MemberTagDO;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
|
||||
import cn.iocoder.yudao.module.member.dal.mysql.group.MemberGroupMapper;
|
||||
import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelMapper;
|
||||
import cn.iocoder.yudao.module.member.dal.mysql.memberCode.MemberCodeMapper;
|
||||
import cn.iocoder.yudao.module.member.dal.mysql.tag.MemberTagMapper;
|
||||
import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.member.service.clubCard.ClubCardService;
|
||||
import cn.iocoder.yudao.module.member.service.group.MemberGroupService;
|
||||
@ -52,6 +55,15 @@ import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLogi
|
||||
@Validated
|
||||
public class MemberUserController {
|
||||
|
||||
@Resource
|
||||
private MemberLevelMapper memberLevelMapper;
|
||||
|
||||
@Resource
|
||||
private MemberGroupMapper memberGroupMapper;
|
||||
|
||||
@Resource
|
||||
private MemberTagMapper memberTagMapper;
|
||||
|
||||
@Resource
|
||||
private MemberUserService memberUserService;
|
||||
@Resource
|
||||
@ -169,4 +181,23 @@ public class MemberUserController {
|
||||
memberCodeMapper.insert(memberCodeDo);
|
||||
return success(uuid);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/getUserInfo")
|
||||
public CommonResult<MemberUserDO> getUserInfo(Long id){
|
||||
MemberUserDO user = memberUserService.getUser(id);
|
||||
|
||||
if (user.getGroupId() != null){
|
||||
MemberGroupDO groupDO = memberGroupMapper.selectOne("id", user.getGroupId());
|
||||
user.setGroupName(groupDO.getName());
|
||||
}
|
||||
|
||||
if (user.getLevelId() != null && user.getLevelId() != 0){
|
||||
MemberLevelDO levelDO = memberLevelMapper.selectOne("id", user.getLevelId());
|
||||
user.setLevelName(levelDO.getName());
|
||||
}
|
||||
|
||||
return success(user);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -131,6 +131,9 @@ public class MemberUserDO extends TenantBaseDO {
|
||||
* 关联 {@link MemberLevelDO#getId()} 字段
|
||||
*/
|
||||
private Long levelId;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String levelName;
|
||||
/**
|
||||
* 会员经验
|
||||
*/
|
||||
@ -142,6 +145,9 @@ public class MemberUserDO extends TenantBaseDO {
|
||||
*/
|
||||
private Long groupId;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String groupName;
|
||||
|
||||
/**
|
||||
* 是否绑过卡,是否开通过会员(0:未开通,1:试用,2:有效期,3:永久,4:过期)
|
||||
*/
|
||||
|
@ -1,13 +1,20 @@
|
||||
package cn.iocoder.yudao.module.pay.controller.admin.wallet;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.recharge.WalletRechargePageReqVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.recharge.WalletRechargeRespVO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargeDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.WalletRechargeDO;
|
||||
import cn.iocoder.yudao.module.pay.service.wallet.PayWalletRechargeService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@ -55,4 +62,12 @@ public class PayWalletRechargeController {
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得钱包充值分页")
|
||||
@PreAuthorize("@ss.hasPermission('pay:wallet-recharge:query')")
|
||||
public CommonResult<PageResult<WalletRechargeRespVO>> getWalletRechargePage(@Valid WalletRechargePageReqVO pageReqVO) {
|
||||
PageResult<PayWalletRechargeDO> pageResult = walletRechargeService.getWalletRechargePage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, WalletRechargeRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,69 @@
|
||||
package cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.recharge;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 钱包充值分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class WalletRechargePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "钱包编号", example = "3219")
|
||||
private Long walletId;
|
||||
|
||||
@Schema(description = "充值实际到账", example = "24628")
|
||||
private Integer totalPrice;
|
||||
|
||||
@Schema(description = "实际支付金额", example = "11386")
|
||||
private Integer payPrice;
|
||||
|
||||
@Schema(description = "钱包赠送金额", example = "6594")
|
||||
private Integer bonusPrice;
|
||||
|
||||
@Schema(description = "充值套餐编号", example = "2831")
|
||||
private Long packageId;
|
||||
|
||||
@Schema(description = "是否支付", example = "2")
|
||||
private Boolean payStatus;
|
||||
|
||||
@Schema(description = "支付订单编号", example = "5515")
|
||||
private Long payOrderId;
|
||||
|
||||
@Schema(description = "支付成功的支付渠道")
|
||||
private String payChannelCode;
|
||||
|
||||
@Schema(description = "订单支付时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] payTime;
|
||||
|
||||
@Schema(description = "支付退款单编号", example = "22733")
|
||||
private Long payRefundId;
|
||||
|
||||
@Schema(description = "退款金额(包含赠送金额)", example = "15904")
|
||||
private Integer refundTotalPrice;
|
||||
|
||||
@Schema(description = "退款支付金额", example = "30626")
|
||||
private Integer refundPayPrice;
|
||||
|
||||
@Schema(description = "退款钱包赠送金额", example = "2421")
|
||||
private Integer refundBonusPrice;
|
||||
|
||||
@Schema(description = "退款时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] refundTime;
|
||||
|
||||
@Schema(description = "退款状态", example = "2")
|
||||
private Integer refundStatus;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
package cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.recharge;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import com.alibaba.excel.annotation.*;
|
||||
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
|
||||
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
|
||||
|
||||
@Schema(description = "管理后台 - 钱包充值 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class WalletRechargeRespVO {
|
||||
|
||||
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "13484")
|
||||
@ExcelProperty("id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "钱包编号", example = "3219")
|
||||
@ExcelProperty("钱包编号")
|
||||
private Long walletId;
|
||||
|
||||
@Schema(description = "充值实际到账", example = "24628")
|
||||
@ExcelProperty("充值实际到账")
|
||||
private Integer totalPrice;
|
||||
|
||||
@Schema(description = "实际支付金额", example = "11386")
|
||||
@ExcelProperty("实际支付金额")
|
||||
private Integer payPrice;
|
||||
|
||||
@Schema(description = "钱包赠送金额", example = "6594")
|
||||
@ExcelProperty("钱包赠送金额")
|
||||
private Integer bonusPrice;
|
||||
|
||||
@Schema(description = "充值套餐编号", example = "2831")
|
||||
@ExcelProperty("充值套餐编号")
|
||||
private Long packageId;
|
||||
|
||||
@Schema(description = "是否支付", example = "2")
|
||||
@ExcelProperty(value = "是否支付", converter = DictConvert.class)
|
||||
@DictFormat("pay_wallet_recharge_pay_status") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
|
||||
private Boolean payStatus;
|
||||
|
||||
@Schema(description = "支付订单编号", example = "5515")
|
||||
@ExcelProperty("支付订单编号")
|
||||
private Long payOrderId;
|
||||
|
||||
@Schema(description = "支付成功的支付渠道")
|
||||
@ExcelProperty("支付成功的支付渠道")
|
||||
private String payChannelCode;
|
||||
|
||||
@Schema(description = "订单支付时间")
|
||||
@ExcelProperty("订单支付时间")
|
||||
private LocalDateTime payTime;
|
||||
|
||||
@Schema(description = "支付退款单编号", example = "22733")
|
||||
@ExcelProperty("支付退款单编号")
|
||||
private Long payRefundId;
|
||||
|
||||
@Schema(description = "退款金额(包含赠送金额)", example = "15904")
|
||||
@ExcelProperty("退款金额(包含赠送金额)")
|
||||
private Integer refundTotalPrice;
|
||||
|
||||
@Schema(description = "退款支付金额", example = "30626")
|
||||
@ExcelProperty("退款支付金额")
|
||||
private Integer refundPayPrice;
|
||||
|
||||
@Schema(description = "退款钱包赠送金额", example = "2421")
|
||||
@ExcelProperty("退款钱包赠送金额")
|
||||
private Integer refundBonusPrice;
|
||||
|
||||
@Schema(description = "退款时间")
|
||||
@ExcelProperty("退款时间")
|
||||
private LocalDateTime refundTime;
|
||||
|
||||
@Schema(description = "退款状态", example = "2")
|
||||
@ExcelProperty("退款状态")
|
||||
private Integer refundStatus;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
private String avatar;
|
||||
|
||||
private String name;
|
||||
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.recharge;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import javax.validation.constraints.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 钱包充值新增/修改 Request VO")
|
||||
@Data
|
||||
public class WalletRechargeSaveReqVO {
|
||||
|
||||
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "13484")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "钱包编号", example = "3219")
|
||||
private Long walletId;
|
||||
|
||||
@Schema(description = "充值实际到账", example = "24628")
|
||||
private Integer totalPrice;
|
||||
|
||||
@Schema(description = "实际支付金额", example = "11386")
|
||||
private Integer payPrice;
|
||||
|
||||
@Schema(description = "钱包赠送金额", example = "6594")
|
||||
private Integer bonusPrice;
|
||||
|
||||
@Schema(description = "充值套餐编号", example = "2831")
|
||||
private Long packageId;
|
||||
|
||||
@Schema(description = "是否支付", example = "2")
|
||||
private Boolean payStatus;
|
||||
|
||||
@Schema(description = "支付订单编号", example = "5515")
|
||||
private Long payOrderId;
|
||||
|
||||
@Schema(description = "支付成功的支付渠道")
|
||||
private String payChannelCode;
|
||||
|
||||
@Schema(description = "订单支付时间")
|
||||
private LocalDateTime payTime;
|
||||
|
||||
@Schema(description = "支付退款单编号", example = "22733")
|
||||
private Long payRefundId;
|
||||
|
||||
@Schema(description = "退款金额(包含赠送金额)", example = "15904")
|
||||
private Integer refundTotalPrice;
|
||||
|
||||
@Schema(description = "退款支付金额", example = "30626")
|
||||
private Integer refundPayPrice;
|
||||
|
||||
@Schema(description = "退款钱包赠送金额", example = "2421")
|
||||
private Integer refundBonusPrice;
|
||||
|
||||
@Schema(description = "退款时间")
|
||||
private LocalDateTime refundTime;
|
||||
|
||||
@Schema(description = "退款状态", example = "2")
|
||||
private Integer refundStatus;
|
||||
|
||||
}
|
@ -4,10 +4,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
|
||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
@ -114,4 +111,10 @@ public class PayWalletRechargeDO extends BaseDO {
|
||||
*/
|
||||
private Integer refundStatus;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String avatar;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String name;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,95 @@
|
||||
package cn.iocoder.yudao.module.pay.dal.dataobject.wallet;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 钱包充值 DO
|
||||
*
|
||||
* @author 管理员
|
||||
*/
|
||||
@TableName("pay_wallet_recharge")
|
||||
@KeySequence("pay_wallet_recharge_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class WalletRechargeDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 钱包编号
|
||||
*/
|
||||
private Long walletId;
|
||||
/**
|
||||
* 充值实际到账
|
||||
*/
|
||||
private Integer totalPrice;
|
||||
/**
|
||||
* 实际支付金额
|
||||
*/
|
||||
private Integer payPrice;
|
||||
/**
|
||||
* 钱包赠送金额
|
||||
*/
|
||||
private Integer bonusPrice;
|
||||
/**
|
||||
* 充值套餐编号
|
||||
*/
|
||||
private Long packageId;
|
||||
/**
|
||||
* 是否支付
|
||||
*
|
||||
* 枚举 {@link TODO pay_wallet_recharge_pay_status 对应的类}
|
||||
*/
|
||||
private Boolean payStatus;
|
||||
/**
|
||||
* 支付订单编号
|
||||
*/
|
||||
private Long payOrderId;
|
||||
/**
|
||||
* 支付成功的支付渠道
|
||||
*/
|
||||
private String payChannelCode;
|
||||
/**
|
||||
* 订单支付时间
|
||||
*/
|
||||
private LocalDateTime payTime;
|
||||
/**
|
||||
* 支付退款单编号
|
||||
*/
|
||||
private Long payRefundId;
|
||||
/**
|
||||
* 退款金额(包含赠送金额)
|
||||
*/
|
||||
private Integer refundTotalPrice;
|
||||
/**
|
||||
* 退款支付金额
|
||||
*/
|
||||
private Integer refundPayPrice;
|
||||
/**
|
||||
* 退款钱包赠送金额
|
||||
*/
|
||||
private Integer refundBonusPrice;
|
||||
/**
|
||||
* 退款时间
|
||||
*/
|
||||
private LocalDateTime refundTime;
|
||||
/**
|
||||
* 退款状态
|
||||
*/
|
||||
private Integer refundStatus;
|
||||
|
||||
}
|
@ -4,8 +4,10 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.recharge.WalletRechargePageReqVO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargeDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargePackageDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.WalletRechargeDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
@ -28,4 +30,25 @@ public interface PayWalletRechargeMapper extends BaseMapperX<PayWalletRechargeDO
|
||||
.orderByDesc(PayWalletRechargeDO::getId));
|
||||
}
|
||||
|
||||
default PageResult<PayWalletRechargeDO> selectPage(WalletRechargePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<PayWalletRechargeDO>()
|
||||
.eqIfPresent(PayWalletRechargeDO::getWalletId, reqVO.getWalletId())
|
||||
.eqIfPresent(PayWalletRechargeDO::getTotalPrice, reqVO.getTotalPrice())
|
||||
.eqIfPresent(PayWalletRechargeDO::getPayPrice, reqVO.getPayPrice())
|
||||
.eqIfPresent(PayWalletRechargeDO::getBonusPrice, reqVO.getBonusPrice())
|
||||
.eqIfPresent(PayWalletRechargeDO::getPackageId, reqVO.getPackageId())
|
||||
.eqIfPresent(PayWalletRechargeDO::getPayStatus, reqVO.getPayStatus())
|
||||
.eqIfPresent(PayWalletRechargeDO::getPayOrderId, reqVO.getPayOrderId())
|
||||
.eqIfPresent(PayWalletRechargeDO::getPayChannelCode, reqVO.getPayChannelCode())
|
||||
.betweenIfPresent(PayWalletRechargeDO::getPayTime, reqVO.getPayTime())
|
||||
.eqIfPresent(PayWalletRechargeDO::getPayRefundId, reqVO.getPayRefundId())
|
||||
.eqIfPresent(PayWalletRechargeDO::getRefundTotalPrice, reqVO.getRefundTotalPrice())
|
||||
.eqIfPresent(PayWalletRechargeDO::getRefundPayPrice, reqVO.getRefundPayPrice())
|
||||
.eqIfPresent(PayWalletRechargeDO::getRefundBonusPrice, reqVO.getRefundBonusPrice())
|
||||
.betweenIfPresent(PayWalletRechargeDO::getRefundTime, reqVO.getRefundTime())
|
||||
.eqIfPresent(PayWalletRechargeDO::getRefundStatus, reqVO.getRefundStatus())
|
||||
.betweenIfPresent(PayWalletRechargeDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(PayWalletRechargeDO::getId));
|
||||
}
|
||||
|
||||
}
|
@ -2,9 +2,11 @@ package cn.iocoder.yudao.module.pay.service.wallet;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.recharge.WalletRechargePageReqVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge.AppPayWalletRechargeCreateReqVO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargeDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargePackageDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.WalletRechargeDO;
|
||||
|
||||
/**
|
||||
* 钱包充值 Service 接口
|
||||
@ -61,4 +63,12 @@ public interface PayWalletRechargeService {
|
||||
*/
|
||||
void updateWalletRechargeRefunded(Long id, Long payRefundId);
|
||||
|
||||
/**
|
||||
* 获得钱包充值分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 钱包充值分页
|
||||
*/
|
||||
PageResult<PayWalletRechargeDO> getWalletRechargePage(WalletRechargePageReqVO pageReqVO);
|
||||
|
||||
}
|
||||
|
@ -4,14 +4,19 @@ import cn.hutool.core.lang.Assert;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum;
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.wallet.vo.recharge.WalletRechargePageReqVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge.AppPayWalletRechargeCreateReqVO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargeDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargePackageDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.WalletRechargeDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletMapper;
|
||||
import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletRechargeMapper;
|
||||
import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
||||
@ -53,9 +58,14 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService {
|
||||
|
||||
private static final String WALLET_RECHARGE_ORDER_SUBJECT = "钱包余额充值";
|
||||
|
||||
@Resource
|
||||
private MemberUserApi memberUserApi;
|
||||
|
||||
@Resource
|
||||
private PayWalletRechargeMapper walletRechargeMapper;
|
||||
@Resource
|
||||
private PayWalletMapper payWalletMapper;
|
||||
@Resource
|
||||
private PayWalletService payWalletService;
|
||||
@Resource
|
||||
private PayOrderService payOrderService;
|
||||
@ -205,6 +215,24 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService {
|
||||
walletRechargeMapper.updateByIdAndRefunded(id, WAITING.getStatus(), updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<PayWalletRechargeDO> getWalletRechargePage(WalletRechargePageReqVO pageReqVO) {
|
||||
PageResult<PayWalletRechargeDO> payWalletRechargeDOPageResult = walletRechargeMapper.selectPage(pageReqVO);
|
||||
for (int i = 0; i < payWalletRechargeDOPageResult.getList().size(); i++) {
|
||||
PayWalletRechargeDO payWalletRechargeDO = payWalletRechargeDOPageResult.getList().get(i);
|
||||
payWalletRechargeDO.setPayPrice((int) (payWalletRechargeDO.getPayPrice() * 0.01));
|
||||
|
||||
//获取用户头像和昵称
|
||||
PayWalletDO payWalletDO = payWalletMapper.selectById(payWalletRechargeDO.getWalletId());
|
||||
MemberUserRespDTO user = memberUserApi.getUser(payWalletDO.getUserId());
|
||||
|
||||
payWalletRechargeDO.setName(user.getNickname());
|
||||
payWalletRechargeDO.setAvatar(user.getAvatar());
|
||||
|
||||
}
|
||||
return payWalletRechargeDOPageResult;
|
||||
}
|
||||
|
||||
private PayRefundDO validateWalletRechargeCanRefunded(PayWalletRechargeDO walletRecharge, Long payRefundId) {
|
||||
// 1. 校验退款订单匹配
|
||||
if (notEqual(walletRecharge.getPayRefundId(), payRefundId)) {
|
||||
@ -295,4 +323,5 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService {
|
||||
return payOrder;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -27,4 +27,7 @@ public interface NotifyMessageSendApi {
|
||||
*/
|
||||
Long sendSingleMessageToMember(@Valid NotifySendSingleToUserReqDTO reqDTO);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -40,10 +40,12 @@ public class DictDataController {
|
||||
@Resource
|
||||
private DictDataService dictDataService;
|
||||
|
||||
|
||||
@Resource
|
||||
public DictDataApi dictDataApi;
|
||||
|
||||
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "新增字典数据")
|
||||
@PreAuthorize("@ss.hasPermission('system:dict:create')")
|
||||
@ -159,6 +161,54 @@ public class DictDataController {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改装修商品分类字典数据
|
||||
*/
|
||||
@GetMapping(value = "/diy-template-goods")
|
||||
public CommonResult<String> setGoods(String id) {
|
||||
List<DictDataRespDTO> dictDataList = dictDataApi.getDictDataList("diy-template-goods");
|
||||
DictDataRespDTO dictDataRespDTO = dictDataList.get(0);
|
||||
DictDataSaveReqVO dictDataSaveReqVO = BeanUtils.toBean(dictDataRespDTO, DictDataSaveReqVO.class);
|
||||
dictDataSaveReqVO.setValue(id);
|
||||
dictDataService.updateDictData(dictDataSaveReqVO);
|
||||
return success(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改装修商品分类字典数据
|
||||
*/
|
||||
@GetMapping(value = "/getGoods")
|
||||
public CommonResult<String> getGoods() {
|
||||
List<DictDataRespDTO> dictDataList = dictDataApi.getDictDataList("diy-template-goods");
|
||||
DictDataRespDTO dictDataRespDTO = dictDataList.get(0);
|
||||
return success(dictDataRespDTO.getValue());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改装修装修风格字典数据
|
||||
*/
|
||||
@GetMapping(value = "/diy-template-theme")
|
||||
public CommonResult<String> setTheme(String id) {
|
||||
List<DictDataRespDTO> dictDataList = dictDataApi.getDictDataList("diy-template-theme");
|
||||
DictDataRespDTO dictDataRespDTO = dictDataList.get(0);
|
||||
DictDataSaveReqVO dictDataSaveReqVO = BeanUtils.toBean(dictDataRespDTO, DictDataSaveReqVO.class);
|
||||
dictDataSaveReqVO.setValue(id);
|
||||
dictDataService.updateDictData(dictDataSaveReqVO);
|
||||
return success(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改装修装修风格字典数据
|
||||
*/
|
||||
@GetMapping(value = "/getTheme")
|
||||
public CommonResult<String> getTheme() {
|
||||
List<DictDataRespDTO> dictDataList = dictDataApi.getDictDataList("diy-template-theme");
|
||||
DictDataRespDTO dictDataRespDTO = dictDataList.get(0);
|
||||
return success(dictDataRespDTO.getValue());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -254,6 +254,7 @@ public class SocialClientServiceImpl implements SocialClientService {
|
||||
ObjUtil.defaultIfNull(reqVO.getAutoColor(), SocialWxQrcodeReqDTO.AUTO_COLOR),
|
||||
null,
|
||||
ObjUtil.defaultIfNull(reqVO.getHyaline(), SocialWxQrcodeReqDTO.HYALINE));
|
||||
|
||||
} catch (WxErrorException e) {
|
||||
log.error("[getWxQrcode][reqVO({})) 获得小程序码失败]", reqVO, e);
|
||||
throw exception(SOCIAL_CLIENT_WEIXIN_MINI_APP_QRCODE_ERROR);
|
||||
|
@ -57,7 +57,7 @@ spring:
|
||||
# url: jdbc:kingbase8://127.0.0.1:54321/test # 人大金仓 KingbaseES 连接的示例
|
||||
# url: jdbc:postgresql://127.0.0.1:5432/postgres # OpenGauss 连接的示例
|
||||
username: root
|
||||
# password: 123456
|
||||
# password: 123456
|
||||
password: xpower1234
|
||||
# username: sa # SQL Server 连接的示例
|
||||
# password: Yudao@2024 # SQL Server 连接的示例
|
||||
@ -228,7 +228,7 @@ yudao:
|
||||
enable: false
|
||||
demo: false # 关闭演示模式
|
||||
wxa-code:
|
||||
env-version: develop # 小程序版本: 正式版为 "release";体验版为 "trial";开发版为 "develop"
|
||||
env-version: release # 小程序版本: 正式版为 "release";体验版为 "trial";开发版为 "develop"
|
||||
tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc
|
||||
|
||||
justauth:
|
||||
|
@ -210,7 +210,7 @@ yudao:
|
||||
websocket:
|
||||
enable: true # websocket的开关
|
||||
path: /infra/ws # 路径
|
||||
sender-type: local # 消息发送的类型,可选值为 local、redis、rocketmq、kafka、rabbitmq
|
||||
sender-type: redis # 消息发送的类型,可选值为 local、redis、rocketmq、kafka、rabbitmq
|
||||
sender-rocketmq:
|
||||
topic: ${spring.application.name}-websocket # 消息发送的 RocketMQ Topic
|
||||
consumer-group: ${spring.application.name}-websocket-consumer # 消息发送的 RocketMQ Consumer Group
|
||||
|
Loading…
x
Reference in New Issue
Block a user