From 449d1191ff8212555fc9851ac9611f1da5d1b1d4 Mon Sep 17 00:00:00 2001 From: scholar <1145227973@qq.com> Date: Sat, 4 May 2024 22:28:37 +0800 Subject: [PATCH 001/341] =?UTF-8?q?fix=E5=90=8C=E6=AF=94=E7=8E=AF=E6=AF=94?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E8=AE=A1=E7=AE=97=E7=9A=84bug=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/ContractCountPerformance.vue | 14 +++++++------- .../components/ContractPricePerformance.vue | 14 +++++++------- .../components/ReceivablePricePerformance.vue | 14 +++++++------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/views/crm/statistics/performance/components/ContractCountPerformance.vue b/src/views/crm/statistics/performance/components/ContractCountPerformance.vue index f135caa8..5dc4d9e7 100644 --- a/src/views/crm/statistics/performance/components/ContractCountPerformance.vue +++ b/src/views/crm/statistics/performance/components/ContractCountPerformance.vue @@ -57,13 +57,13 @@ const echartsOption = reactive({ data: [] }, { - name: '同比增长率(%)', + name: '环比增长率(%)', type: 'line', yAxisIndex: 1, data: [] }, { - name: '环比增长率(%)', + name: '同比增长率(%)', type: 'line', yAxisIndex: 1, data: [] @@ -166,7 +166,7 @@ const loadData = async () => { (s: StatisticsPerformanceRespVO) => s.lastMonthCount ) echartsOption.series[3]['data'] = performanceList.map( - (s: StatisticsPerformanceRespVO) => s.lastMonthCount !== 0 ? (s.currentMonthCount / s.lastMonthCount*100).toFixed(2) : 'NULL' + (s: StatisticsPerformanceRespVO) => s.lastMonthCount !== 0 ? ((s.currentMonthCount - s.lastMonthCount) / s.lastMonthCount*100).toFixed(2) : 'NULL' ) } if (echartsOption.series && echartsOption.series[2] && echartsOption.series[2]['data']) { @@ -174,7 +174,7 @@ const loadData = async () => { (s: StatisticsPerformanceRespVO) => s.lastYearCount ) echartsOption.series[4]['data'] = performanceList.map( - (s: StatisticsPerformanceRespVO) => s.lastYearCount !== 0 ? (s.currentMonthCount / s.lastYearCount*100).toFixed(2) : 'NULL' + (s: StatisticsPerformanceRespVO) => s.lastYearCount !== 0 ? ((s.currentMonthCount - s.lastYearCount) / s.lastYearCount*100).toFixed(2) : 'NULL' ) } @@ -188,7 +188,7 @@ const loadData = async () => { // 初始化数据 const columnsData = reactive([]); const tableData = reactive([{title: '当月合同数量统计(个)'}, {title: '上月合同数量统计(个)'}, - {title: '去年当月合同数量统计(个)'}, {title: '同比增长率(%)'}, {title: '环比增长率(%)'}]) + {title: '去年当月合同数量统计(个)'}, {title: '环比增长率(%)'}, {title: '同比增长率(%)'}]) // 定义 convertListData 方法,数据行列转置,展示每月数据 const convertListData = () => { @@ -202,8 +202,8 @@ const convertListData = () => { tableData[0]['prop' + index] = item.currentMonthCount tableData[1]['prop' + index] = item.lastMonthCount tableData[2]['prop' + index] = item.lastYearCount - tableData[3]['prop' + index] = item.lastMonthCount !== 0 ? (item.currentMonthCount / item.lastMonthCount).toFixed(2) : 'NULL' - tableData[4]['prop' + index] = item.lastYearCount !== 0 ? (item.currentMonthCount / item.lastYearCount).toFixed(2) : 'NULL' + tableData[3]['prop' + index] = item.lastMonthCount !== 0 ? ((item.currentMonthCount - item.lastMonthCount) / item.lastMonthCount * 100).toFixed(2) : 'NULL' + tableData[4]['prop' + index] = item.lastYearCount !== 0 ? ((item.currentMonthCount - item.lastYearCount) / item.lastYearCount * 100).toFixed(2) : 'NULL' }) } diff --git a/src/views/crm/statistics/performance/components/ContractPricePerformance.vue b/src/views/crm/statistics/performance/components/ContractPricePerformance.vue index 41228a22..0c33dc22 100644 --- a/src/views/crm/statistics/performance/components/ContractPricePerformance.vue +++ b/src/views/crm/statistics/performance/components/ContractPricePerformance.vue @@ -57,13 +57,13 @@ const echartsOption = reactive({ data: [] }, { - name: '同比增长率(%)', + name: '环比增长率(%)', type: 'line', yAxisIndex: 1, data: [] }, { - name: '环比增长率(%)', + name: '同比增长率(%)', type: 'line', yAxisIndex: 1, data: [] @@ -166,7 +166,7 @@ const loadData = async () => { (s: StatisticsPerformanceRespVO) => s.lastMonthCount ) echartsOption.series[3]['data'] = performanceList.map( - (s: StatisticsPerformanceRespVO) => s.lastMonthCount !== 0 ? (s.currentMonthCount / s.lastMonthCount*100).toFixed(2) : 'NULL' + (s: StatisticsPerformanceRespVO) => s.lastMonthCount !== 0 ? ((s.currentMonthCount - s.lastMonthCount) / s.lastMonthCount*100).toFixed(2) : 'NULL' ) } if (echartsOption.series && echartsOption.series[2] && echartsOption.series[2]['data']) { @@ -174,7 +174,7 @@ const loadData = async () => { (s: StatisticsPerformanceRespVO) => s.lastYearCount ) echartsOption.series[4]['data'] = performanceList.map( - (s: StatisticsPerformanceRespVO) => s.lastYearCount !== 0 ? (s.currentMonthCount / s.lastYearCount*100).toFixed(2) : 'NULL' + (s: StatisticsPerformanceRespVO) => s.lastYearCount !== 0 ? ((s.currentMonthCount - s.lastYearCount) / s.lastYearCount*100).toFixed(2) : 'NULL' ) } @@ -188,7 +188,7 @@ const loadData = async () => { // 初始化数据 const columnsData = reactive([]); const tableData = reactive([{title: '当月合同金额统计(元)'}, {title: '上月合同金额统计(元)'}, {title: '去年当月合同金额统计(元)'}, - {title: '同比增长率(%)'}, {title: '环比增长率(%)'}]) + {title: '环比增长率(%)'}, {title: '同比增长率(%)'}]) // 定义 init 方法 const convertListData = () => { @@ -202,8 +202,8 @@ const convertListData = () => { tableData[0]['prop' + index] = item.currentMonthCount tableData[1]['prop' + index] = item.lastMonthCount tableData[2]['prop' + index] = item.lastYearCount - tableData[3]['prop' + index] = item.lastMonthCount !== 0 ? (item.currentMonthCount / item.lastMonthCount).toFixed(2) : 'NULL' - tableData[4]['prop' + index] = item.lastYearCount !== 0 ? (item.currentMonthCount / item.lastYearCount).toFixed(2) : 'NULL' + tableData[3]['prop' + index] = item.lastMonthCount !== 0 ? ((item.currentMonthCount - item.lastMonthCount) / item.lastMonthCount*100).toFixed(2) : 'NULL' + tableData[4]['prop' + index] = item.lastYearCount !== 0 ? ((item.currentMonthCount - item.lastYearCount) / item.lastYearCount*100).toFixed(2) : 'NULL' }) } diff --git a/src/views/crm/statistics/performance/components/ReceivablePricePerformance.vue b/src/views/crm/statistics/performance/components/ReceivablePricePerformance.vue index 1efcf920..aa3f5b19 100644 --- a/src/views/crm/statistics/performance/components/ReceivablePricePerformance.vue +++ b/src/views/crm/statistics/performance/components/ReceivablePricePerformance.vue @@ -57,13 +57,13 @@ const echartsOption = reactive({ data: [] }, { - name: '同比增长率(%)', + name: '环比增长率(%)', type: 'line', yAxisIndex: 1, data: [] }, { - name: '环比增长率(%)', + name: '同比增长率(%)', type: 'line', yAxisIndex: 1, data: [] @@ -166,7 +166,7 @@ const loadData = async () => { (s: StatisticsPerformanceRespVO) => s.lastMonthCount ) echartsOption.series[3]['data'] = performanceList.map( - (s: StatisticsPerformanceRespVO) => s.lastMonthCount !== 0 ? (s.currentMonthCount / s.lastMonthCount*100).toFixed(2) : 'NULL' + (s: StatisticsPerformanceRespVO) => s.lastMonthCount !== 0 ? ((s.currentMonthCount - s.lastMonthCount) / s.lastMonthCount*100).toFixed(2) : 'NULL' ) } if (echartsOption.series && echartsOption.series[2] && echartsOption.series[1]['data']) { @@ -174,7 +174,7 @@ const loadData = async () => { (s: StatisticsPerformanceRespVO) => s.lastYearCount ) echartsOption.series[4]['data'] = performanceList.map( - (s: StatisticsPerformanceRespVO) => s.lastYearCount !== 0 ? (s.currentMonthCount / s.lastYearCount*100).toFixed(2) : 'NULL' + (s: StatisticsPerformanceRespVO) => s.lastYearCount !== 0 ? ((s.currentMonthCount - s.lastYearCount) / s.lastYearCount*100).toFixed(2) : 'NULL' ) } @@ -188,7 +188,7 @@ const loadData = async () => { // 初始化数据 const columnsData = reactive([]); const tableData = reactive([{title: '当月回款金额统计(元)'}, {title: '上月回款金额统计(元)'}, - {title: '去年当月回款金额统计(元)'}, {title: '同比增长率(%)'}, {title: '环比增长率(%)'}]); + {title: '去年当月回款金额统计(元)'}, {title: '环比增长率(%)'}, {title: '同比增长率(%)'}]); // 定义 init 方法 const convertListData = () => { @@ -202,8 +202,8 @@ const convertListData = () => { tableData[0]['prop' + index] = item.currentMonthCount tableData[1]['prop' + index] = item.lastMonthCount tableData[2]['prop' + index] = item.lastYearCount - tableData[3]['prop' + index] = item.lastMonthCount !== 0 ? (item.currentMonthCount / item.lastMonthCount).toFixed(2) : 'NULL' - tableData[4]['prop' + index] = item.lastYearCount !== 0 ? (item.currentMonthCount / item.lastYearCount).toFixed(2) : 'NULL' + tableData[3]['prop' + index] = item.lastMonthCount !== 0 ? ((item.currentMonthCount - item.lastMonthCount) / item.lastMonthCount*100).toFixed(2) : 'NULL' + tableData[4]['prop' + index] = item.lastYearCount !== 0 ? ((item.currentMonthCount - item.lastYearCount) / item.lastYearCount*100).toFixed(2) : 'NULL' }) } -- Gitee From 40fe87920b075e91ff04e1215e320974b7d25106 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Thu, 9 May 2024 14:35:57 +0800 Subject: [PATCH 002/341] =?UTF-8?q?form-create:=20=E4=BC=98=E5=8C=96=20sel?= =?UTF-8?q?ect=20option=20=E9=80=89=E9=A1=B9=E8=A7=A3=E6=9E=90=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20el=20=E8=A1=A8=E8=BE=BE=E5=BC=8F=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E3=80=81=E8=87=AA=E5=AE=9A=E4=B9=89=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=20(data:=20any)=3D>{=20label:=20string;=20va?= =?UTF-8?q?lue:=20any=20}?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/useApiSelect.tsx | 41 +++++++++++++++++-- .../FormCreate/src/config/selectRule.ts | 13 +++++- src/components/FormCreate/src/utils/index.ts | 1 - 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/components/FormCreate/src/components/useApiSelect.tsx b/src/components/FormCreate/src/components/useApiSelect.tsx index 54c0a33b..62f25eb3 100644 --- a/src/components/FormCreate/src/components/useApiSelect.tsx +++ b/src/components/FormCreate/src/components/useApiSelect.tsx @@ -27,6 +27,11 @@ export const useApiSelect = (option: ApiSelectProps) => { type: String, default: 'GET' }, + // 选项解析函数 + parseFunc: { + type: String, + default: '' + }, // 请求参数 data: { type: String, @@ -63,15 +68,43 @@ export const useApiSelect = (option: ApiSelectProps) => { } if (Array.isArray(data)) { - options.value = data.map((item: any) => ({ - label: item[props.labelField], - value: item[props.valueField] - })) + let parse: any = null + if (!!props.parseFunc) { + // 解析字符串函数 + parse = new Function(`return ${props.parseFunc}`)() + } + options.value = data.map( + (item: any) => + parse?.(item) ?? { + label: parseExpression(item, props.labelField), + value: parseExpression(item, props.valueField) + } + ) return } console.log(`接口[${props.url}] 返回结果不是一个数组`) } + function parseExpression(data: any, template: string) { + // 检测是否使用了表达式 + if (template.indexOf('${') === -1) { + return data[template] + } + // 正则表达式匹配模板字符串中的 ${...} + const pattern = /\$\{([^}]*)}/g + // 使用replace函数配合正则表达式和回调函数来进行替换 + return template.replace(pattern, (_, expr) => { + // expr 是匹配到的 ${} 内的表达式(这里是属性名),从 data 中获取对应的值 + const result = data[expr.trim()] // 去除前后空白,以防用户输入带空格的属性名 + if (!result) { + console.warn( + `接口选择器选项模版[${template}][${expr.trim()}] 解析值失败结果为[${result}], 请检查属性名称是否存在于接口返回值中,存在则忽略此条!!!` + ) + } + return result + }) + } + onMounted(async () => { await getOptions() }) diff --git a/src/components/FormCreate/src/config/selectRule.ts b/src/components/FormCreate/src/config/selectRule.ts index 281d3739..ec5af7c7 100644 --- a/src/components/FormCreate/src/config/selectRule.ts +++ b/src/components/FormCreate/src/config/selectRule.ts @@ -13,7 +13,7 @@ const selectRule = [ control: [ { value: 'select', - condition: '=', + condition: '==', method: 'hidden', rule: ['multiple'] } @@ -141,6 +141,17 @@ const apiSelectRule = [ props: { placeholder: 'id' } + }, + { + type: 'input', + field: 'parseFunc', + title: '选项解析函数', + info: '(data: any)=>{ label: string; value: any }', + props: { + autosize: true, + rows: { minRows: 2, maxRows: 6 }, + type: 'textarea' + } } ] diff --git a/src/components/FormCreate/src/utils/index.ts b/src/components/FormCreate/src/utils/index.ts index e5480981..c297e841 100644 --- a/src/components/FormCreate/src/utils/index.ts +++ b/src/components/FormCreate/src/utils/index.ts @@ -1,4 +1,3 @@ -// TODO puhui999: 借鉴一下 form-create-designer utils 方法 🤣 (导入不了只能先 copy 过来用下) export function makeRequiredRule() { return { type: 'Required', -- Gitee From 9cde4885777576a145c06253ff634cef63c1fdd3 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Thu, 9 May 2024 17:30:49 +0800 Subject: [PATCH 003/341] =?UTF-8?q?form-create:=20=E5=AE=8C=E5=96=84=20sel?= =?UTF-8?q?ect=20=E8=BF=9C=E7=A8=8B=E6=90=9C=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/useApiSelect.tsx | 108 +++++++++++++++--- .../FormCreate/src/config/selectRule.ts | 34 +++++- .../src/config/useDictSelectRule.ts | 4 +- .../FormCreate/src/config/useSelectRule.ts | 4 +- src/components/FormCreate/src/utils/index.ts | 60 ---------- 5 files changed, 124 insertions(+), 86 deletions(-) diff --git a/src/components/FormCreate/src/components/useApiSelect.tsx b/src/components/FormCreate/src/components/useApiSelect.tsx index 62f25eb3..29cd3027 100644 --- a/src/components/FormCreate/src/components/useApiSelect.tsx +++ b/src/components/FormCreate/src/components/useApiSelect.tsx @@ -46,43 +46,88 @@ export const useApiSelect = (option: ApiSelectProps) => { multiple: { type: Boolean, default: false + }, + // 是否远程搜索 + remote: { + type: Boolean, + default: false + }, + // 远程搜索时携带的参数 + remoteField: { + type: String, + default: 'label' } }, setup(props) { const attrs = useAttrs() const options = ref([]) // 下拉数据 + const loading = ref(false) // 是否正在从远程获取数据 + const queryParam = ref() // 当前输入的值 const getOptions = async () => { options.value = [] // 接口选择器 if (isEmpty(props.url)) { return } - let data = [] switch (props.method) { case 'GET': - data = await request.get({ url: props.url }) + let url: string = props.url + if (props.remote) { + url = `${url}?${props.remoteField}=${queryParam.value}` + } + parseOptions(await request.get({ url: url })) break case 'POST': - data = await request.post({ url: props.url, data: jsonParse(props.data) }) + const data: any = jsonParse(props.data) + if (props.remote) { + data[props.remoteField] = queryParam.value + } + parseOptions(await request.post({ url: props.url, data: data })) break } + } + function parseOptions(data: any) { + // 情况一:如果有自定义解析函数优先使用自定义解析 + if (!isEmpty(props.parseFunc)) { + options.value = parseFunc()?.(data) + return + } + // 情况二:返回的直接是一个列表 if (Array.isArray(data)) { - let parse: any = null - if (!!props.parseFunc) { - // 解析字符串函数 - parse = new Function(`return ${props.parseFunc}`)() - } - options.value = data.map( - (item: any) => - parse?.(item) ?? { - label: parseExpression(item, props.labelField), - value: parseExpression(item, props.valueField) - } - ) + parseOptions0(data) + return + } + // 情况二:返回的是分页数据,尝试读取 list + data = data.list + if (!!data && Array.isArray(data)) { + parseOptions0(data) + return + } + // 情况三:不是 yudao-vue-pro 标准返回 + console.warn( + `接口[${props.url}] 返回结果不是 yudao-vue-pro 标准返回建议采用自定义解析函数处理` + ) + } + + function parseOptions0(data: any[]) { + if (Array.isArray(data)) { + options.value = data.map((item: any) => ({ + label: parseExpression(item, props.labelField), + value: parseExpression(item, props.valueField) + })) return } - console.log(`接口[${props.url}] 返回结果不是一个数组`) + console.warn(`接口[${props.url}] 返回结果不是一个数组`) + } + + function parseFunc() { + let parse: any = null + if (!!props.parseFunc) { + // 解析字符串函数 + parse = new Function(`return ${props.parseFunc}`)() + } + return parse } function parseExpression(data: any, template: string) { @@ -105,6 +150,19 @@ export const useApiSelect = (option: ApiSelectProps) => { }) } + const remoteMethod = async (query: any) => { + if (!query) { + return + } + loading.value = true + try { + queryParam.value = query + await getOptions() + } finally { + loading.value = false + } + } + onMounted(async () => { await getOptions() }) @@ -113,15 +171,29 @@ export const useApiSelect = (option: ApiSelectProps) => { if (props.multiple) { // fix:多写此步是为了解决 multiple 属性问题 return ( - + {options.value.map((item, index) => ( ))} ) } + debugger return ( - + {options.value.map((item, index) => ( ))} diff --git a/src/components/FormCreate/src/config/selectRule.ts b/src/components/FormCreate/src/config/selectRule.ts index ec5af7c7..5d24c713 100644 --- a/src/components/FormCreate/src/config/selectRule.ts +++ b/src/components/FormCreate/src/config/selectRule.ts @@ -15,7 +15,20 @@ const selectRule = [ value: 'select', condition: '==', method: 'hidden', - rule: ['multiple'] + rule: [ + 'multiple', + 'clearable', + 'collapseTags', + 'multipleLimit', + 'allowCreate', + 'filterable', + 'noMatchText', + 'remote', + 'remoteMethod', + 'reserveKeyword', + 'defaultFirstOption', + 'automaticDropdown' + ] } ] }, @@ -60,9 +73,10 @@ const selectRule = [ title: '其中的选项是否从服务器远程加载' }, { - type: 'Struct', - field: 'remoteMethod', - title: '自定义远程搜索方法' + type: 'input', + field: 'remoteField', + title: '请求参数', + info: '远程请求时请求携带的参数名称,如:name' }, { type: 'input', field: 'noDataText', title: '选项为空时显示的文字' }, { @@ -130,6 +144,7 @@ const apiSelectRule = [ type: 'input', field: 'labelField', title: 'label 属性', + info: '可以使用 el 表达式:${属性},来实现复杂数据组合。如:${nickname}-${id}', props: { placeholder: 'nickname' } @@ -138,6 +153,7 @@ const apiSelectRule = [ type: 'input', field: 'valueField', title: 'value 属性', + info: '可以使用 el 表达式:${属性},来实现复杂数据组合。如:${nickname}-${id}', props: { placeholder: 'id' } @@ -146,11 +162,17 @@ const apiSelectRule = [ type: 'input', field: 'parseFunc', title: '选项解析函数', - info: '(data: any)=>{ label: string; value: any }', + info: `data 为接口返回值,需要写一个匿名函数解析返回值为选择器 options 列表 + (data: any)=>{ label: string; value: any }[]`, props: { autosize: true, rows: { minRows: 2, maxRows: 6 }, - type: 'textarea' + type: 'textarea', + placeholder: ` + function (data) { + console.log(data) + return data.list.map(item=> ({label: item.nickname,value: item.id})) + }` } } ] diff --git a/src/components/FormCreate/src/config/useDictSelectRule.ts b/src/components/FormCreate/src/config/useDictSelectRule.ts index 3db630bc..5c5e8cad 100644 --- a/src/components/FormCreate/src/config/useDictSelectRule.ts +++ b/src/components/FormCreate/src/config/useDictSelectRule.ts @@ -2,6 +2,7 @@ import { generateUUID } from '@/utils' import * as DictDataApi from '@/api/system/dict/dict.type' import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils' import { selectRule } from '@/components/FormCreate/src/config/selectRule' +import { cloneDeep } from 'lodash-es' /** * 字典选择器规则,如果规则使用到动态数据则需要单独配置不能使用 useSelectRule @@ -9,6 +10,7 @@ import { selectRule } from '@/components/FormCreate/src/config/selectRule' export const useDictSelectRule = () => { const label = '字典选择器' const name = 'DictSelect' + const rules = cloneDeep(selectRule) const dictOptions = ref<{ label: string; value: string }[]>([]) // 字典类型下拉数据 onMounted(async () => { const data = await DictDataApi.getSimpleDictTypeList() @@ -55,7 +57,7 @@ export const useDictSelectRule = () => { { label: '布尔值', value: 'bool' } ] }, - ...selectRule + ...rules ]) } } diff --git a/src/components/FormCreate/src/config/useSelectRule.ts b/src/components/FormCreate/src/config/useSelectRule.ts index 732c5269..3e5f1eb2 100644 --- a/src/components/FormCreate/src/config/useSelectRule.ts +++ b/src/components/FormCreate/src/config/useSelectRule.ts @@ -2,6 +2,7 @@ import { generateUUID } from '@/utils' import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils' import { selectRule } from '@/components/FormCreate/src/config/selectRule' import { SelectRuleOption } from '@/components/FormCreate/src/type' +import { cloneDeep } from 'lodash-es' /** * 通用选择器规则 hook @@ -10,6 +11,7 @@ import { SelectRuleOption } from '@/components/FormCreate/src/type' export const useSelectRule = (option: SelectRuleOption) => { const label = option.label const name = option.name + const rules = cloneDeep(selectRule) return { icon: option.icon, label, @@ -27,7 +29,7 @@ export const useSelectRule = (option: SelectRuleOption) => { if (!option.props) { option.props = [] } - return localeProps(t, name + '.props', [makeRequiredRule(), ...option.props, ...selectRule]) + return localeProps(t, name + '.props', [makeRequiredRule(), ...option.props, ...rules]) } } } diff --git a/src/components/FormCreate/src/utils/index.ts b/src/components/FormCreate/src/utils/index.ts index c297e841..2d4a6fd7 100644 --- a/src/components/FormCreate/src/utils/index.ts +++ b/src/components/FormCreate/src/utils/index.ts @@ -16,63 +16,3 @@ export const localeProps = (t, prefix, rules) => { return rule }) } - -export function upper(str) { - return str.replace(str[0], str[0].toLocaleUpperCase()) -} - -export function makeOptionsRule(t, to, userOptions) { - console.log(userOptions[0]) - const options = [ - { label: t('props.optionsType.struct'), value: 0 }, - { label: t('props.optionsType.json'), value: 1 }, - { label: '用户数据', value: 2 } - ] - - const control = [ - { - value: 0, - rule: [ - { - type: 'TableOptions', - field: 'formCreate' + upper(to).replace('.', '>'), - props: { defaultValue: [] } - } - ] - }, - { - value: 1, - rule: [ - { - type: 'Struct', - field: 'formCreate' + upper(to).replace('.', '>'), - props: { defaultValue: [] } - } - ] - }, - { - value: 2, - rule: [ - { - type: 'TableOptions', - field: 'formCreate' + upper(to).replace('.', '>'), - props: { modelValue: [] } - } - ] - } - ] - options.splice(0, 0) - control.push() - - return { - type: 'radio', - title: t('props.options'), - field: '_optionType', - value: 0, - options, - props: { - type: 'button' - }, - control - } -} -- Gitee From 24f2c49e0b04c4e73239ffc11524ed34462b7425 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Thu, 9 May 2024 18:02:57 +0800 Subject: [PATCH 004/341] =?UTF-8?q?form-create:=20=E5=AE=8C=E5=96=84=20sel?= =?UTF-8?q?ect=20=E8=BF=9C=E7=A8=8B=E6=90=9C=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FormCreate/src/config/selectRule.ts | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/components/FormCreate/src/config/selectRule.ts b/src/components/FormCreate/src/config/selectRule.ts index 5d24c713..a6f3841f 100644 --- a/src/components/FormCreate/src/config/selectRule.ts +++ b/src/components/FormCreate/src/config/selectRule.ts @@ -32,6 +32,11 @@ const selectRule = [ } ] }, + { + type: 'switch', + field: 'filterable', + title: '是否可搜索' + }, { type: 'switch', field: 'multiple', title: '是否多选' }, { type: 'switch', @@ -56,28 +61,12 @@ const selectRule = [ title: 'autocomplete 属性' }, { type: 'input', field: 'placeholder', title: '占位符' }, - { - type: 'switch', - field: 'filterable', - title: '是否可搜索' - }, { type: 'switch', field: 'allowCreate', title: '是否允许用户创建新条目' }, { type: 'input', field: 'noMatchText', title: '搜索条件无匹配时显示的文字' }, - { - type: 'switch', - field: 'remote', - title: '其中的选项是否从服务器远程加载' - }, - { - type: 'input', - field: 'remoteField', - title: '请求参数', - info: '远程请求时请求携带的参数名称,如:name' - }, { type: 'input', field: 'noDataText', title: '选项为空时显示的文字' }, { type: 'switch', @@ -174,6 +163,18 @@ const apiSelectRule = [ return data.list.map(item=> ({label: item.nickname,value: item.id})) }` } + }, + { + type: 'switch', + field: 'remote', + info: '是否可搜索', + title: '其中的选项是否从服务器远程加载' + }, + { + type: 'input', + field: 'remoteField', + title: '请求参数', + info: '远程请求时请求携带的参数名称,如:name' } ] -- Gitee From 5525bc2257c7cbb7852b02143a9edee0a55bb2b9 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 9 May 2024 22:13:23 +0800 Subject: [PATCH 005/341] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20ai=20chat=20=E4=B8=BB=E6=A1=86=E6=9E=B6?= =?UTF-8?q?=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/chat/index.vue | 228 +++++++++++++++++++++++++----------- 1 file changed, 160 insertions(+), 68 deletions(-) diff --git a/src/views/ai/chat/index.vue b/src/views/ai/chat/index.vue index bc846a3d..ec49b774 100644 --- a/src/views/ai/chat/index.vue +++ b/src/views/ai/chat/index.vue @@ -1,67 +1,92 @@ @@ -105,21 +130,60 @@ const searchConversation = () => { } -- Gitee From 02fe7e31d058ab111f9c55d0dd53175749097e6c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 9 May 2024 23:02:57 +0800 Subject: [PATCH 006/341] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9AAPI=20=E5=AF=86=E9=92=A5=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/ai/model/apiKey/index.ts | 39 +++++ src/permission.ts | 2 +- src/utils/dict.ts | 9 +- src/views/ai/model/apiKey/ApiKeyForm.vue | 132 +++++++++++++++++ src/views/ai/model/apiKey/index.vue | 181 +++++++++++++++++++++++ 5 files changed, 359 insertions(+), 4 deletions(-) create mode 100644 src/api/ai/model/apiKey/index.ts create mode 100644 src/views/ai/model/apiKey/ApiKeyForm.vue create mode 100644 src/views/ai/model/apiKey/index.vue diff --git a/src/api/ai/model/apiKey/index.ts b/src/api/ai/model/apiKey/index.ts new file mode 100644 index 00000000..47e415e4 --- /dev/null +++ b/src/api/ai/model/apiKey/index.ts @@ -0,0 +1,39 @@ +import request from '@/config/axios' + +// AI API 密钥 VO +export interface ApiKeyVO { + id: number // 编号 + name: string // 名称 + apiKey: string // 密钥 + platform: string // 平台 + url: string // 自定义 API 地址 + status: number // 状态 +} + +// AI API 密钥 API +export const ApiKeyApi = { + // 查询AI API 密钥分页 + getApiKeyPage: async (params: any) => { + return await request.get({ url: `/ai/api-key/page`, params }) + }, + + // 查询AI API 密钥详情 + getApiKey: async (id: number) => { + return await request.get({ url: `/ai/api-key/get?id=` + id }) + }, + + // 新增AI API 密钥 + createApiKey: async (data: ApiKeyVO) => { + return await request.post({ url: `/ai/api-key/create`, data }) + }, + + // 修改AI API 密钥 + updateApiKey: async (data: ApiKeyVO) => { + return await request.put({ url: `/ai/api-key/update`, data }) + }, + + // 删除AI API 密钥 + deleteApiKey: async (id: number) => { + return await request.delete({ url: `/ai/api-key/delete?id=` + id }) + } +} diff --git a/src/permission.ts b/src/permission.ts index d538303b..b04bc3c1 100644 --- a/src/permission.ts +++ b/src/permission.ts @@ -83,7 +83,7 @@ router.beforeEach(async (to, from, next) => { const redirectPath = from.query.redirect || to.path // 修复跳转时不带参数的问题 const redirect = decodeURIComponent(redirectPath as string) - const { basePath, paramsObject: query } = parseURL(redirect) + const { paramsObject: query } = parseURL(redirect) const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect, query } next(nextData) } else { diff --git a/src/utils/dict.ts b/src/utils/dict.ts index 631a40b0..ab6e2923 100644 --- a/src/utils/dict.ts +++ b/src/utils/dict.ts @@ -1,8 +1,8 @@ /** * 数据字典工具类 */ -import {useDictStoreWithOut} from '@/store/modules/dict' -import {ElementPlusInfoType} from '@/types/elementPlus' +import { useDictStoreWithOut } from '@/store/modules/dict' +import { ElementPlusInfoType } from '@/types/elementPlus' const dictStore = useDictStoreWithOut() @@ -209,5 +209,8 @@ export enum DICT_TYPE { // ========== ERP - 企业资源计划模块 ========== ERP_AUDIT_STATUS = 'erp_audit_status', // ERP 审批状态 - ERP_STOCK_RECORD_BIZ_TYPE = 'erp_stock_record_biz_type' // 库存明细的业务类型 + ERP_STOCK_RECORD_BIZ_TYPE = 'erp_stock_record_biz_type', // 库存明细的业务类型 + + // ========== AI - 人工智能模块 ========== + AI_PLATFORM = 'ai_platform' // AI 平台 } diff --git a/src/views/ai/model/apiKey/ApiKeyForm.vue b/src/views/ai/model/apiKey/ApiKeyForm.vue new file mode 100644 index 00000000..2f9ba580 --- /dev/null +++ b/src/views/ai/model/apiKey/ApiKeyForm.vue @@ -0,0 +1,132 @@ + + diff --git a/src/views/ai/model/apiKey/index.vue b/src/views/ai/model/apiKey/index.vue new file mode 100644 index 00000000..fcafc463 --- /dev/null +++ b/src/views/ai/model/apiKey/index.vue @@ -0,0 +1,181 @@ + + + -- Gitee From 1776217f1c861c65e15f3c48ff8b14c489b6d70f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 10 May 2024 22:48:33 +0800 Subject: [PATCH 007/341] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9AAPI=20=E6=A8=A1=E5=9E=8B=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/ai/model/apiKey/index.ts | 10 +- src/api/ai/model/chatModel/index.ts | 43 +++++ .../ai/model/chatModel/ChatModelForm.vue | 140 ++++++++++++++ src/views/ai/model/chatModel/index.vue | 179 ++++++++++++++++++ 4 files changed, 367 insertions(+), 5 deletions(-) create mode 100644 src/api/ai/model/chatModel/index.ts create mode 100644 src/views/ai/model/chatModel/ChatModelForm.vue create mode 100644 src/views/ai/model/chatModel/index.vue diff --git a/src/api/ai/model/apiKey/index.ts b/src/api/ai/model/apiKey/index.ts index 47e415e4..c96f2a66 100644 --- a/src/api/ai/model/apiKey/index.ts +++ b/src/api/ai/model/apiKey/index.ts @@ -12,27 +12,27 @@ export interface ApiKeyVO { // AI API 密钥 API export const ApiKeyApi = { - // 查询AI API 密钥分页 + // 查询 API 密钥分页 getApiKeyPage: async (params: any) => { return await request.get({ url: `/ai/api-key/page`, params }) }, - // 查询AI API 密钥详情 + // 查询 API 密钥详情 getApiKey: async (id: number) => { return await request.get({ url: `/ai/api-key/get?id=` + id }) }, - // 新增AI API 密钥 + // 新增 API 密钥 createApiKey: async (data: ApiKeyVO) => { return await request.post({ url: `/ai/api-key/create`, data }) }, - // 修改AI API 密钥 + // 修改 API 密钥 updateApiKey: async (data: ApiKeyVO) => { return await request.put({ url: `/ai/api-key/update`, data }) }, - // 删除AI API 密钥 + // 删除 API 密钥 deleteApiKey: async (id: number) => { return await request.delete({ url: `/ai/api-key/delete?id=` + id }) } diff --git a/src/api/ai/model/chatModel/index.ts b/src/api/ai/model/chatModel/index.ts new file mode 100644 index 00000000..09f8d66b --- /dev/null +++ b/src/api/ai/model/chatModel/index.ts @@ -0,0 +1,43 @@ +import request from '@/config/axios' + +// AI 聊天模型 VO +export interface ChatModelVO { + id: number // 编号 + keyId: number // API 秘钥编号 + name: string // 模型名字 + model: string // 模型标识 + platform: string // 模型平台 + sort: number // 排序 + status: number // 状态 + temperature: number // 温度参数 + maxTokens: number // 单条回复的最大 Token 数量 + maxContexts: number // 上下文的最大 Message 数量 +} + +// AI 聊天模型 API +export const ChatModelApi = { + // 查询聊天模型分页 + getChatModelPage: async (params: any) => { + return await request.get({ url: `/ai/chat-model/page`, params }) + }, + + // 查询聊天模型详情 + getChatModel: async (id: number) => { + return await request.get({ url: `/ai/chat-model/get?id=` + id }) + }, + + // 新增聊天模型 + createChatModel: async (data: ChatModelVO) => { + return await request.post({ url: `/ai/chat-model/create`, data }) + }, + + // 修改聊天模型 + updateChatModel: async (data: ChatModelVO) => { + return await request.put({ url: `/ai/chat-model/update`, data }) + }, + + // 删除聊天模型 + deleteChatModel: async (id: number) => { + return await request.delete({ url: `/ai/chat-model/delete?id=` + id }) + } +} diff --git a/src/views/ai/model/chatModel/ChatModelForm.vue b/src/views/ai/model/chatModel/ChatModelForm.vue new file mode 100644 index 00000000..65374291 --- /dev/null +++ b/src/views/ai/model/chatModel/ChatModelForm.vue @@ -0,0 +1,140 @@ + + diff --git a/src/views/ai/model/chatModel/index.vue b/src/views/ai/model/chatModel/index.vue new file mode 100644 index 00000000..d43051aa --- /dev/null +++ b/src/views/ai/model/chatModel/index.vue @@ -0,0 +1,179 @@ + + + -- Gitee From 9d322c3a94616d00bd1511828f3f581dd33c938e Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 10 May 2024 23:35:47 +0800 Subject: [PATCH 008/341] =?UTF-8?q?=E3=80=90=E6=B7=BB=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E8=B0=83=E6=95=B4ui=20=E5=A2=9E=E5=8A=A0=20chat=E5=AF=B9?= =?UTF-8?q?=E8=AF=9D=E5=92=8C=E5=8F=91=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src/assets/ai/copy.svg | 1 + src/assets/ai/delete.svg | 1 + src/views/ai/chat/index.vue | 252 +++++++++++++++++++++++++++++++++--- 4 files changed, 234 insertions(+), 22 deletions(-) create mode 100644 src/assets/ai/copy.svg create mode 100644 src/assets/ai/delete.svg diff --git a/package.json b/package.json index b450bf69..db819026 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "private": false, "scripts": { "i": "pnpm install", - "dev": "vite", + "dev": "vite --mode env.local", "dev-server": "vite --mode dev", "ts:check": "vue-tsc --noEmit", "build:local": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build", diff --git a/src/assets/ai/copy.svg b/src/assets/ai/copy.svg new file mode 100644 index 00000000..f51f8d81 --- /dev/null +++ b/src/assets/ai/copy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/ai/delete.svg b/src/assets/ai/delete.svg new file mode 100644 index 00000000..d2ee18ed --- /dev/null +++ b/src/assets/ai/delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/views/ai/chat/index.vue b/src/views/ai/chat/index.vue index ec49b774..116f0e34 100644 --- a/src/views/ai/chat/index.vue +++ b/src/views/ai/chat/index.vue @@ -5,7 +5,7 @@
- + 新建对话 @@ -17,11 +17,11 @@ @keyup="searchConversation" > -
+
置顶 @@ -32,15 +32,15 @@ @click="changeConversation(conversation)" >
- + {{ conversation.title }}
- + - +
@@ -50,12 +50,12 @@
- + 角色仓库
- - 清空未置顶对话 + + 清空未置顶对话
@@ -67,25 +67,96 @@ 标题......
- 3.5-turbo-0125 + 3.5-turbo-0125 + + - + - + - +
- 对话列表 - - + + +
+ +
+
+ +
+
+
+ 2024-05-10 22:38 +
+
+ + 如果您想获取某个网页或程序的截图,可以使用浏览器自带的截图功能,或者使用第三方截图工具,如Snipping + Tool、FastStone Capture等。如果您想将屏幕上的某个区域截取下来,可以使用键盘上的“Prt + Sc”键(或“Print Screen”键)来获取整个屏幕的截图,并将其粘贴到图像编辑软件中进行编辑和保存。 + 如果您需要更具体的帮助,例如如何使用特定的截图工具或如何编辑截图,请提供更多详细信息,我将尽力为您提供帮助。 + + +
+
+
+ + 复制 +
+
+ + 删除 +
+
+
+
+ +
+
+ +
+
+
+ 2024-05-10 22:38 +
+
+ + 今天天气 + +
+
+
+ + 复制 +
+
+ + 删除 +
+
+
+ +
+
+ + +
+ + +
+ + 发送 +
@@ -172,8 +243,10 @@ const searchConversation = () => { border-radius: 5px; align-items: center; line-height: 30px; + &.active { background-color: #e6e6e6; + .button { display: inline-block; } @@ -184,6 +257,7 @@ const searchConversation = () => { flex-direction: row; align-items: center; } + .title { padding: 5px 10px; max-width: 220px; @@ -192,6 +266,7 @@ const searchConversation = () => { white-space: nowrap; text-overflow: ellipsis; } + .avatar { width: 28px; height: 28px; @@ -199,6 +274,7 @@ const searchConversation = () => { flex-direction: row; justify-items: center; } + // 对话编辑、删除 .button-wrapper { right: 2px; @@ -206,6 +282,7 @@ const searchConversation = () => { flex-direction: row; justify-items: center; color: #606266; + .el-icon { margin-right: 5px; } @@ -227,6 +304,7 @@ const searchConversation = () => { color: #606266; padding: 0; margin: 0; + > span { margin-left: 5px; } @@ -234,6 +312,7 @@ const searchConversation = () => { } } +// 头部 .detail-container { background: #ffffff; @@ -243,16 +322,147 @@ const searchConversation = () => { align-items: center; justify-content: space-between; background: #fbfbfb; + box-shadow: 0 0 0 0 #dcdfe6; .title { - font-size: 23px; + font-size: 18px; font-weight: bold; } } +} + +// 中间 +.chat-list { + display: flex; + flex-direction: column; + + .message-item { + margin-top: 50px; + } + + .left-message { + display: flex; + flex-direction: row; + + } + + .right-message { + display: flex; + flex-direction: row-reverse; + justify-content: flex-start; + } + + .avatar { + //height: 170px; + //width: 170px; + } + + .message { + display: flex; + flex-direction: column; + text-align: left; + margin-left: 15px; + + .time { + text-align: left; + line-height: 30px; + } + + .left-text-container { + display: flex; + flex-direction: column; + overflow-wrap: break-word; + background-color: #e4e4e4; + box-shadow: 0 0 0 1px #e4e4e4; + border-radius: 10px; + padding: 10px 10px 5px 10px; + + .left-text { + color: #393939; + } + } + + .right-text-container { + display: flex; + flex-direction: column; + overflow-wrap: break-word; + background-color: #267fff; + color: #FFF; + box-shadow: 0 0 0 1px #267fff; + border-radius: 10px; + padding: 10px; + + .right-text { + color: #FFF; + } + } + + .left-btns, .right-btns { + display: flex; + flex-direction: row; + margin-top: 8px; + } + + + } + + // 复制、删除按钮 + .btn-cus { + display: flex; + background-color: transparent; + align-items: center; + + .btn-image { + height: 20px; + margin-right: 5px; + } + + .btn-cus-text { + color: #757575; + } + } + + .btn-cus:hover { + cursor: pointer; + } + + .btn-cus:focus { + background-color: #8c939d; + } +} + +// 底部 +.footer-container { + display: flex; + flex-direction: column; + height: auto; + border: 1px solid #e3e3e3; + border-radius: 10px; + margin: 20px 20px; + padding: 9px 10px; .prompt-input { + height: 80px; + //box-shadow: none; + border: none; + box-sizing: border-box; + resize: none; + padding: 0px 2px; + //padding: 5px 5px; + overflow: hidden; + } + + .prompt-input:focus { + outline: none; + } + + .prompt-btns { + display: flex; + justify-content: space-between; + padding-bottom: 0px; + padding-top: 5px; } } -- Gitee From b19d56ad026f705e09505ed40413c18f47de893f Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 10 May 2024 23:38:44 +0800 Subject: [PATCH 009/341] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E8=B0=83=E6=95=B4=20right=20=E5=AF=B9=E8=AF=9D=20=E5=A4=B4?= =?UTF-8?q?=E5=83=8F=E8=B7=9D=E7=A6=BB=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/chat/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/ai/chat/index.vue b/src/views/ai/chat/index.vue index 116f0e34..4b4bee22 100644 --- a/src/views/ai/chat/index.vue +++ b/src/views/ai/chat/index.vue @@ -361,7 +361,7 @@ const searchConversation = () => { display: flex; flex-direction: column; text-align: left; - margin-left: 15px; + margin: 0 15px; .time { text-align: left; -- Gitee From f01dc0a539d7e52229bd64b5ac5b9afef86a308a Mon Sep 17 00:00:00 2001 From: scholar <1145227973@qq.com> Date: Sat, 11 May 2024 11:26:47 +0800 Subject: [PATCH 010/341] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/crm/statistics/performance/index.vue | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/views/crm/statistics/performance/index.vue b/src/views/crm/statistics/performance/index.vue index ea43ed4d..469569af 100644 --- a/src/views/crm/statistics/performance/index.vue +++ b/src/views/crm/statistics/performance/index.vue @@ -75,6 +75,7 @@ import { defaultProps, handleTree } from '@/utils/tree' import ContractCountPerformance from './components/ContractCountPerformance.vue' import ContractPricePerformance from './components/ContractPricePerformance.vue' import ReceivablePricePerformance from './components/ReceivablePricePerformance.vue' +import dayjs from "dayjs" defineOptions({ name: 'CrmStatisticsCustomer' }) @@ -82,8 +83,8 @@ const queryParams = reactive({ deptId: useUserStore().getUser.deptId, userId: undefined, times: [ - // 默认显示当年的数据 - formatDate(beginOfDay(new Date(new Date().getTime() - 3600 * 1000 * 24 * 7))) + formatDate(beginOfDay(new Date(new Date().getFullYear(),0, 1, 0, 0, 0))), // 默认查询当年的数据,比如2024年,起始时间2024-01-01 00:00:00 + formatDate(beginOfDay(new Date(new Date().getFullYear()+1,0, 1, 0, 0, 0))) //查询时间范围结束时间,2025-01-01 00:00:00 ] }) @@ -111,13 +112,13 @@ const handleQuery = () => { // 从 queryParams.times[0] 中获取到了年份 const selectYear = parseInt(queryParams.times[0]) - // 创建一个新的 Date 对象,设置为指定的年份的第一天 - const fullDate = new Date(selectYear, 0, 1, 0, 0, 0) + // 创建一个新的 Date 对象,设置为指定的年份的第一天,以及第二年的第一天,以时间段的方式,将查询时间传递给后端 + const fullDate = new Date(selectYear, 0, 1, 0, 0, 0) //比如2024年,起始时间2024-01-01 00:00:00 + const nextFullDate = new Date(selectYear+1, 0, 1, 0, 0, 0) //查询时间范围结束时间,2025-01-01 00:00:00 // 将完整的日期时间格式化为需要的字符串形式,比如 2004-01-01 00:00:00 - queryParams.times[0] = `${fullDate.getFullYear()}-${ - String(fullDate.getMonth() + 1).padStart(2, '0') - }-${String(fullDate.getDate()).padStart(2, '0')} ${String(fullDate.getHours()).padStart(2, '0')}:${String(fullDate.getMinutes()).padStart(2, '0')}:${String(fullDate.getSeconds()).padStart(2, '0')}` + queryParams.times[0] = dayjs(fullDate).format('YYYY-MM-DD HH:mm:ss') + queryParams.times[1] = dayjs(nextFullDate).format('YYYY-MM-DD HH:mm:ss') switch (activeTab.value) { case 'ContractCountPerformance': -- Gitee From dd2c4b6b3ca8a3992b11535d1a12f2fe875fb4e7 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 11 May 2024 19:46:33 +0800 Subject: [PATCH 011/341] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9AAPI=20=E6=A8=A1=E5=9E=8B=E7=AE=A1=E7=90=86=EF=BC=88?= =?UTF-8?q?=E5=AE=8C=E5=96=84=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/ai/model/apiKey/index.ts | 5 +++ src/views/ai/model/apiKey/ApiKeyForm.vue | 18 ++++---- src/views/ai/model/apiKey/index.vue | 9 ++-- .../ai/model/chatModel/ChatModelForm.vue | 41 +++++++++++++++---- src/views/ai/model/chatModel/index.vue | 37 ++++++++++------- 5 files changed, 73 insertions(+), 37 deletions(-) diff --git a/src/api/ai/model/apiKey/index.ts b/src/api/ai/model/apiKey/index.ts index c96f2a66..60d8a46c 100644 --- a/src/api/ai/model/apiKey/index.ts +++ b/src/api/ai/model/apiKey/index.ts @@ -17,6 +17,11 @@ export const ApiKeyApi = { return await request.get({ url: `/ai/api-key/page`, params }) }, + // 获得 API 密钥列表 + getApiKeyList: async () => { + return await request.get({ url: `/ai/api-key/simple-list` }) + }, + // 查询 API 密钥详情 getApiKey: async (id: number) => { return await request.get({ url: `/ai/api-key/get?id=` + id }) diff --git a/src/views/ai/model/apiKey/ApiKeyForm.vue b/src/views/ai/model/apiKey/ApiKeyForm.vue index 2f9ba580..a8fc0128 100644 --- a/src/views/ai/model/apiKey/ApiKeyForm.vue +++ b/src/views/ai/model/apiKey/ApiKeyForm.vue @@ -7,13 +7,7 @@ label-width="120px" v-loading="formLoading" > - - - - - - - + - - + + + + + + + + diff --git a/src/views/ai/model/apiKey/index.vue b/src/views/ai/model/apiKey/index.vue index fcafc463..6daf6a7d 100644 --- a/src/views/ai/model/apiKey/index.vue +++ b/src/views/ai/model/apiKey/index.vue @@ -60,15 +60,14 @@ - - - - + - + + + -- Gitee From 73e851602420bac1dbf34103ecce0c1de3b5b1a6 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 11 May 2024 22:30:44 +0800 Subject: [PATCH 012/341] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91CRM=EF=BC=9A=E4=BC=98=E5=8C=96=E5=91=98?= =?UTF-8?q?=E5=B7=A5=E4=B8=9A=E7=BB=A9=E7=BB=9F=E8=AE=A1=E7=9A=84=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/ContractCountPerformance.vue | 102 +++++++++++------- .../components/ContractPricePerformance.vue | 102 +++++++++++------- .../components/ReceivablePricePerformance.vue | 102 +++++++++++------- .../crm/statistics/performance/index.vue | 34 +++--- 4 files changed, 197 insertions(+), 143 deletions(-) diff --git a/src/views/crm/statistics/performance/components/ContractCountPerformance.vue b/src/views/crm/statistics/performance/components/ContractCountPerformance.vue index 5dc4d9e7..fa5a897b 100644 --- a/src/views/crm/statistics/performance/components/ContractCountPerformance.vue +++ b/src/views/crm/statistics/performance/components/ContractCountPerformance.vue @@ -10,9 +10,15 @@ - + @@ -23,7 +29,7 @@ import { EChartsOption } from 'echarts' import { StatisticsPerformanceApi, StatisticsPerformanceRespVO -} from "@/api/crm/statistics/performance" +} from '@/api/crm/statistics/performance' defineOptions({ name: 'ContractCountPerformance' }) const props = defineProps<{ queryParams: any }>() // 搜索参数 @@ -86,29 +92,30 @@ const echartsOption = reactive({ type: 'shadow' } }, - yAxis: [{ - type: 'value', - name: '数量(个)', - axisTick: { - show: false - }, - axisLabel: { - color: '#BDBDBD', - formatter: '{value}' - }, - /** 坐标轴轴线相关设置 */ - axisLine: { - lineStyle: { - color: '#BDBDBD' + yAxis: [ + { + type: 'value', + name: '数量(个)', + axisTick: { + show: false + }, + axisLabel: { + color: '#BDBDBD', + formatter: '{value}' + }, + /** 坐标轴轴线相关设置 */ + axisLine: { + lineStyle: { + color: '#BDBDBD' + } + }, + splitLine: { + show: true, + lineStyle: { + color: '#e6e6e6' + } } }, - splitLine: { - show: true, - lineStyle: { - color: '#e6e6e6' - } - } - }, { type: 'value', name: '', @@ -134,7 +141,8 @@ const echartsOption = reactive({ color: '#e6e6e6' } } - }], + } + ], xAxis: { type: 'category', name: '日期', @@ -152,9 +160,7 @@ const loadData = async () => { // 2.1 更新 Echarts 数据 if (echartsOption.xAxis && echartsOption.xAxis['data']) { - echartsOption.xAxis['data'] = performanceList.map( - (s: StatisticsPerformanceRespVO) => s.time - ) + echartsOption.xAxis['data'] = performanceList.map((s: StatisticsPerformanceRespVO) => s.time) } if (echartsOption.series && echartsOption.series[0] && echartsOption.series[0]['data']) { echartsOption.series[0]['data'] = performanceList.map( @@ -165,16 +171,20 @@ const loadData = async () => { echartsOption.series[1]['data'] = performanceList.map( (s: StatisticsPerformanceRespVO) => s.lastMonthCount ) - echartsOption.series[3]['data'] = performanceList.map( - (s: StatisticsPerformanceRespVO) => s.lastMonthCount !== 0 ? ((s.currentMonthCount - s.lastMonthCount) / s.lastMonthCount*100).toFixed(2) : 'NULL' + echartsOption.series[3]['data'] = performanceList.map((s: StatisticsPerformanceRespVO) => + s.lastMonthCount !== 0 + ? (((s.currentMonthCount - s.lastMonthCount) / s.lastMonthCount) * 100).toFixed(2) + : 'NULL' ) } if (echartsOption.series && echartsOption.series[2] && echartsOption.series[2]['data']) { echartsOption.series[2]['data'] = performanceList.map( (s: StatisticsPerformanceRespVO) => s.lastYearCount ) - echartsOption.series[4]['data'] = performanceList.map( - (s: StatisticsPerformanceRespVO) => s.lastYearCount !== 0 ? ((s.currentMonthCount - s.lastYearCount) / s.lastYearCount*100).toFixed(2) : 'NULL' + echartsOption.series[4]['data'] = performanceList.map((s: StatisticsPerformanceRespVO) => + s.lastYearCount !== 0 + ? (((s.currentMonthCount - s.lastYearCount) / s.lastYearCount) * 100).toFixed(2) + : 'NULL' ) } @@ -182,28 +192,38 @@ const loadData = async () => { list.value = performanceList convertListData() loading.value = false - } // 初始化数据 -const columnsData = reactive([]); -const tableData = reactive([{title: '当月合同数量统计(个)'}, {title: '上月合同数量统计(个)'}, - {title: '去年当月合同数量统计(个)'}, {title: '环比增长率(%)'}, {title: '同比增长率(%)'}]) +const columnsData = reactive([]) +const tableData = reactive([ + { title: '当月合同数量统计(个)' }, + { title: '上月合同数量统计(个)' }, + { title: '去年当月合同数量统计(个)' }, + { title: '环比增长率(%)' }, + { title: '同比增长率(%)' } +]) // 定义 convertListData 方法,数据行列转置,展示每月数据 const convertListData = () => { - const columnObj = {label: '日期', prop: 'title'} - columnsData.splice(0, columnsData.length);//清空数组 + const columnObj = { label: '日期', prop: 'title' } + columnsData.splice(0, columnsData.length) //清空数组 columnsData.push(columnObj) list.value.forEach((item, index) => { - const columnObj = {label: item.time, prop: 'prop' + index} + const columnObj = { label: item.time, prop: 'prop' + index } columnsData.push(columnObj) tableData[0]['prop' + index] = item.currentMonthCount tableData[1]['prop' + index] = item.lastMonthCount tableData[2]['prop' + index] = item.lastYearCount - tableData[3]['prop' + index] = item.lastMonthCount !== 0 ? ((item.currentMonthCount - item.lastMonthCount) / item.lastMonthCount * 100).toFixed(2) : 'NULL' - tableData[4]['prop' + index] = item.lastYearCount !== 0 ? ((item.currentMonthCount - item.lastYearCount) / item.lastYearCount * 100).toFixed(2) : 'NULL' + tableData[3]['prop' + index] = + item.lastMonthCount !== 0 + ? (((item.currentMonthCount - item.lastMonthCount) / item.lastMonthCount) * 100).toFixed(2) + : 'NULL' + tableData[4]['prop' + index] = + item.lastYearCount !== 0 + ? (((item.currentMonthCount - item.lastYearCount) / item.lastYearCount) * 100).toFixed(2) + : 'NULL' }) } diff --git a/src/views/crm/statistics/performance/components/ContractPricePerformance.vue b/src/views/crm/statistics/performance/components/ContractPricePerformance.vue index 0c33dc22..dd52d9fb 100644 --- a/src/views/crm/statistics/performance/components/ContractPricePerformance.vue +++ b/src/views/crm/statistics/performance/components/ContractPricePerformance.vue @@ -10,9 +10,15 @@ - + @@ -23,7 +29,7 @@ import { EChartsOption } from 'echarts' import { StatisticsPerformanceApi, StatisticsPerformanceRespVO -} from "@/api/crm/statistics/performance" +} from '@/api/crm/statistics/performance' defineOptions({ name: 'ContractPricePerformance' }) const props = defineProps<{ queryParams: any }>() // 搜索参数 @@ -86,29 +92,30 @@ const echartsOption = reactive({ type: 'shadow' } }, - yAxis: [{ - type: 'value', - name: '金额(元)', - axisTick: { - show: false - }, - axisLabel: { - color: '#BDBDBD', - formatter: '{value}' - }, - /** 坐标轴轴线相关设置 */ - axisLine: { - lineStyle: { - color: '#BDBDBD' + yAxis: [ + { + type: 'value', + name: '金额(元)', + axisTick: { + show: false + }, + axisLabel: { + color: '#BDBDBD', + formatter: '{value}' + }, + /** 坐标轴轴线相关设置 */ + axisLine: { + lineStyle: { + color: '#BDBDBD' + } + }, + splitLine: { + show: true, + lineStyle: { + color: '#e6e6e6' + } } }, - splitLine: { - show: true, - lineStyle: { - color: '#e6e6e6' - } - } - }, { type: 'value', name: '', @@ -134,7 +141,8 @@ const echartsOption = reactive({ color: '#e6e6e6' } } - }], + } + ], xAxis: { type: 'category', name: '日期', @@ -152,9 +160,7 @@ const loadData = async () => { // 2.1 更新 Echarts 数据 if (echartsOption.xAxis && echartsOption.xAxis['data']) { - echartsOption.xAxis['data'] = performanceList.map( - (s: StatisticsPerformanceRespVO) => s.time - ) + echartsOption.xAxis['data'] = performanceList.map((s: StatisticsPerformanceRespVO) => s.time) } if (echartsOption.series && echartsOption.series[0] && echartsOption.series[0]['data']) { echartsOption.series[0]['data'] = performanceList.map( @@ -165,16 +171,20 @@ const loadData = async () => { echartsOption.series[1]['data'] = performanceList.map( (s: StatisticsPerformanceRespVO) => s.lastMonthCount ) - echartsOption.series[3]['data'] = performanceList.map( - (s: StatisticsPerformanceRespVO) => s.lastMonthCount !== 0 ? ((s.currentMonthCount - s.lastMonthCount) / s.lastMonthCount*100).toFixed(2) : 'NULL' + echartsOption.series[3]['data'] = performanceList.map((s: StatisticsPerformanceRespVO) => + s.lastMonthCount !== 0 + ? (((s.currentMonthCount - s.lastMonthCount) / s.lastMonthCount) * 100).toFixed(2) + : 'NULL' ) } if (echartsOption.series && echartsOption.series[2] && echartsOption.series[2]['data']) { echartsOption.series[2]['data'] = performanceList.map( (s: StatisticsPerformanceRespVO) => s.lastYearCount ) - echartsOption.series[4]['data'] = performanceList.map( - (s: StatisticsPerformanceRespVO) => s.lastYearCount !== 0 ? ((s.currentMonthCount - s.lastYearCount) / s.lastYearCount*100).toFixed(2) : 'NULL' + echartsOption.series[4]['data'] = performanceList.map((s: StatisticsPerformanceRespVO) => + s.lastYearCount !== 0 + ? (((s.currentMonthCount - s.lastYearCount) / s.lastYearCount) * 100).toFixed(2) + : 'NULL' ) } @@ -182,28 +192,38 @@ const loadData = async () => { list.value = performanceList convertListData() loading.value = false - } // 初始化数据 -const columnsData = reactive([]); -const tableData = reactive([{title: '当月合同金额统计(元)'}, {title: '上月合同金额统计(元)'}, {title: '去年当月合同金额统计(元)'}, - {title: '环比增长率(%)'}, {title: '同比增长率(%)'}]) +const columnsData = reactive([]) +const tableData = reactive([ + { title: '当月合同金额统计(元)' }, + { title: '上月合同金额统计(元)' }, + { title: '去年当月合同金额统计(元)' }, + { title: '环比增长率(%)' }, + { title: '同比增长率(%)' } +]) // 定义 init 方法 const convertListData = () => { - const columnObj = {label: '日期', prop: 'title'} - columnsData.splice(0, columnsData.length)//清空数组 + const columnObj = { label: '日期', prop: 'title' } + columnsData.splice(0, columnsData.length) //清空数组 columnsData.push(columnObj) list.value.forEach((item, index) => { - const columnObj = {label: item.time, prop: 'prop' + index} + const columnObj = { label: item.time, prop: 'prop' + index } columnsData.push(columnObj) tableData[0]['prop' + index] = item.currentMonthCount tableData[1]['prop' + index] = item.lastMonthCount tableData[2]['prop' + index] = item.lastYearCount - tableData[3]['prop' + index] = item.lastMonthCount !== 0 ? ((item.currentMonthCount - item.lastMonthCount) / item.lastMonthCount*100).toFixed(2) : 'NULL' - tableData[4]['prop' + index] = item.lastYearCount !== 0 ? ((item.currentMonthCount - item.lastYearCount) / item.lastYearCount*100).toFixed(2) : 'NULL' + tableData[3]['prop' + index] = + item.lastMonthCount !== 0 + ? (((item.currentMonthCount - item.lastMonthCount) / item.lastMonthCount) * 100).toFixed(2) + : 'NULL' + tableData[4]['prop' + index] = + item.lastYearCount !== 0 + ? (((item.currentMonthCount - item.lastYearCount) / item.lastYearCount) * 100).toFixed(2) + : 'NULL' }) } diff --git a/src/views/crm/statistics/performance/components/ReceivablePricePerformance.vue b/src/views/crm/statistics/performance/components/ReceivablePricePerformance.vue index aa3f5b19..169f074b 100644 --- a/src/views/crm/statistics/performance/components/ReceivablePricePerformance.vue +++ b/src/views/crm/statistics/performance/components/ReceivablePricePerformance.vue @@ -10,9 +10,15 @@ - + @@ -23,7 +29,7 @@ import { EChartsOption } from 'echarts' import { StatisticsPerformanceApi, StatisticsPerformanceRespVO -} from "@/api/crm/statistics/performance" +} from '@/api/crm/statistics/performance' defineOptions({ name: 'ContractPricePerformance' }) const props = defineProps<{ queryParams: any }>() // 搜索参数 @@ -86,29 +92,30 @@ const echartsOption = reactive({ type: 'shadow' } }, - yAxis: [{ - type: 'value', - name: '金额(元)', - axisTick: { - show: false - }, - axisLabel: { - color: '#BDBDBD', - formatter: '{value}' - }, - /** 坐标轴轴线相关设置 */ - axisLine: { - lineStyle: { - color: '#BDBDBD' + yAxis: [ + { + type: 'value', + name: '金额(元)', + axisTick: { + show: false + }, + axisLabel: { + color: '#BDBDBD', + formatter: '{value}' + }, + /** 坐标轴轴线相关设置 */ + axisLine: { + lineStyle: { + color: '#BDBDBD' + } + }, + splitLine: { + show: true, + lineStyle: { + color: '#e6e6e6' + } } }, - splitLine: { - show: true, - lineStyle: { - color: '#e6e6e6' - } - } - }, { type: 'value', name: '', @@ -134,7 +141,8 @@ const echartsOption = reactive({ color: '#e6e6e6' } } - }], + } + ], xAxis: { type: 'category', name: '日期', @@ -152,9 +160,7 @@ const loadData = async () => { // 2.1 更新 Echarts 数据 if (echartsOption.xAxis && echartsOption.xAxis['data']) { - echartsOption.xAxis['data'] = performanceList.map( - (s: StatisticsPerformanceRespVO) => s.time - ) + echartsOption.xAxis['data'] = performanceList.map((s: StatisticsPerformanceRespVO) => s.time) } if (echartsOption.series && echartsOption.series[0] && echartsOption.series[0]['data']) { echartsOption.series[0]['data'] = performanceList.map( @@ -165,16 +171,20 @@ const loadData = async () => { echartsOption.series[1]['data'] = performanceList.map( (s: StatisticsPerformanceRespVO) => s.lastMonthCount ) - echartsOption.series[3]['data'] = performanceList.map( - (s: StatisticsPerformanceRespVO) => s.lastMonthCount !== 0 ? ((s.currentMonthCount - s.lastMonthCount) / s.lastMonthCount*100).toFixed(2) : 'NULL' + echartsOption.series[3]['data'] = performanceList.map((s: StatisticsPerformanceRespVO) => + s.lastMonthCount !== 0 + ? (((s.currentMonthCount - s.lastMonthCount) / s.lastMonthCount) * 100).toFixed(2) + : 'NULL' ) } if (echartsOption.series && echartsOption.series[2] && echartsOption.series[1]['data']) { echartsOption.series[2]['data'] = performanceList.map( (s: StatisticsPerformanceRespVO) => s.lastYearCount ) - echartsOption.series[4]['data'] = performanceList.map( - (s: StatisticsPerformanceRespVO) => s.lastYearCount !== 0 ? ((s.currentMonthCount - s.lastYearCount) / s.lastYearCount*100).toFixed(2) : 'NULL' + echartsOption.series[4]['data'] = performanceList.map((s: StatisticsPerformanceRespVO) => + s.lastYearCount !== 0 + ? (((s.currentMonthCount - s.lastYearCount) / s.lastYearCount) * 100).toFixed(2) + : 'NULL' ) } @@ -182,28 +192,38 @@ const loadData = async () => { list.value = performanceList convertListData() loading.value = false - } // 初始化数据 -const columnsData = reactive([]); -const tableData = reactive([{title: '当月回款金额统计(元)'}, {title: '上月回款金额统计(元)'}, - {title: '去年当月回款金额统计(元)'}, {title: '环比增长率(%)'}, {title: '同比增长率(%)'}]); +const columnsData = reactive([]) +const tableData = reactive([ + { title: '当月回款金额统计(元)' }, + { title: '上月回款金额统计(元)' }, + { title: '去年当月回款金额统计(元)' }, + { title: '环比增长率(%)' }, + { title: '同比增长率(%)' } +]) // 定义 init 方法 const convertListData = () => { - const columnObj = {label: '日期', prop: 'title'} - columnsData.splice(0, columnsData.length)//清空数组 + const columnObj = { label: '日期', prop: 'title' } + columnsData.splice(0, columnsData.length) //清空数组 columnsData.push(columnObj) list.value.forEach((item, index) => { - const columnObj = {label: item.time, prop: 'prop' + index} + const columnObj = { label: item.time, prop: 'prop' + index } columnsData.push(columnObj) tableData[0]['prop' + index] = item.currentMonthCount tableData[1]['prop' + index] = item.lastMonthCount tableData[2]['prop' + index] = item.lastYearCount - tableData[3]['prop' + index] = item.lastMonthCount !== 0 ? ((item.currentMonthCount - item.lastMonthCount) / item.lastMonthCount*100).toFixed(2) : 'NULL' - tableData[4]['prop' + index] = item.lastYearCount !== 0 ? ((item.currentMonthCount - item.lastYearCount) / item.lastYearCount*100).toFixed(2) : 'NULL' + tableData[3]['prop' + index] = + item.lastMonthCount !== 0 + ? (((item.currentMonthCount - item.lastMonthCount) / item.lastMonthCount) * 100).toFixed(2) + : 'NULL' + tableData[4]['prop' + index] = + item.lastYearCount !== 0 + ? (((item.currentMonthCount - item.lastYearCount) / item.lastYearCount) * 100).toFixed(2) + : 'NULL' }) } diff --git a/src/views/crm/statistics/performance/index.vue b/src/views/crm/statistics/performance/index.vue index 469569af..822afec9 100644 --- a/src/views/crm/statistics/performance/index.vue +++ b/src/views/crm/statistics/performance/index.vue @@ -60,7 +60,10 @@ - + @@ -70,12 +73,11 @@ import * as DeptApi from '@/api/system/dept' import * as UserApi from '@/api/system/user' import { useUserStore } from '@/store/modules/user' -import { beginOfDay, defaultShortcuts, endOfDay, formatDate } from '@/utils/formatTime' +import { beginOfDay, endOfDay, formatDate } from '@/utils/formatTime' import { defaultProps, handleTree } from '@/utils/tree' import ContractCountPerformance from './components/ContractCountPerformance.vue' import ContractPricePerformance from './components/ContractPricePerformance.vue' import ReceivablePricePerformance from './components/ReceivablePricePerformance.vue' -import dayjs from "dayjs" defineOptions({ name: 'CrmStatisticsCustomer' }) @@ -83,8 +85,8 @@ const queryParams = reactive({ deptId: useUserStore().getUser.deptId, userId: undefined, times: [ - formatDate(beginOfDay(new Date(new Date().getFullYear(),0, 1, 0, 0, 0))), // 默认查询当年的数据,比如2024年,起始时间2024-01-01 00:00:00 - formatDate(beginOfDay(new Date(new Date().getFullYear()+1,0, 1, 0, 0, 0))) //查询时间范围结束时间,2025-01-01 00:00:00 + formatDate(beginOfDay(new Date(new Date().getFullYear(), 0, 1))), + formatDate(endOfDay(new Date(new Date().getFullYear(), 11, 31))) ] }) @@ -100,26 +102,18 @@ const userListByDeptId = computed(() => // 活跃标签 const activeTab = ref('ContractCountPerformance') -// 1.员工合同数量统计 -const ContractCountPerformanceRef = ref() -// 2.员工合同金额统计 -const ContractPricePerformanceRef = ref() -// 3.员工回款金额统计 -const ReceivablePricePerformanceRef = ref() +const ContractCountPerformanceRef = ref() // 员工合同数量统计 +const ContractPricePerformanceRef = ref() // 员工合同金额统计 +const ReceivablePricePerformanceRef = ref() // 员工回款金额统计 /** 搜索按钮操作 */ -const handleQuery = () => { +const handleQuery = () => { // 从 queryParams.times[0] 中获取到了年份 const selectYear = parseInt(queryParams.times[0]) + queryParams.times[0] = formatDate(beginOfDay(new Date(selectYear, 0, 1))) + queryParams.times[1] = formatDate(endOfDay(new Date(selectYear, 11, 31))) - // 创建一个新的 Date 对象,设置为指定的年份的第一天,以及第二年的第一天,以时间段的方式,将查询时间传递给后端 - const fullDate = new Date(selectYear, 0, 1, 0, 0, 0) //比如2024年,起始时间2024-01-01 00:00:00 - const nextFullDate = new Date(selectYear+1, 0, 1, 0, 0, 0) //查询时间范围结束时间,2025-01-01 00:00:00 - - // 将完整的日期时间格式化为需要的字符串形式,比如 2004-01-01 00:00:00 - queryParams.times[0] = dayjs(fullDate).format('YYYY-MM-DD HH:mm:ss') - queryParams.times[1] = dayjs(nextFullDate).format('YYYY-MM-DD HH:mm:ss') - + // 执行查询 switch (activeTab.value) { case 'ContractCountPerformance': ContractCountPerformanceRef.value?.loadData?.() -- Gitee From b116d82376119753924a39332ddca3c9a4f4acb7 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 12 May 2024 14:28:27 +0800 Subject: [PATCH 013/341] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20chat=20=E8=81=8A=E5=A4=A9=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E3=80=81=E5=88=A0=E9=99=A4=E3=80=81=E5=A4=8D=E5=88=B6?= =?UTF-8?q?=E5=88=B0=E7=B2=98=E8=B4=B4=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/ai/chat/message/index.ts | 41 +++ src/views/ai/chat/components/MessageList.vue | 276 +++++++++++++++++++ src/views/ai/chat/index.vue | 180 +----------- 3 files changed, 332 insertions(+), 165 deletions(-) create mode 100644 src/api/ai/chat/message/index.ts create mode 100644 src/views/ai/chat/components/MessageList.vue diff --git a/src/api/ai/chat/message/index.ts b/src/api/ai/chat/message/index.ts new file mode 100644 index 00000000..3dc1ea0f --- /dev/null +++ b/src/api/ai/chat/message/index.ts @@ -0,0 +1,41 @@ +import request from '@/config/axios' + +// 聊天VO +export interface ChatMessageVO { + id: number // 编号 + conversationId: string // 会话编号 + type: string // 消息类型 + userId: string // 用户编号 + roleId: string // 角色编号 + model: number // 模型标志 + modelId: number // 模型编号 + content: number // 聊天内容 + tokens: number // 消耗 Token 数量 + createTime: Date // 创建时间 +} + +export interface ChatMessageSendVO { + conversationId: string // 会话编号 + content: number // 聊天内容 +} + +// AI chat 聊天 +export const ChatMessageApi = { + + // 消息列表 + messageList: async (conversationId: string) => { + return await request.get({ url: `/ai/chat/message/list-by-conversation-id?conversationId=${conversationId}`}) + }, + + // 发送 send 消息 + send: async (data: ChatMessageSendVO) => { + return await request.post({ url: `/ai/chat/message/send`, data }) + }, + + + // 发送 send 消息 + delete: async (id: string) => { + return await request.delete({ url: `/ai/chat/message/delete?id=${id}` }) + }, + +} diff --git a/src/views/ai/chat/components/MessageList.vue b/src/views/ai/chat/components/MessageList.vue new file mode 100644 index 00000000..3038f886 --- /dev/null +++ b/src/views/ai/chat/components/MessageList.vue @@ -0,0 +1,276 @@ + + + + + + diff --git a/src/views/ai/chat/index.vue b/src/views/ai/chat/index.vue index 4b4bee22..f3dc471f 100644 --- a/src/views/ai/chat/index.vue +++ b/src/views/ai/chat/index.vue @@ -81,73 +81,10 @@
- - -
- -
-
- -
-
-
- 2024-05-10 22:38 -
-
- - 如果您想获取某个网页或程序的截图,可以使用浏览器自带的截图功能,或者使用第三方截图工具,如Snipping - Tool、FastStone Capture等。如果您想将屏幕上的某个区域截取下来,可以使用键盘上的“Prt - Sc”键(或“Print Screen”键)来获取整个屏幕的截图,并将其粘贴到图像编辑软件中进行编辑和保存。 - 如果您需要更具体的帮助,例如如何使用特定的截图工具或如何编辑截图,请提供更多详细信息,我将尽力为您提供帮助。 - - -
-
-
- - 复制 -
-
- - 删除 -
-
-
-
- -
-
- -
-
-
- 2024-05-10 22:38 -
-
- - 今天天气 - -
-
-
- - 复制 -
-
- - 删除 -
-
-
- -
-
- + + + +
- 发送 + 发送
@@ -100,25 +158,15 @@ diff --git a/src/components/MdPreview/md.ts b/src/components/MdPreview/md.ts new file mode 100644 index 00000000..81aa7b65 --- /dev/null +++ b/src/components/MdPreview/md.ts @@ -0,0 +1,30 @@ + +// @ts-ignore +import markdownit from 'markdown-it'; +import hljs from 'highlight.js'; // https://highlightjs.org +import katexPlugin from '@iktakahiro/markdown-it-katex'; +const codeTool = (text: string) => ``; + +const md = markdownit({ + html: true, + linkfy: true, + highlight: function (str: string, lang: string) { + const baseText = str + if (lang && hljs.getLanguage(lang)) { + try { + return '
' +
+                    hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
+                    '' + codeTool(baseText) + '
'; + } catch (__) { } + } + return '
' + md.utils.escapeHtml(str) + '' + codeTool(baseText) + '
'; + } +}); + +md.use(katexPlugin); + +export default md; diff --git a/src/views/ai/chat/index.vue b/src/views/ai/chat/index.vue index 2e5cead6..317f6838 100644 --- a/src/views/ai/chat/index.vue +++ b/src/views/ai/chat/index.vue @@ -98,11 +98,12 @@ {{formatDate(item.createTime)}}
-
+ +
- + 复制
@@ -124,7 +125,7 @@ {{formatDate(item.createTime)}}
-
+
{{item.content}}
@@ -161,21 +162,30 @@ diff --git a/src/views/ai/model/chatRole/ChatRoleForm.vue b/src/views/ai/model/chatRole/ChatRoleForm.vue index 1e184bff..b83dea51 100644 --- a/src/views/ai/model/chatRole/ChatRoleForm.vue +++ b/src/views/ai/model/chatRole/ChatRoleForm.vue @@ -7,29 +7,37 @@ label-width="100px" v-loading="formLoading" > - - - - + + + + + + - - - - + - + - + @@ -42,7 +50,10 @@ - + + + + import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict' import { ChatRoleApi, ChatRoleVO } from '@/api/ai/model/chatRole' +import { CommonStatusEnum } from '@/utils/constants' +import { ChatModelApi, ChatModelVO } from '@/api/ai/model/chatModel' /** AI 聊天角色 表单 */ defineOptions({ name: 'ChatRoleForm' }) @@ -84,8 +97,8 @@ const formData = ref({ description: undefined, welcomeMessage: undefined, systemMessage: undefined, - publicStatus: undefined, - status: undefined + publicStatus: true, + status: CommonStatusEnum.ENABLE }) const formRules = reactive({ name: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }], @@ -98,6 +111,7 @@ const formRules = reactive({ publicStatus: [{ required: true, message: '是否公开不能为空', trigger: 'blur' }] }) const formRef = ref() // 表单 Ref +const chatModelList = ref([] as ChatModelVO[]) // 聊天模型列表 /** 打开弹窗 */ const open = async (type: string, id?: number) => { @@ -114,6 +128,8 @@ const open = async (type: string, id?: number) => { formLoading.value = false } } + // 获得下拉数据 + chatModelList.value = await ChatModelApi.getChatModelSimpleList(CommonStatusEnum.ENABLE) } defineExpose({ open }) // 提供 open 方法,用于打开弹窗 @@ -153,8 +169,8 @@ const resetForm = () => { description: undefined, welcomeMessage: undefined, systemMessage: undefined, - publicStatus: undefined, - status: undefined + publicStatus: true, + status: CommonStatusEnum.ENABLE } formRef.value?.resetFields() } diff --git a/src/views/ai/model/chatRole/index.vue b/src/views/ai/model/chatRole/index.vue index 40759e87..552d9a68 100644 --- a/src/views/ai/model/chatRole/index.vue +++ b/src/views/ai/model/chatRole/index.vue @@ -59,13 +59,14 @@ - - - - + + + + - @@ -79,13 +80,7 @@ - + + + diff --git a/src/views/ai/chat/index.vue b/src/views/ai/chat/index.vue index 0da53f1e..735e5c90 100644 --- a/src/views/ai/chat/index.vue +++ b/src/views/ai/chat/index.vue @@ -1,81 +1,19 @@ + diff --git a/src/views/ai/chat/index.vue b/src/views/ai/chat/index.vue index a2dd8c05..3ba1046c 100644 --- a/src/views/ai/chat/index.vue +++ b/src/views/ai/chat/index.vue @@ -34,7 +34,7 @@
- +
@@ -82,12 +82,10 @@ + diff --git a/src/views/ai/chat/index.vue b/src/views/ai/chat/index.vue index 704a693e..2d61132a 100644 --- a/src/views/ai/chat/index.vue +++ b/src/views/ai/chat/index.vue @@ -31,12 +31,15 @@
- +
- + +
+ +
- +
+ 上下文 +
() // 对话进行中 abort 控制 const inputTimeout = ref() // 处理输入中回车的定时器 const prompt = ref() // prompt const userInfo = ref() // 用户信息 +const enableContext = ref(true) // 是否开启上下文 const fullText = ref(''); const displayedText = ref(''); @@ -327,6 +330,7 @@ const doSendStream = async (userMessage: ChatMessageVO) => { userMessage.conversationId, // TODO 芋艿:这里可能要在优化; userMessage.content, conversationInAbortController.value, + enableContext.value, async (message) => { const data = JSON.parse(message.data) // TODO 芋艿:类型处理; // 如果内容为空,就不处理。 -- Gitee From e7403ba2a450d50100eecc086cf98264f9614711 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 22 May 2024 17:07:54 +0800 Subject: [PATCH 137/341] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91AI?= =?UTF-8?q?=20chat=20=E5=A2=9E=E5=8A=A0=20new=20chat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/chat/MessageNewChat.vue | 50 ++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/views/ai/chat/MessageNewChat.vue diff --git a/src/views/ai/chat/MessageNewChat.vue b/src/views/ai/chat/MessageNewChat.vue new file mode 100644 index 00000000..aac5f905 --- /dev/null +++ b/src/views/ai/chat/MessageNewChat.vue @@ -0,0 +1,50 @@ + + + + + -- Gitee From 89deddb9e06aa79af9e9fe4cde87644f57eb0346 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 22 May 2024 17:08:13 +0800 Subject: [PATCH 138/341] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91AI=20=E5=88=A0=E9=99=A4=E5=AF=B9=E8=AF=9D=EF=BC=8C?= =?UTF-8?q?=E4=B8=8D=E9=BB=98=E8=AE=A4=E9=80=89=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/chat/Conversation.vue | 17 ++++++++++------- src/views/ai/chat/index.vue | 18 +++++++++++++++--- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/views/ai/chat/Conversation.vue b/src/views/ai/chat/Conversation.vue index 46988a63..f735252c 100644 --- a/src/views/ai/chat/Conversation.vue +++ b/src/views/ai/chat/Conversation.vue @@ -174,15 +174,15 @@ const getChatConversationList = async () => { conversationList.value = res // 3、默认选中 if (!activeId?.value) { - await handleConversationClick(res[0].id) + // await handleConversationClick(res[0].id) } else { // tip: 删除的刚好是选中的,那么需要重新挑选一个来进行选中 - const filterConversationList = conversationList.value.filter(item => { - return item.id === activeId.value - }) - if (filterConversationList.length <= 0) { - await handleConversationClick(res[0].id) - } + // const filterConversationList = conversationList.value.filter(item => { + // return item.id === activeId.value + // }) + // if (filterConversationList.length <= 0) { + // await handleConversationClick(res[0].id) + // } } // 4、没有 任何对话情况 if (conversationList.value.length === 0) { @@ -367,6 +367,9 @@ watch(activeId, async (newValue, oldValue) => { activeConversationId.value = newValue as string }) +// 定义 public 方法 +defineExpose({createConversation}) + onMounted(async () => { // 默认选中 if (props.activeId != null) { diff --git a/src/views/ai/chat/index.vue b/src/views/ai/chat/index.vue index 999e1736..0aaa164c 100644 --- a/src/views/ai/chat/index.vue +++ b/src/views/ai/chat/index.vue @@ -2,6 +2,7 @@
- {{ activeConversation?.title }} + {{ activeConversation?.title ? activeConversation?.title : '对话' }}
-
+
@@ -32,11 +33,12 @@
+ + -
@@ -93,6 +95,7 @@ import Conversation from './Conversation.vue' import Message from './Message.vue' import ChatEmpty from './ChatEmpty.vue' import MessageLoading from './MessageLoading.vue' +import MessageNewChat from './MessageNewChat.vue' import {ChatMessageApi, ChatMessageVO} from '@/api/ai/chat/message' import {ChatConversationApi, ChatConversationVO} from '@/api/ai/chat/conversation' import { getUserProfile, ProfileVO } from '@/api/system/user/profile' @@ -126,6 +129,7 @@ const listLoadingTime = ref() // time定时器,如果加载速度很快 // 判断 消息列表 滚动的位置(用于判断是否需要滚动到消息最下方) const messageRef = ref() +const conversationRef = ref() const isComposing = ref(false) // 判断用户是否在输入 // 默认 role 头像 @@ -490,6 +494,14 @@ const getConversation = async (id: string | null) => { } } +/** + * 对话 - 新建 + */ +const handlerNewChat = async () => { + // 创建对话 + await conversationRef.value.createConversation() +} + // ============ message =========== /** -- Gitee From f1beb488ce06bcce4895a301ef473870255e42ad Mon Sep 17 00:00:00 2001 From: cherishsince Date: Wed, 22 May 2024 17:17:43 +0800 Subject: [PATCH 139/341] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91AI=20chat=20=E6=A0=87=E9=A2=98=E5=90=8E=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E5=AF=B9=E8=AF=9D=E6=95=B0=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/chat/index.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/views/ai/chat/index.vue b/src/views/ai/chat/index.vue index 0aaa164c..a1366272 100644 --- a/src/views/ai/chat/index.vue +++ b/src/views/ai/chat/index.vue @@ -13,6 +13,7 @@
{{ activeConversation?.title ? activeConversation?.title : '对话' }} + ({{list.length}})
-- Gitee From 03c6a6ce59361cfcf6850eedc37c5845487077c1 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 24 May 2024 10:32:08 +0800 Subject: [PATCH 140/341] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91Chat=20message=20=E5=A2=9E=E5=8A=A0=E5=88=B7=E6=96=B0?= =?UTF-8?q?=E5=92=8C=E7=BC=96=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/chat/Message.vue | 24 ++++++++++++++++++++++-- src/views/ai/chat/index.vue | 18 +++++++++++++++++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/views/ai/chat/Message.vue b/src/views/ai/chat/Message.vue index 1a33b4bd..20277562 100644 --- a/src/views/ai/chat/Message.vue +++ b/src/views/ai/chat/Message.vue @@ -43,6 +43,12 @@ + + + + + +
@@ -59,7 +65,7 @@ import MarkdownView from "@/components/MarkdownView/index.vue"; import {ChatMessageApi, ChatMessageVO} from "@/api/ai/chat/message"; import {useClipboard} from "@vueuse/core"; import {PropType} from "vue"; -import {ArrowDownBold} from "@element-plus/icons-vue"; +import {ArrowDownBold, Edit, RefreshRight} from "@element-plus/icons-vue"; const {copy} = useClipboard() // 初始化 copy 到粘贴板 // 判断 消息列表 滚动的位置(用于判断是否需要滚动到消息最下方) @@ -125,6 +131,20 @@ const onDelete = async (id) => { emits('onDeleteSuccess') } +/** + * 刷新 + */ +const onRefresh = async (message: ChatMessageVO) => { + emits('onRefresh', message) +} + +/** + * 编辑 + */ +const onEdit = async (message: ChatMessageVO) => { + emits('onEdit', message) +} + /** * 回到底部 */ @@ -151,7 +171,7 @@ watch(list, async (newValue, oldValue) => { defineExpose({scrollToBottom, handlerGoTop}) // 定义 emits -const emits = defineEmits(['onDeleteSuccess']) +const emits = defineEmits(['onDeleteSuccess', 'onRefresh', 'onEdit']) // onMounted onMounted(async () => { diff --git a/src/views/ai/chat/index.vue b/src/views/ai/chat/index.vue index a1366272..ac97e1ec 100644 --- a/src/views/ai/chat/index.vue +++ b/src/views/ai/chat/index.vue @@ -39,7 +39,9 @@ + @on-delete-success="handlerMessageDelete" + @on-edit="handlerMessageEdit" + @on-refresh="handlerMessageRefresh"/>
@@ -513,6 +515,20 @@ const handlerMessageDelete = async () => { await getMessageList() } +/** + * 编辑 message + */ +const handlerMessageEdit = async (message: ChatMessageVO) => { + prompt.value = message.content +} + +/** + * 编辑 message + */ +const handlerMessageRefresh = async (message: ChatMessageVO) => { + await doSend(message.content) +} + /** * 回到顶部 */ -- Gitee From bebf1e7ae3b5372de72cc82aded87c183e107f86 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 24 May 2024 10:35:11 +0800 Subject: [PATCH 141/341] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91Chat=20=E8=81=8A=E5=A4=A9=EF=BC=8C=E6=96=B0=E5=BB=BA?= =?UTF-8?q?=E5=AF=B9=E8=AF=9D=E6=B8=85=E7=A9=BA=E8=BE=93=E5=85=A5=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/chat/Conversation.vue | 9 ++++++++- src/views/ai/chat/index.vue | 9 +++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/views/ai/chat/Conversation.vue b/src/views/ai/chat/Conversation.vue index f735252c..946735f7 100644 --- a/src/views/ai/chat/Conversation.vue +++ b/src/views/ai/chat/Conversation.vue @@ -122,7 +122,12 @@ const props = defineProps({ }) // 定义钩子 -const emits = defineEmits(['onConversationClick', 'onConversationClear', 'onConversationDelete']) +const emits = defineEmits([ + 'onConversationCreate', + 'onConversationClick', + 'onConversationClear', + 'onConversationDelete' +]) /** * 对话 - 搜索 @@ -256,6 +261,8 @@ const createConversation = async () => { await getChatConversationList() // 3、选中对话 await handleConversationClick(conversationId) + // 4、回调 + emits('onConversationCreate') } /** diff --git a/src/views/ai/chat/index.vue b/src/views/ai/chat/index.vue index ac97e1ec..d9a44df1 100644 --- a/src/views/ai/chat/index.vue +++ b/src/views/ai/chat/index.vue @@ -3,6 +3,7 @@ { await getConversation(activeConversationId.value) } +/** + * 对话 - 创建 + */ +const handleConversationCreate = async () => { + // 创建新的对话,清空输入框 + prompt.value = '' +} + /** * 对话 - 点击 */ -- Gitee From 8fb54dbb7c2d797ae754cd97e6ceafdddbd1e8e5 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 24 May 2024 10:39:12 +0800 Subject: [PATCH 142/341] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91Chat=20=E5=AF=B9=E8=AF=9D=E9=BB=98=E8=AE=A4=E9=80=89?= =?UTF-8?q?=E4=B8=AD=E7=AC=AC=E4=B8=80=E4=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/chat/Conversation.vue | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/views/ai/chat/Conversation.vue b/src/views/ai/chat/Conversation.vue index 946735f7..4b2d60ef 100644 --- a/src/views/ai/chat/Conversation.vue +++ b/src/views/ai/chat/Conversation.vue @@ -378,12 +378,17 @@ watch(activeId, async (newValue, oldValue) => { defineExpose({createConversation}) onMounted(async () => { + // 获取 对话列表 + await getChatConversationList() // 默认选中 if (props.activeId != null) { activeConversationId.value = props.activeId + } else { + // 首次默认选中第一个 + if (conversationList.value.length) { + activeConversationId.value = conversationList.value[0].id + } } - // 获取 对话列表 - await getChatConversationList() }) -- Gitee From 8764c6c4712bd51c0df22e0bbb32acb1fd98bfa0 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 24 May 2024 15:39:05 +0800 Subject: [PATCH 143/341] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E6=96=B0=E5=BB=BA=E5=AF=B9=E8=AF=9D=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E4=B8=8D=E4=BD=BF=E7=94=A8=E9=BB=98=E8=AE=A4=E8=A7=92=E8=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/ai/chat/conversation/index.ts | 2 +- src/views/ai/chat/Message.vue | 61 ++++++++++++++++++--------- src/views/ai/chat/index.vue | 26 +++++++++--- 3 files changed, 63 insertions(+), 26 deletions(-) diff --git a/src/api/ai/chat/conversation/index.ts b/src/api/ai/chat/conversation/index.ts index b363ea7b..0834643d 100644 --- a/src/api/ai/chat/conversation/index.ts +++ b/src/api/ai/chat/conversation/index.ts @@ -12,8 +12,8 @@ export interface ChatConversationVO { temperature: number // 温度参数 maxTokens: number // 单条回复的最大 Token 数量 maxContexts: number // 上下文的最大 Message 数量 - updateTime: number // 更新时间 // 额外字段 + systemMessage?: string // 角色设定 modelName?: string // 模型名字 roleAvatar?: string // 角色头像 modelMaxTokens?: string // 模型的单条回复的最大 Token 数量 diff --git a/src/views/ai/chat/Message.vue b/src/views/ai/chat/Message.vue index 20277562..445182e5 100644 --- a/src/views/ai/chat/Message.vue +++ b/src/views/ai/chat/Message.vue @@ -1,8 +1,7 @@ -- Gitee From 4c259cd60fb20c696b98da464e4cc4e12bcc5c4b Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 25 May 2024 08:59:56 +0800 Subject: [PATCH 149/341] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E5=AF=B9=E8=AF=9D=E7=AE=A1=E7=90=86=20100%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/ai/chat/conversation/index.ts | 5 + src/api/ai/chat/message/index.ts | 17 +- .../ai/chat/manager/ChatConversationList.vue | 163 ++++++++++++++++ src/views/ai/chat/manager/ChatMessageList.vue | 175 ++++++++++++++++++ src/views/ai/chat/manager/index.vue | 173 +---------------- 5 files changed, 365 insertions(+), 168 deletions(-) create mode 100644 src/views/ai/chat/manager/ChatConversationList.vue create mode 100644 src/views/ai/chat/manager/ChatMessageList.vue diff --git a/src/api/ai/chat/conversation/index.ts b/src/api/ai/chat/conversation/index.ts index 07643255..08ad26a1 100644 --- a/src/api/ai/chat/conversation/index.ts +++ b/src/api/ai/chat/conversation/index.ts @@ -55,5 +55,10 @@ export const ChatConversationApi = { // 获得对话分页 getChatConversationPage: async (params: any) => { return await request.get({ url: `/ai/chat/conversation/page`, params }) + }, + + // 管理员删除消息 + deleteChatConversationByAdmin: async (id: number) => { + return await request.delete({ url: `/ai/chat/conversation/delete-by-admin?id=${id}` }) } } diff --git a/src/api/ai/chat/message/index.ts b/src/api/ai/chat/message/index.ts index 7b46f9c2..f9e807a1 100644 --- a/src/api/ai/chat/message/index.ts +++ b/src/api/ai/chat/message/index.ts @@ -55,7 +55,7 @@ export const ChatMessageApi = { body: JSON.stringify({ conversationId, content, - useContext: enableContext, + useContext: enableContext }), onmessage: onMessage, onerror: onError, @@ -71,7 +71,18 @@ export const ChatMessageApi = { // 删除消息 - 对话所有消息 deleteByConversationId: async (conversationId: string) => { - return await request.delete({ url: `/ai/chat/message/delete-by-conversation-id?conversationId=${conversationId}` }) - } + return await request.delete({ + url: `/ai/chat/message/delete-by-conversation-id?conversationId=${conversationId}` + }) + }, + // 获得消息分页 + getChatMessagePage: async (params: any) => { + return await request.get({ url: '/ai/chat/message/page', params }) + }, + + // 管理员删除消息 + deleteChatMessageByAdmin: async (id: number) => { + return await request.delete({ url: `/ai/chat/message/delete-by-admin?id=${id}` }) + } } diff --git a/src/views/ai/chat/manager/ChatConversationList.vue b/src/views/ai/chat/manager/ChatConversationList.vue new file mode 100644 index 00000000..23933f01 --- /dev/null +++ b/src/views/ai/chat/manager/ChatConversationList.vue @@ -0,0 +1,163 @@ + + + diff --git a/src/views/ai/chat/manager/ChatMessageList.vue b/src/views/ai/chat/manager/ChatMessageList.vue new file mode 100644 index 00000000..0d841840 --- /dev/null +++ b/src/views/ai/chat/manager/ChatMessageList.vue @@ -0,0 +1,175 @@ + + + diff --git a/src/views/ai/chat/manager/index.vue b/src/views/ai/chat/manager/index.vue index b36fa413..720ac1ea 100644 --- a/src/views/ai/chat/manager/index.vue +++ b/src/views/ai/chat/manager/index.vue @@ -1,174 +1,17 @@ -- Gitee From 46eb89695d9b502c6de6bca917515099ca3ff9c6 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 25 May 2024 10:54:04 +0800 Subject: [PATCH 150/341] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91AI=EF=BC=9Areview=20=E8=81=8A=E5=A4=A9?= =?UTF-8?q?=E5=AF=B9=E8=AF=9D=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/chat/ChatEmpty.vue | 5 -- src/views/ai/chat/Conversation.vue | 41 +++++----- src/views/ai/chat/Message.vue | 4 +- src/views/ai/chat/components/Header.vue | 2 - src/views/ai/chat/index.vue | 41 +++++++--- src/views/ai/chat/role/RoleList.vue | 2 +- src/views/ai/chat/role/index.vue | 101 ++++++++++++------------ 7 files changed, 105 insertions(+), 91 deletions(-) diff --git a/src/views/ai/chat/ChatEmpty.vue b/src/views/ai/chat/ChatEmpty.vue index 68a53be9..4268b3d7 100644 --- a/src/views/ai/chat/ChatEmpty.vue +++ b/src/views/ai/chat/ChatEmpty.vue @@ -1,4 +1,3 @@ - diff --git a/src/views/ai/chat/index.vue b/src/views/ai/chat/index.vue index 83231b57..5386563a 100644 --- a/src/views/ai/chat/index.vue +++ b/src/views/ai/chat/index.vue @@ -10,27 +10,27 @@ /> -
{{ activeConversation?.title ? activeConversation?.title : '对话' }} ({{list.length}})
- - + + +
- +
@@ -87,7 +87,7 @@ - + -- Gitee From cdf0a1137d95771d361db871e44fd11ab1c84080 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 25 May 2024 11:49:23 +0800 Subject: [PATCH 151/341] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91AI?= =?UTF-8?q?=EF=BC=9A=E5=AF=B9=E8=AF=9D=E7=9A=84=20user=E3=80=81role=20?= =?UTF-8?q?=E5=A4=B4=E5=83=8F=E4=BB=8E=E5=89=8D=E7=AB=AF=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/chat/Conversation.vue | 3 +- src/views/ai/chat/Message.vue | 27 +++--- src/views/ai/chat/index.vue | 131 ++++++++++++++--------------- 3 files changed, 75 insertions(+), 86 deletions(-) diff --git a/src/views/ai/chat/Conversation.vue b/src/views/ai/chat/Conversation.vue index c8290175..2afeb9ac 100644 --- a/src/views/ai/chat/Conversation.vue +++ b/src/views/ai/chat/Conversation.vue @@ -43,7 +43,7 @@ :class="conversation.id === activeConversationId ? 'conversation active' : 'conversation'" >
- + {{ conversation.title }}
@@ -99,6 +99,7 @@ import {ChatConversationApi, ChatConversationVO} from '@/api/ai/chat/conversatio import {ref} from "vue"; import Role from "@/views/ai/chat/role/index.vue"; import {Bottom, Top} from "@element-plus/icons-vue"; +import roleAvatarDefaultImg from '@/assets/ai/gpt.svg' const message = useMessage() // 消息弹窗 diff --git a/src/views/ai/chat/Message.vue b/src/views/ai/chat/Message.vue index bf03becc..942961ed 100644 --- a/src/views/ai/chat/Message.vue +++ b/src/views/ai/chat/Message.vue @@ -1,10 +1,10 @@ -- Gitee From 60de1b973779e955b5cd4ab1a09905d780e79548 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 25 May 2024 21:06:58 +0800 Subject: [PATCH 158/341] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91Dal?= =?UTF-8?q?l3=20=E5=A2=9E=E5=8A=A0=E5=9B=BE=E7=89=87=E7=94=9F=E6=88=90=20(?= =?UTF-8?q?function=20=E5=BE=85=E5=AE=9E=E7=8E=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/image/dall3/index.vue | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/views/ai/image/dall3/index.vue b/src/views/ai/image/dall3/index.vue index 95cc5a31..d9ba09f8 100644 --- a/src/views/ai/image/dall3/index.vue +++ b/src/views/ai/image/dall3/index.vue @@ -65,7 +65,10 @@
- +
+ + 生成内容 +
-- Gitee From f156ba18772acdd14f818d5ad1d661cd5abe0014 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 25 May 2024 21:12:36 +0800 Subject: [PATCH 159/341] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91AI?= =?UTF-8?q?=20Image=20=E5=A2=9E=E5=8A=A0model=20=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E5=88=87=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/image/index.vue | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/views/ai/image/index.vue b/src/views/ai/image/index.vue index 874f9b61..2d594b82 100644 --- a/src/views/ai/image/index.vue +++ b/src/views/ai/image/index.vue @@ -3,10 +3,11 @@
- +
@@ -20,10 +21,11 @@ -- Gitee From 12e87cc0f26fa00354c2778aa89fee83806c3d66 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 25 May 2024 21:18:43 +0800 Subject: [PATCH 160/341] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91Ai?= =?UTF-8?q?=20Image=20midjourney=20=E5=A2=9E=E5=8A=A0=EF=BC=8C=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E8=AF=8D=E3=80=81=E6=A8=A1=E5=9E=8B=E3=80=81=E5=B0=BA?= =?UTF-8?q?=E5=AF=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/image/midjourney/index.vue | 277 +++++++++++++++++++++++- 1 file changed, 275 insertions(+), 2 deletions(-) diff --git a/src/views/ai/image/midjourney/index.vue b/src/views/ai/image/midjourney/index.vue index 93704d65..bbd523f6 100644 --- a/src/views/ai/image/midjourney/index.vue +++ b/src/views/ai/image/midjourney/index.vue @@ -1,10 +1,283 @@ - + -- Gitee From 86f3ae23016cced342f1385e2ad50cc7f85fcb69 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sat, 25 May 2024 21:20:43 +0800 Subject: [PATCH 161/341] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91AI?= =?UTF-8?q?=20image=20dall3=20=E8=B0=83=E6=95=B4=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E7=9A=84=E5=90=8D=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/image/dall3/index.vue | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/views/ai/image/dall3/index.vue b/src/views/ai/image/dall3/index.vue index d9ba09f8..587cfbf8 100644 --- a/src/views/ai/image/dall3/index.vue +++ b/src/views/ai/image/dall3/index.vue @@ -46,6 +46,7 @@ fit="contain" @click="handlerModelClick(model)" /> +
{{model.name}}
@@ -198,13 +199,20 @@ const handlerGenerateImage = async () => { margin-top: 15px; .modal-item { - width: 90px; - height: 50px; + width: 110px; //outline: 1px solid blue; overflow: hidden; display: flex; + flex-direction: column; + align-items: center; border: 3px solid transparent; cursor: pointer; + + .model-font { + font-size: 14px; + color: #3e3e3e; + font-weight: bold; + } } .selectModel { -- Gitee From ffa691c4ee9c622fa0cbd43dfc8c6739db323ed1 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 26 May 2024 20:08:43 +0800 Subject: [PATCH 162/341] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A8=A1=E5=9E=8B=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/image/dall3/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/ai/image/dall3/index.vue b/src/views/ai/image/dall3/index.vue index 587cfbf8..f141ca1c 100644 --- a/src/views/ai/image/dall3/index.vue +++ b/src/views/ai/image/dall3/index.vue @@ -99,7 +99,7 @@ const models = ref([ }, { key: 'ziran', - name: '清晰', + name: '自然', image: 'https://h5.cxyhub.com/images/model_2.png', }, ]) // 模型 -- Gitee From bfa396b127036558fb05c585f4b486525ea1e720 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 26 May 2024 20:22:36 +0800 Subject: [PATCH 163/341] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=20midjourney=20=E6=A8=A1=E5=9E=8B=E5=9B=BE?= =?UTF-8?q?=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/image/midjourney/index.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/views/ai/image/midjourney/index.vue b/src/views/ai/image/midjourney/index.vue index bbd523f6..114a1467 100644 --- a/src/views/ai/image/midjourney/index.vue +++ b/src/views/ai/image/midjourney/index.vue @@ -95,12 +95,12 @@ const models = ref([ { key: 'qinxi', name: 'MJ', - image: 'https://h5.cxyhub.com/images/mj.jpeg', + image: 'https://bigpt8.com/pc/_nuxt/mj.34a61377.png', }, { key: 'ziran', name: 'NIJI', - image: 'https://h5.cxyhub.com/images/niji.jpeg', + image: 'https://bigpt8.com/pc/_nuxt/nj.ca79b143.png', }, ]) // 模型 @@ -210,7 +210,7 @@ const handlerGenerateImage = async () => { display: flex; flex-direction: column; align-items: center; - width: 110px; + width: 150px; //outline: 1px solid blue; overflow: hidden; border: 3px solid transparent; -- Gitee From 131e071b2d4cb048c981480dcb0b340b25024645 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 26 May 2024 20:47:29 +0800 Subject: [PATCH 164/341] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91Ai?= =?UTF-8?q?=20Image=20task=20=E4=BB=BB=E5=8A=A1=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/image/ImageTask.vue | 68 ++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/views/ai/image/ImageTask.vue diff --git a/src/views/ai/image/ImageTask.vue b/src/views/ai/image/ImageTask.vue new file mode 100644 index 00000000..f4c4b9b2 --- /dev/null +++ b/src/views/ai/image/ImageTask.vue @@ -0,0 +1,68 @@ + + + + + -- Gitee From 9c8d10b70c58735fcf5f82e08f8a2cadc956cd17 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 26 May 2024 20:59:42 +0800 Subject: [PATCH 165/341] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91AI?= =?UTF-8?q?=20image=20=E5=A2=9E=E5=8A=A0=E5=9B=BE=E7=89=87=E8=AF=A6?= =?UTF-8?q?=E6=83=85=EF=BC=8C=E6=8A=BD=E5=B1=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/image/ImageDetailDrawer.vue | 42 ++++++++++++++++++++++++ src/views/ai/image/ImageTask.vue | 29 ++++++++++++++-- 2 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 src/views/ai/image/ImageDetailDrawer.vue diff --git a/src/views/ai/image/ImageDetailDrawer.vue b/src/views/ai/image/ImageDetailDrawer.vue new file mode 100644 index 00000000..a4e234e8 --- /dev/null +++ b/src/views/ai/image/ImageDetailDrawer.vue @@ -0,0 +1,42 @@ + + + + diff --git a/src/views/ai/image/ImageTask.vue b/src/views/ai/image/ImageTask.vue index f4c4b9b2..58046f84 100644 --- a/src/views/ai/image/ImageTask.vue +++ b/src/views/ai/image/ImageTask.vue @@ -11,19 +11,42 @@
- +
- + + -- Gitee From c06dd8e273564e6f4c4cd9e582decf15b275271e Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 26 May 2024 21:51:42 +0800 Subject: [PATCH 171/341] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91Ima?= =?UTF-8?q?ge=20Task=20=E4=BD=BF=E7=94=A8=20card=20=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/image/ImageTask.vue | 66 +++++++++++--------------------- 1 file changed, 22 insertions(+), 44 deletions(-) diff --git a/src/views/ai/image/ImageTask.vue b/src/views/ai/image/ImageTask.vue index 58046f84..a612a85d 100644 --- a/src/views/ai/image/ImageTask.vue +++ b/src/views/ai/image/ImageTask.vue @@ -2,22 +2,7 @@ -- Gitee From cb7c5b745808c82f6df89adf2456f70279d9cd89 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 26 May 2024 21:53:26 +0800 Subject: [PATCH 172/341] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91Ima?= =?UTF-8?q?ge=20=E6=8A=BD=E5=B1=89=EF=BC=8C=E4=BD=BF=E7=94=A8=20Card=20?= =?UTF-8?q?=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/image/ImageDetailDrawer.vue | 66 +++++++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/src/views/ai/image/ImageDetailDrawer.vue b/src/views/ai/image/ImageDetailDrawer.vue index a4e234e8..7114beda 100644 --- a/src/views/ai/image/ImageDetailDrawer.vue +++ b/src/views/ai/image/ImageDetailDrawer.vue @@ -4,13 +4,35 @@ title="图片详细" @close="handlerDrawerClose" > - Hi, there! +
+
+
图片
+
+ + + +
+
+
+ +
+
+
+
提示词
+
+ {{imageDetail.prompt}} +
+
-- Gitee From 959ee908108357c253ef701a65361d1070aa6c6c Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 26 May 2024 21:56:10 +0800 Subject: [PATCH 173/341] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=20Image=20Task=20Card=20=E6=8C=89=E9=94=AE?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/image/ImageTask.vue | 11 ++++++++++- src/views/ai/image/ImageTaskCard.vue | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/views/ai/image/ImageTask.vue b/src/views/ai/image/ImageTask.vue index a612a85d..50a2a7ad 100644 --- a/src/views/ai/image/ImageTask.vue +++ b/src/views/ai/image/ImageTask.vue @@ -2,7 +2,7 @@ @@ -24,11 +21,33 @@ import Dall3 from './dall3/index.vue' import Midjourney from './midjourney/index.vue' import ImageTask from './ImageTask.vue' +// ref +const imageTaskRef = ref() // image task ref + // 定义属性 const selectModel = ref('DALL3绘画') const modelOptions = ['DALL3绘画', 'MJ绘画'] +/** + * 绘画 - start + */ +const handlerDrawStart = async (type) => { + // todo +} + +/** + * 绘画 - complete + */ +const handlerDrawComplete = async (type) => { + // todo + await imageTaskRef.value.getImageList() +} + +// +onMounted( async () => { +}) + -- Gitee From ad10328b735a913a82157c978970d4d815248d06 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 28 May 2024 10:04:44 +0800 Subject: [PATCH 187/341] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91AI?= =?UTF-8?q?=20Image=20=E5=88=97=E8=A1=A8=E5=A2=9E=E5=8A=A0=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E5=88=87=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/image/ImageTaskCard.vue | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/views/ai/image/ImageTaskCard.vue b/src/views/ai/image/ImageTaskCard.vue index e8a73db9..959209e6 100644 --- a/src/views/ai/image/ImageTaskCard.vue +++ b/src/views/ai/image/ImageTaskCard.vue @@ -1,9 +1,11 @@ + -- Gitee From bd4f2b8b7c98a13b36ce38e85f901e3e32f7f77f Mon Sep 17 00:00:00 2001 From: AhJindeg Date: Tue, 25 Jun 2024 11:21:16 +0800 Subject: [PATCH 236/341] =?UTF-8?q?fix:=20=F0=9F=90=9E=20add=20result=20fi?= =?UTF-8?q?eld=20to=20JobLogDetail=20el-descriptions-item?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/infra/jobLog/index.ts | 1 + src/views/infra/job/logger/JobLogDetail.vue | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/api/infra/jobLog/index.ts b/src/api/infra/jobLog/index.ts index dc80f1d9..ed54761c 100644 --- a/src/api/infra/jobLog/index.ts +++ b/src/api/infra/jobLog/index.ts @@ -12,6 +12,7 @@ export interface JobLogVO { duration: string status: number createTime: string + result: string } // 任务日志列表 diff --git a/src/views/infra/job/logger/JobLogDetail.vue b/src/views/infra/job/logger/JobLogDetail.vue index 1a84e4e8..7216f527 100644 --- a/src/views/infra/job/logger/JobLogDetail.vue +++ b/src/views/infra/job/logger/JobLogDetail.vue @@ -26,7 +26,7 @@ - {{ detailData.duration + ' result' }} + {{ detailData.result }} -- Gitee From ef9ed50533cd4f08db50e920d280d661b3d84291 Mon Sep 17 00:00:00 2001 From: AhJindeg Date: Tue, 25 Jun 2024 11:30:24 +0800 Subject: [PATCH 237/341] =?UTF-8?q?fix:=20=F0=9F=90=9E=20update=20axios=20?= =?UTF-8?q?interceptors=20response?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config/axios/service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/config/axios/service.ts b/src/config/axios/service.ts index 25936068..aed40908 100644 --- a/src/config/axios/service.ts +++ b/src/config/axios/service.ts @@ -174,6 +174,7 @@ service.interceptors.response.use( if (msg === '无效的刷新令牌') { // hard coding:忽略这个提示,直接登出 console.log(msg) + return handleAuthorized() } else { ElNotification.error({ title: msg }) } -- Gitee From 36dc3c0b5c03fca829463d947671a52d90f390c5 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 26 Jun 2024 12:38:21 +0800 Subject: [PATCH 238/341] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E3=80=91AI=EF=BC=9AMJ=20=E4=BA=8C=E6=AC=A1=20Action?= =?UTF-8?q?=20=E7=9A=84=E6=8E=A5=E5=8F=A3=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/ai/image/index.ts | 76 ++++++++++-------------- src/views/ai/image/ImageDetailDrawer.vue | 6 +- src/views/ai/image/ImageTask.vue | 16 ++--- src/views/ai/image/ImageTaskCard.vue | 6 +- src/views/ai/image/midjourney/index.vue | 4 -- 5 files changed, 46 insertions(+), 62 deletions(-) diff --git a/src/api/ai/image/index.ts b/src/api/ai/image/index.ts index 4fd35abe..205d0803 100644 --- a/src/api/ai/image/index.ts +++ b/src/api/ai/image/index.ts @@ -1,51 +1,28 @@ import request from '@/config/axios' // AI API 密钥 VO -// TODO @fan:要不前端不弄太多 VO,就用这个 ImageDetailVO?! -export interface ImageDetailVO { +export interface ImageRespVO { id: number // 编号 + platform: string // 平台 + model: string // 模型 prompt: string // 提示词 + width: number // 图片宽度 + height: number // 图片高度 status: number // 状态 - errorMessage: string // 错误信息 - type: string // 模型下分不同的类型(清晰、真实...) - taskId: number // dr 任务id + publicStatus: string // 公开状态 picUrl: string // 任务地址 - originalPicUrl: string // 绘制图片地址 - platform: string // 平台 - model: string // 模型 - style: string // 图像生成的风格 - size: string // 图片尺寸 + errorMessage: string // 错误信息 + options: object // 配置 Map + taskId: number // 任务编号 buttons: ImageMjButtonsVO[] // mj 操作按钮 createTime: string // 创建时间 - updateTime: string // 更新事件 } -export interface ImageMjButtonsVO { - customId: string // MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862 动作标识 - emoji: string // 图标 emoji - label: string // Make Variations 文本 - style: number // 样式: 2(Primary)、3(Green) -} - -export interface ImageMjActionVO { - id: string // MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862 动作标识 - customId: string // MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862 动作标识 -} - - export interface ImagePageReqVO { pageNo: number // 分页编号 pageSize: number // 分页大小 } -export interface ImageDallReqVO { - prompt: string // 提示词 - model: string // 模型 - style: string // 图像生成的风格 - width: string // 图片宽度 - height: string // 图片高度 -} - export interface ImageDrawReqVO { platform: string // 平台 prompt: string // 提示词 @@ -65,34 +42,45 @@ export interface ImageMidjourneyImagineReqVO { version: string // 版本 } -// TODO 芋艿:review 下整体注释、方法名 +export interface ImageMjActionVO { + id: number // 图片编号 + customId: string // MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862 动作标识 +} + +export interface ImageMjButtonsVO { + customId: string // MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862 动作标识 + emoji: string // 图标 emoji + label: string // Make Variations 文本 + style: number // 样式: 2(Primary)、3(Green) +} + // AI API 密钥 API export const ImageApi = { - // 获取 image 列表 - getImageList: async (params: ImagePageReqVO) => { + // 获取我的图片列表 + getImagePageMy: async (params: ImagePageReqVO) => { return await request.get({ url: `/ai/image/my-page`, params }) }, - // 获取 image 详细信息 - getImageDetail: async (id: number) => { + // 获取我的图片 + getImageMy: async (id: number) => { return await request.get({ url: `/ai/image/get-my?id=${id}`}) }, // 生成图片 drawImage: async (data: ImageDrawReqVO)=> { return await request.post({ url: `/ai/image/draw`, data }) }, - // 删除 - deleteImage: async (id: number)=> { + // 删除我的图片 + deleteImageMy: async (id: number)=> { return await request.delete({ url: `/ai/image/delete-my?id=${id}`}) }, - // ------------ midjourney + // ================ midjourney 专属 ================ - // midjourney - imagine + // 【Midjourney】生成图片 midjourneyImagine: async (data: ImageMidjourneyImagineReqVO)=> { return await request.post({ url: `/ai/image/midjourney/imagine`, data }) }, - // midjourney - action - midjourneyAction: async (params: ImageMjActionVO)=> { - return await request.get({ url: `/ai/image/midjourney/action`, params }) + // 【Midjourney】Action 操作(二次生成图片) + midjourneyAction: async (data: ImageMjActionVO)=> { + return await request.post({ url: `/ai/image/midjourney/action`, data }) }, } diff --git a/src/views/ai/image/ImageDetailDrawer.vue b/src/views/ai/image/ImageDetailDrawer.vue index e26a719a..7c74ef35 100644 --- a/src/views/ai/image/ImageDetailDrawer.vue +++ b/src/views/ai/image/ImageDetailDrawer.vue @@ -60,11 +60,11 @@ diff --git a/src/views/ai/image/manager/index.vue b/src/views/ai/image/manager/index.vue new file mode 100644 index 00000000..ef505036 --- /dev/null +++ b/src/views/ai/image/manager/index.vue @@ -0,0 +1,247 @@ + + + -- Gitee From 9516e7184ffa4d4deb67f409155c38d5eff74f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E5=A9=B7=28luot1=29?= <1315228474@qq.com> Date: Thu, 27 Jun 2024 17:50:48 +0800 Subject: [PATCH 241/341] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9EAI=20music?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E9=A1=B5=E9=9D=A2=E4=BB=A5=E5=8F=8A=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=EF=BC=8C=E8=B0=83=E6=95=B4=E4=BA=86APPview=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2min-height=E4=B8=BAheight=EF=BC=8C=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=E4=BA=86=E7=99=BB=E5=BD=95=E6=97=B6dict=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=EF=BC=8C=E5=9C=A8contentWrap=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E6=96=B0=E5=A2=9E=E4=BA=86bodystyle=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ContentWrap/src/ContentWrap.vue | 9 +- src/layout/components/AppView.vue | 12 +-- src/router/modules/remaining.ts | 20 ++++ src/store/modules/dict.ts | 8 +- .../music/components/list/audioBar/index.vue | 9 ++ src/views/ai/music/components/list/index.vue | 94 +++++++++++++++++++ .../music/components/list/songCard/index.vue | 29 ++++++ .../music/components/list/songInfo/index.vue | 33 +++++++ src/views/ai/music/components/mode/desc.vue | 55 +++++++++++ src/views/ai/music/components/mode/index.vue | 44 +++++++++ src/views/ai/music/components/mode/lyric.vue | 83 ++++++++++++++++ src/views/ai/music/components/title/index.vue | 25 +++++ src/views/ai/music/index.vue | 21 +++++ 13 files changed, 428 insertions(+), 14 deletions(-) create mode 100644 src/views/ai/music/components/list/audioBar/index.vue create mode 100644 src/views/ai/music/components/list/index.vue create mode 100644 src/views/ai/music/components/list/songCard/index.vue create mode 100644 src/views/ai/music/components/list/songInfo/index.vue create mode 100644 src/views/ai/music/components/mode/desc.vue create mode 100644 src/views/ai/music/components/mode/index.vue create mode 100644 src/views/ai/music/components/mode/lyric.vue create mode 100644 src/views/ai/music/components/title/index.vue create mode 100644 src/views/ai/music/index.vue diff --git a/src/components/ContentWrap/src/ContentWrap.vue b/src/components/ContentWrap/src/ContentWrap.vue index 454e95c9..c75e4b71 100644 --- a/src/components/ContentWrap/src/ContentWrap.vue +++ b/src/components/ContentWrap/src/ContentWrap.vue @@ -10,12 +10,13 @@ const prefixCls = getPrefixCls('content-wrap') defineProps({ title: propTypes.string.def(''), - message: propTypes.string.def('') + message: propTypes.string.def(''), + bodyStyle: propTypes.object.def({ padding: '20px' }) }) diff --git a/src/layout/components/AppView.vue b/src/layout/components/AppView.vue index 44341873..88d5f0cc 100644 --- a/src/layout/components/AppView.vue +++ b/src/layout/components/AppView.vue @@ -38,24 +38,24 @@ provide('reload', reload) :class="[ 'p-[var(--app-content-padding)] w-[calc(100%-var(--app-content-padding)-var(--app-content-padding))] bg-[var(--app-content-bg-color)] dark:bg-[var(--el-bg-color)]', { - '!min-h-[calc(100%-var(--app-content-padding)-var(--app-content-padding)-var(--app-footer-height))]': + '!h-[calc(100%-var(--app-content-padding)-var(--app-content-padding)-var(--app-footer-height))]': (fixedHeader && (layout === 'classic' || layout === 'topLeft' || layout === 'top') && footer) || (!tagsView && layout === 'top' && footer), - '!min-h-[calc(100%-var(--app-content-padding)-var(--app-content-padding)-var(--app-footer-height)-var(--tags-view-height))]': + '!h-[calc(100%-var(--app-content-padding)-var(--app-content-padding)-var(--app-footer-height)-var(--tags-view-height))]': tagsView && layout === 'top' && footer, - '!min-h-[calc(100%-var(--tags-view-height)-var(--app-content-padding)-var(--app-content-padding)-var(--top-tool-height)-var(--app-footer-height))]': + '!h-[calc(100%-var(--tags-view-height)-var(--app-content-padding)-var(--app-content-padding)-var(--top-tool-height)-var(--app-footer-height))]': !fixedHeader && layout === 'classic' && footer, - '!min-h-[calc(100%-var(--tags-view-height)-var(--app-content-padding)-var(--app-content-padding)-var(--app-footer-height))]': + '!h-[calc(100%-var(--tags-view-height)-var(--app-content-padding)-var(--app-content-padding)-var(--app-footer-height))]': !fixedHeader && layout === 'topLeft' && footer, - '!min-h-[calc(100%-var(--top-tool-height)-var(--app-content-padding)-var(--app-content-padding))]': + '!h-[calc(100%-var(--top-tool-height)-var(--app-content-padding)-var(--app-content-padding))]': fixedHeader && layout === 'cutMenu' && footer, - '!min-h-[calc(100%-var(--top-tool-height)-var(--app-content-padding)-var(--app-content-padding)-var(--tags-view-height))]': + '!h-[calc(100%-var(--top-tool-height)-var(--app-content-padding)-var(--app-content-padding)-var(--tags-view-height))]': !fixedHeader && layout === 'cutMenu' && footer } ]" diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts index bc62a3c4..ff2c5d92 100644 --- a/src/router/modules/remaining.ts +++ b/src/router/modules/remaining.ts @@ -70,6 +70,26 @@ const remainingRouter: AppRouteRecordRaw[] = [ } ] }, + { + path: '/ai/music', + component: Layout, + redirect: '/index', + name: 'AIMusic', + meta: {}, + children: [ + { + path: 'index', + component: () => import('@/views/ai//music/index.vue'), + name: 'AIMusicIndex', + meta: { + title: 'AI 音乐', + icon: 'ep:home-filled', + noCache: false, + affix: true + } + } + ] + }, { path: '/user', component: Layout, diff --git a/src/store/modules/dict.ts b/src/store/modules/dict.ts index e239fb00..1a45335c 100644 --- a/src/store/modules/dict.ts +++ b/src/store/modules/dict.ts @@ -4,7 +4,7 @@ import { store } from '../index' import { DictDataVO } from '@/api/system/dict/types' import { CACHE_KEY, useCache } from '@/hooks/web/useCache' const { wsCache } = useCache('sessionStorage') -import { getSimpleDictDataList } from '@/api/system/dict/dict.data' +// import { getSimpleDictDataList } from '@/api/system/dict/dict.data' export interface DictValueType { value: any @@ -45,7 +45,8 @@ export const useDictStore = defineStore('dict', { this.dictMap = dictMap this.isSetDict = true } else { - const res = await getSimpleDictDataList() + const res = [] + // const res = await getSimpleDictDataList() // 设置数据 const dictDataMap = new Map() res.forEach((dictData: DictDataVO) => { @@ -75,7 +76,8 @@ export const useDictStore = defineStore('dict', { }, async resetDict() { wsCache.delete(CACHE_KEY.DICT_CACHE) - const res = await getSimpleDictDataList() + const res = [] + // const res = await getSimpleDictDataList() // 设置数据 const dictDataMap = new Map() res.forEach((dictData: DictDataVO) => { diff --git a/src/views/ai/music/components/list/audioBar/index.vue b/src/views/ai/music/components/list/audioBar/index.vue new file mode 100644 index 00000000..2b25e40f --- /dev/null +++ b/src/views/ai/music/components/list/audioBar/index.vue @@ -0,0 +1,9 @@ + + + diff --git a/src/views/ai/music/components/list/index.vue b/src/views/ai/music/components/list/index.vue new file mode 100644 index 00000000..bc21034d --- /dev/null +++ b/src/views/ai/music/components/list/index.vue @@ -0,0 +1,94 @@ + + + + + + diff --git a/src/views/ai/music/components/list/songCard/index.vue b/src/views/ai/music/components/list/songCard/index.vue new file mode 100644 index 00000000..dc1ffa8b --- /dev/null +++ b/src/views/ai/music/components/list/songCard/index.vue @@ -0,0 +1,29 @@ + + + diff --git a/src/views/ai/music/components/list/songInfo/index.vue b/src/views/ai/music/components/list/songInfo/index.vue new file mode 100644 index 00000000..4832bfcb --- /dev/null +++ b/src/views/ai/music/components/list/songInfo/index.vue @@ -0,0 +1,33 @@ + + + diff --git a/src/views/ai/music/components/mode/desc.vue b/src/views/ai/music/components/mode/desc.vue new file mode 100644 index 00000000..4488461e --- /dev/null +++ b/src/views/ai/music/components/mode/desc.vue @@ -0,0 +1,55 @@ + + + diff --git a/src/views/ai/music/components/mode/index.vue b/src/views/ai/music/components/mode/index.vue new file mode 100644 index 00000000..bb6cf116 --- /dev/null +++ b/src/views/ai/music/components/mode/index.vue @@ -0,0 +1,44 @@ + + + diff --git a/src/views/ai/music/components/mode/lyric.vue b/src/views/ai/music/components/mode/lyric.vue new file mode 100644 index 00000000..f774003a --- /dev/null +++ b/src/views/ai/music/components/mode/lyric.vue @@ -0,0 +1,83 @@ + + + diff --git a/src/views/ai/music/components/title/index.vue b/src/views/ai/music/components/title/index.vue new file mode 100644 index 00000000..a0658027 --- /dev/null +++ b/src/views/ai/music/components/title/index.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/views/ai/music/index.vue b/src/views/ai/music/index.vue new file mode 100644 index 00000000..b48abb6b --- /dev/null +++ b/src/views/ai/music/index.vue @@ -0,0 +1,21 @@ + + + -- Gitee From 14c9e33b60ebaeb921ac0cadac440549e7ce2e35 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 27 Jun 2024 18:11:22 +0800 Subject: [PATCH 242/341] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91get=20=E8=BD=AE=E8=AE=AD=EF=BC=8C=E4=B8=B4=E6=97=B6?= =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/image/ImageTask.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/ai/image/ImageTask.vue b/src/views/ai/image/ImageTask.vue index d458db00..ac2e51ff 100644 --- a/src/views/ai/image/ImageTask.vue +++ b/src/views/ai/image/ImageTask.vue @@ -34,6 +34,7 @@ import {ElLoading, LoadingOptionsResolved} from "element-plus"; const message = useMessage() // 消息弹窗 const imageList = ref([]) // image 列表 +const watchImageList = ref([]) // 监听的 image list,一般是生成中,需要轮训 const imageListInterval = ref() // image 列表定时器,刷新列表 const isShowImageDetail = ref(false) // 是否显示 task 详情 const showImageDetailId = ref(0) // 是否显示 task 详情 @@ -83,7 +84,6 @@ const getImageList = async (apply:boolean = false) => { const handlerImageBtnClick = async (type, imageDetail: ImageDetailVO) => { // 获取 image detail id showImageDetailId.value = imageDetail.id - console.log('type', imageDetail.id) // 处理不用 btn if (type === 'more') { await handlerDrawerOpen() -- Gitee From 75d0be9742f01ff6d759386f2a9d9ff436d63f7f Mon Sep 17 00:00:00 2001 From: xiaohong <1315228474@qq.com> Date: Thu, 27 Jun 2024 22:31:49 +0800 Subject: [PATCH 243/341] =?UTF-8?q?feat:=20=E5=B0=86=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E6=94=B9=E6=88=90=E5=8D=95=E6=8E=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/music/components/list/index.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/ai/music/components/list/index.vue b/src/views/ai/music/components/list/index.vue index bc21034d..6dce9b8c 100644 --- a/src/views/ai/music/components/list/index.vue +++ b/src/views/ai/music/components/list/index.vue @@ -5,7 +5,7 @@ - + @@ -15,7 +15,7 @@ - + -- Gitee From 8d33476472ddd6667c72ba59f5e7f3f4319fe11c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 27 Jun 2024 23:08:50 +0800 Subject: [PATCH 244/341] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=91AI=EF=BC=9A=E9=9F=B3=E4=B9=90=E7=AE=A1?= =?UTF-8?q?=E7=90=86=2050%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/ai/image/index.ts | 4 +- src/api/ai/music/index.ts | 40 +++++ src/views/ai/image/ImageDetailDrawer.vue | 34 ++-- src/views/ai/image/ImageTask.vue | 46 ++--- src/views/ai/image/ImageTaskCard.vue | 48 +++-- src/views/ai/image/manager/index.vue | 6 +- src/views/ai/music/manager/index.vue | 215 +++++++++++++++++++++++ 7 files changed, 329 insertions(+), 64 deletions(-) create mode 100644 src/api/ai/music/index.ts create mode 100644 src/views/ai/music/manager/index.vue diff --git a/src/api/ai/image/index.ts b/src/api/ai/image/index.ts index cb5a5afd..b895986d 100644 --- a/src/api/ai/image/index.ts +++ b/src/api/ai/image/index.ts @@ -1,7 +1,7 @@ import request from '@/config/axios' -// AI API 密钥 VO -export interface ImageRespVO { +// AI 绘图 VO +export interface ImageVO { id: number // 编号 platform: string // 平台 model: string // 模型 diff --git a/src/api/ai/music/index.ts b/src/api/ai/music/index.ts new file mode 100644 index 00000000..9415d3a2 --- /dev/null +++ b/src/api/ai/music/index.ts @@ -0,0 +1,40 @@ +import request from '@/config/axios' + +// AI 音乐 VO +export interface MusicVO { + id: number // 编号 + userId: number // 用户编号 + title: string // 音乐名称 + lyric: string // 歌词 + imageUrl: string // 图片地址 + audioUrl: string // 音频地址 + videoUrl: string // 视频地址 + status: number // 音乐状态 + gptDescriptionPrompt: string // 描述词 + prompt: string // 提示词 + platform: string // 模型平台 + model: string // 模型 + generateMode: number // 生成模式 + tags: string // 音乐风格标签 + publicStatus: boolean // 是否发布 + taskId: string // 任务id + errorMessage: string // 错误信息 +} + +// AI 音乐 API +export const MusicApi = { + // 查询音乐分页 + getMusicPage: async (params: any) => { + return await request.get({ url: `/ai/music/page`, params }) + }, + + // 修改音乐 + updateMusic: async (data: MusicVO) => { + return await request.put({ url: `/ai/music/update`, data }) + }, + + // 删除音乐 + deleteMusic: async (id: number) => { + return await request.delete({ url: `/ai/music/delete?id=` + id }) + } +} diff --git a/src/views/ai/image/ImageDetailDrawer.vue b/src/views/ai/image/ImageDetailDrawer.vue index 7c74ef35..fca087da 100644 --- a/src/views/ai/image/ImageDetailDrawer.vue +++ b/src/views/ai/image/ImageDetailDrawer.vue @@ -7,11 +7,11 @@ >
- - - - - + + + + +
@@ -21,30 +21,30 @@
时间
-
提交时间:{{imageDetail.createTime}}
+
提交时间:{{ imageDetail.createTime }}
-
生成时间:{{imageDetail.updateTime}}
+
生成时间:{{ imageDetail.updateTime }}
模型
- {{imageDetail.model}}({{imageDetail.height}}x{{imageDetail.width}}) + {{ imageDetail.model }}({{ imageDetail.height }}x{{ imageDetail.width }})
提示词
- {{imageDetail.prompt}} + {{ imageDetail.prompt }}
图片地址
- {{imageDetail.picUrl}} + {{ imageDetail.picUrl }}
@@ -53,18 +53,18 @@
- {{imageDetail?.options?.style}} + {{ imageDetail?.options?.style }}
diff --git a/src/views/ai/image/manager/index.vue b/src/views/ai/image/manager/index.vue index ef505036..d7ac6c81 100644 --- a/src/views/ai/image/manager/index.vue +++ b/src/views/ai/image/manager/index.vue @@ -163,7 +163,7 @@ -- Gitee From e3c46cab5305f3e8badaa84428100579797d21ff Mon Sep 17 00:00:00 2001 From: xiaohong <1315228474@qq.com> Date: Fri, 28 Jun 2024 09:26:58 +0800 Subject: [PATCH 245/341] =?UTF-8?q?feat:=20=E8=B0=83=E6=95=B4ai=20music=20?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E6=96=87=E4=BB=B6=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/router/modules/remaining.ts | 2 +- src/views/ai/music/{ => components}/index.vue | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/views/ai/music/{ => components}/index.vue (82%) diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts index ff2c5d92..6da3b0a4 100644 --- a/src/router/modules/remaining.ts +++ b/src/router/modules/remaining.ts @@ -79,7 +79,7 @@ const remainingRouter: AppRouteRecordRaw[] = [ children: [ { path: 'index', - component: () => import('@/views/ai//music/index.vue'), + component: () => import('@/views/ai/music/components/index.vue'), name: 'AIMusicIndex', meta: { title: 'AI 音乐', diff --git a/src/views/ai/music/index.vue b/src/views/ai/music/components/index.vue similarity index 82% rename from src/views/ai/music/index.vue rename to src/views/ai/music/components/index.vue index b48abb6b..21272522 100644 --- a/src/views/ai/music/index.vue +++ b/src/views/ai/music/components/index.vue @@ -8,8 +8,8 @@ -- Gitee From 6f9cb4f8f205ea9567d7865bf16ea73b4135a23e Mon Sep 17 00:00:00 2001 From: cherishsince Date: Fri, 28 Jun 2024 16:41:12 +0800 Subject: [PATCH 247/341] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91=E5=A6=82=E6=9E=9C=E6=9C=89=E7=94=9F=E6=88=90=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E5=9B=BE=E7=89=87=EF=BC=8C=E8=BD=AE=E8=AF=A2=E6=94=B9?= =?UTF-8?q?=E6=88=90=20get=20=E6=8E=A5=E5=8F=A3=E5=8E=BB=E8=BD=AE=E8=AF=A2?= =?UTF-8?q?=EF=BC=8C=E4=B8=8D=E5=9F=BA=E4=BA=8E=20page=20=E8=BD=AE?= =?UTF-8?q?=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/ai/image/index.ts | 4 ++++ src/views/ai/image/ImageTask.vue | 35 ++++++++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/api/ai/image/index.ts b/src/api/ai/image/index.ts index cb5a5afd..75103182 100644 --- a/src/api/ai/image/index.ts +++ b/src/api/ai/image/index.ts @@ -64,6 +64,10 @@ export const ImageApi = { getImageMy: async (id: number) => { return await request.get({ url: `/ai/image/get-my?id=${id}` }) }, + // 获取我的图片 + getImageMyIds: async (params) => { + return await request.get({ url: `/ai/image/get-my-ids`, params}) + }, // 生成图片 drawImage: async (data: ImageDrawReqVO) => { return await request.post({ url: `/ai/image/draw`, data }) diff --git a/src/views/ai/image/ImageTask.vue b/src/views/ai/image/ImageTask.vue index 38bf7483..992120bd 100644 --- a/src/views/ai/image/ImageTask.vue +++ b/src/views/ai/image/ImageTask.vue @@ -26,7 +26,7 @@ /> diff --git a/src/views/mall/promotion/kefu/components/KefuChatBox.vue b/src/views/mall/promotion/kefu/components/KefuChatBox.vue new file mode 100644 index 00000000..394c8424 --- /dev/null +++ b/src/views/mall/promotion/kefu/components/KefuChatBox.vue @@ -0,0 +1,77 @@ + + + + + diff --git a/src/views/mall/promotion/kefu/components/constants.ts b/src/views/mall/promotion/kefu/components/constants.ts new file mode 100644 index 00000000..015b46a7 --- /dev/null +++ b/src/views/mall/promotion/kefu/components/constants.ts @@ -0,0 +1,14 @@ +export const KeFuMessageContentTypeEnum = { + TEXT: 1, // 文本消息 + IMAGE: 2, // 图片消息 + VOICE: 3, // 语音消息 + VIDEO: 4, // 视频消息 + SYSTEM: 5, // 系统消息 + // ========== 商城特殊消息 ========== + PRODUCT: 10, // 商品消息 + ORDER: 11 // 订单消息" +} +export const UserTypeEnum = { + MEMBER: 1, // 会员 面向 c 端,普通用户 + ADMIN: 2 // 管理员 面向 b 端,管理后台 +} diff --git a/src/views/mall/promotion/kefu/components/emoji.ts b/src/views/mall/promotion/kefu/components/emoji.ts new file mode 100644 index 00000000..6ccd0cff --- /dev/null +++ b/src/views/mall/promotion/kefu/components/emoji.ts @@ -0,0 +1,91 @@ +export const emojiList = [ + { name: '[笑掉牙]', file: 'xiaodiaoya.png' }, + { name: '[可爱]', file: 'keai.png' }, + { name: '[冷酷]', file: 'lengku.png' }, + { name: '[闭嘴]', file: 'bizui.png' }, + { name: '[生气]', file: 'shengqi.png' }, + { name: '[惊恐]', file: 'jingkong.png' }, + { name: '[瞌睡]', file: 'keshui.png' }, + { name: '[大笑]', file: 'daxiao.png' }, + { name: '[爱心]', file: 'aixin.png' }, + { name: '[坏笑]', file: 'huaixiao.png' }, + { name: '[飞吻]', file: 'feiwen.png' }, + { name: '[疑问]', file: 'yiwen.png' }, + { name: '[开心]', file: 'kaixin.png' }, + { name: '[发呆]', file: 'fadai.png' }, + { name: '[流泪]', file: 'liulei.png' }, + { name: '[汗颜]', file: 'hanyan.png' }, + { name: '[惊悚]', file: 'jingshu.png' }, + { name: '[困~]', file: 'kun.png' }, + { name: '[心碎]', file: 'xinsui.png' }, + { name: '[天使]', file: 'tianshi.png' }, + { name: '[晕]', file: 'yun.png' }, + { name: '[啊]', file: 'a.png' }, + { name: '[愤怒]', file: 'fennu.png' }, + { name: '[睡着]', file: 'shuizhuo.png' }, + { name: '[面无表情]', file: 'mianwubiaoqing.png' }, + { name: '[难过]', file: 'nanguo.png' }, + { name: '[犯困]', file: 'fankun.png' }, + { name: '[好吃]', file: 'haochi.png' }, + { name: '[呕吐]', file: 'outu.png' }, + { name: '[龇牙]', file: 'ziya.png' }, + { name: '[懵比]', file: 'mengbi.png' }, + { name: '[白眼]', file: 'baiyan.png' }, + { name: '[饿死]', file: 'esi.png' }, + { name: '[凶]', file: 'xiong.png' }, + { name: '[感冒]', file: 'ganmao.png' }, + { name: '[流汗]', file: 'liuhan.png' }, + { name: '[笑哭]', file: 'xiaoku.png' }, + { name: '[流口水]', file: 'liukoushui.png' }, + { name: '[尴尬]', file: 'ganga.png' }, + { name: '[惊讶]', file: 'jingya.png' }, + { name: '[大惊]', file: 'dajing.png' }, + { name: '[不好意思]', file: 'buhaoyisi.png' }, + { name: '[大闹]', file: 'danao.png' }, + { name: '[不可思议]', file: 'bukesiyi.png' }, + { name: '[爱你]', file: 'aini.png' }, + { name: '[红心]', file: 'hongxin.png' }, + { name: '[点赞]', file: 'dianzan.png' }, + { name: '[恶魔]', file: 'emo.png' } +] + +export const emojiPage = {} +emojiList.forEach((item, index) => { + if (!emojiPage[Math.floor(index / 30) + 1]) { + emojiPage[Math.floor(index / 30) + 1] = [] + } + emojiPage[Math.floor(index / 30) + 1].push(item) +}) + +// 后端上传地址 +const staticUrl = import.meta.env.VITE_STATIC_URL + +// 处理表情 +export function replaceEmoji(data: string) { + let newData = data + if (typeof newData !== 'object') { + const reg = /\[(.+?)\]/g // [] 中括号 + const zhEmojiName = newData.match(reg) + if (zhEmojiName) { + zhEmojiName.forEach((item) => { + const emojiFile = selEmojiFile(item) + newData = newData.replace( + item, + `` + ) + }) + } + } + return newData +} + +function selEmojiFile(name: string) { + for (const index in emojiList) { + if (emojiList[index].name === name) { + return emojiList[index].file + } + } + return false +} diff --git a/src/views/mall/promotion/kefu/components/index.ts b/src/views/mall/promotion/kefu/components/index.ts new file mode 100644 index 00000000..afd2fd76 --- /dev/null +++ b/src/views/mall/promotion/kefu/components/index.ts @@ -0,0 +1,5 @@ +import KeFuConversationBox from './KeFuConversationBox.vue' +import KeFuChatBox from './KefuChatBox.vue' +import * as Constants from './constants' + +export { KeFuConversationBox, KeFuChatBox, Constants } diff --git a/src/views/mall/promotion/kefu/index.vue b/src/views/mall/promotion/kefu/index.vue new file mode 100644 index 00000000..52c6f2ba --- /dev/null +++ b/src/views/mall/promotion/kefu/index.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/types/env.d.ts b/types/env.d.ts index 057b5268..63d9c3ee 100644 --- a/types/env.d.ts +++ b/types/env.d.ts @@ -19,6 +19,7 @@ interface ImportMetaEnv { readonly VITE_UPLOAD_URL: string readonly VITE_API_URL: string readonly VITE_BASE_PATH: string + readonly VITE_STATIC_URL: string readonly VITE_DROP_DEBUGGER: string readonly VITE_DROP_CONSOLE: string readonly VITE_SOURCEMAP: string -- Gitee From d3b4063b94b159dc8d2256fd11c5fc409e79d7c1 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 1 Jul 2024 16:15:27 +0800 Subject: [PATCH 254/341] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91?= =?UTF-8?q?=EF=BC=9Amall=20=E5=AE=A2=E6=9C=8D=E6=B6=88=E6=81=AF=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mall/promotion/kefu/conversation/index.ts | 2 +- src/api/mall/promotion/kefu/message/index.ts | 70 ++++++++ .../promotion/kefu/components/KeFuChatBox.vue | 167 ++++++++++++++++++ .../kefu/components/KeFuConversationBox.vue | 8 +- .../promotion/kefu/components/KefuChatBox.vue | 77 -------- .../promotion/kefu/components/constants.ts | 4 - .../mall/promotion/kefu/components/index.ts | 2 +- src/views/mall/promotion/kefu/index.vue | 7 +- 8 files changed, 249 insertions(+), 88 deletions(-) create mode 100644 src/api/mall/promotion/kefu/message/index.ts create mode 100644 src/views/mall/promotion/kefu/components/KeFuChatBox.vue delete mode 100644 src/views/mall/promotion/kefu/components/KefuChatBox.vue diff --git a/src/api/mall/promotion/kefu/conversation/index.ts b/src/api/mall/promotion/kefu/conversation/index.ts index 17432b35..96a23706 100644 --- a/src/api/mall/promotion/kefu/conversation/index.ts +++ b/src/api/mall/promotion/kefu/conversation/index.ts @@ -16,7 +16,7 @@ export interface KeFuConversationRespVO { /** * 会话所属用户昵称 */ - nickname: string + userNickname: string /** * 最后聊天时间 */ diff --git a/src/api/mall/promotion/kefu/message/index.ts b/src/api/mall/promotion/kefu/message/index.ts new file mode 100644 index 00000000..3408f1e0 --- /dev/null +++ b/src/api/mall/promotion/kefu/message/index.ts @@ -0,0 +1,70 @@ +import request from '@/config/axios' + +export interface KeFuMessageRespVO { + /** + * 编号 + */ + id: number + /** + * 会话编号 + */ + conversationId: number + /** + * 发送人编号 + */ + senderId: number + /** + * 发送人头像 + */ + senderAvatar: string + /** + * 发送人类型 + */ + senderType: number + /** + * 接收人编号 + */ + receiverId: number + /** + * 接收人类型 + */ + receiverType: number + /** + * 消息类型 + */ + contentType: number + /** + * 消息 + */ + content: string + /** + * 是否已读 + */ + readStatus: boolean + /** + * 创建时间 + */ + createTime: Date +} + +// 客服会话 API +export const KeFuMessageApi = { + // 发送客服消息 + sendKeFuMessage: async (data: any) => { + return await request.put({ + url: '/promotion/kefu-message/send', + data + }) + }, + // 更新客服消息已读状态 + updateKeFuMessageReadStatus: async (data: any) => { + return await request.put({ + url: '/promotion/kefu-message/update-read-status', + data + }) + }, + // 获得消息分页数据 + getKeFuMessagePage: async (params: any) => { + return await request.get({ url: '/promotion/kefu-message/page', params }) + } +} diff --git a/src/views/mall/promotion/kefu/components/KeFuChatBox.vue b/src/views/mall/promotion/kefu/components/KeFuChatBox.vue new file mode 100644 index 00000000..ee41564b --- /dev/null +++ b/src/views/mall/promotion/kefu/components/KeFuChatBox.vue @@ -0,0 +1,167 @@ + + + + + diff --git a/src/views/mall/promotion/kefu/components/KeFuConversationBox.vue b/src/views/mall/promotion/kefu/components/KeFuConversationBox.vue index c94c01c3..595475be 100644 --- a/src/views/mall/promotion/kefu/components/KeFuConversationBox.vue +++ b/src/views/mall/promotion/kefu/components/KeFuConversationBox.vue @@ -10,7 +10,7 @@
-
{{ item.nickname }}
+
{{ item.userNickname }}
{ userId: 283, userAvatar: 'https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKMezSxtOImrC9lbhwHiazYwck3xwrEcO7VJfG6WQo260whaeVNoByE5RreiaGsGfOMlIiaDhSaA991w/132', - nickname: '辉辉鸭' + i, + userNickname: '辉辉鸭' + i, lastMessageTime: getNowDateTime(), lastMessageContent: '[爱心][爱心]你好哇', lastMessageContentType: 1, @@ -54,12 +54,12 @@ const getConversationList = async () => { } defineExpose({ getConversationList }) const emits = defineEmits<{ - (e: 'change', v: number): void + (e: 'change', v: KeFuConversationRespVO): void }>() // 打开右侧消息 const openRightMessage = (item: KeFuConversationRespVO, index: number) => { activeConversationIndex.value = index - emits('change', item.id) + emits('change', item) } diff --git a/src/views/mall/promotion/kefu/components/KefuChatBox.vue b/src/views/mall/promotion/kefu/components/KefuChatBox.vue deleted file mode 100644 index 394c8424..00000000 --- a/src/views/mall/promotion/kefu/components/KefuChatBox.vue +++ /dev/null @@ -1,77 +0,0 @@ - - - - - diff --git a/src/views/mall/promotion/kefu/components/constants.ts b/src/views/mall/promotion/kefu/components/constants.ts index 015b46a7..f8599160 100644 --- a/src/views/mall/promotion/kefu/components/constants.ts +++ b/src/views/mall/promotion/kefu/components/constants.ts @@ -8,7 +8,3 @@ export const KeFuMessageContentTypeEnum = { PRODUCT: 10, // 商品消息 ORDER: 11 // 订单消息" } -export const UserTypeEnum = { - MEMBER: 1, // 会员 面向 c 端,普通用户 - ADMIN: 2 // 管理员 面向 b 端,管理后台 -} diff --git a/src/views/mall/promotion/kefu/components/index.ts b/src/views/mall/promotion/kefu/components/index.ts index afd2fd76..fcf6bd5b 100644 --- a/src/views/mall/promotion/kefu/components/index.ts +++ b/src/views/mall/promotion/kefu/components/index.ts @@ -1,5 +1,5 @@ import KeFuConversationBox from './KeFuConversationBox.vue' -import KeFuChatBox from './KefuChatBox.vue' +import KeFuChatBox from './KeFuChatBox.vue' import * as Constants from './constants' export { KeFuConversationBox, KeFuChatBox, Constants } diff --git a/src/views/mall/promotion/kefu/index.vue b/src/views/mall/promotion/kefu/index.vue index 52c6f2ba..1204b8dc 100644 --- a/src/views/mall/promotion/kefu/index.vue +++ b/src/views/mall/promotion/kefu/index.vue @@ -15,12 +15,17 @@ diff --git a/src/views/ai/image/manager/index.vue b/src/views/ai/image/manager/index.vue index f0e94faa..84403f35 100644 --- a/src/views/ai/image/manager/index.vue +++ b/src/views/ai/image/manager/index.vue @@ -121,7 +121,7 @@ :active-value="true" :inactive-value="false" @change="handleUpdatePublicStatusChange(scope.row)" - :disabled="scope.row.status !== 20" + :disabled="scope.row.status !== AiImageStatusEnum.SUCCESS" /> @@ -165,6 +165,7 @@ import { getIntDictOptions, DICT_TYPE, getStrDictOptions, getBoolDictOptions } f import { dateFormatter } from '@/utils/formatTime' import { ImageApi, ImageVO } from '@/api/ai/image' import * as UserApi from '@/api/system/user' +import { AiImageStatusEnum } from '@/views/ai/utils/constants' /** AI 绘画 列表 */ defineOptions({ name: 'AiImageManager' }) diff --git a/src/views/ai/music/manager/index.vue b/src/views/ai/music/manager/index.vue index ec3c12b0..342f8dd8 100644 --- a/src/views/ai/music/manager/index.vue +++ b/src/views/ai/music/manager/index.vue @@ -158,7 +158,7 @@ :active-value="true" :inactive-value="false" @change="handleUpdatePublicStatusChange(scope.row)" - :disabled="scope.row.status !== 20" + :disabled="scope.row.status !== AiMusicStatusEnum.SUCCESS" /> @@ -199,6 +199,7 @@ import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict' import { dateFormatter } from '@/utils/formatTime' import { MusicApi, MusicVO } from '@/api/ai/music' import * as UserApi from '@/api/system/user' +import { AiMusicStatusEnum } from '@/views/ai/utils/constants' /** AI 音乐 列表 */ defineOptions({ name: 'AiMusicManager' }) diff --git a/src/views/ai/utils/constants.ts b/src/views/ai/utils/constants.ts new file mode 100644 index 00000000..2e7b9ac5 --- /dev/null +++ b/src/views/ai/utils/constants.ts @@ -0,0 +1,41 @@ +/** + * Created by 芋道源码 + * + * AI 枚举类 + * + * 问题:为什么不放在 src/utils/constants.ts 呢? + * 回答:主要 AI 是可选模块,考虑到独立、解耦,所以放在了 /views/ai/utils/constants.ts + */ + +/** + * AI 平台的枚举 + */ +export const AiPlatformEnum = { + OPENAI: 'OpenAI', + Ollama: 'Ollama', + YI_YAN: 'YiYan', // 百度 + XING_HUO: 'XingHuo', // 讯飞 + QIAN_WEN: 'QianWen', // 阿里 + GEMIR: 'gemir', // 谷歌 + STABLE_DIFFUSION: 'StableDiffusion', // Stability AI + MIDJOURNEY: 'Midjourney', // Midjourney + SUNO: 'Suno' // Suno AI +} + +/** + * AI 图像生成状态的枚举 + */ +export const AiImageStatusEnum = { + IN_PROGRESS: 10, // 进行中 + SUCCESS: 20, // 已完成 + FAIL: 30 // 已失败 +} + +/** + * AI 音乐生成状态的枚举 + */ +export const AiMusicStatusEnum = { + IN_PROGRESS: 10, // 进行中 + SUCCESS: 20, // 已完成 + FAIL: 30 // 已失败 +} -- Gitee From b0b62eb2506d80726f22505a8109f5d4a28ee87c Mon Sep 17 00:00:00 2001 From: puhui999 Date: Wed, 3 Jul 2024 17:51:58 +0800 Subject: [PATCH 262/341] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=EF=BC=9Amall=20=E5=AE=A2=E6=9C=8D=E8=A1=A8=E6=83=85=E5=8C=85?= =?UTF-8?q?=E5=AD=98=E6=94=BE=E5=88=B0=E6=9C=AC=E5=9C=B0=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.local | 4 - .../kefu/components/EmojiSelectPopover.vue | 3 +- .../promotion/kefu/components/KeFuChatBox.vue | 4 +- .../kefu/components/KeFuConversationBox.vue | 3 +- .../mall/promotion/kefu/components/emoji.ts | 93 ++++++++++-------- .../promotion/kefu/components/images/a.png | Bin 0 -> 4237 bytes .../promotion/kefu/components/images/aini.png | Bin 0 -> 2309 bytes .../kefu/components/images/aixin.png | Bin 0 -> 4431 bytes .../kefu/components/images/baiyan.png | Bin 0 -> 3792 bytes .../kefu/components/images/bizui.png | Bin 0 -> 3768 bytes .../kefu/components/images/buhaoyisi.png | Bin 0 -> 4443 bytes .../kefu/components/images/bukesiyi.png | Bin 0 -> 3979 bytes .../kefu/components/images/dajing.png | Bin 0 -> 4298 bytes .../kefu/components/images/danao.png | Bin 0 -> 4568 bytes .../kefu/components/images/daxiao.png | Bin 0 -> 4382 bytes .../kefu/components/images/dianzan.png | Bin 0 -> 1878 bytes .../promotion/kefu/components/images/emo.png | Bin 0 -> 4956 bytes .../promotion/kefu/components/images/esi.png | Bin 0 -> 3873 bytes .../kefu/components/images/fadai.png | Bin 0 -> 3823 bytes .../kefu/components/images/fankun.png | Bin 0 -> 4236 bytes .../kefu/components/images/feiwen.png | Bin 0 -> 6873 bytes .../kefu/components/images/fennu.png | Bin 0 -> 4590 bytes .../kefu/components/images/ganga.png | Bin 0 -> 4396 bytes .../kefu/components/images/ganmao.png | Bin 0 -> 4727 bytes .../kefu/components/images/hanyan.png | Bin 0 -> 2966 bytes .../kefu/components/images/haochi.png | Bin 0 -> 3794 bytes .../kefu/components/images/hongxin.png | Bin 0 -> 3844 bytes .../kefu/components/images/huaixiao.png | Bin 0 -> 4234 bytes .../kefu/components/images/jingkong.png | Bin 0 -> 4272 bytes .../kefu/components/images/jingshu.png | Bin 0 -> 4702 bytes .../kefu/components/images/jingya.png | Bin 0 -> 4167 bytes .../kefu/components/images/kaixin.png | Bin 0 -> 4008 bytes .../promotion/kefu/components/images/keai.png | Bin 0 -> 4060 bytes .../kefu/components/images/keshui.png | Bin 0 -> 3975 bytes .../promotion/kefu/components/images/kun.png | Bin 0 -> 4460 bytes .../kefu/components/images/lengku.png | Bin 0 -> 4630 bytes .../kefu/components/images/liuhan.png | Bin 0 -> 3823 bytes .../kefu/components/images/liukoushui.png | Bin 0 -> 4072 bytes .../kefu/components/images/liulei.png | Bin 0 -> 4246 bytes .../kefu/components/images/mengbi.png | Bin 0 -> 3345 bytes .../kefu/components/images/mianwubiaoqing.png | Bin 0 -> 2928 bytes .../kefu/components/images/nanguo.png | Bin 0 -> 3882 bytes .../promotion/kefu/components/images/outu.png | Bin 0 -> 4403 bytes .../kefu/components/images/shengqi.png | Bin 0 -> 4629 bytes .../kefu/components/images/shuizhuo.png | Bin 0 -> 4641 bytes .../kefu/components/images/tianshi.png | Bin 0 -> 4192 bytes .../kefu/components/images/xiaodiaoya.png | Bin 0 -> 4326 bytes .../kefu/components/images/xiaoku.png | Bin 0 -> 4725 bytes .../kefu/components/images/xinsui.png | Bin 0 -> 4377 bytes .../kefu/components/images/xiong.png | Bin 0 -> 4525 bytes .../kefu/components/images/yiwen.png | Bin 0 -> 4615 bytes .../promotion/kefu/components/images/yun.png | Bin 0 -> 5991 bytes .../promotion/kefu/components/images/ziya.png | Bin 0 -> 4126 bytes 53 files changed, 58 insertions(+), 49 deletions(-) create mode 100644 src/views/mall/promotion/kefu/components/images/a.png create mode 100644 src/views/mall/promotion/kefu/components/images/aini.png create mode 100644 src/views/mall/promotion/kefu/components/images/aixin.png create mode 100644 src/views/mall/promotion/kefu/components/images/baiyan.png create mode 100644 src/views/mall/promotion/kefu/components/images/bizui.png create mode 100644 src/views/mall/promotion/kefu/components/images/buhaoyisi.png create mode 100644 src/views/mall/promotion/kefu/components/images/bukesiyi.png create mode 100644 src/views/mall/promotion/kefu/components/images/dajing.png create mode 100644 src/views/mall/promotion/kefu/components/images/danao.png create mode 100644 src/views/mall/promotion/kefu/components/images/daxiao.png create mode 100644 src/views/mall/promotion/kefu/components/images/dianzan.png create mode 100644 src/views/mall/promotion/kefu/components/images/emo.png create mode 100644 src/views/mall/promotion/kefu/components/images/esi.png create mode 100644 src/views/mall/promotion/kefu/components/images/fadai.png create mode 100644 src/views/mall/promotion/kefu/components/images/fankun.png create mode 100644 src/views/mall/promotion/kefu/components/images/feiwen.png create mode 100644 src/views/mall/promotion/kefu/components/images/fennu.png create mode 100644 src/views/mall/promotion/kefu/components/images/ganga.png create mode 100644 src/views/mall/promotion/kefu/components/images/ganmao.png create mode 100644 src/views/mall/promotion/kefu/components/images/hanyan.png create mode 100644 src/views/mall/promotion/kefu/components/images/haochi.png create mode 100644 src/views/mall/promotion/kefu/components/images/hongxin.png create mode 100644 src/views/mall/promotion/kefu/components/images/huaixiao.png create mode 100644 src/views/mall/promotion/kefu/components/images/jingkong.png create mode 100644 src/views/mall/promotion/kefu/components/images/jingshu.png create mode 100644 src/views/mall/promotion/kefu/components/images/jingya.png create mode 100644 src/views/mall/promotion/kefu/components/images/kaixin.png create mode 100644 src/views/mall/promotion/kefu/components/images/keai.png create mode 100644 src/views/mall/promotion/kefu/components/images/keshui.png create mode 100644 src/views/mall/promotion/kefu/components/images/kun.png create mode 100644 src/views/mall/promotion/kefu/components/images/lengku.png create mode 100644 src/views/mall/promotion/kefu/components/images/liuhan.png create mode 100644 src/views/mall/promotion/kefu/components/images/liukoushui.png create mode 100644 src/views/mall/promotion/kefu/components/images/liulei.png create mode 100644 src/views/mall/promotion/kefu/components/images/mengbi.png create mode 100644 src/views/mall/promotion/kefu/components/images/mianwubiaoqing.png create mode 100644 src/views/mall/promotion/kefu/components/images/nanguo.png create mode 100644 src/views/mall/promotion/kefu/components/images/outu.png create mode 100644 src/views/mall/promotion/kefu/components/images/shengqi.png create mode 100644 src/views/mall/promotion/kefu/components/images/shuizhuo.png create mode 100644 src/views/mall/promotion/kefu/components/images/tianshi.png create mode 100644 src/views/mall/promotion/kefu/components/images/xiaodiaoya.png create mode 100644 src/views/mall/promotion/kefu/components/images/xiaoku.png create mode 100644 src/views/mall/promotion/kefu/components/images/xinsui.png create mode 100644 src/views/mall/promotion/kefu/components/images/xiong.png create mode 100644 src/views/mall/promotion/kefu/components/images/yiwen.png create mode 100644 src/views/mall/promotion/kefu/components/images/yun.png create mode 100644 src/views/mall/promotion/kefu/components/images/ziya.png diff --git a/.env.local b/.env.local index 82a3f72a..005d2f0d 100644 --- a/.env.local +++ b/.env.local @@ -29,9 +29,5 @@ VITE_BASE_PATH=/ # 商城H5会员端域名 VITE_MALL_H5_DOMAIN='http://localhost:3000' -# TODO puhui999:这个可以不走 cdn 地址么? -# 客户端静态资源地址 空=默认使用服务端指定的CDN资源地址前缀 | local=本地 | http(s)://xxx.xxx=自定义静态资源地址前缀 -VITE_STATIC_URL = https://file.sheepjs.com - # 验证码的开关 VITE_APP_CAPTCHA_ENABLE=false diff --git a/src/views/mall/promotion/kefu/components/EmojiSelectPopover.vue b/src/views/mall/promotion/kefu/components/EmojiSelectPopover.vue index 03a963c6..4c777efb 100644 --- a/src/views/mall/promotion/kefu/components/EmojiSelectPopover.vue +++ b/src/views/mall/promotion/kefu/components/EmojiSelectPopover.vue @@ -26,8 +26,9 @@ diff --git a/src/views/mall/promotion/kefu/components/constants.ts b/src/views/mall/promotion/kefu/components/tools/constants.ts similarity index 100% rename from src/views/mall/promotion/kefu/components/constants.ts rename to src/views/mall/promotion/kefu/components/tools/constants.ts diff --git a/src/views/mall/promotion/kefu/components/emoji.ts b/src/views/mall/promotion/kefu/components/tools/emoji.ts similarity index 100% rename from src/views/mall/promotion/kefu/components/emoji.ts rename to src/views/mall/promotion/kefu/components/tools/emoji.ts -- Gitee From e89b274e3f66d8c0ac539b62e22f00d4577290e0 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Thu, 4 Jul 2024 15:41:15 +0800 Subject: [PATCH 274/341] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=EF=BC=9Amall=20=E5=AE=A2=E6=9C=8D=E6=B6=88=E6=81=AF=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E6=8A=BD=E7=A6=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../promotion/kefu/components/KeFuChatBox.vue | 52 +++---------------- .../components/message/ImageMessageItem.vue | 40 ++++++++++++++ .../components/message/TextMessageItem.vue | 29 +++++++++++ 3 files changed, 76 insertions(+), 45 deletions(-) create mode 100644 src/views/mall/promotion/kefu/components/message/ImageMessageItem.vue create mode 100644 src/views/mall/promotion/kefu/components/message/TextMessageItem.vue diff --git a/src/views/mall/promotion/kefu/components/KeFuChatBox.vue b/src/views/mall/promotion/kefu/components/KeFuChatBox.vue index cba5869b..da25c9d9 100644 --- a/src/views/mall/promotion/kefu/components/KeFuChatBox.vue +++ b/src/views/mall/promotion/kefu/components/KeFuChatBox.vue @@ -19,49 +19,18 @@ class="flex mb-20px w-[100%]" >
- - + - +
@@ -94,14 +63,14 @@ import { KeFuMessageApi, KeFuMessageRespVO } from '@/api/mall/promotion/kefu/mes import { KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation' import EmojiSelectPopover from './tools/EmojiSelectPopover.vue' import PictureSelectUpload from './tools/PictureSelectUpload.vue' -import { Emoji, useEmoji } from './tools/emoji' +import TextMessageItem from './message/TextMessageItem.vue' +import ImageMessageItem from './message/ImageMessageItem.vue' +import { Emoji } from './tools/emoji' import { KeFuMessageContentTypeEnum } from './tools/constants' import { isEmpty } from '@/utils/is' import { UserTypeEnum } from '@/utils/constants' -import { createImageViewer } from '@/components/ImageViewer' defineOptions({ name: 'KeFuMessageBox' }) -const { replaceEmoji } = useEmoji() const messageTool = useMessage() const message = ref('') // 消息 const messageList = ref([]) // 消息列表 @@ -175,13 +144,6 @@ const scrollToBottom = async () => { scrollbarRef.value!.setScrollTop(innerRef.value!.clientHeight) } -/** 图预览 */ -const imagePreview = (imgUrl: string) => { - createImageViewer({ - urlList: [imgUrl] - }) -} - // TODO puhui999: 轮训相关,功能完善后移除 onBeforeUnmount(() => { if (!poller.value) { diff --git a/src/views/mall/promotion/kefu/components/message/ImageMessageItem.vue b/src/views/mall/promotion/kefu/components/message/ImageMessageItem.vue new file mode 100644 index 00000000..7b890cf1 --- /dev/null +++ b/src/views/mall/promotion/kefu/components/message/ImageMessageItem.vue @@ -0,0 +1,40 @@ + + + diff --git a/src/views/mall/promotion/kefu/components/message/TextMessageItem.vue b/src/views/mall/promotion/kefu/components/message/TextMessageItem.vue new file mode 100644 index 00000000..fd4b6edb --- /dev/null +++ b/src/views/mall/promotion/kefu/components/message/TextMessageItem.vue @@ -0,0 +1,29 @@ + + + -- Gitee From b6ff9ede11107e22c27daf8f95f5939b30f8f2f3 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Thu, 4 Jul 2024 16:01:08 +0800 Subject: [PATCH 275/341] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91handle=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/image/ImageDetailDrawer.vue | 10 +++---- src/views/ai/image/ImageTask.vue | 20 +++++++------- src/views/ai/image/ImageTaskCard.vue | 20 +++++++------- src/views/ai/image/dall3/index.vue | 27 +++++++++---------- src/views/ai/image/index.vue | 14 +++++----- src/views/ai/image/midjourney/index.vue | 25 +++++++++-------- src/views/ai/image/stable-diffusion/index.vue | 2 +- 7 files changed, 57 insertions(+), 61 deletions(-) diff --git a/src/views/ai/image/ImageDetailDrawer.vue b/src/views/ai/image/ImageDetailDrawer.vue index fca087da..95ec146c 100644 --- a/src/views/ai/image/ImageDetailDrawer.vue +++ b/src/views/ai/image/ImageDetailDrawer.vue @@ -2,7 +2,7 @@ @@ -79,8 +79,8 @@ const props = defineProps({ }) /** 抽屉 - close */ -const handlerDrawerClose = async () => { - emits('handlerDrawerClose') +const handleDrawerClose = async () => { + emits('handleDrawerClose') } /** 获取 - 图片 detail */ @@ -90,7 +90,7 @@ const getImageDetail = async (id) => { } /** 任务 - detail */ -const handlerTaskDetail = async () => { +const handleTaskDetail = async () => { showDrawer.value = true } @@ -107,7 +107,7 @@ watch(id, async (newVal, oldVal) => { } }) // -const emits = defineEmits(['handlerDrawerClose']) +const emits = defineEmits(['handleDrawerClose']) // onMounted(async () => {}) diff --git a/src/views/ai/image/ImageTask.vue b/src/views/ai/image/ImageTask.vue index 9ddd7461..b4cbd253 100644 --- a/src/views/ai/image/ImageTask.vue +++ b/src/views/ai/image/ImageTask.vue @@ -6,8 +6,8 @@ v-for="image in imageList" :key="image" :image-detail="image" - @on-btn-click="handlerImageBtnClick" - @on-mj-btn-click="handlerImageMjBtnClick" + @on-btn-click="handleImageBtnClick" + @on-mj-btn-click="handleImageMjBtnClick" />
@@ -16,7 +16,7 @@ layout="prev, pager, next" :default-page-size="pageSize" :total="pageTotal" - @change="handlerPageChange" + @change="handlePageChange" />
@@ -24,7 +24,7 @@ diff --git a/src/views/ai/image/dall3/index.vue b/src/views/ai/image/dall3/index.vue index 69e767a3..1751eace 100644 --- a/src/views/ai/image/dall3/index.vue +++ b/src/views/ai/image/dall3/index.vue @@ -25,7 +25,7 @@ :type="(selectHotWord === hotWord ? 'primary' : 'default')" v-for="hotWord in hotWords" :key="hotWord" - @click="handlerHotWordClick(hotWord)" + @click="handleHotWordClick(hotWord)" > {{ hotWord }} @@ -45,7 +45,7 @@
{{model.name}}
@@ -64,7 +64,7 @@
{{imageStyle.name}}
@@ -78,7 +78,7 @@
+ @click="handleSizeClick(imageSize)">
@@ -91,7 +91,7 @@ size="large" round :loading="drawIn" - @click="handlerGenerateImage"> + @click="handleGenerateImage"> {{drawIn ? '生成中' : '生成内容'}}
@@ -183,10 +183,8 @@ const props = defineProps({}) // 定义 emits const emits = defineEmits(['onDrawStart', 'onDrawComplete']) -// TODO @fan:如果是简单注释,建议用 /** */,主要是现在项目里是这种风格哈,保持一致好点~ -// TODO @fan:handler 应该改成 handle 哈 /** 热词 - click */ -const handlerHotWordClick = async (hotWord: string) => { +const handleHotWordClick = async (hotWord: string) => { // 取消选中 if (selectHotWord.value == hotWord) { selectHotWord.value = '' @@ -199,22 +197,22 @@ const handlerHotWordClick = async (hotWord: string) => { } /** 模型 - click */ -const handlerModelClick = async (model: ImageModelVO) => { +const handleModelClick = async (model: ImageModelVO) => { selectModel.value = model.key } /** 样式 - click */ -const handlerStyleClick = async (imageStyle: ImageModelVO) => { +const handleStyleClick = async (imageStyle: ImageModelVO) => { selectImageStyle.value = imageStyle.key } /** size - click */ -const handlerSizeClick = async (imageSize: ImageSizeVO) => { +const handleSizeClick = async (imageSize: ImageSizeVO) => { selectImageSize.value = imageSize.key } /** 图片生产 */ -const handlerGenerateImage = async () => { +const handleGenerateImage = async () => { // 二次确认 await message.confirm(`确认生成内容?`) try { @@ -251,15 +249,14 @@ const settingValues = async (imageDetail: ImageVO) => { selectImageStyle.value = imageDetail.options?.style // const imageSize = imageSizeList.value.find(item => item.key === `${imageDetail.width}x${imageDetail.height}`) as ImageSizeVO - console.log('imageSize', imageSize) - await handlerSizeClick(imageSize) + await handleSizeClick(imageSize) } /** 暴露组件方法 */ defineExpose({ settingValues }) + -- Gitee From 6f86ea96da367ab3b25fe04dc74ef9cdd8df9454 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 7 Jul 2024 11:22:02 +0800 Subject: [PATCH 290/341] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91AI=EF=BC=9A=E6=8E=A5=E5=85=A5=E6=9B=B4?= =?UTF-8?q?=E5=A4=9A=20AI=20=E5=A4=A7=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/utils/constants.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/views/ai/utils/constants.ts b/src/views/ai/utils/constants.ts index 2e7b9ac5..337cfda3 100644 --- a/src/views/ai/utils/constants.ts +++ b/src/views/ai/utils/constants.ts @@ -11,12 +11,13 @@ * AI 平台的枚举 */ export const AiPlatformEnum = { - OPENAI: 'OpenAI', - Ollama: 'Ollama', + TONG_YI: 'TongYi', // 阿里 YI_YAN: 'YiYan', // 百度 + DEEP_SEEK: 'DeepSeek', // DeepSeek + ZHI_PU: 'ZhiPu', // 智谱 AI XING_HUO: 'XingHuo', // 讯飞 - QIAN_WEN: 'QianWen', // 阿里 - GEMIR: 'gemir', // 谷歌 + OPENAI: 'OpenAI', + Ollama: 'Ollama', STABLE_DIFFUSION: 'StableDiffusion', // Stability AI MIDJOURNEY: 'Midjourney', // Midjourney SUNO: 'Suno' // Suno AI -- Gitee From f3777f63348fbaaea21ae5c311a64b3d0b88e843 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 7 Jul 2024 17:22:16 +0800 Subject: [PATCH 291/341] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91AI=EF=BC=9A=E5=B0=86=E5=AF=B9=E8=AF=9D?= =?UTF-8?q?=E3=80=81=E8=81=8A=E5=A4=A9=E6=8C=AA=E5=88=B0=20index=20?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E4=B8=8B=EF=BC=8C=E6=9B=B4=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/chat/{ => index}/ChatEmpty.vue | 0 .../ai/chat/{ => index}/Conversation.vue | 2 +- src/views/ai/chat/{ => index}/Message.vue | 0 .../ai/chat/{ => index}/MessageLoading.vue | 0 .../ai/chat/{ => index}/MessageNewChat.vue | 0 .../components/ChatConversationUpdateForm.vue | 0 .../ai/chat/{ => index}/components/Header.vue | 0 src/views/ai/chat/{ => index}/index.vue | 2 +- .../{ => index}/role/RoleCategoryList.vue | 0 .../ai/chat/{ => index}/role/RoleList.vue | 0 src/views/ai/chat/{ => index}/role/index.vue | 2 +- .../image/{ => index}/ImageDetailDrawer.vue | 0 src/views/ai/image/{ => index}/ImageTask.vue | 0 .../ai/image/{ => index}/ImageTaskCard.vue | 0 .../ai/image/{ => index}/dall3/index.vue | 0 src/views/ai/image/{ => index}/index.vue | 0 .../ai/image/{ => index}/midjourney/index.vue | 0 .../{ => index}/stable-diffusion/index.vue | 33 ++++++++++++++----- .../ai/utils/{common-utils.ts => utils.ts} | 0 19 files changed, 27 insertions(+), 12 deletions(-) rename src/views/ai/chat/{ => index}/ChatEmpty.vue (100%) rename src/views/ai/chat/{ => index}/Conversation.vue (99%) rename src/views/ai/chat/{ => index}/Message.vue (100%) rename src/views/ai/chat/{ => index}/MessageLoading.vue (100%) rename src/views/ai/chat/{ => index}/MessageNewChat.vue (100%) rename src/views/ai/chat/{ => index}/components/ChatConversationUpdateForm.vue (100%) rename src/views/ai/chat/{ => index}/components/Header.vue (100%) rename src/views/ai/chat/{ => index}/index.vue (99%) rename src/views/ai/chat/{ => index}/role/RoleCategoryList.vue (100%) rename src/views/ai/chat/{ => index}/role/RoleList.vue (100%) rename src/views/ai/chat/{ => index}/role/index.vue (99%) rename src/views/ai/image/{ => index}/ImageDetailDrawer.vue (100%) rename src/views/ai/image/{ => index}/ImageTask.vue (100%) rename src/views/ai/image/{ => index}/ImageTaskCard.vue (100%) rename src/views/ai/image/{ => index}/dall3/index.vue (100%) rename src/views/ai/image/{ => index}/index.vue (100%) rename src/views/ai/image/{ => index}/midjourney/index.vue (100%) rename src/views/ai/image/{ => index}/stable-diffusion/index.vue (93%) rename src/views/ai/utils/{common-utils.ts => utils.ts} (100%) diff --git a/src/views/ai/chat/ChatEmpty.vue b/src/views/ai/chat/index/ChatEmpty.vue similarity index 100% rename from src/views/ai/chat/ChatEmpty.vue rename to src/views/ai/chat/index/ChatEmpty.vue diff --git a/src/views/ai/chat/Conversation.vue b/src/views/ai/chat/index/Conversation.vue similarity index 99% rename from src/views/ai/chat/Conversation.vue rename to src/views/ai/chat/index/Conversation.vue index 5976171b..be184cf8 100644 --- a/src/views/ai/chat/Conversation.vue +++ b/src/views/ai/chat/index/Conversation.vue @@ -98,7 +98,7 @@ diff --git a/src/views/ai/writer/components/Right.vue b/src/views/ai/writer/components/Right.vue new file mode 100644 index 00000000..a11b7c24 --- /dev/null +++ b/src/views/ai/writer/components/Right.vue @@ -0,0 +1,25 @@ + + + + + diff --git a/src/views/ai/writer/components/Tag.vue b/src/views/ai/writer/components/Tag.vue new file mode 100644 index 00000000..4a32e572 --- /dev/null +++ b/src/views/ai/writer/components/Tag.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/src/views/ai/writer/index.vue b/src/views/ai/writer/index.vue new file mode 100644 index 00000000..3cb4a7d7 --- /dev/null +++ b/src/views/ai/writer/index.vue @@ -0,0 +1,20 @@ + + + + + -- Gitee From 1064bbe5700a73c7eb14f3bf4f61012d332a24f9 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 7 Jul 2024 20:30:44 +0800 Subject: [PATCH 293/341] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91AI=EF=BC=9A=E8=81=8A=E5=A4=A9=E5=AF=B9?= =?UTF-8?q?=E8=AF=9D=20index.vue=20=E4=BB=A3=E7=A0=81=E6=A2=B3=E7=90=86=20?= =?UTF-8?q?20%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/ai/chat/conversation/index.ts | 4 +- src/api/ai/chat/message/index.ts | 13 +- src/views/ai/chat/index/MessageNewChat.vue | 8 +- .../conversation/ConversationList.vue} | 5 +- .../ConversationUpdateForm.vue} | 10 +- src/views/ai/chat/index/index.vue | 368 +++++++++--------- 6 files changed, 198 insertions(+), 210 deletions(-) rename src/views/ai/chat/index/{Conversation.vue => components/conversation/ConversationList.vue} (99%) rename src/views/ai/chat/index/components/{ChatConversationUpdateForm.vue => conversation/ConversationUpdateForm.vue} (95%) diff --git a/src/api/ai/chat/conversation/index.ts b/src/api/ai/chat/conversation/index.ts index 9f5f70f2..acc21fc6 100644 --- a/src/api/ai/chat/conversation/index.ts +++ b/src/api/ai/chat/conversation/index.ts @@ -2,7 +2,7 @@ import request from '@/config/axios' // AI 聊天对话 VO export interface ChatConversationVO { - id: string // ID 编号 + id: number // ID 编号 userId: number // 用户编号 title: string // 对话标题 pinned: boolean // 是否置顶 @@ -23,7 +23,7 @@ export interface ChatConversationVO { // AI 聊天对话 API export const ChatConversationApi = { // 获得【我的】聊天对话 - getChatConversationMy: async (id: string) => { + getChatConversationMy: async (id: number) => { return await request.get({ url: `/ai/chat/conversation/get-my?id=${id}` }) }, diff --git a/src/api/ai/chat/message/index.ts b/src/api/ai/chat/message/index.ts index f9e807a1..90736266 100644 --- a/src/api/ai/chat/message/index.ts +++ b/src/api/ai/chat/message/index.ts @@ -19,22 +19,17 @@ export interface ChatMessageVO { userAvatar: string // 创建时间 } -export interface ChatMessageSendVO { - conversationId: string // 对话编号 - content: number // 聊天内容 -} - // AI chat 聊天 export const ChatMessageApi = { // 消息列表 - messageList: async (conversationId: string | null) => { + getChatMessageListByConversationId: async (conversationId: number | null) => { return await request.get({ url: `/ai/chat/message/list-by-conversation-id?conversationId=${conversationId}` }) }, - // 发送 send stream 消息 - // TODO axios 可以么? https://apifox.com/apiskills/how-to-create-axios-stream/ + // 发送 Stream 消息 + // 为什么不用 axios 呢?因为它不支持 SSE 调用 sendStream: async ( conversationId: number, content: string, @@ -70,7 +65,7 @@ export const ChatMessageApi = { }, // 删除消息 - 对话所有消息 - deleteByConversationId: async (conversationId: string) => { + deleteByConversationId: async (conversationId: number) => { return await request.delete({ url: `/ai/chat/message/delete-by-conversation-id?conversationId=${conversationId}` }) diff --git a/src/views/ai/chat/index/MessageNewChat.vue b/src/views/ai/chat/index/MessageNewChat.vue index aac5f905..727fb282 100644 --- a/src/views/ai/chat/index/MessageNewChat.vue +++ b/src/views/ai/chat/index/MessageNewChat.vue @@ -1,15 +1,16 @@ + const emits = defineEmits(['update:msg', 'stopStream']) + + const { copied, copy } = useClipboard() + + const compMsg = computed({ + get() { + return props.msg + }, + set(val) { + emits('update:msg', val) + } + }) + + const showCopy = computed(() => props.msg && !props.isWriting) + + const inputId = computed(() => getCurrentInstance()?.uid) + + const contentRef = ref() + defineExpose({ + scrollToBottom() { + contentRef.value?.scrollTo(0, contentRef.value?.scrollHeight) + } + }) + + // 点击复制的时候复制msg + const copyMsg = () => { + copy(props.msg) + } + + watch(copied, (val) => { + console.log({ copied: val }) + if (val) { + message.success('复制成功') + } + }) + diff --git a/src/views/ai/writer/data.json b/src/views/ai/writer/data.json new file mode 100644 index 00000000..3f20951b --- /dev/null +++ b/src/views/ai/writer/data.json @@ -0,0 +1,11 @@ +{ + "write": { + "prompt": "vue", + "data": "Vue.js 是一种用于构建用户界面的渐进式 JavaScript 框架。它的核心库只关注视图层,易于上手,同时也便于与其他库或已有项目整合。\n\nVue.js 的特点包括:\n- 响应式的数据绑定:Vue.js 会自动将数据与 DOM 同步,使得状态管理变得更加简单。\n- 组件化:Vue.js 允许开发者通过小型、独立和通常可复用的组件构建大型应用。\n- 虚拟 DOM:Vue.js 使用虚拟 DOM 实现快速渲染,提高了性能。\n\n在 Vue.js 中,一个典型的应用结构可能包括:\n1. 根实例:每个 Vue 应用都需要一个根实例作为入口点。\n2. 组件系统:可以创建自定义的可复用组件。\n3. 指令:特殊的带有前缀 v- 的属性,为 DOM 元素提供特殊的行为。\n4. 插值:用于文本内容,将数据动态地插入到 HTML。\n5. 计算属性和侦听器:用于处理数据的复杂逻辑和响应数据变化。\n6. 条件渲染:根据条件决定元素的渲染。\n7. 列表渲染:用于显示列表数据。\n8. 事件处理:响应用户交互。\n9. 表单输入绑定:处理表单输入和验证。\n10. 组件生命周期钩子:在组件的不同阶段执行特定的函数。\n\nVue.js 还提供了官方的路由器 Vue Router 和状态管理库 Vuex,以支持构建复杂的单页应用(SPA)。\n\n在开发过程中,开发者通常会使用 Vue CLI,这是一个强大的命令行工具,用于快速生成 Vue 项目脚手架,集成了诸如 Babel、Webpack 等现代前端工具,以及热重载、代码检测等开发体验优化功能。\n\nVue.js 的生态系统还包括大量的第三方库和插件,如 Vuetify(UI 组件库)、Vue Test Utils(测试工具)等,这些都极大地丰富了 Vue.js 的开发生态。\n\n总的来说,Vue.js 是一个灵活、高效的前端框架,适合从小型项目到大型企业级应用的开发。它的易用性、灵活性和强大的社区支持使其成为许多开发者的首选框架之一。" + }, + "reply": { + "originalContent": "领导,我想请假", + "prompt": "不批", + "data": "您的请假申请已收悉,经核实和考虑,暂时无法批准您的请假申请。\n\n如有特殊情况或紧急事务,请及时与我联系。\n\n祝工作顺利。\n\n谢谢。" + } +} diff --git a/src/views/ai/writer/index.vue b/src/views/ai/writer/index.vue index 3cb4a7d7..8875830f 100644 --- a/src/views/ai/writer/index.vue +++ b/src/views/ai/writer/index.vue @@ -1,7 +1,13 @@ @@ -9,12 +15,47 @@ import Left from './components/Left.vue' import Right from './components/Right.vue' import { writeStream } from '@/api/ai/writer' + import dataJson from './data.json' - const msg = ref('') + const message = useMessage() + const msgResult = ref('') + const isWriting = ref(false) - const submit = async (params) => { - const res = await writeStream(params) + const abortController = ref() + + const stopStream = () => { + abortController.value?.abort() + isWriting.value = false } - - + const rightRef = ref>() + + // 点击示例触发 + const example = (type: keyof typeof dataJson) => { + msgResult.value = dataJson[type].data + } + + const submit = async (data) => { + abortController.value = new AbortController() + msgResult.value = '' + isWriting.value = true + writeStream({ + data, + onMessage: async (res) => { + const { code, data, msg } = JSON.parse(res.data) + if (code !== 0) { + message.alert(`写作异常! ${msg}`) + stopStream() + return + } + msgResult.value = msgResult.value + data + nextTick(() => { + rightRef.value?.scrollToBottom() + }) + }, + ctrl: abortController.value, + onClose: stopStream, + onError: stopStream + }) + } + -- Gitee From e9bb9403b4ade987b2d7071619dbd9bfa2c13565 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 8 Jul 2024 12:00:34 +0800 Subject: [PATCH 296/341] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91spu?= =?UTF-8?q?=EF=BC=9A=E6=96=B0=E5=A2=9E=E5=95=86=E5=93=81=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E5=80=BC=E4=B8=BA=E7=A9=BA=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mall/product/spu/components/SkuList.vue | 36 ++++++++++++------- .../product/spu/form/ProductAttributes.vue | 12 +++---- src/views/mall/product/spu/form/SkuForm.vue | 14 ++++---- 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/views/mall/product/spu/components/SkuList.vue b/src/views/mall/product/spu/components/SkuList.vue index 2befe640..9bbd38e4 100644 --- a/src/views/mall/product/spu/components/SkuList.vue +++ b/src/views/mall/product/spu/components/SkuList.vue @@ -292,6 +292,7 @@ import { createImageViewer } from '@/components/ImageViewer' import { RuleConfig } from '@/views/mall/product/spu/components/index' import { PropertyAndValues } from './index' import { ElTable } from 'element-plus' +import { isEmpty } from '@/utils/is' defineOptions({ name: 'SkuList' }) const message = useMessage() // 消息弹窗 @@ -340,11 +341,22 @@ const imagePreview = (imgUrl: string) => { /** 批量添加 */ const batchAdd = () => { + validateProperty() formData.value!.skus!.forEach((item) => { copyValueToTarget(item, skuList.value[0]) }) } - +/** 校验商品属性属性值 */ +const validateProperty = () => { + // 校验商品属性属性值是否为空,有一个为空都不给过 + const warningInfo = '存在属性属性值为空,请先检查完善属性值后重试!!!' + for (const item of props.propertyList) { + if (!item.values || isEmpty(item.values)) { + message.warning(warningInfo) + throw new Error(warningInfo) + } + } +} /** 删除 sku */ const deleteSku = (row) => { const index = formData.value!.skus!.findIndex( @@ -358,6 +370,7 @@ const tableHeaders = ref<{ prop: string; label: string }[]>([]) // 多属性表 * 保存时,每个商品规格的表单要校验下。例如说,销售金额最低是 0.01 这种。 */ const validateSku = () => { + validateProperty() let warningInfo = '请检查商品各行相关属性配置,' let validate = true // 默认通过 for (const sku of formData.value!.skus!) { @@ -421,7 +434,7 @@ watch( const generateTableData = (propertyList: any[]) => { // 构建数据结构 const propertyValues = propertyList.map((item) => - item.values.map((v) => ({ + item.values.map((v: any) => ({ propertyId: item.id, propertyName: item.name, valueId: v.id, @@ -464,15 +477,14 @@ const generateTableData = (propertyList: any[]) => { */ const validateData = (propertyList: any[]) => { const skuPropertyIds: number[] = [] - formData.value!.skus!.forEach( - (sku) => - sku.properties - ?.map((property) => property.propertyId) - ?.forEach((propertyId) => { - if (skuPropertyIds.indexOf(propertyId!) === -1) { - skuPropertyIds.push(propertyId!) - } - }) + formData.value!.skus!.forEach((sku) => + sku.properties + ?.map((property) => property.propertyId) + ?.forEach((propertyId) => { + if (skuPropertyIds.indexOf(propertyId!) === -1) { + skuPropertyIds.push(propertyId!) + } + }) ) const propertyIds = propertyList.map((item) => item.id) return skuPropertyIds.length === propertyIds.length @@ -543,7 +555,7 @@ watch( return } // 添加新属性没有属性值也不做处理 - if (propertyList.some((item) => item.values!.length === 0)) { + if (propertyList.some((item) => !item.values || isEmpty(item.values))) { return } // 生成 table 数据,即 sku 列表 diff --git a/src/views/mall/product/spu/form/ProductAttributes.vue b/src/views/mall/product/spu/form/ProductAttributes.vue index 28962f47..ffe7397d 100644 --- a/src/views/mall/product/spu/form/ProductAttributes.vue +++ b/src/views/mall/product/spu/form/ProductAttributes.vue @@ -3,7 +3,7 @@
属性名: - + {{ item.name }}
@@ -12,8 +12,8 @@ {{ value.name }} @@ -44,7 +44,6 @@ -- Gitee From 2b0789112f345da0fc020d5ebd9dc2a5b286298f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 8 Jul 2024 12:39:49 +0800 Subject: [PATCH 297/341] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91AI=EF=BC=9A=E5=86=99=E4=BD=9C=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E7=9A=84=E5=BB=BA=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/ai/writer/index.ts | 4 +- .../conversation/ConversationList.vue | 3 +- src/views/ai/writer/components/Left.vue | 190 +++++++++--------- src/views/ai/writer/components/Right.vue | 80 ++++---- src/views/ai/writer/components/Tag.vue | 27 ++- src/views/ai/writer/index.vue | 92 +++++---- 6 files changed, 204 insertions(+), 192 deletions(-) diff --git a/src/api/ai/writer/index.ts b/src/api/ai/writer/index.ts index 01664b3d..57c23b4f 100644 --- a/src/api/ai/writer/index.ts +++ b/src/api/ai/writer/index.ts @@ -3,7 +3,9 @@ import { fetchEventSource } from '@microsoft/fetch-event-source' import { getAccessToken } from '@/utils/auth' import { config } from '@/config/axios/config' +// TODO @hhhero:可以改成 WriteVO 哈,主要是保持一致 export interface WriteParams { + // TODO @hhhero:注释。每个属性的后面哈。会更简洁一点 /** * 1:撰写 2:回复 */ @@ -33,6 +35,7 @@ export interface WriteParams { */ language: number } + export const writeStream = ({ data, onClose, @@ -46,7 +49,6 @@ export const writeStream = ({ onClose?: (...args: any[]) => void ctrl: AbortController }) => { - // return request.post({ url: '/ai/write/generate-stream', data }) const token = getAccessToken() return fetchEventSource(`${config.base_url}/ai/write/generate-stream`, { method: 'post', diff --git a/src/views/ai/chat/index/components/conversation/ConversationList.vue b/src/views/ai/chat/index/components/conversation/ConversationList.vue index 911f0fbb..6a7e32fa 100644 --- a/src/views/ai/chat/index/components/conversation/ConversationList.vue +++ b/src/views/ai/chat/index/components/conversation/ConversationList.vue @@ -226,7 +226,7 @@ const conversationTimeGroup = async (list: ChatConversationVO[]) => { const threeDays = 3 * oneDay const sevenDays = 7 * oneDay const thirtyDays = 30 * oneDay - for (const conversation: ChatConversationVO of list) { + for (const conversation of list) { // 置顶 if (conversation.pinned) { groupMap['置顶'].push(conversation) @@ -247,7 +247,6 @@ const conversationTimeGroup = async (list: ChatConversationVO[]) => { groupMap['三十天前'].push(conversation) } } - console.log('----groupMap', groupMap) return groupMap } diff --git a/src/views/ai/writer/components/Left.vue b/src/views/ai/writer/components/Left.vue index af808b15..0369d9df 100644 --- a/src/views/ai/writer/components/Left.vue +++ b/src/views/ai/writer/components/Left.vue @@ -1,5 +1,5 @@ diff --git a/src/views/ai/writer/components/Right.vue b/src/views/ai/writer/components/Right.vue index 30b74cdc..94140011 100644 --- a/src/views/ai/writer/components/Right.vue +++ b/src/views/ai/writer/components/Right.vue @@ -35,52 +35,52 @@ diff --git a/src/views/ai/writer/components/Tag.vue b/src/views/ai/writer/components/Tag.vue index 4a32e572..d496b517 100644 --- a/src/views/ai/writer/components/Tag.vue +++ b/src/views/ai/writer/components/Tag.vue @@ -13,20 +13,19 @@ - diff --git a/src/views/ai/writer/index.vue b/src/views/ai/writer/index.vue index 8875830f..27276431 100644 --- a/src/views/ai/writer/index.vue +++ b/src/views/ai/writer/index.vue @@ -1,61 +1,67 @@ + -- Gitee From 1a6afa3263e8797c4d96d8ed93f433bc336660f0 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 8 Jul 2024 13:00:24 +0800 Subject: [PATCH 298/341] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91AI=EF=BC=9A=E8=81=8A=E5=A4=A9=E5=AF=B9?= =?UTF-8?q?=E8=AF=9D=20index.vue=20=E4=BB=A3=E7=A0=81=E6=A2=B3=E7=90=86=20?= =?UTF-8?q?40%=EF=BC=88message=20=E9=83=A8=E5=88=86=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/ai/chat/conversation/index.ts | 1 + .../index/components/message/MessageList.vue | 127 ++++++------------ .../components/message/MessageListEmpty.vue | 26 ++-- .../message/MessageNewConversation.vue | 5 +- 4 files changed, 61 insertions(+), 98 deletions(-) diff --git a/src/api/ai/chat/conversation/index.ts b/src/api/ai/chat/conversation/index.ts index acc21fc6..6ce4482f 100644 --- a/src/api/ai/chat/conversation/index.ts +++ b/src/api/ai/chat/conversation/index.ts @@ -12,6 +12,7 @@ export interface ChatConversationVO { temperature: number // 温度参数 maxTokens: number // 单条回复的最大 Token 数量 maxContexts: number // 上下文的最大 Message 数量 + createTime?: Date // 创建时间 // 额外字段 systemMessage?: string // 角色设定 modelName?: string // 模型名字 diff --git a/src/views/ai/chat/index/components/message/MessageList.vue b/src/views/ai/chat/index/components/message/MessageList.vue index fa6e8ab1..b48fc295 100644 --- a/src/views/ai/chat/index/components/message/MessageList.vue +++ b/src/views/ai/chat/index/components/message/MessageList.vue @@ -1,7 +1,7 @@ diff --git a/src/views/ai/chat/index/components/role/index.vue b/src/views/ai/chat/index/components/role/RoleRepository.vue similarity index 80% rename from src/views/ai/chat/index/components/role/index.vue rename to src/views/ai/chat/index/components/role/RoleRepository.vue index 8a9806cf..42f37494 100644 --- a/src/views/ai/chat/index/components/role/index.vue +++ b/src/views/ai/chat/index/components/role/RoleRepository.vue @@ -2,8 +2,8 @@ - -- Gitee From 2204876076ba3c98f5cd32130c6798619624c04d Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 9 Jul 2024 17:05:07 +0800 Subject: [PATCH 308/341] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91=E5=AF=B9=E8=AF=9D=E4=B8=AD=E4=B8=8D=E5=85=81=E8=AE=B8?= =?UTF-8?q?=E5=88=87=E6=8D=A2(=E8=87=AA=E5=8A=A8stop=20stream=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/chat/index/index.vue | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/views/ai/chat/index/index.vue b/src/views/ai/chat/index/index.vue index 6b79f138..37dadaec 100644 --- a/src/views/ai/chat/index/index.vue +++ b/src/views/ai/chat/index/index.vue @@ -180,11 +180,6 @@ const handleConversationClick = async (conversation: ChatConversationVO) => { // 更新选中的对话 id activeConversationId.value = conversation.id activeConversation.value = conversation - // 处理进行中的对话 - // TODO @fan:这里,和上面的 “对话进行中,不允许切换” 是不是重叠了? - if (conversationInProgress.value) { - await stopStream() - } // 刷新 message 列表 await getMessageList() // 滚动底部 -- Gitee From b4b901586959c36c2c1e413d07fda9d596f3c5e9 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 9 Jul 2024 17:14:38 +0800 Subject: [PATCH 309/341] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91=E5=AF=B9=E8=AF=9D=E4=B8=AD=E4=B8=8D=E8=83=BD=E6=B8=85?= =?UTF-8?q?=E6=A5=9A=20chat=20=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/chat/index/index.vue | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/views/ai/chat/index/index.vue b/src/views/ai/chat/index/index.vue index 37dadaec..c00617bc 100644 --- a/src/views/ai/chat/index/index.vue +++ b/src/views/ai/chat/index/index.vue @@ -198,7 +198,11 @@ const handlerConversationDelete = async (delConversation: ChatConversationVO) => } /** 清空选中的对话 */ const handleConversationClear = async () => { - // TODO @fan:需要加一个 对话进行中,不允许切换 + // 对话进行中,不允许切换 + if (conversationInProgress.value) { + message.alert('对话中,不允许切换!') + return false + } activeConversationId.value = null activeConversation.value = null activeMessageList.value = [] -- Gitee From cb68ef5fa7073d5fd510208130cacc1af4d2e97a Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 9 Jul 2024 17:17:45 +0800 Subject: [PATCH 310/341] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91ai-layout=20100%=E9=AB=98=E5=AE=BD=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=8C=E5=8F=AA=E8=83=BD=E9=80=9A=E8=BF=87=20position:=20abs?= =?UTF-8?q?olute=20=E6=9D=A5=E7=89=B9=E6=AE=8A=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/chat/index/index.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/src/views/ai/chat/index/index.vue b/src/views/ai/chat/index/index.vue index c00617bc..9d9e98e1 100644 --- a/src/views/ai/chat/index/index.vue +++ b/src/views/ai/chat/index/index.vue @@ -570,7 +570,6 @@ onMounted(async () => { diff --git a/src/views/mall/promotion/kefu/components/message/ProductItem.vue b/src/views/mall/promotion/kefu/components/message/ProductItem.vue index 6805f24f..482ba6f8 100644 --- a/src/views/mall/promotion/kefu/components/message/ProductItem.vue +++ b/src/views/mall/promotion/kefu/components/message/ProductItem.vue @@ -116,6 +116,7 @@ const imagePrediv = (imgUrl: string) => { .ss-order-card-warp { padding: 20px; + border-radius: 10px; background-color: #e2e2e2; .img-box { diff --git a/src/views/mall/promotion/kefu/components/message/ProductMessageItem.vue b/src/views/mall/promotion/kefu/components/message/ProductMessageItem.vue index 923d366b..daf1b0bc 100644 --- a/src/views/mall/promotion/kefu/components/message/ProductMessageItem.vue +++ b/src/views/mall/promotion/kefu/components/message/ProductMessageItem.vue @@ -28,7 +28,7 @@ import ProductItem from './ProductItem.vue' import { UserTypeEnum } from '@/utils/constants' import { KeFuMessageRespVO } from '@/api/mall/promotion/kefu/message' -defineOptions({ name: 'ImageMessageItem' }) +defineOptions({ name: 'ProductMessageItem' }) const props = defineProps<{ message: KeFuMessageRespVO }>() -- Gitee From 326fc3d03f3a6e55416f03bc774c0647d984a35f Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 9 Jul 2024 17:41:58 +0800 Subject: [PATCH 312/341] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91el-button=20icon=20=E6=94=B9=E4=B8=BA=20Icon=20?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=20iconfy=20=E8=B5=84=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/ai/clear.svg | 1 - src/views/ai/chat/index/index.vue | 11 +++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) delete mode 100644 src/assets/ai/clear.svg diff --git a/src/assets/ai/clear.svg b/src/assets/ai/clear.svg deleted file mode 100644 index e75a4e8a..00000000 --- a/src/assets/ai/clear.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/views/ai/chat/index/index.vue b/src/views/ai/chat/index/index.vue index 9d9e98e1..724c67ce 100644 --- a/src/views/ai/chat/index/index.vue +++ b/src/views/ai/chat/index/index.vue @@ -22,11 +22,14 @@ - + + + + + + + - - -
-- Gitee From 5734faa5fcddafe28406983b049e904751b83f90 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 9 Jul 2024 17:42:30 +0800 Subject: [PATCH 313/341] =?UTF-8?q?=E3=80=90todo=E3=80=91keydown.shift.ent?= =?UTF-8?q?er=20=E4=BF=AE=E6=94=B9=E4=B8=BA@=E8=8A=8B=E8=89=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/chat/index/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/ai/chat/index/index.vue b/src/views/ai/chat/index/index.vue index 724c67ce..229b8959 100644 --- a/src/views/ai/chat/index/index.vue +++ b/src/views/ai/chat/index/index.vue @@ -365,7 +365,7 @@ const handlePromptInput = (event) => { isComposing.value = false }, 400) } -// TODO @fan:是不是可以通过 @keydown.enter、@keydown.shift.enter 来实现,回车发送、shift+回车换行;主要看看,是不是可以简化 isComposing 相关的逻辑 +// TODO @芋艿:是不是可以通过 @keydown.enter、@keydown.shift.enter 来实现,回车发送、shift+回车换行;主要看看,是不是可以简化 isComposing 相关的逻辑 const onCompositionstart = () => { isComposing.value = true } -- Gitee From 4cfc78566742c2892d56347919af00a6e4235871 Mon Sep 17 00:00:00 2001 From: cherishsince Date: Tue, 9 Jul 2024 17:51:08 +0800 Subject: [PATCH 314/341] =?UTF-8?q?=E3=80=90=E8=A7=A3=E5=86=B3todo?= =?UTF-8?q?=E3=80=91=E8=A7=92=E8=89=B2=E5=88=97=E8=A1=A8=20icon=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=BA=E4=B8=BA=20Icon=20=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/chat/index/components/role/RoleList.vue | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/views/ai/chat/index/components/role/RoleList.vue b/src/views/ai/chat/index/components/role/RoleList.vue index 01b1d179..b148b220 100644 --- a/src/views/ai/chat/index/components/role/RoleList.vue +++ b/src/views/ai/chat/index/components/role/RoleList.vue @@ -10,15 +10,13 @@ - @@ -43,9 +41,9 @@ - -- Gitee From 5730707be9681920a67f06f8ee094751c388b78b Mon Sep 17 00:00:00 2001 From: hhhero Date: Tue, 9 Jul 2024 00:44:27 +0800 Subject: [PATCH 323/341] =?UTF-8?q?[=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96]A?= =?UTF-8?q?I:=20=E5=86=99=E4=BD=9C=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=8F=AF=E8=AF=BB=E6=80=A7=EF=BC=8C?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=BB=A3=E7=A0=81=EF=BC=8C=E6=96=B9=E4=BE=BF?= =?UTF-8?q?=E5=90=8E=E7=BB=AD=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/ai/writer/index.ts | 41 +++-------- src/views/ai/utils/constants.ts | 8 +++ src/views/ai/utils/utils.ts | 13 ++++ src/views/ai/writer/components/Left.vue | 92 +++++++++++------------- src/views/ai/writer/components/Right.vue | 29 ++++---- src/views/ai/writer/data.json | 11 --- src/views/ai/writer/index.vue | 67 ----------------- src/views/ai/writer/index/index.vue | 67 +++++++++++++++++ 8 files changed, 154 insertions(+), 174 deletions(-) delete mode 100644 src/views/ai/writer/data.json delete mode 100644 src/views/ai/writer/index.vue create mode 100644 src/views/ai/writer/index/index.vue diff --git a/src/api/ai/writer/index.ts b/src/api/ai/writer/index.ts index 57c23b4f..9402d9a2 100644 --- a/src/api/ai/writer/index.ts +++ b/src/api/ai/writer/index.ts @@ -3,37 +3,14 @@ import { fetchEventSource } from '@microsoft/fetch-event-source' import { getAccessToken } from '@/utils/auth' import { config } from '@/config/axios/config' -// TODO @hhhero:可以改成 WriteVO 哈,主要是保持一致 -export interface WriteParams { - // TODO @hhhero:注释。每个属性的后面哈。会更简洁一点 - /** - * 1:撰写 2:回复 - */ - type: 1 | 2 - /** - * 写作内容提示 1。撰写 2回复 - */ - prompt: string - /** - * 原文 - */ - originalContent: string - /** - * 长度 - */ - length: number - /** - * 格式 - */ - format: number - /** - * 语气 - */ - tone: number - /** - * 语言 - */ - language: number +export interface WriteVO { + type: 1 | 2 // 1:撰写 2:回复 + prompt: string // 写作内容提示 1。撰写 2回复 + originalContent: string // 原文 + length: number // 长度 + format: number // 格式 + tone: number // 语气 + language: number // 语言 } export const writeStream = ({ @@ -43,7 +20,7 @@ export const writeStream = ({ onError, ctrl }: { - data: WriteParams + data: WriteVO onMessage?: (res: any) => void onError?: (...args: any[]) => void onClose?: (...args: any[]) => void diff --git a/src/views/ai/utils/constants.ts b/src/views/ai/utils/constants.ts index 337cfda3..442f83b5 100644 --- a/src/views/ai/utils/constants.ts +++ b/src/views/ai/utils/constants.ts @@ -40,3 +40,11 @@ export const AiMusicStatusEnum = { SUCCESS: 20, // 已完成 FAIL: 30 // 已失败 } + +/** + * AI 写作类型的枚举 + */ +export enum AiWriteTypeEnum { + WRITING = 1, // 撰写 + REPLY // 回复 +} diff --git a/src/views/ai/utils/utils.ts b/src/views/ai/utils/utils.ts index fc4f8e6c..d79e7609 100644 --- a/src/views/ai/utils/utils.ts +++ b/src/views/ai/utils/utils.ts @@ -11,3 +11,16 @@ export const hasChinese = async (str) => { return /[\u4e00-\u9fa5]/.test(str) } + +/** 写作点击示例时的数据 **/ +export const WriteExampleDataJson = { + write: { + prompt: 'vue', + data: 'Vue.js 是一种用于构建用户界面的渐进式 JavaScript 框架。它的核心库只关注视图层,易于上手,同时也便于与其他库或已有项目整合。\n\nVue.js 的特点包括:\n- 响应式的数据绑定:Vue.js 会自动将数据与 DOM 同步,使得状态管理变得更加简单。\n- 组件化:Vue.js 允许开发者通过小型、独立和通常可复用的组件构建大型应用。\n- 虚拟 DOM:Vue.js 使用虚拟 DOM 实现快速渲染,提高了性能。\n\n在 Vue.js 中,一个典型的应用结构可能包括:\n1. 根实例:每个 Vue 应用都需要一个根实例作为入口点。\n2. 组件系统:可以创建自定义的可复用组件。\n3. 指令:特殊的带有前缀 v- 的属性,为 DOM 元素提供特殊的行为。\n4. 插值:用于文本内容,将数据动态地插入到 HTML。\n5. 计算属性和侦听器:用于处理数据的复杂逻辑和响应数据变化。\n6. 条件渲染:根据条件决定元素的渲染。\n7. 列表渲染:用于显示列表数据。\n8. 事件处理:响应用户交互。\n9. 表单输入绑定:处理表单输入和验证。\n10. 组件生命周期钩子:在组件的不同阶段执行特定的函数。\n\nVue.js 还提供了官方的路由器 Vue Router 和状态管理库 Vuex,以支持构建复杂的单页应用(SPA)。\n\n在开发过程中,开发者通常会使用 Vue CLI,这是一个强大的命令行工具,用于快速生成 Vue 项目脚手架,集成了诸如 Babel、Webpack 等现代前端工具,以及热重载、代码检测等开发体验优化功能。\n\nVue.js 的生态系统还包括大量的第三方库和插件,如 Vuetify(UI 组件库)、Vue Test Utils(测试工具)等,这些都极大地丰富了 Vue.js 的开发生态。\n\n总的来说,Vue.js 是一个灵活、高效的前端框架,适合从小型项目到大型企业级应用的开发。它的易用性、灵活性和强大的社区支持使其成为许多开发者的首选框架之一。' + }, + reply: { + originalContent: '领导,我想请假', + prompt: '不批', + data: '您的请假申请已收悉,经核实和考虑,暂时无法批准您的请假申请。\n\n如有特殊情况或紧急事务,请及时与我联系。\n\n祝工作顺利。\n\n谢谢。' + } +} diff --git a/src/views/ai/writer/components/Left.vue b/src/views/ai/writer/components/Left.vue index 0369d9df..e7851649 100644 --- a/src/views/ai/writer/components/Left.vue +++ b/src/views/ai/writer/components/Left.vue @@ -24,7 +24,7 @@ - +
@@ -65,7 +65,7 @@ type="textarea" :rows="5" :maxlength="500" - v-model="writeForm.originalContent" + v-model="formData.originalContent" placeholder="请输入原文" showWordLimit /> @@ -75,20 +75,20 @@ type="textarea" :rows="5" :maxlength="500" - v-model="writeForm.prompt" + v-model="formData.prompt" placeholder="请输入回复内容" showWordLimit /> - + - + - + - +
重置 @@ -103,12 +103,13 @@ import { createReusableTemplate } from '@vueuse/core' import { ref } from 'vue' import Tag from './Tag.vue' -import { WriteParams } from '@/api/ai/writer' +import { WriteVO } from '@/api/ai/writer' import { omit } from 'lodash-es' import { getIntDictOptions } from '@/utils/dict' -import dataJson from '../data.json' +import { WriteExampleDataJson } from '@/views/ai/utils/utils' +import { AiWriteTypeEnum } from "@/views/ai/utils/constants"; -type TabType = WriteParams['type'] +type TabType = WriteVO['type'] const message = useMessage() @@ -117,25 +118,25 @@ defineProps<{ }>() const emits = defineEmits<{ - (e: 'submit', params: Partial) + (e: 'submit', params: Partial) (e: 'example', param: 'write' | 'reply') }>() const example = (type: 'write' | 'reply') => { - writeForm.value = { + formData.value = { ...initData, - ...omit(dataJson[type], ['data']) + ...omit(WriteExampleDataJson[type], ['data']) } emits('example', type) } -const selectedTab = ref(1) +const selectedTab = ref(AiWriteTypeEnum.WRITING) const tabs: { text: string value: TabType }[] = [ - { text: '撰写', value: 1 }, // TODO @hhhero:1、2 这个枚举到 constants 里。方便后续万一要调整 - { text: '回复', value: 2 } + { text: '撰写', value: AiWriteTypeEnum.WRITING }, + { text: '回复', value: AiWriteTypeEnum.REPLY } ] const [DefineTab, ReuseTab] = createReusableTemplate<{ active?: boolean @@ -143,7 +144,21 @@ const [DefineTab, ReuseTab] = createReusableTemplate<{ itemClick: () => void }>() -const initData: WriteParams = { +/** + * 可以在template里边定义可复用的组件,DefineLabel,ReuseLabel是采用的解构赋值,都是Vue组件 + * 直接通过组件的形式使用,中间是需要复用的组件代码,通过来使用定义的组件 + * DefineLabel里边的v-slot="{ label, hint, hintClick }“相当于是解构了组件的prop,需要注意的是boolean类型,需要显式的赋值比如 + * 事件也得以prop形式传入,不能是@event的形式,比如下面的hintClick需要 + * @see https://vueuse.org/createReusableTemplate + */ +const [DefineLabel, ReuseLabel] = createReusableTemplate<{ + label: string + class?: string + hint?: string + hintClick?: () => void +}>() + +const initData: WriteVO = { type: 1, prompt: '', originalContent: '', @@ -152,49 +167,26 @@ const initData: WriteParams = { length: 1, format: 1 } -// TODO @hhhero:这个字段,要不叫 formData,和其他模块保持一致。然后 initData 和它也更好对应上 -const writeForm = ref({ ...initData }) - -// TODO @hhhero:这种一次性的变量,要不直接 vue template 直接调用。目的是:让 ts 这块,更专注逻辑哈。 -const writeTags = { - // 长度 TODO @hhhero:注释放在和面哈; - // TODO @hhhero:一般 length 不用缩写哈。更完整会更容易阅读; - lenTags: getIntDictOptions('ai_write_length'), - // 格式 - - formatTags: getIntDictOptions('ai_write_format'), - // 语气 - - toneTags: getIntDictOptions('ai_write_tone'), - // 语言 - langTags: getIntDictOptions('ai_write_language') - // -} - -// TODO @hhhero:这个写法不错。要不写个简单的注释,我怕很多人不懂哈。 -const [DefineLabel, ReuseLabel] = createReusableTemplate<{ - label: string - class?: string - hint?: string - hintClick?: () => void -}>() - +const formData = ref({ ...initData }) +/** 切换tab **/ const switchTab = (value: TabType) => { selectedTab.value = value - writeForm.value = { ...initData } + formData.value = { ...initData } } const submit = () => { - if (selectedTab.value === 2 && !writeForm.value.originalContent) { + if (selectedTab.value === 2 && !formData.value.originalContent) { message.warning('请输入原文') return } - if (!writeForm.value.prompt) { + if (!formData.value.prompt) { message.warning(`请输入${selectedTab.value === 1 ? '写作' : '回复'}内容`) return } emits('submit', { - ...(selectedTab.value === 1 ? omit(writeForm.value, ['originalContent']) : writeForm.value), + /** 撰写的时候没有 originalContent 字段**/ + ...(selectedTab.value === 1 ? omit(formData.value, ['originalContent']) : formData.value), + /** 使用选中tab值覆盖当前的type类型 **/ type: selectedTab.value }) } diff --git a/src/views/ai/writer/components/Right.vue b/src/views/ai/writer/components/Right.vue index 94140011..4b27ef8c 100644 --- a/src/views/ai/writer/components/Right.vue +++ b/src/views/ai/writer/components/Right.vue @@ -5,9 +5,8 @@ 复制 @@ -23,7 +22,7 @@ props.msg && !props.isWriting) // 是否展示拷贝 -const inputId = computed(() => getCurrentInstance()?.uid) // TODO @hhhero:这个可以写个注释哈 -const copyMsg = () => { - copy(props.msg) +const showCopy = computed(() => props.content && !props.isWriting) // 是否展示复制按钮,在生成内容完成的时候展示 +const copyContent = () => { + copy(props.content) } +// 复制成功的时候copied.value为true watch(copied, (val) => { if (val) { message.success('复制成功') diff --git a/src/views/ai/writer/data.json b/src/views/ai/writer/data.json deleted file mode 100644 index 3f20951b..00000000 --- a/src/views/ai/writer/data.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "write": { - "prompt": "vue", - "data": "Vue.js 是一种用于构建用户界面的渐进式 JavaScript 框架。它的核心库只关注视图层,易于上手,同时也便于与其他库或已有项目整合。\n\nVue.js 的特点包括:\n- 响应式的数据绑定:Vue.js 会自动将数据与 DOM 同步,使得状态管理变得更加简单。\n- 组件化:Vue.js 允许开发者通过小型、独立和通常可复用的组件构建大型应用。\n- 虚拟 DOM:Vue.js 使用虚拟 DOM 实现快速渲染,提高了性能。\n\n在 Vue.js 中,一个典型的应用结构可能包括:\n1. 根实例:每个 Vue 应用都需要一个根实例作为入口点。\n2. 组件系统:可以创建自定义的可复用组件。\n3. 指令:特殊的带有前缀 v- 的属性,为 DOM 元素提供特殊的行为。\n4. 插值:用于文本内容,将数据动态地插入到 HTML。\n5. 计算属性和侦听器:用于处理数据的复杂逻辑和响应数据变化。\n6. 条件渲染:根据条件决定元素的渲染。\n7. 列表渲染:用于显示列表数据。\n8. 事件处理:响应用户交互。\n9. 表单输入绑定:处理表单输入和验证。\n10. 组件生命周期钩子:在组件的不同阶段执行特定的函数。\n\nVue.js 还提供了官方的路由器 Vue Router 和状态管理库 Vuex,以支持构建复杂的单页应用(SPA)。\n\n在开发过程中,开发者通常会使用 Vue CLI,这是一个强大的命令行工具,用于快速生成 Vue 项目脚手架,集成了诸如 Babel、Webpack 等现代前端工具,以及热重载、代码检测等开发体验优化功能。\n\nVue.js 的生态系统还包括大量的第三方库和插件,如 Vuetify(UI 组件库)、Vue Test Utils(测试工具)等,这些都极大地丰富了 Vue.js 的开发生态。\n\n总的来说,Vue.js 是一个灵活、高效的前端框架,适合从小型项目到大型企业级应用的开发。它的易用性、灵活性和强大的社区支持使其成为许多开发者的首选框架之一。" - }, - "reply": { - "originalContent": "领导,我想请假", - "prompt": "不批", - "data": "您的请假申请已收悉,经核实和考虑,暂时无法批准您的请假申请。\n\n如有特殊情况或紧急事务,请及时与我联系。\n\n祝工作顺利。\n\n谢谢。" - } -} diff --git a/src/views/ai/writer/index.vue b/src/views/ai/writer/index.vue deleted file mode 100644 index 27276431..00000000 --- a/src/views/ai/writer/index.vue +++ /dev/null @@ -1,67 +0,0 @@ - - - - diff --git a/src/views/ai/writer/index/index.vue b/src/views/ai/writer/index/index.vue new file mode 100644 index 00000000..655e806a --- /dev/null +++ b/src/views/ai/writer/index/index.vue @@ -0,0 +1,67 @@ + + + -- Gitee From 9e628ba59d186f24d6feab5f19f50c3ef935a041 Mon Sep 17 00:00:00 2001 From: hhhero Date: Wed, 10 Jul 2024 00:11:00 +0800 Subject: [PATCH 324/341] =?UTF-8?q?[=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96]A?= =?UTF-8?q?I:=20=E5=86=99=E4=BD=9C=E6=B7=BB=E5=8A=A0=E9=A2=84=E8=A7=88head?= =?UTF-8?q?er=EF=BC=8C=E8=B0=83=E6=95=B4=E7=94=9F=E6=88=90=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E5=8C=BA=E5=9F=9F=E5=B8=83=E5=B1=80=EF=BC=8C=E5=B0=86?= =?UTF-8?q?=E5=8F=B3=E8=BE=B9=E9=93=BA=E6=BB=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/ai/writer/components/Left.vue | 10 ++- src/views/ai/writer/components/Right.vue | 49 ++++++++--- src/views/ai/writer/index/index.vue | 101 ++++++++++++----------- 3 files changed, 100 insertions(+), 60 deletions(-) diff --git a/src/views/ai/writer/components/Left.vue b/src/views/ai/writer/components/Left.vue index e7851649..b09982b0 100644 --- a/src/views/ai/writer/components/Left.vue +++ b/src/views/ai/writer/components/Left.vue @@ -91,7 +91,7 @@
- 重置 + 重置 生成
@@ -120,8 +120,10 @@ defineProps<{ const emits = defineEmits<{ (e: 'submit', params: Partial) (e: 'example', param: 'write' | 'reply') + (e: 'reset') }>() +/** 点击示例的时候,将定义好的文章作为示例展示出来 **/ const example = (type: 'write' | 'reply') => { formData.value = { ...initData, @@ -129,7 +131,11 @@ const example = (type: 'write' | 'reply') => { } emits('example', type) } - +/** 重置,将表单值作为初选值 **/ +const reset = () => { + formData.value = {...initData} + emits('reset') +} const selectedTab = ref(AiWriteTypeEnum.WRITING) const tabs: { text: string diff --git a/src/views/ai/writer/components/Right.vue b/src/views/ai/writer/components/Right.vue index 4b27ef8c..393a055b 100644 --- a/src/views/ai/writer/components/Right.vue +++ b/src/views/ai/writer/components/Right.vue @@ -1,24 +1,37 @@