Merge remote-tracking branch 'refs/remotes/yudao/dev' into dev-crm

# Conflicts:
#	src/components/FormCreate/src/components/useApiSelect.tsx
This commit is contained in:
puhui999 2024-05-09 18:04:17 +08:00
commit cb82578b27
26 changed files with 264 additions and 80 deletions

View File

@ -1,6 +1,6 @@
{
"name": "yudao-ui-admin-vue3",
"version": "2.0.1-snapshot",
"version": "2.1.0-snapshot",
"description": "基于vue3、vite4、element-plus、typesScript",
"author": "xingyu",
"private": false,

View File

@ -13,8 +13,8 @@ export interface ProductCategoryVO {
// ERP 产品分类 API
export const ProductCategoryApi = {
// 查询产品分类列表
getProductCategoryList: async (params) => {
return await request.get({ url: `/erp/product-category/list`, params })
getProductCategoryList: async () => {
return await request.get({ url: `/erp/product-category/list` })
},
// 查询产品分类精简列表

View File

@ -7,8 +7,8 @@ export interface Demo02CategoryVO {
}
// 查询示例分类列表
export const getDemo02CategoryList = async (params) => {
return await request.get({ url: `/infra/demo02-category/list`, params })
export const getDemo02CategoryList = async () => {
return await request.get({ url: `/infra/demo02-category/list` })
}
// 查询示例分类详情

View File

@ -17,6 +17,11 @@ export const SeckillConfigApi = {
return await request.get({ url: `/promotion/seckill-config/page`, params })
},
// 查询秒杀时段列表
getSimpleSeckillConfigList: async () => {
return await request.get({ url: `/promotion/seckill-config/simple-list` })
},
// 查询秒杀时段详情
getSeckillConfig: async (id: number) => {
return await request.get({ url: `/promotion/seckill-config/get?id=` + id })

View File

@ -141,7 +141,7 @@ export const getExpressTrackList = async (id: number | null) => {
}
export interface DeliveryVO {
id: number // 订单编号
id?: number // 订单编号
logisticsId: number | null // 物流公司编号
logisticsNo: string // 物流编号
}

View File

@ -6,6 +6,7 @@ import { cloneDeep } from 'lodash-es'
/**
* hook
*
* @param option
*/
export const useSelectRule = (option: SelectRuleOption) => {

View File

@ -17,6 +17,7 @@ import {
import FcDesigner from '@form-create/designer'
import formCreate from '@form-create/element-ui'
import install from '@form-create/element-ui/auto-import'
//======================= 自定义组件 =======================
import { UploadFile, UploadImg, UploadImgs } from '@/components/UploadFile'
import { useApiSelect } from '@/components/FormCreate'

View File

@ -1,4 +1,4 @@
import {toNumber} from 'lodash-es'
import { toNumber } from 'lodash-es'
/**
*
@ -445,7 +445,7 @@ export function jsonParse(str: string) {
try {
return JSON.parse(str)
} catch (e) {
console.log(`str[${str}] 不是一个 JSON 字符串`)
console.error(`str[${str}] 不是一个 JSON 字符串`)
return ''
}
}

View File

@ -62,7 +62,14 @@
<template #header>
<div class="h-3 flex justify-between">
<span>{{ t('workplace.project') }}</span>
<el-link type="primary" :underline="false">{{ t('action.more') }}</el-link>
<el-link
type="primary"
:underline="false"
href="https://github.com/yudaocode"
target="_blank"
>
{{ t('action.more') }}
</el-link>
</div>
</template>
<el-skeleton :loading="loading" animated>
@ -76,13 +83,13 @@
:sm="24"
:xs="24"
>
<el-card shadow="hover">
<el-card shadow="hover" class="mr-5px mt-5px">
<div class="flex items-center">
<Icon :icon="item.icon" :size="25" class="mr-8px" />
<span class="text-16px">{{ item.name }}</span>
</div>
<div class="mt-16px text-14px text-gray-400">{{ t(item.message) }}</div>
<div class="mt-16px flex justify-between text-12px text-gray-400">
<div class="mt-12px text-9px text-gray-400">{{ t(item.message) }}</div>
<div class="mt-12px flex justify-between text-12px text-gray-400">
<span>{{ item.personal }}</span>
<span>{{ formatTime(item.time, 'yyyy-MM-dd') }}</span>
</div>
@ -204,45 +211,45 @@ let projects = reactive<Project[]>([])
const getProject = async () => {
const data = [
{
name: 'Github',
name: 'ruoyi-vue-pro',
icon: 'akar-icons:github-fill',
message: 'workplace.introduction',
personal: 'Archer',
message: 'https://github.com/YunaiV/ruoyi-vue-pro',
personal: 'Spring Boot 单体架构',
time: new Date()
},
{
name: 'Vue',
name: 'yudao-ui-admin-vue3',
icon: 'logos:vue',
message: 'workplace.introduction',
personal: 'Archer',
message: 'https://github.com/yudaocode/yudao-ui-admin-vue3',
personal: 'Vue3 + element-plus',
time: new Date()
},
{
name: 'Angular',
icon: 'logos:angular-icon',
message: 'workplace.introduction',
personal: 'Archer',
name: 'yudao-ui-admin-vben',
icon: 'logos:vue',
message: 'https://github.com/yudaocode/yudao-ui-admin-vben',
personal: 'Vue3 + vben(antd)',
time: new Date()
},
{
name: 'React',
icon: 'logos:react',
message: 'workplace.introduction',
personal: 'Archer',
name: 'yudao-cloud',
icon: 'akar-icons:github',
message: 'https://github.com/YunaiV/yudao-cloud',
personal: 'Spring Cloud 微服务架构',
time: new Date()
},
{
name: 'Webpack',
icon: 'logos:webpack',
message: 'workplace.introduction',
personal: 'Archer',
name: 'yudao-ui-mall-uniapp',
icon: 'logos:vue',
message: 'https://github.com/yudaocode/yudao-ui-admin-uniapp',
personal: 'Vue3 + uniapp',
time: new Date()
},
{
name: 'Vite',
icon: 'vscode-icons:file-type-vite',
message: 'workplace.introduction',
personal: 'Archer',
name: 'yudao-ui-admin-vue2',
icon: 'logos:vue',
message: 'https://github.com/yudaocode/yudao-ui-admin-vue2',
personal: 'Vue2 + element-ui',
time: new Date()
}
]
@ -254,27 +261,27 @@ let notice = reactive<Notice[]>([])
const getNotice = async () => {
const data = [
{
title: '系统升级版本',
title: '系统支持 JDK 8/17/21Vue 2/3',
type: '通知',
keys: ['通知', '升级'],
keys: ['通知', '8', '17', '21', '2', '3'],
date: new Date()
},
{
title: '系统凌晨维护',
title: '后端提供 Spring Boot 2.7/3.2 + Cloud 双架构',
type: '公告',
keys: ['公告', '维护'],
keys: ['公告', 'Boot', 'Cloud'],
date: new Date()
},
{
title: '系统升级版本',
title: '全部开源,个人与企业可 100% 直接使用,无需授权',
type: '通知',
keys: ['通知', '升级'],
keys: ['通知', '无需授权'],
date: new Date()
},
{
title: '系统凌晨维护',
title: '国内使用最广泛的快速开发平台,超 300+ 人贡献',
type: '公告',
keys: ['公告', '维护'],
keys: ['公告', '最广泛'],
date: new Date()
}
]

166
src/views/ai/chat/index.vue Normal file
View File

@ -0,0 +1,166 @@
<template>
<el-container>
<!-- 左侧会话列表 -->
<el-aside width="260px" class="conversation-container">
<!-- 左顶部新建对话 -->
<el-button class="w-1/1" type="primary">
<Icon icon="ep:plus" class="mr-5px" />
新建对话
</el-button>
<!-- 左顶部搜索对话 -->
<el-input
v-model="searchName"
class="mt-10px"
placeholder="搜索历史记录"
@keyup="searchConversation"
>
<template #prefix>
<Icon icon="ep:search" />
</template>
</el-input>
<!-- 左中间对话列表 -->
<div class="conversation-list" :style="{ height: leftHeight + 'px' }">
<el-row v-for="conversation in conversationList" :key="conversation.id">
<div
:class="conversation.id === conversationId ? 'conversation active' : 'conversation'"
@click="changeConversation(conversation)"
>
<el-image :src="conversation.avatar" class="avatar" />
<span class="title">{{ conversation.title }}</span>
<span class="button">
<!-- TODO 芋艿缺置顶按钮 -->
<el-icon title="编辑" @click="updateConversationTitle(conversation)">
<Icon icon="ep:edit" />
</el-icon>
<el-icon title="删除会话" @click="deleteConversationTitle(conversation)">
<Icon icon="ep:delete" />
</el-icon>
</span>
</div>
</el-row>
</div>
<!-- 左底部工具栏 TODO 芋艿50% 不太对 -->
<div class="tool-box">
<sapn class="w-1/2"> <Icon icon="ep:user" /> 角色仓库 </sapn>
<sapn class="w-1/2"> <Icon icon="ep:delete" />清空未置顶对话</sapn>
</div>
</el-aside>
<!-- 右侧会话详情 -->
<el-container class="detail-container">
<!-- 右顶部 TODO 芋艿右对齐 -->
<el-header class="header">
<el-button>3.5-turbo-0125 <Icon icon="ep:setting" /></el-button>
<el-button>
<Icon icon="ep:user" />
</el-button>
<el-button>
<Icon icon="ep:download" />
</el-button>
<el-button>
<Icon icon="ep:arrow-up" />
</el-button>
</el-header>
<el-main>对话列表</el-main>
<el-footer>发送消息框</el-footer>
</el-container>
</el-container>
</template>
<script setup lang="ts">
const conversationList = [
{
id: 1,
title: '测试标题',
avatar:
'http://test.yudao.iocoder.cn/96c787a2ce88bf6d0ce3cd8b6cf5314e80e7703cd41bf4af8cd2e2909dbd6b6d.png'
},
{
id: 2,
title: '测试对话',
avatar:
'http://test.yudao.iocoder.cn/96c787a2ce88bf6d0ce3cd8b6cf5314e80e7703cd41bf4af8cd2e2909dbd6b6d.png'
}
]
const conversationId = ref(1)
const searchName = ref('')
const leftHeight = window.innerHeight - 240 // TODO
const changeConversation = (conversation) => {
console.log(conversation)
conversationId.value = conversation.id
// TODO
}
const updateConversationTitle = (conversation) => {
console.log(conversation)
// TODO
}
const deleteConversationTitle = (conversation) => {
console.log(conversation)
// TODO
}
const searchConversation = () => {
// TODO
}
</script>
<style lang="scss" scoped>
.conversation-container {
.conversation-list {
.conversation {
display: flex;
justify-content: flex-start;
width: 100%;
padding: 5px 5px 0 0;
cursor: pointer;
&.active {
// TODO
background-color: #343540;
.button {
display: inline;
}
}
.title {
padding: 5px 10px;
max-width: 220px;
font-size: 14px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.avatar {
width: 28px;
height: 28px;
border-radius: 50%;
}
.button {
position: absolute;
right: 2px;
top: 16px;
.el-icon {
margin-right: 5px;
}
}
}
.tool-box {
display: flex;
justify-content: flex-start;
padding: 0 20px 10px 20px;
border-top: 1px solid black;
}
}
}
.detail-container {
.header {
width: 100%;
height: 30px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding-top: 10px;
}
}
</style>

View File

@ -100,7 +100,7 @@ const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: 0,
id: undefined,
name: '',
deptIds: [],
statuses: []
@ -168,7 +168,7 @@ const submitForm = async () => {
const resetForm = () => {
checkStrictly.value = true
formData.value = {
id: 0,
id: undefined,
name: '',
deptIds: [],
statuses: []

View File

@ -46,7 +46,7 @@
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { ProductCategoryApi } from '@/api/erp/product/category'
import { ProductCategoryApi, ProductCategoryVO } from '@/api/erp/product/category'
import { defaultProps, handleTree } from '@/utils/tree'
import { CommonStatusEnum } from '@/utils/constants'
@ -66,7 +66,7 @@ const formData = ref({
name: undefined,
code: undefined,
sort: undefined,
status: undefined
status: CommonStatusEnum.ENABLE
})
const formRules = reactive({
parentId: [{ required: true, message: '上级编号不能为空', trigger: 'blur' }],
@ -105,7 +105,7 @@ const submitForm = async () => {
//
formLoading.value = true
try {
const data = formData.value as unknown as ProductCategoryApi.ProductCategoryVO
const data = formData.value as unknown as ProductCategoryVO
if (formType.value === 'create') {
await ProductCategoryApi.createProductCategory(data)
message.success(t('common.createSuccess'))

View File

@ -157,7 +157,7 @@
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import * as SeckillActivityApi from '@/api/mall/promotion/seckill/seckillActivity'
import * as SeckillConfigApi from '@/api/mall/promotion/seckill/seckillConfig'
import { SeckillConfigApi } from '@/api/mall/promotion/seckill/seckillConfig'
import SeckillActivityForm from './SeckillActivityForm.vue'
import { formatDate } from '@/utils/formatTime'
import { fenToYuanFormat } from '@/utils/formatter'

View File

@ -1,6 +1,6 @@
import type { CrudSchema } from '@/hooks/web/useCrudSchemas'
import { dateFormatter, dateFormatter2 } from '@/utils/formatTime'
import { getSimpleSeckillConfigList } from '@/api/mall/promotion/seckill/seckillConfig'
import { dateFormatter2 } from '@/utils/formatTime'
import { SeckillConfigApi } from '@/api/mall/promotion/seckill/seckillConfig'
// 表单校验
export const rules = reactive({
@ -88,7 +88,7 @@ const crudSchemas = reactive<CrudSchema[]>([
valueField: 'id'
}
},
api: getSimpleSeckillConfigList
api: SeckillConfigApi.getSimpleSeckillConfigList
},
table: {
width: 300

View File

@ -26,9 +26,9 @@
icon="ep:view"
icon-color="bg-blue-100"
icon-bg-color="text-blue-500"
prefix=""
:decimals="2"
:value="fenToYuan(trendSummary?.value?.browseCount || 0)"
prefix=""
:decimals="0"
:value="trendSummary?.value?.browseCount || 0"
:percent="
calculateRelativeRate(
trendSummary?.value?.browseCount,
@ -44,9 +44,9 @@
icon="ep:user-filled"
icon-color="bg-purple-100"
icon-bg-color="text-purple-500"
prefix=""
:decimals="2"
:value="fenToYuan(trendSummary?.value?.browseUserCount || 0)"
prefix=""
:decimals="0"
:value="trendSummary?.value?.browseUserCount || 0"
:percent="
calculateRelativeRate(
trendSummary?.value?.browseUserCount,
@ -62,9 +62,9 @@
icon="fa-solid:money-check-alt"
icon-color="bg-yellow-100"
icon-bg-color="text-yellow-500"
prefix=""
:decimals="2"
:value="fenToYuan(trendSummary?.value?.orderPayCount || 0)"
prefix=""
:decimals="0"
:value="trendSummary?.value?.orderPayCount || 0"
:percent="
calculateRelativeRate(
trendSummary?.value?.orderPayCount,
@ -98,9 +98,9 @@
icon="fa-solid:wallet"
icon-color="bg-cyan-100"
icon-bg-color="text-cyan-500"
prefix=""
:decimals="2"
:value="fenToYuan(trendSummary?.value?.afterSaleCount || 0)"
prefix=""
:decimals="0"
:value="trendSummary?.value?.afterSaleCount || 0"
:percent="
calculateRelativeRate(
trendSummary?.value?.afterSaleCount,

View File

@ -27,7 +27,7 @@ const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) //
const formLoading = ref(false) // 12
const formData = ref({
id: 0, //
id: undefined, //
auditReason: '' //
})
const formRef = ref() // Ref
@ -62,7 +62,7 @@ const submitForm = async () => {
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: 0, //
id: undefined, //
auditReason: '' //
}
formRef.value?.resetFields()

View File

@ -103,7 +103,7 @@ const submitForm = async () => {
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: 0,
id: undefined,
bindUserId: undefined
}
formRef.value?.resetFields()

View File

@ -43,7 +43,7 @@ const dialogVisible = ref(false) // 弹窗的是否展示
const formLoading = ref(false) // 12
const expressType = ref('express') // expressnone
const formData = ref<TradeOrderApi.DeliveryVO>({
id: 0, //
id: undefined, //
logisticsId: null, //
logisticsNo: '' //
})
@ -86,7 +86,7 @@ const submitForm = async () => {
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: 0, //
id: undefined, //
logisticsId: null, //
logisticsNo: '' //
}

View File

@ -44,7 +44,7 @@ const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) //
const formLoading = ref(false) // 12
const formData = ref({
id: 0, //
id: undefined, //
receiverName: '', //
receiverMobile: '', //
receiverAreaId: null, //
@ -82,7 +82,7 @@ const submitForm = async () => {
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: 0, //
id: undefined, //
receiverName: '', //
receiverMobile: '', //
receiverAreaId: null, //

View File

@ -31,7 +31,7 @@ const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) //
const formLoading = ref(false) // 12
const formData = ref({
id: 0, //
id: undefined, //
adjustPrice: 0, //
payPrice: '', // ()
newPayPrice: '' // ()
@ -85,7 +85,7 @@ const submitForm = async () => {
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: 0, //
id: undefined, //
adjustPrice: 0, //
payPrice: '', // ()
newPayPrice: '' // ()

View File

@ -27,7 +27,7 @@ const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) //
const formLoading = ref(false) // 12
const formData = ref({
id: 0, //
id: undefined, //
remark: '' //
})
const formRef = ref() // Ref
@ -62,7 +62,7 @@ const submitForm = async () => {
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: 0, //
id: undefined, //
remark: '' //
}
formRef.value?.resetFields()

View File

@ -1,5 +1,7 @@
<template>
<ContentWrap>
<doc-alert title="大屏设计器" url="https://doc.iocoder.cn/report/screen/" />
<IFrame :src="src" />
</ContentWrap>
</template>

View File

@ -1,5 +1,7 @@
<template>
<ContentWrap>
<doc-alert title="报表设计器" url="https://doc.iocoder.cn/report/" />
<IFrame :src="src" />
</ContentWrap>
</template>

View File

@ -130,7 +130,7 @@ const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: 0,
id: undefined,
name: '',
permission: '',
type: SystemMenuTypeEnum.DIR,
@ -231,7 +231,7 @@ const getTree = async () => {
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: 0,
id: undefined,
name: '',
permission: '',
type: SystemMenuTypeEnum.DIR,

View File

@ -58,7 +58,7 @@ const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) //
const formLoading = ref(false) // 12
const formData = reactive({
id: 0,
id: undefined,
name: '',
code: '',
menuIds: []
@ -126,7 +126,7 @@ const resetForm = () => {
menuExpand.value = false
//
formData.value = {
id: 0,
id: undefined,
name: '',
code: '',
menuIds: []

View File

@ -78,7 +78,7 @@ const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) //
const formLoading = ref(false) // 12
const formData = reactive({
id: 0,
id: undefined,
name: '',
code: '',
dataScope: undefined,
@ -141,7 +141,7 @@ const resetForm = () => {
checkStrictly.value = true
//
formData.value = {
id: 0,
id: undefined,
name: '',
code: '',
dataScope: undefined,