Merge branch 'master' of https://gitee.com/yudaocode/yudao-ui-admin-vue3
commit
d9ed3d1a6b
@ -0,0 +1,57 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
export interface BusinessVO {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
statusTypeId: number
|
||||||
|
statusId: number
|
||||||
|
contactNextTime: Date
|
||||||
|
customerId: number
|
||||||
|
dealTime: Date
|
||||||
|
price: number
|
||||||
|
discountPercent: number
|
||||||
|
productPrice: number
|
||||||
|
remark: string
|
||||||
|
ownerUserId: number
|
||||||
|
roUserIds: string
|
||||||
|
rwUserIds: string
|
||||||
|
endStatus: number
|
||||||
|
endRemark: string
|
||||||
|
contactLastTime: Date
|
||||||
|
followUpStatus: number
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询 CRM 商机列表
|
||||||
|
export const getBusinessPage = async (params) => {
|
||||||
|
return await request.get({ url: `/crm/business/page`, params })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询 CRM 商机列表,基于指定客户
|
||||||
|
export const getBusinessPageByCustomer = async (params) => {
|
||||||
|
return await request.get({ url: `/crm/business/page-by-customer`, params })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询 CRM 商机详情
|
||||||
|
export const getBusiness = async (id: number) => {
|
||||||
|
return await request.get({ url: `/crm/business/get?id=` + id })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增 CRM 商机
|
||||||
|
export const createBusiness = async (data: BusinessVO) => {
|
||||||
|
return await request.post({ url: `/crm/business/create`, data })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改 CRM 商机
|
||||||
|
export const updateBusiness = async (data: BusinessVO) => {
|
||||||
|
return await request.put({ url: `/crm/business/update`, data })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除 CRM 商机
|
||||||
|
export const deleteBusiness = async (id: number) => {
|
||||||
|
return await request.delete({ url: `/crm/business/delete?id=` + id })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出 CRM 商机 Excel
|
||||||
|
export const exportBusiness = async (params) => {
|
||||||
|
return await request.download({ url: `/crm/business/export-excel`, params })
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
export interface BusinessStatusTypeVO {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
deptIds: number[]
|
||||||
|
status: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询商机状态类型列表
|
||||||
|
export const getBusinessStatusTypePage = async (params) => {
|
||||||
|
return await request.get({ url: `/crm/business-status-type/page`, params })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询商机状态类型详情
|
||||||
|
export const getBusinessStatusType = async (id: number) => {
|
||||||
|
return await request.get({ url: `/crm/business-status-type/get?id=` + id })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增商机状态类型
|
||||||
|
export const createBusinessStatusType = async (data: BusinessStatusTypeVO) => {
|
||||||
|
return await request.post({ url: `/crm/business-status-type/create`, data })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改商机状态类型
|
||||||
|
export const updateBusinessStatusType = async (data: BusinessStatusTypeVO) => {
|
||||||
|
return await request.put({ url: `/crm/business-status-type/update`, data })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除商机状态类型
|
||||||
|
export const deleteBusinessStatusType = async (id: number) => {
|
||||||
|
return await request.delete({ url: `/crm/business-status-type/delete?id=` + id })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出商机状态类型 Excel
|
||||||
|
export const exportBusinessStatusType = async (params) => {
|
||||||
|
return await request.download({ url: `/crm/business-status-type/export-excel`, params })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取商机状态类型信息列表
|
||||||
|
export const getBusinessStatusTypeList = async () => {
|
||||||
|
return await request.get({ url: `/crm/business-status-type/get-simple-list` })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据类型ID获取商机状态信息列表
|
||||||
|
export const getBusinessStatusListByTypeId = async (typeId: number) => {
|
||||||
|
return await request.get({ url: `/crm/business-status-type/get-status-list?typeId=` + typeId })
|
||||||
|
}
|
||||||
@ -0,0 +1,246 @@
|
|||||||
|
// APP 链接类型(需要特殊处理,例如商品详情)
|
||||||
|
export const enum APP_LINK_TYPE_ENUM {
|
||||||
|
// 拼团活动
|
||||||
|
ACTIVITY_COMBINATION,
|
||||||
|
// 秒杀活动
|
||||||
|
ACTIVITY_SECKILL,
|
||||||
|
// 文章详情
|
||||||
|
ARTICLE_DETAIL,
|
||||||
|
// 优惠券详情
|
||||||
|
COUPON_DETAIL,
|
||||||
|
// 自定义页面详情
|
||||||
|
DIY_PAGE_DETAIL,
|
||||||
|
// 品类列表
|
||||||
|
PRODUCT_CATEGORY_LIST,
|
||||||
|
// 商品列表
|
||||||
|
PRODUCT_LIST,
|
||||||
|
// 商品详情
|
||||||
|
PRODUCT_DETAIL_NORMAL,
|
||||||
|
// 拼团商品详情
|
||||||
|
PRODUCT_DETAIL_COMBINATION,
|
||||||
|
// 积分商品详情
|
||||||
|
PRODUCT_DETAIL_POINT,
|
||||||
|
// 秒杀商品详情
|
||||||
|
PRODUCT_DETAIL_SECKILL
|
||||||
|
}
|
||||||
|
|
||||||
|
// APP 链接列表(做一下持久化?)
|
||||||
|
export const APP_LINK_GROUP_LIST = [
|
||||||
|
{
|
||||||
|
name: '商城',
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
name: '首页',
|
||||||
|
path: '/pages/index/index'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '商品分类',
|
||||||
|
path: '/pages/index/category',
|
||||||
|
type: APP_LINK_TYPE_ENUM.PRODUCT_CATEGORY_LIST
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '购物车',
|
||||||
|
path: '/pages/index/cart'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '个人中心',
|
||||||
|
path: '/pages/index/user'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '商品搜索',
|
||||||
|
path: '/pages/index/search'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '自定义页面',
|
||||||
|
path: '/pages/index/page',
|
||||||
|
type: APP_LINK_TYPE_ENUM.DIY_PAGE_DETAIL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '客服',
|
||||||
|
path: '/pages/chat/index'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '系统设置',
|
||||||
|
path: '/pages/public/setting'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '问题反馈',
|
||||||
|
path: '/pages/public/feedback'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '常见问题',
|
||||||
|
path: '/pages/public/faq'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '商品',
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
name: '商品列表',
|
||||||
|
path: '/pages/goods/list',
|
||||||
|
type: APP_LINK_TYPE_ENUM.PRODUCT_LIST
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '商品详情',
|
||||||
|
path: '/pages/goods/index',
|
||||||
|
type: APP_LINK_TYPE_ENUM.PRODUCT_DETAIL_NORMAL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '拼团商品详情',
|
||||||
|
path: '/pages/goods/groupon',
|
||||||
|
type: APP_LINK_TYPE_ENUM.PRODUCT_DETAIL_COMBINATION
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '秒杀商品详情',
|
||||||
|
path: '/pages/goods/seckill',
|
||||||
|
type: APP_LINK_TYPE_ENUM.PRODUCT_DETAIL_SECKILL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '积分商品详情',
|
||||||
|
path: '/pages/goods/score',
|
||||||
|
type: APP_LINK_TYPE_ENUM.PRODUCT_DETAIL_POINT
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '营销活动',
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
name: '拼团订单',
|
||||||
|
path: '/pages/activity/groupon/order'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '营销商品',
|
||||||
|
path: '/pages/activity/index'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '拼团活动',
|
||||||
|
path: '/pages/activity/groupon/list',
|
||||||
|
type: APP_LINK_TYPE_ENUM.ACTIVITY_COMBINATION
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '秒杀活动',
|
||||||
|
path: '/pages/activity/seckill/list',
|
||||||
|
type: APP_LINK_TYPE_ENUM.ACTIVITY_SECKILL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '签到中心',
|
||||||
|
path: '/pages/app/sign'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '积分商城',
|
||||||
|
path: '/pages/app/score-shop'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '优惠券中心',
|
||||||
|
path: '/pages/coupon/list'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '优惠券详情',
|
||||||
|
path: '/pages/coupon/detail',
|
||||||
|
type: APP_LINK_TYPE_ENUM.COUPON_DETAIL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '文章详情',
|
||||||
|
path: '/pages/public/richtext',
|
||||||
|
type: APP_LINK_TYPE_ENUM.ARTICLE_DETAIL
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '分销商城',
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
name: '分销中心',
|
||||||
|
path: '/pages/commission/index'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '申请分销商',
|
||||||
|
path: '/pages/commission/apply'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '推广商品',
|
||||||
|
path: '/pages/commission/goods'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '分销订单',
|
||||||
|
path: '/pages/commission/order'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '分享记录',
|
||||||
|
path: '/pages/commission/share-log'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '我的团队',
|
||||||
|
path: '/pages/commission/team'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '支付',
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
name: '充值余额',
|
||||||
|
path: '/pages/pay/recharge'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '充值记录',
|
||||||
|
path: '/pages/pay/recharge-log'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '申请提现',
|
||||||
|
path: '/pages/pay/withdraw'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '提现记录',
|
||||||
|
path: '/pages/pay/withdraw-log'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '用户中心',
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
name: '用户信息',
|
||||||
|
path: '/pages/user/info'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '用户订单',
|
||||||
|
path: '/pages/order/list'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '售后订单',
|
||||||
|
path: '/pages/order/aftersale/list'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '商品收藏',
|
||||||
|
path: '/pages/user/goods-collect'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '浏览记录',
|
||||||
|
path: '/pages/user/goods-log'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '地址管理',
|
||||||
|
path: '/pages/user/address/list'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '发票管理',
|
||||||
|
path: '/pages/user/invoice/list'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '用户佣金',
|
||||||
|
path: '/pages/user/wallet/commission'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '用户余额',
|
||||||
|
path: '/pages/user/wallet/money'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '用户积分',
|
||||||
|
path: '/pages/user/wallet/score'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
<template>
|
||||||
|
<el-input v-model="appLink" placeholder="输入或选择链接">
|
||||||
|
<template #append>
|
||||||
|
<el-button @click="handleOpenDialog">选择</el-button>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
<AppLinkSelectDialog ref="dialogRef" @change="handleLinkSelected" />
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { propTypes } from '@/utils/propTypes'
|
||||||
|
|
||||||
|
// APP 链接输入框
|
||||||
|
defineOptions({ name: 'AppLinkInput' })
|
||||||
|
// 定义属性
|
||||||
|
const props = defineProps({
|
||||||
|
// 当前选中的链接
|
||||||
|
modelValue: propTypes.string.def('')
|
||||||
|
})
|
||||||
|
// 当前的链接
|
||||||
|
const appLink = ref('')
|
||||||
|
// 选择对话框
|
||||||
|
const dialogRef = ref()
|
||||||
|
// 处理打开对话框
|
||||||
|
const handleOpenDialog = () => dialogRef.value?.open(appLink.value)
|
||||||
|
// 处理 APP 链接选中
|
||||||
|
const handleLinkSelected = (link: string) => (appLink.value = link)
|
||||||
|
|
||||||
|
// getter
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
() => (appLink.value = props.modelValue),
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
// setter
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'update:modelValue': [link: string]
|
||||||
|
}>()
|
||||||
|
watch(
|
||||||
|
() => appLink,
|
||||||
|
() => emit('update:modelValue', appLink.value)
|
||||||
|
)
|
||||||
|
</script>
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
|
||||||
|
|
||||||
|
/** 营销文章属性 */
|
||||||
|
export interface PromotionArticleProperty {
|
||||||
|
// 文章编号
|
||||||
|
id: number
|
||||||
|
// 组件样式
|
||||||
|
style: ComponentStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义组件
|
||||||
|
export const component = {
|
||||||
|
id: 'PromotionArticle',
|
||||||
|
name: '营销文章',
|
||||||
|
icon: 'ph:article-medium',
|
||||||
|
property: {
|
||||||
|
style: {
|
||||||
|
bgType: 'color',
|
||||||
|
bgColor: '',
|
||||||
|
marginLeft: 8,
|
||||||
|
marginRight: 8,
|
||||||
|
marginBottom: 8
|
||||||
|
} as ComponentStyle
|
||||||
|
}
|
||||||
|
} as DiyComponent<PromotionArticleProperty>
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
<template>
|
||||||
|
<div class="min-h-30px" v-html="article.content"></div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { PromotionArticleProperty } from './config'
|
||||||
|
import * as ArticleApi from '@/api/mall/promotion/article/index'
|
||||||
|
|
||||||
|
/** 营销文章 */
|
||||||
|
defineOptions({ name: 'PromotionArticle' })
|
||||||
|
// 定义属性
|
||||||
|
const props = defineProps<{ property: PromotionArticleProperty }>()
|
||||||
|
// 商品列表
|
||||||
|
const article = ref<ArticleApi.ArticleVO[]>({})
|
||||||
|
watch(
|
||||||
|
() => props.property.id,
|
||||||
|
async () => {
|
||||||
|
if (props.property.id) {
|
||||||
|
article.value = await ArticleApi.getArticle(props.property.id)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
<template>
|
||||||
|
<ComponentContainerProperty v-model="formData.style">
|
||||||
|
<el-form label-width="40px" :model="formData">
|
||||||
|
<el-form-item label="文章" prop="id">
|
||||||
|
<el-select
|
||||||
|
v-model="formData.id"
|
||||||
|
placeholder="请选择文章"
|
||||||
|
class="w-full"
|
||||||
|
filterable
|
||||||
|
remote
|
||||||
|
:remote-method="queryArticleList"
|
||||||
|
:loading="loading"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="article in articles"
|
||||||
|
:key="article.id"
|
||||||
|
:label="article.title"
|
||||||
|
:value="article.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</ComponentContainerProperty>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { PromotionArticleProperty } from './config'
|
||||||
|
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||||
|
import * as ArticleApi from '@/api/mall/promotion/article/index'
|
||||||
|
|
||||||
|
// 营销文章属性面板
|
||||||
|
defineOptions({ name: 'PromotionArticleProperty' })
|
||||||
|
|
||||||
|
const props = defineProps<{ modelValue: PromotionArticleProperty }>()
|
||||||
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||||
|
// 文章列表
|
||||||
|
const articles = ref<ArticleApi.ArticleVO>([])
|
||||||
|
|
||||||
|
// 加载中
|
||||||
|
const loading = ref(false)
|
||||||
|
// 查询文章列表
|
||||||
|
const queryArticleList = async (title?: string) => {
|
||||||
|
loading.value = true
|
||||||
|
const { list } = await ArticleApi.getArticlePage({ title, pageSize: 10 })
|
||||||
|
articles.value = list
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
queryArticleList()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
|
||||||
|
|
||||||
|
/** 拼团属性 */
|
||||||
|
export interface PromotionCombinationProperty {
|
||||||
|
// 布局类型:单列 | 三列
|
||||||
|
layoutType: 'oneCol' | 'threeCol'
|
||||||
|
// 商品字段
|
||||||
|
fields: {
|
||||||
|
// 商品名称
|
||||||
|
name: PromotionCombinationFieldProperty
|
||||||
|
// 商品价格
|
||||||
|
price: PromotionCombinationFieldProperty
|
||||||
|
}
|
||||||
|
// 角标
|
||||||
|
badge: {
|
||||||
|
// 是否显示
|
||||||
|
show: boolean
|
||||||
|
// 角标图片
|
||||||
|
imgUrl: string
|
||||||
|
}
|
||||||
|
// 上圆角
|
||||||
|
borderRadiusTop: number
|
||||||
|
// 下圆角
|
||||||
|
borderRadiusBottom: number
|
||||||
|
// 间距
|
||||||
|
space: number
|
||||||
|
// 拼团活动编号
|
||||||
|
activityId: number
|
||||||
|
// 组件样式
|
||||||
|
style: ComponentStyle
|
||||||
|
}
|
||||||
|
// 商品字段
|
||||||
|
export interface PromotionCombinationFieldProperty {
|
||||||
|
// 是否显示
|
||||||
|
show: boolean
|
||||||
|
// 颜色
|
||||||
|
color: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义组件
|
||||||
|
export const component = {
|
||||||
|
id: 'PromotionCombination',
|
||||||
|
name: '拼团',
|
||||||
|
icon: 'mdi:account-group',
|
||||||
|
property: {
|
||||||
|
activityId: undefined,
|
||||||
|
layoutType: 'oneCol',
|
||||||
|
fields: {
|
||||||
|
name: { show: true, color: '#000' },
|
||||||
|
price: { show: true, color: '#ff3000' }
|
||||||
|
},
|
||||||
|
badge: { show: false, imgUrl: '' },
|
||||||
|
borderRadiusTop: 8,
|
||||||
|
borderRadiusBottom: 8,
|
||||||
|
space: 8,
|
||||||
|
style: {
|
||||||
|
bgType: 'color',
|
||||||
|
bgColor: '',
|
||||||
|
marginLeft: 8,
|
||||||
|
marginRight: 8,
|
||||||
|
marginBottom: 8
|
||||||
|
} as ComponentStyle
|
||||||
|
}
|
||||||
|
} as DiyComponent<PromotionCombinationProperty>
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
|
||||||
|
|
||||||
|
/** 秒杀属性 */
|
||||||
|
export interface PromotionSeckillProperty {
|
||||||
|
// 布局类型:单列 | 三列
|
||||||
|
layoutType: 'oneCol' | 'threeCol'
|
||||||
|
// 商品字段
|
||||||
|
fields: {
|
||||||
|
// 商品名称
|
||||||
|
name: PromotionSeckillFieldProperty
|
||||||
|
// 商品价格
|
||||||
|
price: PromotionSeckillFieldProperty
|
||||||
|
}
|
||||||
|
// 角标
|
||||||
|
badge: {
|
||||||
|
// 是否显示
|
||||||
|
show: boolean
|
||||||
|
// 角标图片
|
||||||
|
imgUrl: string
|
||||||
|
}
|
||||||
|
// 上圆角
|
||||||
|
borderRadiusTop: number
|
||||||
|
// 下圆角
|
||||||
|
borderRadiusBottom: number
|
||||||
|
// 间距
|
||||||
|
space: number
|
||||||
|
// 秒杀活动编号
|
||||||
|
activityId: number
|
||||||
|
// 组件样式
|
||||||
|
style: ComponentStyle
|
||||||
|
}
|
||||||
|
// 商品字段
|
||||||
|
export interface PromotionSeckillFieldProperty {
|
||||||
|
// 是否显示
|
||||||
|
show: boolean
|
||||||
|
// 颜色
|
||||||
|
color: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义组件
|
||||||
|
export const component = {
|
||||||
|
id: 'PromotionSeckill',
|
||||||
|
name: '秒杀',
|
||||||
|
icon: 'mdi:calendar-time',
|
||||||
|
property: {
|
||||||
|
activityId: undefined,
|
||||||
|
layoutType: 'oneCol',
|
||||||
|
fields: {
|
||||||
|
name: { show: true, color: '#000' },
|
||||||
|
price: { show: true, color: '#ff3000' }
|
||||||
|
},
|
||||||
|
badge: { show: false, imgUrl: '' },
|
||||||
|
borderRadiusTop: 8,
|
||||||
|
borderRadiusBottom: 8,
|
||||||
|
space: 8,
|
||||||
|
style: {
|
||||||
|
bgType: 'color',
|
||||||
|
bgColor: '',
|
||||||
|
marginLeft: 8,
|
||||||
|
marginRight: 8,
|
||||||
|
marginBottom: 8
|
||||||
|
} as ComponentStyle
|
||||||
|
}
|
||||||
|
} as DiyComponent<PromotionSeckillProperty>
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
|
||||||
|
|
||||||
|
/** 用户卡片属性 */
|
||||||
|
export interface UserCardProperty {
|
||||||
|
// 组件样式
|
||||||
|
style: ComponentStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义组件
|
||||||
|
export const component = {
|
||||||
|
id: 'UserCard',
|
||||||
|
name: '用户卡片',
|
||||||
|
icon: 'mdi:user-card-details',
|
||||||
|
property: {
|
||||||
|
style: {
|
||||||
|
bgType: 'color',
|
||||||
|
bgColor: '',
|
||||||
|
marginBottom: 8
|
||||||
|
} as ComponentStyle
|
||||||
|
}
|
||||||
|
} as DiyComponent<UserCardProperty>
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<div class="flex items-center justify-between p-x-18px p-y-24px">
|
||||||
|
<div class="flex flex-1 items-center gap-16px">
|
||||||
|
<el-avatar :size="60">
|
||||||
|
<Icon icon="ep:avatar" :size="60" />
|
||||||
|
</el-avatar>
|
||||||
|
<span class="text-18px font-bold">芋道源码</span>
|
||||||
|
</div>
|
||||||
|
<Icon icon="tdesign:qrcode" :size="20" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex items-center justify-between justify-between bg-white p-x-20px p-y-8px text-12px"
|
||||||
|
>
|
||||||
|
<span class="color-#ff690d">点击绑定手机号</span>
|
||||||
|
<span class="rounded-26px bg-#ff6100 p-x-8px p-y-5px color-white">去绑定</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { UserCardProperty } from './config'
|
||||||
|
|
||||||
|
/** 用户卡片 */
|
||||||
|
defineOptions({ name: 'UserCard' })
|
||||||
|
// 定义属性
|
||||||
|
defineProps<{ property: UserCardProperty }>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
<template>
|
||||||
|
<ComponentContainerProperty v-model="formData.style" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { UserCardProperty } from './config'
|
||||||
|
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||||
|
|
||||||
|
// 用户卡片属性面板
|
||||||
|
defineOptions({ name: 'UserCardProperty' })
|
||||||
|
|
||||||
|
const props = defineProps<{ modelValue: UserCardProperty }>()
|
||||||
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
|
||||||
|
|
||||||
|
/** 用户卡券属性 */
|
||||||
|
export interface UserCouponProperty {
|
||||||
|
// 组件样式
|
||||||
|
style: ComponentStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义组件
|
||||||
|
export const component = {
|
||||||
|
id: 'UserCoupon',
|
||||||
|
name: '用户卡券',
|
||||||
|
icon: 'ep:ticket',
|
||||||
|
property: {
|
||||||
|
style: {
|
||||||
|
bgType: 'color',
|
||||||
|
bgColor: '',
|
||||||
|
marginLeft: 8,
|
||||||
|
marginRight: 8,
|
||||||
|
marginBottom: 8
|
||||||
|
} as ComponentStyle
|
||||||
|
}
|
||||||
|
} as DiyComponent<UserCouponProperty>
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
<template>
|
||||||
|
<el-image
|
||||||
|
src="https://shopro.sheepjs.com/admin/static/images/shop/decorate/couponCardStyle.png"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { UserCouponProperty } from './config'
|
||||||
|
|
||||||
|
/** 用户卡券 */
|
||||||
|
defineOptions({ name: 'UserCoupon' })
|
||||||
|
// 定义属性
|
||||||
|
defineProps<{ property: UserCouponProperty }>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
<template>
|
||||||
|
<ComponentContainerProperty v-model="formData.style" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { UserCouponProperty } from './config'
|
||||||
|
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||||
|
|
||||||
|
// 用户卡券属性面板
|
||||||
|
defineOptions({ name: 'UserCouponProperty' })
|
||||||
|
|
||||||
|
const props = defineProps<{ modelValue: UserCouponProperty }>()
|
||||||
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
|
||||||
|
|
||||||
|
/** 用户订单属性 */
|
||||||
|
export interface UserOrderProperty {
|
||||||
|
// 组件样式
|
||||||
|
style: ComponentStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义组件
|
||||||
|
export const component = {
|
||||||
|
id: 'UserOrder',
|
||||||
|
name: '用户订单',
|
||||||
|
icon: 'ep:list',
|
||||||
|
property: {
|
||||||
|
style: {
|
||||||
|
bgType: 'color',
|
||||||
|
bgColor: '',
|
||||||
|
marginLeft: 8,
|
||||||
|
marginRight: 8,
|
||||||
|
marginBottom: 8
|
||||||
|
} as ComponentStyle
|
||||||
|
}
|
||||||
|
} as DiyComponent<UserOrderProperty>
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
<template>
|
||||||
|
<el-image src="https://shopro.sheepjs.com/admin/static/images/shop/decorate/orderCardStyle.png" />
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { UserOrderProperty } from './config'
|
||||||
|
|
||||||
|
/** 用户订单 */
|
||||||
|
defineOptions({ name: 'UserOrder' })
|
||||||
|
// 定义属性
|
||||||
|
defineProps<{ property: UserOrderProperty }>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
<template>
|
||||||
|
<ComponentContainerProperty v-model="formData.style" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { UserOrderProperty } from './config'
|
||||||
|
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||||
|
|
||||||
|
// 用户订单属性面板
|
||||||
|
defineOptions({ name: 'UserOrderProperty' })
|
||||||
|
|
||||||
|
const props = defineProps<{ modelValue: UserOrderProperty }>()
|
||||||
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
|
||||||
|
|
||||||
|
/** 用户资产属性 */
|
||||||
|
export interface UserWalletProperty {
|
||||||
|
// 组件样式
|
||||||
|
style: ComponentStyle
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义组件
|
||||||
|
export const component = {
|
||||||
|
id: 'UserWallet',
|
||||||
|
name: '用户资产',
|
||||||
|
icon: 'ep:wallet-filled',
|
||||||
|
property: {
|
||||||
|
style: {
|
||||||
|
bgType: 'color',
|
||||||
|
bgColor: '',
|
||||||
|
marginLeft: 8,
|
||||||
|
marginRight: 8,
|
||||||
|
marginBottom: 8
|
||||||
|
} as ComponentStyle
|
||||||
|
}
|
||||||
|
} as DiyComponent<UserWalletProperty>
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
<template>
|
||||||
|
<el-image
|
||||||
|
src="https://shopro.sheepjs.com/admin/static/images/shop/decorate/walletCardStyle.png"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { UserWalletProperty } from './config'
|
||||||
|
|
||||||
|
/** 用户资产 */
|
||||||
|
defineOptions({ name: 'UserWallet' })
|
||||||
|
// 定义属性
|
||||||
|
defineProps<{ property: UserWalletProperty }>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
<template>
|
||||||
|
<ComponentContainerProperty v-model="formData.style" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { UserWalletProperty } from './config'
|
||||||
|
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||||
|
|
||||||
|
// 用户资产属性面板
|
||||||
|
defineOptions({ name: 'UserWalletProperty' })
|
||||||
|
|
||||||
|
const props = defineProps<{ modelValue: UserWalletProperty }>()
|
||||||
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@ -1,138 +0,0 @@
|
|||||||
<template>
|
|
||||||
<!-- 操作栏 -->
|
|
||||||
<el-row justify="end">
|
|
||||||
<el-button type="primary" @click="openForm">
|
|
||||||
<Icon class="mr-5px" icon="ep:plus" />
|
|
||||||
新增
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="handleEdit">
|
|
||||||
<Icon class="mr-5px" icon="ep:edit" />
|
|
||||||
编辑
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="handleDelete">
|
|
||||||
<Icon class="mr-5px" icon="ep:delete" />
|
|
||||||
移除
|
|
||||||
</el-button>
|
|
||||||
<el-button type="danger" @click="handleQuit"> 退出团队</el-button>
|
|
||||||
</el-row>
|
|
||||||
<!-- 团队成员展示 -->
|
|
||||||
<el-table
|
|
||||||
v-loading="loading"
|
|
||||||
:data="list"
|
|
||||||
:show-overflow-tooltip="true"
|
|
||||||
:stripe="true"
|
|
||||||
class="mt-20px"
|
|
||||||
@selection-change="handleSelectionChange"
|
|
||||||
>
|
|
||||||
<el-table-column type="selection" width="55" />
|
|
||||||
<el-table-column align="center" label="姓名" prop="nickname" />
|
|
||||||
<el-table-column align="center" label="部门" prop="deptName" />
|
|
||||||
<el-table-column align="center" label="岗位" prop="postNames" />
|
|
||||||
<el-table-column align="center" label="权限级别" prop="level">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<dict-tag :type="DICT_TYPE.CRM_PERMISSION_LEVEL" :value="row.level" />
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column :formatter="dateFormatter" align="center" label="加入时间" prop="createTime" />
|
|
||||||
</el-table>
|
|
||||||
<CrmPermissionForm ref="permissionFormRef" @success="getList" />
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { dateFormatter } from '@/utils/formatTime'
|
|
||||||
import { ElTable } from 'element-plus'
|
|
||||||
import * as PermissionApi from '@/api/crm/permission'
|
|
||||||
import { useUserStoreWithOut } from '@/store/modules/user'
|
|
||||||
import CrmPermissionForm from './CrmPermissionForm.vue'
|
|
||||||
import { CrmPermissionLevelEnum } from './index'
|
|
||||||
import { DICT_TYPE } from '@/utils/dict'
|
|
||||||
|
|
||||||
defineOptions({ name: 'CrmPermissionList' })
|
|
||||||
|
|
||||||
const message = useMessage() // 消息
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
bizType: number // 模块类型
|
|
||||||
bizId: number // 模块数据编号
|
|
||||||
}>()
|
|
||||||
const loading = ref(true) // 列表的加载中
|
|
||||||
const list = ref<PermissionApi.PermissionVO[]>([]) // 列表的数据
|
|
||||||
|
|
||||||
/** 查询列表 */
|
|
||||||
const getList = async () => {
|
|
||||||
loading.value = true
|
|
||||||
try {
|
|
||||||
const data = await PermissionApi.getPermissionList({
|
|
||||||
bizType: props.bizType,
|
|
||||||
bizId: props.bizId
|
|
||||||
})
|
|
||||||
list.value = data
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const multipleSelection = ref<PermissionApi.PermissionVO[]>([]) // 选择的团队成员
|
|
||||||
const handleSelectionChange = (val: PermissionApi.PermissionVO[]) => {
|
|
||||||
multipleSelection.value = val
|
|
||||||
}
|
|
||||||
|
|
||||||
const permissionFormRef = ref<InstanceType<typeof CrmPermissionForm>>() // 权限表单 Ref
|
|
||||||
/**
|
|
||||||
* 编辑团队成员
|
|
||||||
*/
|
|
||||||
const handleEdit = () => {
|
|
||||||
if (multipleSelection.value?.length === 0) {
|
|
||||||
message.warning('请先选择团队成员后操作!')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const ids = multipleSelection.value?.map((item) => item.id)
|
|
||||||
permissionFormRef.value?.open('update', props.bizType, props.bizId, ids)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 移除团队成员
|
|
||||||
*/
|
|
||||||
const handleDelete = async () => {
|
|
||||||
if (multipleSelection.value?.length === 0) {
|
|
||||||
message.warning('请先选择团队成员后操作!')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await message.delConfirm()
|
|
||||||
const ids = multipleSelection.value?.map((item) => item.id)
|
|
||||||
await PermissionApi.deletePermission({
|
|
||||||
bizType: props.bizType,
|
|
||||||
bizId: props.bizId,
|
|
||||||
ids
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 添加团队成员
|
|
||||||
*/
|
|
||||||
const openForm = () => {
|
|
||||||
permissionFormRef.value?.open('create', props.bizType, props.bizId)
|
|
||||||
}
|
|
||||||
|
|
||||||
const userStore = useUserStoreWithOut() // 用户信息缓存
|
|
||||||
/**
|
|
||||||
* 退出团队
|
|
||||||
*/
|
|
||||||
const handleQuit = async () => {
|
|
||||||
const permission = list.value.find(
|
|
||||||
(item) => item.userId === userStore.getUser.id && item.level === CrmPermissionLevelEnum.OWNER
|
|
||||||
)
|
|
||||||
if (permission) {
|
|
||||||
message.warning('负责人不能退出团队!')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const userPermission = list.value.find((item) => item.userId === userStore.getUser.id)
|
|
||||||
await PermissionApi.quitTeam(userPermission?.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.bizId,
|
|
||||||
() => {
|
|
||||||
getList()
|
|
||||||
},
|
|
||||||
{ immediate: true, deep: true }
|
|
||||||
)
|
|
||||||
</script>
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
import CrmPermissionList from './CrmPermissionList.vue'
|
|
||||||
|
|
||||||
enum CrmBizTypeEnum {
|
|
||||||
CRM_LEADS = 1, // 线索
|
|
||||||
CRM_CUSTOMER = 2, // 客户
|
|
||||||
CRM_CONTACTS = 3, // 联系人
|
|
||||||
CRM_BUSINESS = 5, // 商机
|
|
||||||
CRM_CONTRACT = 6 // 合同
|
|
||||||
}
|
|
||||||
|
|
||||||
enum CrmPermissionLevelEnum {
|
|
||||||
OWNER = 1 // 负责人
|
|
||||||
}
|
|
||||||
|
|
||||||
export { CrmPermissionList, CrmBizTypeEnum, CrmPermissionLevelEnum }
|
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 列表 -->
|
||||||
|
<ContentWrap>
|
||||||
|
<el-tabs>
|
||||||
|
<el-tab-pane label="拥有客户数限制">
|
||||||
|
<CustomerLimitConfigList :confType="LimitConfType.CUSTOMER_QUANTITY_LIMIT" />
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="锁定客户数限制">
|
||||||
|
<CustomerLimitConfigList :confType="LimitConfType.CUSTOMER_LOCK_LIMIT" />
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</ContentWrap>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import CustomerLimitConfigList from '@/views/crm/config/customerLimitConfig/CustomerLimitConfigList.vue'
|
||||||
|
import { LimitConfType } from '@/api/crm/customerLimitConfig'
|
||||||
|
|
||||||
|
defineOptions({ name: 'CrmCustomerLimitConfig' })
|
||||||
|
</script>
|
||||||
@ -1,16 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-col>
|
|
||||||
<el-row>
|
|
||||||
<span class="text-xl font-bold">{{ customer.name }}</span>
|
|
||||||
</el-row>
|
|
||||||
</el-col>
|
|
||||||
<el-col class="mt-10px">
|
|
||||||
<!-- TODO 标签 -->
|
|
||||||
<!-- <Icon icon="ant-design:tag-filled" />-->
|
|
||||||
</el-col>
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts">
|
|
||||||
import * as CustomerApi from '@/api/crm/customer'
|
|
||||||
|
|
||||||
const { customer } = defineProps<{ customer: CustomerApi.CustomerVO }>()
|
|
||||||
</script>
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue