feat: style
parent
7276d0a909
commit
a4f4c0d6f6
|
@ -29,14 +29,14 @@ withDefaults(
|
|||
<Card :body-style="bodyStyle" :title="title" class="mb-4">
|
||||
<template v-if="title" #title>
|
||||
<div class="flex items-center">
|
||||
<span class="text-4 font-[700]">{{ title }}</span>
|
||||
<span class="text-base font-bold">{{ title }}</span>
|
||||
<Tooltip placement="right">
|
||||
<template #title>
|
||||
<div class="max-w-[200px]">{{ message }}</div>
|
||||
</template>
|
||||
<ShieldQuestion :size="14" class="ml-5px" />
|
||||
<ShieldQuestion :size="14" class="ml-1" />
|
||||
</Tooltip>
|
||||
<div class="pl-20px flex flex-grow">
|
||||
<div class="flex flex-grow pl-5">
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -6,6 +6,7 @@ import type { CropperAvatarProps } from './typing';
|
|||
import { computed, ref, unref, watch, watchEffect } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { $t } from '@vben/locales';
|
||||
|
||||
import { Button, message } from 'ant-design-vue';
|
||||
|
@ -80,15 +81,16 @@ defineExpose({
|
|||
@click="openModal"
|
||||
>
|
||||
<div :class="`${prefixCls}-image-mask`" :style="getImageWrapperStyle">
|
||||
<span
|
||||
<IconifyIcon
|
||||
icon="lucide:cloud-upload"
|
||||
class="text-gray-400"
|
||||
:style="{
|
||||
...getImageWrapperStyle,
|
||||
width: `${getIconWidth}`,
|
||||
height: `${getIconWidth}`,
|
||||
lineHeight: `${getIconWidth}`,
|
||||
}"
|
||||
class="icon-[ant-design--cloud-upload-outlined] text-[#d6d6d6]"
|
||||
></span>
|
||||
/>
|
||||
</div>
|
||||
<img v-if="sourceValue" :src="sourceValue" alt="avatar" />
|
||||
</div>
|
||||
|
|
|
@ -4,6 +4,7 @@ import type { CropendResult, CropperModalProps, CropperType } from './typing';
|
|||
import { ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { $t } from '@vben/locales';
|
||||
import { dataURLtoBlob, isFunction } from '@vben/utils';
|
||||
|
||||
|
@ -118,7 +119,7 @@ async function handleOk() {
|
|||
:confirm-text="$t('ui.cropper.okText')"
|
||||
:fullscreen-button="false"
|
||||
:title="$t('ui.cropper.modalTitle')"
|
||||
class="w-[800px]"
|
||||
class="w-2/3"
|
||||
>
|
||||
<div :class="prefixCls">
|
||||
<div :class="`${prefixCls}-left`" class="w-full">
|
||||
|
@ -143,7 +144,7 @@ async function handleOk() {
|
|||
<Button size="small" type="primary">
|
||||
<template #icon>
|
||||
<div class="flex items-center justify-center">
|
||||
<span class="icon-[ant-design--upload-outlined]"></span>
|
||||
<IconifyIcon icon="lucide:upload" />
|
||||
</div>
|
||||
</template>
|
||||
</Button>
|
||||
|
@ -159,7 +160,7 @@ async function handleOk() {
|
|||
>
|
||||
<template #icon>
|
||||
<div class="flex items-center justify-center">
|
||||
<span class="icon-[ant-design--reload-outlined]"></span>
|
||||
<IconifyIcon icon="lucide:rotate-ccw" />
|
||||
</div>
|
||||
</template>
|
||||
</Button>
|
||||
|
@ -176,9 +177,7 @@ async function handleOk() {
|
|||
>
|
||||
<template #icon>
|
||||
<div class="flex items-center justify-center">
|
||||
<span
|
||||
class="icon-[ant-design--rotate-left-outlined]"
|
||||
></span>
|
||||
<IconifyIcon icon="ant-design:rotate-left-outlined" />
|
||||
</div>
|
||||
</template>
|
||||
</Button>
|
||||
|
@ -189,16 +188,13 @@ async function handleOk() {
|
|||
>
|
||||
<Button
|
||||
:disabled="!src"
|
||||
pre-icon="ant-design:rotate-right-outlined"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handlerToolbar('rotate', 45)"
|
||||
>
|
||||
<template #icon>
|
||||
<div class="flex items-center justify-center">
|
||||
<span
|
||||
class="icon-[ant-design--rotate-right-outlined]"
|
||||
></span>
|
||||
<IconifyIcon icon="ant-design:rotate-right-outlined" />
|
||||
</div>
|
||||
</template>
|
||||
</Button>
|
||||
|
@ -212,7 +208,7 @@ async function handleOk() {
|
|||
>
|
||||
<template #icon>
|
||||
<div class="flex items-center justify-center">
|
||||
<span class="icon-[vaadin--arrows-long-h]"></span>
|
||||
<IconifyIcon icon="vaadin--arrows-long-h" />
|
||||
</div>
|
||||
</template>
|
||||
</Button>
|
||||
|
@ -226,7 +222,7 @@ async function handleOk() {
|
|||
>
|
||||
<template #icon>
|
||||
<div class="flex items-center justify-center">
|
||||
<span class="icon-[vaadin--arrows-long-v]"></span>
|
||||
<IconifyIcon icon="vaadin:arrows-long-v" />
|
||||
</div>
|
||||
</template>
|
||||
</Button>
|
||||
|
@ -240,7 +236,7 @@ async function handleOk() {
|
|||
>
|
||||
<template #icon>
|
||||
<div class="flex items-center justify-center">
|
||||
<span class="icon-[ant-design--zoom-in-outlined]"></span>
|
||||
<IconifyIcon icon="lucide:zoom-in" />
|
||||
</div>
|
||||
</template>
|
||||
</Button>
|
||||
|
@ -254,7 +250,7 @@ async function handleOk() {
|
|||
>
|
||||
<template #icon>
|
||||
<div class="flex items-center justify-center">
|
||||
<span class="icon-[ant-design--zoom-out-outlined]"></span>
|
||||
<IconifyIcon icon="lucide:zoom-out" />
|
||||
</div>
|
||||
</template>
|
||||
</Button>
|
||||
|
|
|
@ -45,7 +45,7 @@ const getDictOptions = computed(() => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Select v-if="selectType === 'select'" class="w-1/1" v-bind="attrs">
|
||||
<Select v-if="selectType === 'select'" class="w-full" v-bind="attrs">
|
||||
<SelectOption
|
||||
v-for="(dict, index) in getDictOptions"
|
||||
:key="index"
|
||||
|
@ -54,7 +54,7 @@ const getDictOptions = computed(() => {
|
|||
{{ dict.label }}
|
||||
</SelectOption>
|
||||
</Select>
|
||||
<RadioGroup v-if="selectType === 'radio'" class="w-1/1" v-bind="attrs">
|
||||
<RadioGroup v-if="selectType === 'radio'" class="w-full" v-bind="attrs">
|
||||
<Radio
|
||||
v-for="(dict, index) in getDictOptions"
|
||||
:key="index"
|
||||
|
@ -63,7 +63,7 @@ const getDictOptions = computed(() => {
|
|||
{{ dict.label }}
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
<CheckboxGroup v-if="selectType === 'checkbox'" class="w-1/1" v-bind="attrs">
|
||||
<CheckboxGroup v-if="selectType === 'checkbox'" class="w-full" v-bind="attrs">
|
||||
<Checkbox
|
||||
v-for="(dict, index) in getDictOptions"
|
||||
:key="index"
|
||||
|
|
|
@ -190,7 +190,7 @@ export const useApiSelect = (option: ApiSelectProps) => {
|
|||
// fix:多写此步是为了解决 multiple 属性问题
|
||||
return (
|
||||
<Select
|
||||
class="w-1/1"
|
||||
class="w-full"
|
||||
loading={loading.value}
|
||||
mode="multiple"
|
||||
{...attrs}
|
||||
|
@ -210,7 +210,7 @@ export const useApiSelect = (option: ApiSelectProps) => {
|
|||
}
|
||||
return (
|
||||
<Select
|
||||
class="w-1/1"
|
||||
class="w-full"
|
||||
loading={loading.value}
|
||||
{...attrs}
|
||||
// TODO: @dhb52 remote 对等实现, 还是说没作用
|
||||
|
@ -235,7 +235,7 @@ export const useApiSelect = (option: ApiSelectProps) => {
|
|||
];
|
||||
}
|
||||
return (
|
||||
<CheckboxGroup class="w-1/1" {...attrs}>
|
||||
<CheckboxGroup class="w-full" {...attrs}>
|
||||
{options.value.map(
|
||||
(item: { label: any; value: any }, index: any) => (
|
||||
<Checkbox key={index} value={item.value}>
|
||||
|
@ -254,7 +254,7 @@ export const useApiSelect = (option: ApiSelectProps) => {
|
|||
];
|
||||
}
|
||||
return (
|
||||
<RadioGroup class="w-1/1" {...attrs}>
|
||||
<RadioGroup class="w-full" {...attrs}>
|
||||
{options.value.map(
|
||||
(item: { label: any; value: any }, index: any) => (
|
||||
<Radio key={index} value={item.value}>
|
||||
|
|
|
@ -43,7 +43,7 @@ function getUserTypeColor(userType: number) {
|
|||
<template #dot>
|
||||
<p
|
||||
:style="{ backgroundColor: getUserTypeColor(log.userType) }"
|
||||
class="absolute left-[-5px] flex h-5 w-5 items-center justify-center rounded-full text-xs text-white"
|
||||
class="absolute left--1 flex h-5 w-5 items-center justify-center rounded-full text-xs text-white"
|
||||
>
|
||||
{{ getDictLabel(DICT_TYPE.USER_TYPE, log.userType)[0] }}
|
||||
</p>
|
||||
|
|
|
@ -122,7 +122,7 @@ function handleCheck() {
|
|||
}
|
||||
</script>
|
||||
<template>
|
||||
<Modal :title="title" key="dept-select-modal" class="w-[40%]">
|
||||
<Modal :title="title" key="dept-select-modal" class="w-2/5">
|
||||
<Row class="h-full">
|
||||
<Col :span="24">
|
||||
<Card class="h-full">
|
||||
|
|
|
@ -408,7 +408,7 @@ function processDeptNode(node: any): DeptTreeNode {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal class="w-[40%]" key="user-select-modal" :title="title">
|
||||
<Modal class="w-2/5" key="user-select-modal" :title="title">
|
||||
<Row :gutter="[16, 16]">
|
||||
<Col :span="6">
|
||||
<div class="h-[500px] overflow-auto rounded border">
|
||||
|
|
|
@ -158,7 +158,7 @@ function changeNodeName() {
|
|||
defineExpose({ open }); // 提供 open 方法,用于打开弹窗
|
||||
</script>
|
||||
<template>
|
||||
<Drawer class="w-[580px]">
|
||||
<Drawer class="w-1/3">
|
||||
<template #title>
|
||||
<div class="flex items-center">
|
||||
<Input
|
||||
|
|
|
@ -207,14 +207,14 @@ onMounted(() => {
|
|||
defineExpose({ showCopyTaskNodeConfig }); // 暴露方法给父组件
|
||||
</script>
|
||||
<template>
|
||||
<Drawer class="w-[580px]">
|
||||
<Drawer class="w-1/3">
|
||||
<template #title>
|
||||
<div class="config-header">
|
||||
<Input
|
||||
v-if="showInput"
|
||||
ref="inputRef"
|
||||
type="text"
|
||||
class="config-editable-input"
|
||||
class="focus:border-blue-500 focus:shadow-[0_0_0_2px_rgba(24,144,255,0.2)] focus:outline-none"
|
||||
@blur="changeNodeName()"
|
||||
@press-enter="changeNodeName()"
|
||||
v-model:value="nodeName"
|
||||
|
@ -446,7 +446,7 @@ defineExpose({ showCopyTaskNodeConfig }); // 暴露方法给父组件
|
|||
v-if="formType === BpmModelFormType.NORMAL"
|
||||
>
|
||||
<div class="p-1">
|
||||
<div class="mb-4 text-[16px] font-bold">字段权限</div>
|
||||
<div class="mb-4 text-base font-bold">字段权限</div>
|
||||
|
||||
<!-- 表头 -->
|
||||
<Row class="border border-gray-200 px-4 py-3">
|
||||
|
@ -522,12 +522,3 @@ defineExpose({ showCopyTaskNodeConfig }); // 暴露方法给父组件
|
|||
</Tabs>
|
||||
</Drawer>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.config-editable-input {
|
||||
&:focus {
|
||||
outline: 0;
|
||||
border-color: #40a9ff;
|
||||
box-shadow: 0 0 0 2px rgb(24 144 255 / 20%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -152,7 +152,7 @@ function openDrawer(node: SimpleFlowNode) {
|
|||
defineExpose({ openDrawer }); // 暴露方法给父组件
|
||||
</script>
|
||||
<template>
|
||||
<Drawer class="w-[480px]">
|
||||
<Drawer class="w-1/3">
|
||||
<template #title>
|
||||
<div class="flex items-center">
|
||||
<Input
|
||||
|
|
|
@ -178,7 +178,7 @@ defineExpose({ validate });
|
|||
{{ condition.conditionGroups.and ? '且' : '或' }}
|
||||
</template>
|
||||
<Card
|
||||
class="group relative w-full hover:border-[#1890ff]"
|
||||
class="group relative w-full hover:border-blue-500"
|
||||
v-for="(equation, cIdx) in condition.conditionGroups.conditions"
|
||||
:key="cIdx"
|
||||
>
|
||||
|
@ -187,7 +187,7 @@ defineExpose({ validate });
|
|||
v-if="condition.conditionGroups.conditions.length > 1"
|
||||
>
|
||||
<IconifyIcon
|
||||
color="#0089ff"
|
||||
color="blue"
|
||||
icon="lucide:circle-x"
|
||||
class="size-4"
|
||||
@click="
|
||||
|
@ -290,7 +290,7 @@ defineExpose({ validate });
|
|||
</FormItem>
|
||||
</Col>
|
||||
<Col :span="3">
|
||||
<div class="flex h-[32px] items-center">
|
||||
<div class="flex h-8 items-center">
|
||||
<Trash2
|
||||
v-if="equation.rules.length > 1"
|
||||
class="mr-2 size-4 cursor-pointer text-red-500"
|
||||
|
@ -307,7 +307,7 @@ defineExpose({ validate });
|
|||
</Space>
|
||||
<div title="添加条件组" class="mt-4 cursor-pointer">
|
||||
<Plus
|
||||
class="size-[24px] text-blue-500"
|
||||
class="size-6 text-blue-500"
|
||||
@click="addConditionGroup(condition.conditionGroups?.conditions)"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import type { HttpRequestParam } from '../../../consts';
|
||||
|
||||
import { Plus, Trash2 } from '@vben/icons';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import {
|
||||
Button,
|
||||
|
@ -121,9 +121,10 @@ function deleteHttpRequestParam(arr: HttpRequestParam[], index: number) {
|
|||
</FormItem>
|
||||
</Col>
|
||||
<Col :span="2">
|
||||
<div class="flex h-[32px] items-center">
|
||||
<Trash2
|
||||
<div class="flex h-8 items-center">
|
||||
<IconifyIcon
|
||||
class="size-4 cursor-pointer text-red-500"
|
||||
icon="lucide:trash-2"
|
||||
@click="deleteHttpRequestParam(props.header, index)"
|
||||
/>
|
||||
</div>
|
||||
|
@ -135,7 +136,7 @@ function deleteHttpRequestParam(arr: HttpRequestParam[], index: number) {
|
|||
class="flex items-center"
|
||||
>
|
||||
<template #icon>
|
||||
<Plus class="size-[18px]" />
|
||||
<IconifyIcon class="size-4" icon="lucide:plus" />
|
||||
</template>
|
||||
添加一行
|
||||
</Button>
|
||||
|
@ -205,9 +206,10 @@ function deleteHttpRequestParam(arr: HttpRequestParam[], index: number) {
|
|||
</FormItem>
|
||||
</Col>
|
||||
<Col :span="2">
|
||||
<div class="flex h-[32px] items-center">
|
||||
<Trash2
|
||||
<div class="flex h-8 items-center">
|
||||
<IconifyIcon
|
||||
class="size-4 cursor-pointer text-red-500"
|
||||
icon="lucide:trash-2"
|
||||
@click="deleteHttpRequestParam(props.body, index)"
|
||||
/>
|
||||
</div>
|
||||
|
@ -219,7 +221,7 @@ function deleteHttpRequestParam(arr: HttpRequestParam[], index: number) {
|
|||
class="flex items-center"
|
||||
>
|
||||
<template #icon>
|
||||
<Plus class="size-[18px]" />
|
||||
<IconifyIcon class="size-4" icon="lucide:plus" />
|
||||
</template>
|
||||
添加一行
|
||||
</Button>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { toRefs, watch } from 'vue';
|
||||
|
||||
import { Plus, Trash2 } from '@vben/icons';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import {
|
||||
Alert,
|
||||
|
@ -153,9 +153,10 @@ function deleteHttpResponseSetting(
|
|||
</FormItem>
|
||||
</Col>
|
||||
<Col :span="2">
|
||||
<div class="flex h-[32px] items-center">
|
||||
<Trash2
|
||||
<div class="flex h-8 items-center">
|
||||
<IconifyIcon
|
||||
class="size-4 cursor-pointer text-red-500"
|
||||
icon="lucide:trash-2"
|
||||
@click="deleteHttpResponseSetting(setting.response!, index)"
|
||||
/>
|
||||
</div>
|
||||
|
@ -167,7 +168,7 @@ function deleteHttpResponseSetting(
|
|||
class="flex items-center"
|
||||
>
|
||||
<template #icon>
|
||||
<Plus class="size-[18px]" />
|
||||
<IconifyIcon class="size-4" icon="lucide:plus" />
|
||||
</template>
|
||||
添加一行
|
||||
</Button>
|
||||
|
|
|
@ -200,7 +200,7 @@ function getRouterNode(node: any) {
|
|||
defineExpose({ openDrawer }); // 暴露方法给父组件
|
||||
</script>
|
||||
<template>
|
||||
<Drawer class="w-[40%]">
|
||||
<Drawer class="w-2/5">
|
||||
<template #title>
|
||||
<div class="flex items-center">
|
||||
<Input
|
||||
|
@ -236,7 +236,7 @@ defineExpose({ openDrawer }); // 暴露方法给父组件
|
|||
<div class="flex items-center font-normal">
|
||||
<span class="font-medium">路由{{ index + 1 }}</span>
|
||||
<FormItem
|
||||
class="mb-0 ml-4 inline-block w-[180px]"
|
||||
class="mb-0 ml-4 inline-block w-48"
|
||||
:name="['routerGroups', index, 'nodeId']"
|
||||
:rules="{
|
||||
required: true,
|
||||
|
|
|
@ -148,7 +148,7 @@ defineExpose({ showStartUserNodeConfig });
|
|||
ref="inputRef"
|
||||
v-if="showInput"
|
||||
type="text"
|
||||
class="config-editable-input"
|
||||
class="focus:border-blue-500 focus:shadow-[0_0_0_2px_rgba(24,144,255,0.2)] focus:outline-none"
|
||||
@blur="changeNodeName()"
|
||||
@press-enter="changeNodeName()"
|
||||
v-model:value="nodeName"
|
||||
|
@ -214,7 +214,7 @@ defineExpose({ showStartUserNodeConfig });
|
|||
v-if="formType === BpmModelFormType.NORMAL"
|
||||
>
|
||||
<div class="p-1">
|
||||
<div class="mb-4 text-[16px] font-bold">字段权限</div>
|
||||
<div class="mb-4 text-base font-bold">字段权限</div>
|
||||
|
||||
<!-- 表头 -->
|
||||
<Row class="border border-gray-200 px-4 py-3">
|
||||
|
|
|
@ -11,7 +11,7 @@ import type {
|
|||
import { computed, getCurrentInstance, onMounted, reactive, ref } from 'vue';
|
||||
|
||||
import { useVbenDrawer } from '@vben/common-ui';
|
||||
import { IconifyIcon, Trash2 } from '@vben/icons';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { cloneDeep } from '@vben/utils';
|
||||
|
||||
import {
|
||||
|
@ -384,14 +384,14 @@ onMounted(() => {
|
|||
});
|
||||
</script>
|
||||
<template>
|
||||
<Drawer class="w-[580px]">
|
||||
<Drawer class="w-1/3">
|
||||
<template #title>
|
||||
<div class="config-header">
|
||||
<Input
|
||||
ref="inputRef"
|
||||
v-if="showInput"
|
||||
type="text"
|
||||
class="config-editable-input"
|
||||
class="focus:border-blue-500 focus:shadow-[0_0_0_2px_rgba(24,144,255,0.2)] focus:outline-none"
|
||||
@blur="changeNodeName()"
|
||||
@press-enter="changeNodeName()"
|
||||
v-model:value="nodeName"
|
||||
|
@ -543,9 +543,10 @@ onMounted(() => {
|
|||
</FormItem>
|
||||
</Col>
|
||||
<Col :span="2">
|
||||
<div class="flex h-[32px] items-center">
|
||||
<Trash2
|
||||
<div class="flex h-8 items-center">
|
||||
<IconifyIcon
|
||||
class="size-4 cursor-pointer text-red-500"
|
||||
icon="lucide:trash-2"
|
||||
@click="deleteFormFieldSetting(formSetting, key)"
|
||||
/>
|
||||
</div>
|
||||
|
@ -684,12 +685,3 @@ onMounted(() => {
|
|||
</div>
|
||||
</Drawer>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.config-editable-input {
|
||||
&:focus {
|
||||
outline: 0;
|
||||
border-color: #40a9ff;
|
||||
box-shadow: 0 0 0 2px rgb(24 144 255 / 20%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -580,14 +580,14 @@ onMounted(() => {
|
|||
});
|
||||
</script>
|
||||
<template>
|
||||
<Drawer class="w-[580px]">
|
||||
<Drawer class="w-1/3">
|
||||
<template #title>
|
||||
<div class="config-header">
|
||||
<Input
|
||||
v-if="showInput"
|
||||
ref="inputRef"
|
||||
type="text"
|
||||
class="config-editable-input"
|
||||
class="focus:border-blue-500 focus:shadow-[0_0_0_2px_rgba(24,144,255,0.2)] focus:outline-none"
|
||||
@blur="changeNodeName()"
|
||||
@press-enter="changeNodeName()"
|
||||
v-model:value="nodeName"
|
||||
|
@ -603,7 +603,7 @@ onMounted(() => {
|
|||
v-if="currentNode.type === BpmNodeTypeEnum.USER_TASK_NODE"
|
||||
class="mb-3 flex items-center"
|
||||
>
|
||||
<span class="mr-3 text-[16px]">审批类型 :</span>
|
||||
<span class="mr-3 text-base">审批类型 :</span>
|
||||
<RadioGroup v-model:value="approveType">
|
||||
<RadioButton
|
||||
v-for="(item, index) in APPROVE_TYPE"
|
||||
|
@ -949,7 +949,7 @@ onMounted(() => {
|
|||
label="超时时间设置"
|
||||
v-if="configForm.timeoutHandlerEnable"
|
||||
label-align="left"
|
||||
class="h-[32px]"
|
||||
class="h-8"
|
||||
:label-col="{ span: 6 }"
|
||||
:wrapper-col="{ span: 18 }"
|
||||
>
|
||||
|
@ -1105,7 +1105,7 @@ onMounted(() => {
|
|||
key="buttons"
|
||||
>
|
||||
<div class="p-1">
|
||||
<div class="mb-4 text-[16px] font-bold">操作按钮</div>
|
||||
<div class="mb-4 text-base font-bold">操作按钮</div>
|
||||
|
||||
<!-- 表头 -->
|
||||
<Row class="border border-gray-200 px-4 py-3">
|
||||
|
@ -1127,7 +1127,7 @@ onMounted(() => {
|
|||
<Input
|
||||
v-if="btnDisplayNameEdit[index]"
|
||||
type="text"
|
||||
class="input-edit max-w-[130px]"
|
||||
class="max-w-32 focus:border-blue-500 focus:shadow-[0_0_0_2px_rgba(24,144,255,0.2)] focus:outline-none"
|
||||
@blur="btnDisplayNameBlurEvent(index)"
|
||||
v-model:value="item.displayName"
|
||||
:placeholder="item.displayName"
|
||||
|
@ -1152,7 +1152,7 @@ onMounted(() => {
|
|||
v-if="formType === BpmModelFormType.NORMAL"
|
||||
>
|
||||
<div class="p-1">
|
||||
<div class="mb-4 text-[16px] font-bold">字段权限</div>
|
||||
<div class="mb-4 text-base font-bold">字段权限</div>
|
||||
|
||||
<!-- 表头 -->
|
||||
<Row class="border border-gray-200 px-4 py-3">
|
||||
|
@ -1234,12 +1234,3 @@ onMounted(() => {
|
|||
</Tabs>
|
||||
</Drawer>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.input-edit {
|
||||
&:focus {
|
||||
outline: 0;
|
||||
border-color: #40a9ff;
|
||||
box-shadow: 0 0 0 2px rgb(24 144 255 / 20%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -235,7 +235,7 @@ defineExpose({ validate });
|
|||
:readonly="false"
|
||||
@save="saveSimpleFlowModel"
|
||||
/>
|
||||
<ErrorModal title="流程设计校验不通过" class="w-[40%]">
|
||||
<ErrorModal title="流程设计校验不通过" class="w-2/5">
|
||||
<div class="mb-2 text-base">以下节点配置不完善,请修改相关配置</div>
|
||||
<div
|
||||
class="mb-3 rounded-md bg-gray-100 p-2 text-sm"
|
||||
|
|
|
@ -201,7 +201,7 @@ onMounted(() => {
|
|||
</script>
|
||||
<template>
|
||||
<div class="simple-process-model-container">
|
||||
<div class="absolute right-[0px] top-[0px] bg-[#fff]">
|
||||
<div class="absolute right-0 top-0 bg-white">
|
||||
<Row type="flex" justify="end">
|
||||
<ButtonGroup key="scale-control">
|
||||
<Button v-if="!readonly" @click="exportJson">
|
||||
|
@ -216,7 +216,7 @@ onMounted(() => {
|
|||
type="file"
|
||||
id="files"
|
||||
ref="refFile"
|
||||
style="display: none"
|
||||
class="hidden"
|
||||
accept=".json"
|
||||
@change="importLocalFile"
|
||||
/>
|
||||
|
@ -226,7 +226,7 @@ onMounted(() => {
|
|||
<Button :plain="true" @click="zoomOut()">
|
||||
<IconifyIcon icon="lucide:zoom-out" />
|
||||
</Button>
|
||||
<Button class="w-80px"> {{ scaleValue }}% </Button>
|
||||
<Button class="w-20"> {{ scaleValue }}% </Button>
|
||||
<Button :plain="true" @click="zoomIn()">
|
||||
<IconifyIcon icon="lucide:zoom-in" />
|
||||
</Button>
|
||||
|
@ -258,7 +258,7 @@ onMounted(() => {
|
|||
>
|
||||
<div class="mb-2">以下节点内容不完善,请修改后保存</div>
|
||||
<div
|
||||
class="b-rounded-1 line-height-normal mb-3 bg-gray-100 p-2"
|
||||
class="line-height-normal mb-3 rounded bg-gray-100 p-2"
|
||||
v-for="(item, index) in errorNodes"
|
||||
:key="index"
|
||||
>
|
||||
|
|
|
@ -16,14 +16,14 @@ defineProps<SummaryCardProps>();
|
|||
class="flex flex-row items-center gap-3 rounded bg-[var(--el-bg-color-overlay)] p-4"
|
||||
>
|
||||
<div
|
||||
class="rounded-1 flex h-12 w-12 flex-shrink-0 items-center justify-center"
|
||||
class="flex h-12 w-12 flex-shrink-0 items-center justify-center rounded"
|
||||
:class="`${iconColor} ${iconBgColor}`"
|
||||
>
|
||||
<IconifyIcon v-if="icon" :icon="icon" class="!text-6" />
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="text-3.5">{{ title }}</span>
|
||||
<span class="text-base">{{ title }}</span>
|
||||
<Tooltip :content="tooltip" placement="topLeft" v-if="tooltip">
|
||||
<IconifyIcon
|
||||
icon="lucide:circle-alert"
|
||||
|
@ -32,7 +32,7 @@ defineProps<SummaryCardProps>();
|
|||
</Tooltip>
|
||||
</div>
|
||||
<div class="flex flex-row items-baseline gap-2">
|
||||
<div class="text-7">
|
||||
<div class="text-lg">
|
||||
<CountTo
|
||||
:prefix="prefix"
|
||||
:end-val="value ?? 0"
|
||||
|
@ -48,7 +48,7 @@ defineProps<SummaryCardProps>();
|
|||
:icon="
|
||||
Number(percent) > 0 ? 'lucide:chevron-up' : 'lucide:chevron-down'
|
||||
"
|
||||
class="!text-3 ml-0.5"
|
||||
class="ml-0.5 !text-sm"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,7 @@ export const ACTION_ICON = {
|
|||
UPLOAD: 'lucide:upload',
|
||||
ADD: 'lucide:plus',
|
||||
EDIT: 'lucide:edit',
|
||||
DELETE: 'lucide:trash',
|
||||
DELETE: 'lucide:trash-2',
|
||||
REFRESH: 'lucide:refresh-cw',
|
||||
SEARCH: 'lucide:search',
|
||||
FILTER: 'lucide:filter',
|
||||
|
|
|
@ -5,7 +5,7 @@ import type { VxeToolbarInstance } from '#/adapter/vxe-table';
|
|||
import { ref } from 'vue';
|
||||
|
||||
import { useContentMaximize, useRefresh } from '@vben/hooks';
|
||||
import { Expand, MsRefresh, Search, TMinimize } from '@vben/icons';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { Button, Tooltip } from 'ant-design-vue';
|
||||
|
||||
|
@ -41,37 +41,39 @@ defineExpose({
|
|||
<slot></slot>
|
||||
<Tooltip placement="bottom">
|
||||
<template #title>
|
||||
<div class="max-w-[200px]">搜索</div>
|
||||
<div class="max-w-52">搜索</div>
|
||||
</template>
|
||||
<Button
|
||||
class="ml-2 font-[8px]"
|
||||
class="ml-2 font-normal"
|
||||
shape="circle"
|
||||
@click="onHiddenSearchBar"
|
||||
>
|
||||
<Search :size="15" />
|
||||
<IconifyIcon icon="lucide:search" :size="15" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip placement="bottom">
|
||||
<template #title>
|
||||
<div class="max-w-[200px]">刷新</div>
|
||||
<div class="max-w-52">刷新</div>
|
||||
</template>
|
||||
<Button class="ml-2 font-[8px]" shape="circle" @click="refresh">
|
||||
<MsRefresh :size="15" />
|
||||
<Button class="ml-2 font-medium" shape="circle" @click="refresh">
|
||||
<IconifyIcon icon="lucide:refresh-cw" :size="15" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip placement="bottom">
|
||||
<template #title>
|
||||
<div class="max-w-[200px]">
|
||||
<div class="max-w-52">
|
||||
{{ contentIsMaximize ? '还原' : '全屏' }}
|
||||
</div>
|
||||
</template>
|
||||
<Button
|
||||
class="ml-2 font-[8px]"
|
||||
class="ml-2 font-medium"
|
||||
shape="circle"
|
||||
@click="toggleMaximizeAndTabbarHidden"
|
||||
>
|
||||
<Expand v-if="!contentIsMaximize" :size="15" />
|
||||
<TMinimize v-else :size="15" />
|
||||
<IconifyIcon
|
||||
:icon="contentIsMaximize ? 'lucide:minimize' : 'lucide:maximize'"
|
||||
:size="15"
|
||||
/>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</template>
|
||||
|
|
|
@ -8,7 +8,7 @@ import type { AxiosProgressEvent } from '#/api/infra/file';
|
|||
|
||||
import { ref, toRefs, watch } from 'vue';
|
||||
|
||||
import { CloudUpload } from '@vben/icons';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { $t } from '@vben/locales';
|
||||
import { isFunction, isObject, isString } from '@vben/utils';
|
||||
|
||||
|
@ -214,13 +214,13 @@ function getValue() {
|
|||
v-if="fileList && fileList.length < maxNumber"
|
||||
class="flex flex-col items-center justify-center"
|
||||
>
|
||||
<CloudUpload />
|
||||
<IconifyIcon icon="lucide:cloud-upload" />
|
||||
<div class="mt-2">{{ $t('ui.upload.imgUpload') }}</div>
|
||||
</div>
|
||||
</Upload>
|
||||
<div
|
||||
v-if="showDescription"
|
||||
class="mt-2 flex flex-wrap items-center text-[14px]"
|
||||
class="mt-2 flex flex-wrap items-center text-sm"
|
||||
>
|
||||
请上传不超过
|
||||
<div class="text-primary mx-1 font-bold">{{ maxSize }}MB</div>
|
||||
|
|
|
@ -17,7 +17,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
});
|
||||
</script>
|
||||
<template>
|
||||
<Modal class="w-[40%]" :title="$t('ui.widgets.qa')">
|
||||
<Modal class="w-2/5" :title="$t('ui.widgets.qa')">
|
||||
<div class="mt-2 flex flex-col">
|
||||
<div class="mt-2 flex flex-row">
|
||||
<VbenButtonGroup class="basis-1/3" :gap="2" border size="large">
|
||||
|
|
|
@ -101,7 +101,7 @@ watch(
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mt-16px md:w-full lg:w-1/2 2xl:w-2/5">
|
||||
<div class="mt-4 md:w-full lg:w-1/2 2xl:w-2/5">
|
||||
<Form />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -88,7 +88,7 @@ async function handleSubmit(values: Recordable<any>) {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mt-[16px] md:w-full lg:w-1/2 2xl:w-2/5">
|
||||
<div class="mt-4 md:w-full lg:w-1/2 2xl:w-2/5">
|
||||
<Form />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -181,9 +181,7 @@ onMounted(() => {
|
|||
/>
|
||||
<div class="flex flex-1 items-center justify-between">
|
||||
<div class="flex flex-col">
|
||||
<h4
|
||||
class="mb-[4px] text-[14px] text-black/85 dark:text-white/85"
|
||||
>
|
||||
<h4 class="mb-1 text-sm text-black/85 dark:text-white/85">
|
||||
{{ getDictLabel(DICT_TYPE.SYSTEM_SOCIAL_TYPE, item.type) }}
|
||||
</h4>
|
||||
<span class="text-black/45 dark:text-white/45">
|
||||
|
@ -191,9 +189,9 @@ onMounted(() => {
|
|||
{{ item.socialUser?.nickname || item.socialUser?.openid }}
|
||||
</template>
|
||||
<template v-else>
|
||||
绑定{{
|
||||
getDictLabel(DICT_TYPE.SYSTEM_SOCIAL_TYPE, item.type)
|
||||
}}账号
|
||||
绑定
|
||||
{{ getDictLabel(DICT_TYPE.SYSTEM_SOCIAL_TYPE, item.type) }}
|
||||
账号
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -6,9 +6,9 @@ import type { AiChatConversationApi } from '#/api/ai/chat/conversation';
|
|||
import { h, onMounted, ref, toRefs, watch } from 'vue';
|
||||
|
||||
import { confirm, prompt, useVbenDrawer } from '@vben/common-ui';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { IconifyIcon, SvgGptIcon } from '@vben/icons';
|
||||
|
||||
import { Button, Empty, Input, Layout, message } from 'ant-design-vue';
|
||||
import { Avatar, Button, Empty, Input, Layout, message } from 'ant-design-vue';
|
||||
|
||||
import {
|
||||
createChatConversationMy,
|
||||
|
@ -20,7 +20,6 @@ import {
|
|||
|
||||
import RoleRepository from '../role/RoleRepository.vue';
|
||||
|
||||
// 加载中定时器
|
||||
// 定义组件 props
|
||||
const props = defineProps({
|
||||
activeId: {
|
||||
|
@ -308,24 +307,24 @@ onMounted(async () => {
|
|||
<template>
|
||||
<Layout.Sider
|
||||
width="260px"
|
||||
class="conversation-container relative flex h-full flex-col justify-between overflow-hidden bg-[hsl(var(--primary-foreground))!important] p-[10px_10px_0]"
|
||||
class="!bg-primary-foreground conversation-container relative flex h-full flex-col justify-between overflow-hidden py-2.5 pb-0 pt-2.5"
|
||||
>
|
||||
<Drawer />
|
||||
<!-- 左顶部:对话 -->
|
||||
<div class="flex h-full flex-col">
|
||||
<Button
|
||||
class="btn-new-conversation h-[38px] w-full"
|
||||
class="btn-new-conversation h-9 w-full"
|
||||
type="primary"
|
||||
@click="createConversation"
|
||||
>
|
||||
<IconifyIcon icon="lucide:plus" class="mr-[5px]" />
|
||||
<IconifyIcon icon="lucide:plus" class="mr-1" />
|
||||
新建对话
|
||||
</Button>
|
||||
|
||||
<Input
|
||||
v-model:value="searchName"
|
||||
size="large"
|
||||
class="search-input mt-[20px]"
|
||||
class="search-input mt-5"
|
||||
placeholder="搜索历史记录"
|
||||
@keyup="searchConversation"
|
||||
>
|
||||
|
@ -335,7 +334,7 @@ onMounted(async () => {
|
|||
</Input>
|
||||
|
||||
<!-- 左中间:对话列表 -->
|
||||
<div class="conversation-list mt-[10px] flex-1 overflow-auto">
|
||||
<div class="conversation-list mt-2.5 flex-1 overflow-auto">
|
||||
<!-- 情况一:加载中 -->
|
||||
<Empty v-if="loading" description="." v-loading="loading" />
|
||||
|
||||
|
@ -347,9 +346,9 @@ onMounted(async () => {
|
|||
>
|
||||
<div
|
||||
v-if="conversationMap[conversationKey].length > 0"
|
||||
class="conversation-item classify-title pt-[10px]"
|
||||
class="conversation-item classify-title pt-2.5"
|
||||
>
|
||||
<b class="mx-[4px]">
|
||||
<b class="mx-1">
|
||||
{{ conversationKey }}
|
||||
</b>
|
||||
</div>
|
||||
|
@ -360,21 +359,22 @@ onMounted(async () => {
|
|||
@click="handleConversationClick(conversation.id)"
|
||||
@mouseover="hoverConversationId = conversation.id"
|
||||
@mouseout="hoverConversationId = null"
|
||||
class="conversation-item mt-[5px]"
|
||||
class="conversation-item mt-1"
|
||||
>
|
||||
<div
|
||||
class="conversation flex cursor-pointer flex-row items-center justify-between rounded-[5px] px-[5px] leading-[30px]"
|
||||
class="conversation flex cursor-pointer flex-row items-center justify-between rounded-lg px-2.5 leading-10"
|
||||
:class="[
|
||||
conversation.id === activeConversationId ? 'bg-[#e6e6e6]' : '',
|
||||
conversation.id === activeConversationId ? 'bg-gray-100' : '',
|
||||
]"
|
||||
>
|
||||
<div class="title-wrapper flex items-center">
|
||||
<img
|
||||
class="avatar h-[25px] w-[25px] rounded-[5px]"
|
||||
:src="conversation.roleAvatar ?? '/static/gpt.svg'"
|
||||
<Avatar
|
||||
v-if="conversation.roleAvatar"
|
||||
:src="conversation.roleAvatar"
|
||||
/>
|
||||
<SvgGptIcon v-else class="size-8" />
|
||||
<span
|
||||
class="title text-black/77 max-w-[150px] overflow-hidden text-ellipsis whitespace-nowrap px-[10px] py-[2px] text-[14px] font-normal"
|
||||
class="max-w-36 overflow-hidden text-ellipsis whitespace-nowrap px-2.5 py-1 text-sm font-normal text-gray-600"
|
||||
>
|
||||
{{ conversation.title }}
|
||||
</span>
|
||||
|
@ -382,35 +382,35 @@ onMounted(async () => {
|
|||
|
||||
<div
|
||||
v-show="hoverConversationId === conversation.id"
|
||||
class="button-wrapper relative right-[2px] flex items-center text-[#606266]"
|
||||
class="button-wrapper relative right-0.5 flex items-center text-gray-400"
|
||||
>
|
||||
<Button
|
||||
class="btn mr-0 px-[5px]"
|
||||
class="mr-0 px-1"
|
||||
type="link"
|
||||
@click.stop="handleTop(conversation)"
|
||||
>
|
||||
<IconifyIcon
|
||||
v-if="!conversation.pinned"
|
||||
icon="lucide:arrow-up"
|
||||
icon="lucide:arrow-up-to-line"
|
||||
/>
|
||||
<IconifyIcon
|
||||
v-if="conversation.pinned"
|
||||
icon="lucide:arrow-down"
|
||||
icon="lucide:arrow-down-from-line"
|
||||
/>
|
||||
</Button>
|
||||
<Button
|
||||
class="btn mr-0 px-[5px]"
|
||||
class="mr-0 px-1"
|
||||
type="link"
|
||||
@click.stop="updateConversationTitle(conversation)"
|
||||
>
|
||||
<IconifyIcon icon="lucide:edit" />
|
||||
</Button>
|
||||
<Button
|
||||
class="btn mr-0 px-[5px]"
|
||||
class="mr-0 px-1"
|
||||
type="link"
|
||||
@click.stop="deleteChatConversation(conversation)"
|
||||
>
|
||||
<IconifyIcon icon="lucide:trash" />
|
||||
<IconifyIcon icon="lucide:trash-2" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -419,26 +419,26 @@ onMounted(async () => {
|
|||
</div>
|
||||
|
||||
<!-- 底部占位 -->
|
||||
<div class="h-[50px] w-full"></div>
|
||||
<div class="h-12 w-full"></div>
|
||||
</div>
|
||||
|
||||
<!-- 左底部:工具栏 -->
|
||||
<div
|
||||
class="tool-box absolute bottom-0 left-0 right-0 flex items-center justify-between bg-[#f4f4f4] px-[20px] leading-[35px] text-[var(--el-text-color)] shadow-[0_0_1px_1px_rgba(228,228,228,0.8)]"
|
||||
class="tool-box absolute bottom-0 left-0 right-0 flex items-center justify-between bg-gray-50 px-5 leading-9 text-gray-400 shadow-sm"
|
||||
>
|
||||
<div
|
||||
class="flex cursor-pointer items-center text-[#606266]"
|
||||
class="flex cursor-pointer items-center text-gray-400"
|
||||
@click="handleRoleRepository"
|
||||
>
|
||||
<IconifyIcon icon="lucide:user" />
|
||||
<span class="ml-[5px]">角色仓库</span>
|
||||
<span class="ml-1">角色仓库</span>
|
||||
</div>
|
||||
<div
|
||||
class="flex cursor-pointer items-center text-[#606266]"
|
||||
class="flex cursor-pointer items-center text-gray-400"
|
||||
@click="handleClearConversation"
|
||||
>
|
||||
<IconifyIcon icon="lucide:trash" />
|
||||
<span class="ml-[5px]">清空未置顶对话</span>
|
||||
<span class="ml-1">清空未置顶对话</span>
|
||||
</div>
|
||||
</div>
|
||||
</Layout.Sider>
|
||||
|
|
|
@ -76,7 +76,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal class="w-[600px]" title="设定">
|
||||
<Modal class="w-2/5" title="设定">
|
||||
<Form class="mx-4" />
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -57,21 +57,21 @@ function handleClick(doc: any) {
|
|||
<!-- 知识引用列表 -->
|
||||
<div
|
||||
v-if="segments && segments.length > 0"
|
||||
class="mt-[10px] rounded-[8px] bg-[#f5f5f5] p-[10px]"
|
||||
class="mt-2 rounded-lg bg-gray-50 p-2"
|
||||
>
|
||||
<div class="text-14px mb-8px flex items-center text-[#666]">
|
||||
<IconifyIcon icon="lucide:file-text" class="mr-[5px]" /> 知识引用
|
||||
<div class="mb-2 flex items-center text-sm text-gray-400">
|
||||
<IconifyIcon icon="lucide:file-text" class="mr-1" /> 知识引用
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-[8px]">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<div
|
||||
v-for="(doc, index) in documentList"
|
||||
:key="index"
|
||||
class="cursor-pointer rounded-[6px] bg-white p-[8px] px-[12px] transition-all hover:bg-[#e6f4ff]"
|
||||
class="cursor-pointer rounded-lg bg-white p-2 px-3 transition-all hover:bg-blue-50"
|
||||
@click="handleClick(doc)"
|
||||
>
|
||||
<div class="mb-[4px] text-[14px] text-[#333]">
|
||||
<div class="mb-1 text-sm text-gray-600">
|
||||
{{ doc.title }}
|
||||
<span class="ml-[4px] text-[12px] text-[#999]">
|
||||
<span class="ml-1 text-xs text-gray-300">
|
||||
({{ doc.segments.length }} 条)
|
||||
</span>
|
||||
</div>
|
||||
|
@ -81,19 +81,19 @@ function handleClick(doc: any) {
|
|||
<Tooltip placement="topLeft" trigger="click">
|
||||
<div ref="documentRef"></div>
|
||||
<template #title>
|
||||
<div class="mb-[12px] text-[16px] font-bold">{{ document?.title }}</div>
|
||||
<div class="mb-3 text-base font-bold">{{ document?.title }}</div>
|
||||
<div class="max-h-[60vh] overflow-y-auto">
|
||||
<div
|
||||
v-for="(segment, index) in document?.segments"
|
||||
:key="index"
|
||||
class="border-b-solid border-b-[#eee] p-[12px] last:border-b-0"
|
||||
class="border-b-solid border-b-gray-200 p-3 last:border-b-0"
|
||||
>
|
||||
<div
|
||||
class="mb-[8px] block w-fit rounded-[4px] bg-[#f5f5f5] px-[8px] py-[2px] text-[12px] text-[#666]"
|
||||
class="mb-2 block w-fit rounded-sm bg-gray-50 px-2 py-1 text-xs text-gray-400"
|
||||
>
|
||||
分段 {{ segment.id }}
|
||||
</div>
|
||||
<div class="mt-[10px] text-[14px] leading-[1.6] text-[#333]">
|
||||
<div class="mt-2 text-sm leading-[1.6] text-gray-600">
|
||||
{{ segment.content }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -114,7 +114,7 @@ onMounted(async () => {
|
|||
<div
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
class="mt-[50px] flex flex-col overflow-y-hidden px-[20px]"
|
||||
class="mt-12 flex flex-col overflow-y-hidden px-5"
|
||||
>
|
||||
<!-- 左侧消息:system、assistant -->
|
||||
<div v-if="item.type !== 'user'" class="flex flex-row">
|
||||
|
@ -125,22 +125,22 @@ onMounted(async () => {
|
|||
/>
|
||||
<SvgGptIcon v-else class="size-8" />
|
||||
</div>
|
||||
<div class="mx-[15px] flex flex-col text-left">
|
||||
<div class="text-left leading-[30px]">
|
||||
<div class="mx-4 flex flex-col text-left">
|
||||
<div class="text-left leading-10">
|
||||
{{ formatDate(item.createTime) }}
|
||||
</div>
|
||||
<div
|
||||
class="relative flex flex-col break-words rounded-[10px] bg-[#e4e4e4cc] p-[10px] pb-[5px] pt-[10px] shadow-[0_0_0_1px_rgba(228,228,228,0.8)]"
|
||||
class="relative flex flex-col break-words rounded-lg bg-gray-100 p-2.5 pb-1 pt-2.5 shadow-sm"
|
||||
>
|
||||
<MarkdownView
|
||||
class="text-[0.95rem] text-[#393939]"
|
||||
class="text-sm text-gray-600"
|
||||
:content="item.content"
|
||||
/>
|
||||
<MessageKnowledge v-if="item.segments" :segments="item.segments" />
|
||||
</div>
|
||||
<div class="mt-[8px] flex flex-row">
|
||||
<div class="mt-2 flex flex-row">
|
||||
<Button
|
||||
class="flex items-center bg-transparent px-[5px] hover:bg-[#f6f6f6]"
|
||||
class="flex items-center bg-transparent px-1.5 hover:bg-gray-100"
|
||||
type="text"
|
||||
@click="copyContent(item.content)"
|
||||
>
|
||||
|
@ -148,7 +148,7 @@ onMounted(async () => {
|
|||
</Button>
|
||||
<Button
|
||||
v-if="item.id > 0"
|
||||
class="flex items-center bg-transparent px-[5px] hover:bg-[#f6f6f6]"
|
||||
class="flex items-center bg-transparent px-1.5 hover:bg-gray-100"
|
||||
type="text"
|
||||
@click="onDelete(item.id)"
|
||||
>
|
||||
|
@ -163,41 +163,41 @@ onMounted(async () => {
|
|||
<div class="avatar">
|
||||
<Avatar :src="userAvatar" />
|
||||
</div>
|
||||
<div class="mx-[15px] flex flex-col text-left">
|
||||
<div class="text-left leading-[30px]">
|
||||
<div class="mx-4 flex flex-col text-left">
|
||||
<div class="text-left leading-8">
|
||||
{{ formatDate(item.createTime) }}
|
||||
</div>
|
||||
<div class="flex flex-row-reverse">
|
||||
<div
|
||||
class="inline w-auto whitespace-pre-wrap break-words rounded-[10px] bg-[#267fff] p-[10px] text-[0.95rem] text-white shadow-[0_0_0_1px_#267fff]"
|
||||
class="inline w-auto whitespace-pre-wrap break-words rounded-lg bg-blue-500 p-2.5 text-sm text-white shadow-sm"
|
||||
>
|
||||
{{ item.content }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[8px] flex flex-row-reverse">
|
||||
<div class="mt-2 flex flex-row-reverse">
|
||||
<Button
|
||||
class="flex items-center bg-transparent px-[5px] hover:bg-[#f6f6f6]"
|
||||
class="flex items-center bg-transparent px-1.5 hover:bg-gray-100"
|
||||
type="text"
|
||||
@click="copyContent(item.content)"
|
||||
>
|
||||
<IconifyIcon icon="lucide:copy" />
|
||||
</Button>
|
||||
<Button
|
||||
class="flex items-center bg-transparent px-[5px] hover:bg-[#f6f6f6]"
|
||||
class="flex items-center bg-transparent px-1.5 hover:bg-gray-100"
|
||||
type="text"
|
||||
@click="onDelete(item.id)"
|
||||
>
|
||||
<IconifyIcon icon="lucide:trash" />
|
||||
</Button>
|
||||
<Button
|
||||
class="flex items-center bg-transparent px-[5px] hover:bg-[#f6f6f6]"
|
||||
class="flex items-center bg-transparent px-1.5 hover:bg-gray-100"
|
||||
type="text"
|
||||
@click="onRefresh(item)"
|
||||
>
|
||||
<IconifyIcon icon="lucide:refresh-cw" />
|
||||
</Button>
|
||||
<Button
|
||||
class="flex items-center bg-transparent px-[5px] hover:bg-[#f6f6f6]"
|
||||
class="flex items-center bg-transparent px-1.5 hover:bg-gray-100"
|
||||
type="text"
|
||||
@click="onEdit(item)"
|
||||
>
|
||||
|
@ -212,7 +212,7 @@ onMounted(async () => {
|
|||
<!-- 回到底部按钮 -->
|
||||
<div
|
||||
v-if="isScrolling"
|
||||
class="absolute bottom-0 right-1/2 z-[1000]"
|
||||
class="z-1000 absolute bottom-0 right-1/2"
|
||||
@click="handleGoBottom"
|
||||
>
|
||||
<Button shape="circle">
|
||||
|
|
|
@ -20,17 +20,15 @@ async function handlerPromptClick(prompt: any) {
|
|||
<!-- center-container -->
|
||||
<div class="flex flex-col justify-center">
|
||||
<!-- title -->
|
||||
<div class="text-center text-[28px] font-bold">芋道 AI</div>
|
||||
<div class="text-center text-3xl font-bold">芋道 AI</div>
|
||||
|
||||
<!-- role-list -->
|
||||
<div
|
||||
class="mt-[20px] flex w-[460px] flex-wrap items-center justify-center"
|
||||
>
|
||||
<div class="mt-5 flex w-96 flex-wrap items-center justify-center">
|
||||
<div
|
||||
v-for="prompt in promptList"
|
||||
:key="prompt.prompt"
|
||||
@click="handlerPromptClick(prompt)"
|
||||
class="m-[10px] flex w-[180px] cursor-pointer justify-center rounded-[10px] border border-[#e4e4e4] leading-[50px] hover:bg-[rgba(243,243,243,0.73)]"
|
||||
class="m-2.5 flex w-44 cursor-pointer justify-center rounded-lg border border-gray-200 leading-10 hover:bg-gray-100"
|
||||
>
|
||||
{{ prompt.prompt }}
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,7 @@ import { Skeleton } from 'ant-design-vue';
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="p-[30px]">
|
||||
<div class="p-8">
|
||||
<Skeleton active />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -12,10 +12,10 @@ function handlerNewChat() {
|
|||
<template>
|
||||
<div class="flex h-full w-full flex-row justify-center">
|
||||
<div class="flex flex-col justify-center">
|
||||
<div class="text-center text-[14px] text-[#858585]">
|
||||
<div class="text-center text-sm text-gray-400">
|
||||
点击下方按钮,开始你的对话吧
|
||||
</div>
|
||||
<div class="mt-[20px] flex flex-row justify-center">
|
||||
<div class="mt-5 flex flex-row justify-center">
|
||||
<Button type="primary" round @click="handlerNewChat">新建对话</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -7,7 +7,7 @@ import { ref } from 'vue';
|
|||
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { Button, Card, Dropdown, Menu } from 'ant-design-vue';
|
||||
import { Avatar, Button, Card, Dropdown, Menu } from 'ant-design-vue';
|
||||
|
||||
// tabs ref
|
||||
|
||||
|
@ -61,17 +61,13 @@ async function handleTabsScroll() {
|
|||
|
||||
<template>
|
||||
<div
|
||||
class="relative flex h-full flex-wrap content-start items-start overflow-auto px-[25px] pb-[140px]"
|
||||
class="relative flex h-full flex-wrap content-start items-start overflow-auto px-6 pb-36"
|
||||
ref="tabsRef"
|
||||
@scroll="handleTabsScroll"
|
||||
>
|
||||
<div
|
||||
class="mb-[20px] mr-[20px] inline-block"
|
||||
v-for="role in roleList"
|
||||
:key="role.id"
|
||||
>
|
||||
<div class="mb-5 mr-5 inline-block" v-for="role in roleList" :key="role.id">
|
||||
<Card
|
||||
class="relative rounded-[10px]"
|
||||
class="relative rounded-lg"
|
||||
:body-style="{
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
|
@ -83,9 +79,9 @@ async function handleTabsScroll() {
|
|||
}"
|
||||
>
|
||||
<!-- 更多操作 -->
|
||||
<div v-if="showMore" class="absolute right-[12px] top-0">
|
||||
<div v-if="showMore" class="absolute right-3 top-0">
|
||||
<Dropdown>
|
||||
<Button type="text">
|
||||
<Button type="link">
|
||||
<IconifyIcon icon="lucide:ellipsis-vertical" />
|
||||
</Button>
|
||||
<template #overlay>
|
||||
|
@ -99,7 +95,7 @@ async function handleTabsScroll() {
|
|||
<Menu.Item @click="handleMoreClick(['delete', role])">
|
||||
<div class="flex items-center">
|
||||
<IconifyIcon icon="lucide:trash" color="red" />
|
||||
<span class="text-red-500">编辑</span>
|
||||
<span class="text-red-500">删除</span>
|
||||
</div>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
|
@ -109,22 +105,19 @@ async function handleTabsScroll() {
|
|||
|
||||
<!-- 角色信息 -->
|
||||
<div>
|
||||
<img
|
||||
:src="role.avatar"
|
||||
class="h-[40px] w-[40px] overflow-hidden rounded-[10px]"
|
||||
/>
|
||||
<Avatar :src="role.avatar" class="h-10 w-10 overflow-hidden" />
|
||||
</div>
|
||||
|
||||
<div class="ml-[10px] w-full">
|
||||
<div class="h-[85px]">
|
||||
<div class="max-w-[140px] text-[18px] font-bold text-[#3e3e3e]">
|
||||
<div class="ml-2 w-full">
|
||||
<div class="h-20">
|
||||
<div class="max-w-36 text-lg font-bold text-gray-600">
|
||||
{{ role.name }}
|
||||
</div>
|
||||
<div class="mt-[10px] text-[14px] text-[#6a6a6a]">
|
||||
<div class="mt-2 text-sm text-gray-400">
|
||||
{{ role.description }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[2px] flex flex-row-reverse">
|
||||
<div class="mt-1 flex flex-row-reverse">
|
||||
<Button type="primary" size="small" @click="handleUseClick(role)">
|
||||
使用
|
||||
</Button>
|
||||
|
|
|
@ -21,7 +21,7 @@ const router = useRouter(); // 路由对象
|
|||
const [Drawer] = useVbenDrawer({
|
||||
title: '角色管理',
|
||||
footer: false,
|
||||
class: 'w-[754px]',
|
||||
class: 'w-2/5',
|
||||
});
|
||||
|
||||
const [FormModal, formModalApi] = useVbenModal({
|
||||
|
@ -179,12 +179,12 @@ onMounted(async () => {
|
|||
<FormModal @success="handlerAddRoleSuccess" />
|
||||
|
||||
<Layout.Content class="relative m-0 flex-1 overflow-hidden p-0">
|
||||
<div class="absolute right-0 top-[-5px] z-[100] mr-[20px] mt-[20px]">
|
||||
<div class="z-100 absolute right-0 top--1 mr-5 mt-5">
|
||||
<!-- 搜索输入框 -->
|
||||
<Input.Search
|
||||
:loading="loading"
|
||||
v-model:value="search"
|
||||
class="w-[240px]"
|
||||
class="w-60"
|
||||
placeholder="请输入搜索的内容"
|
||||
@search="getActiveTabsRole"
|
||||
/>
|
||||
|
@ -192,9 +192,9 @@ onMounted(async () => {
|
|||
v-if="activeTab === 'my-role'"
|
||||
type="primary"
|
||||
@click="handlerAddRole"
|
||||
class="ml-[20px]"
|
||||
class="ml-5"
|
||||
>
|
||||
<IconifyIcon icon="lucide:user" style="margin-right: 5px" />
|
||||
<IconifyIcon icon="lucide:user" class="mr-1.5" />
|
||||
添加角色
|
||||
</Button>
|
||||
</div>
|
||||
|
@ -218,7 +218,7 @@ onMounted(async () => {
|
|||
@on-edit="handlerCardEdit"
|
||||
@on-use="handlerCardUse"
|
||||
@on-page="handlerCardPage('my')"
|
||||
class="mt-[20px]"
|
||||
class="mt-5"
|
||||
/>
|
||||
</Tabs.TabPane>
|
||||
|
||||
|
@ -231,7 +231,7 @@ onMounted(async () => {
|
|||
:category-list="categoryList"
|
||||
:active="activeCategory"
|
||||
@on-category-click="handlerCategoryClick"
|
||||
class="mx-[27px]"
|
||||
class="mx-6"
|
||||
/>
|
||||
<RoleList
|
||||
:role-list="publicRoleList"
|
||||
|
@ -239,7 +239,7 @@ onMounted(async () => {
|
|||
@on-edit="handlerCardEdit"
|
||||
@on-use="handlerCardUse"
|
||||
@on-page="handlerCardPage('public')"
|
||||
class="mt-[20px]"
|
||||
class="mt-5"
|
||||
loading
|
||||
/>
|
||||
</Tabs.TabPane>
|
||||
|
|
|
@ -494,10 +494,10 @@ onMounted(async () => {
|
|||
|
||||
<template>
|
||||
<Page auto-content-height>
|
||||
<Layout class="absolute left-0 top-0 h-full w-full flex-1">
|
||||
<Layout class="absolute left-0 top-0 m-4 h-full w-full flex-1">
|
||||
<!-- 左侧:对话列表 -->
|
||||
<ConversationList
|
||||
:active-id="activeConversationId"
|
||||
:active-id="activeConversationId as any"
|
||||
ref="conversationListRef"
|
||||
@on-conversation-create="handleConversationCreateSuccess"
|
||||
@on-conversation-click="handleConversationClick"
|
||||
|
@ -506,18 +506,18 @@ onMounted(async () => {
|
|||
/>
|
||||
|
||||
<!-- 右侧:详情部分 -->
|
||||
<Layout class="bg-white">
|
||||
<Layout class="ml-4 bg-white">
|
||||
<Layout.Header
|
||||
class="flex items-center justify-between bg-[#fbfbfb!important] shadow-none"
|
||||
class="flex items-center justify-between !bg-gray-50 shadow-none"
|
||||
>
|
||||
<div class="text-[18px] font-bold">
|
||||
<div class="text-lg font-bold">
|
||||
{{ activeConversation?.title ? activeConversation?.title : '对话' }}
|
||||
<span v-if="activeMessageList.length > 0">
|
||||
({{ activeMessageList.length }})
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex w-[300px] justify-end" v-if="activeConversation">
|
||||
<div class="flex w-72 justify-end" v-if="activeConversation">
|
||||
<Button
|
||||
type="primary"
|
||||
ghost
|
||||
|
@ -526,10 +526,10 @@ onMounted(async () => {
|
|||
@click="openChatConversationUpdateForm"
|
||||
>
|
||||
<span v-html="activeConversation?.modelName"></span>
|
||||
<IconifyIcon icon="lucide:settings" class="ml-2" />
|
||||
<IconifyIcon icon="lucide:settings" class="ml-2 size-4" />
|
||||
</Button>
|
||||
<Button size="small" class="mr-2 px-2" @click="handlerMessageClear">
|
||||
<IconifyIcon icon="lucide:trash" color="#787878" />
|
||||
<IconifyIcon icon="lucide:trash-2" color="#787878" />
|
||||
</Button>
|
||||
<Button size="small" class="mr-2 px-2">
|
||||
<IconifyIcon icon="lucide:download" color="#787878" />
|
||||
|
@ -567,12 +567,12 @@ onMounted(async () => {
|
|||
</div>
|
||||
</Layout.Content>
|
||||
|
||||
<Layout.Footer class="m-0 flex flex-col bg-[white!important] p-0">
|
||||
<Layout.Footer class="m-0 flex flex-col !bg-white p-0">
|
||||
<form
|
||||
class="m-[10px_20px_20px] flex flex-col rounded-[10px] border border-[#e3e3e3] p-[9px_10px]"
|
||||
class="my-5 mb-5 mt-2 flex flex-col rounded-xl border border-gray-200 px-2 py-2.5"
|
||||
>
|
||||
<textarea
|
||||
class="box-border h-[80px] resize-none overflow-auto border-none p-[0_2px] focus:outline-none"
|
||||
class="box-border h-20 resize-none overflow-auto border-none px-0 py-0.5 focus:outline-none"
|
||||
v-model="prompt"
|
||||
@keydown="handleSendByKeydown"
|
||||
@input="handlePromptInput"
|
||||
|
@ -580,10 +580,10 @@ onMounted(async () => {
|
|||
@compositionend="onCompositionend"
|
||||
placeholder="问我任何问题...(Shift+Enter 换行,按下 Enter 发送)"
|
||||
></textarea>
|
||||
<div class="flex justify-between pb-0 pt-[5px]">
|
||||
<div class="flex justify-between pb-0 pt-1">
|
||||
<div class="flex items-center">
|
||||
<Switch v-model:checked="enableContext" />
|
||||
<span class="ml-[5px] text-[14px] text-[#8f8f8f]">上下文</span>
|
||||
<span class="ml-1 text-sm text-gray-400">上下文</span>
|
||||
</div>
|
||||
<Button
|
||||
type="primary"
|
||||
|
@ -591,13 +591,22 @@ onMounted(async () => {
|
|||
:loading="conversationInProgress"
|
||||
v-if="conversationInProgress === false"
|
||||
>
|
||||
<IconifyIcon
|
||||
:icon="
|
||||
conversationInProgress
|
||||
? 'lucide:loader'
|
||||
: 'lucide:send-horizontal'
|
||||
"
|
||||
/>
|
||||
{{ conversationInProgress ? '进行中' : '发送' }}
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
danger
|
||||
@click="stopStream()"
|
||||
v-if="conversationInProgress === true"
|
||||
>
|
||||
<IconifyIcon icon="lucide:circle-stop" />
|
||||
停止
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
@ -64,10 +64,7 @@ onMounted(async () => {
|
|||
});
|
||||
</script>
|
||||
<template>
|
||||
<Card
|
||||
body-class=""
|
||||
class="relative flex h-auto w-[320px] flex-col rounded-[10px]"
|
||||
>
|
||||
<Card class="relative flex h-auto w-80 flex-col rounded-lg">
|
||||
<!-- 图片操作区 -->
|
||||
<div class="flex flex-row justify-between">
|
||||
<div>
|
||||
|
@ -83,28 +80,28 @@ onMounted(async () => {
|
|||
</div>
|
||||
<div class="flex">
|
||||
<Button
|
||||
class="m-0 p-[10px]"
|
||||
class="m-0 p-2.5"
|
||||
type="text"
|
||||
@click="handleButtonClick('download', detail)"
|
||||
>
|
||||
<IconifyIcon icon="lucide:download" />
|
||||
</Button>
|
||||
<Button
|
||||
class="m-0 p-[10px]"
|
||||
class="m-0 p-2.5"
|
||||
type="text"
|
||||
@click="handleButtonClick('regeneration', detail)"
|
||||
>
|
||||
<IconifyIcon icon="lucide:refresh-cw" />
|
||||
</Button>
|
||||
<Button
|
||||
class="m-0 p-[10px]"
|
||||
class="m-0 p-2.5"
|
||||
type="text"
|
||||
@click="handleButtonClick('delete', detail)"
|
||||
>
|
||||
<IconifyIcon icon="lucide:trash" />
|
||||
</Button>
|
||||
<Button
|
||||
class="m-0 p-[10px]"
|
||||
class="m-0 p-2.5"
|
||||
type="text"
|
||||
@click="handleButtonClick('more', detail)"
|
||||
>
|
||||
|
@ -114,20 +111,20 @@ onMounted(async () => {
|
|||
</div>
|
||||
|
||||
<!-- 图片展示区域 -->
|
||||
<div class="mt-[20px] h-[280px] flex-1 overflow-hidden" ref="cardImageRef">
|
||||
<Image class="w-full rounded-[10px]" :src="detail?.picUrl" />
|
||||
<div class="mt-5 h-72 flex-1 overflow-hidden" ref="cardImageRef">
|
||||
<Image class="w-full rounded-lg" :src="detail?.picUrl" />
|
||||
<div v-if="detail?.status === AiImageStatusEnum.FAIL">
|
||||
{{ detail?.errorMessage }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Midjourney 专属操作按钮 -->
|
||||
<div class="mt-[5px] flex w-full flex-wrap justify-start">
|
||||
<div class="mt-2 flex w-full flex-wrap justify-start">
|
||||
<Button
|
||||
size="small"
|
||||
v-for="(button, index) in detail?.buttons"
|
||||
:key="index"
|
||||
class="ml-0 mr-[10px] mt-[5px] min-w-[40px]"
|
||||
class="m-2 ml-0 min-w-10"
|
||||
@click="handleMidjourneyBtnClick(button)"
|
||||
>
|
||||
{{ button.label }}{{ button.emoji }}
|
||||
|
|
|
@ -44,15 +44,15 @@ watch(
|
|||
|
||||
<template>
|
||||
<div class="mb-5 w-full overflow-hidden break-words">
|
||||
<div class="body mt-2 text-gray-600">
|
||||
<Image class="rounded-[10px]" :src="detail?.picUrl" />
|
||||
<div class="mt-2 text-gray-600">
|
||||
<Image class="rounded-lg" :src="detail?.picUrl" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 时间 -->
|
||||
<div class="mb-5 w-full overflow-hidden break-words">
|
||||
<div class="tip text-lg font-bold">时间</div>
|
||||
<div class="body mt-2 text-gray-600">
|
||||
<div class="text-lg font-bold">时间</div>
|
||||
<div class="mt-2 text-gray-600">
|
||||
<div>
|
||||
提交时间:{{ formatDate(detail.createTime, 'yyyy-MM-dd HH:mm:ss') }}
|
||||
</div>
|
||||
|
@ -64,24 +64,24 @@ watch(
|
|||
|
||||
<!-- 模型 -->
|
||||
<div class="mb-5 w-full overflow-hidden break-words">
|
||||
<div class="tip text-lg font-bold">模型</div>
|
||||
<div class="body mt-2 text-gray-600">
|
||||
<div class="text-lg font-bold">模型</div>
|
||||
<div class="mt-2 text-gray-600">
|
||||
{{ detail.model }}({{ detail.height }}x{{ detail.width }})
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 提示词 -->
|
||||
<div class="mb-5 w-full overflow-hidden break-words">
|
||||
<div class="tip text-lg font-bold">提示词</div>
|
||||
<div class="body mt-2 text-gray-600">
|
||||
<div class="text-lg font-bold">提示词</div>
|
||||
<div class="mt-2 text-gray-600">
|
||||
{{ detail.prompt }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 图片地址 -->
|
||||
<div class="mb-5 w-full overflow-hidden break-words">
|
||||
<div class="tip text-lg font-bold">图片地址</div>
|
||||
<div class="body mt-2 text-gray-600">
|
||||
<div class="text-lg font-bold">图片地址</div>
|
||||
<div class="mt-2 text-gray-600">
|
||||
{{ detail.picUrl }}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -94,8 +94,8 @@ watch(
|
|||
"
|
||||
class="mb-5 w-full overflow-hidden break-words"
|
||||
>
|
||||
<div class="tip text-lg font-bold">采样方法</div>
|
||||
<div class="body mt-2 text-gray-600">
|
||||
<div class="text-lg font-bold">采样方法</div>
|
||||
<div class="mt-2 text-gray-600">
|
||||
{{
|
||||
StableDiffusionSamplers.find(
|
||||
(item) => item.key === detail?.options?.sampler,
|
||||
|
@ -111,8 +111,8 @@ watch(
|
|||
"
|
||||
class="mb-5 w-full overflow-hidden break-words"
|
||||
>
|
||||
<div class="tip text-lg font-bold">CLIP</div>
|
||||
<div class="body mt-2 text-gray-600">
|
||||
<div class="text-lg font-bold">CLIP</div>
|
||||
<div class="mt-2 text-gray-600">
|
||||
{{
|
||||
StableDiffusionClipGuidancePresets.find(
|
||||
(item) => item.key === detail?.options?.clipGuidancePreset,
|
||||
|
@ -128,8 +128,8 @@ watch(
|
|||
"
|
||||
class="mb-5 w-full overflow-hidden break-words"
|
||||
>
|
||||
<div class="tip text-lg font-bold">风格</div>
|
||||
<div class="body mt-2 text-gray-600">
|
||||
<div class="text-lg font-bold">风格</div>
|
||||
<div class="mt-2 text-gray-600">
|
||||
{{
|
||||
StableDiffusionStylePresets.find(
|
||||
(item) => item.key === detail?.options?.stylePreset,
|
||||
|
@ -145,8 +145,8 @@ watch(
|
|||
"
|
||||
class="mb-5 w-full overflow-hidden break-words"
|
||||
>
|
||||
<div class="tip text-lg font-bold">迭代步数</div>
|
||||
<div class="body mt-2 text-gray-600">{{ detail?.options?.steps }}</div>
|
||||
<div class="text-lg font-bold">迭代步数</div>
|
||||
<div class="mt-2 text-gray-600">{{ detail?.options?.steps }}</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
@ -156,8 +156,8 @@ watch(
|
|||
"
|
||||
class="mb-5 w-full overflow-hidden break-words"
|
||||
>
|
||||
<div class="tip text-lg font-bold">引导系数</div>
|
||||
<div class="body mt-2 text-gray-600">{{ detail?.options?.scale }}</div>
|
||||
<div class="text-lg font-bold">引导系数</div>
|
||||
<div class="mt-2 text-gray-600">{{ detail?.options?.scale }}</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
@ -167,8 +167,8 @@ watch(
|
|||
"
|
||||
class="mb-5 w-full overflow-hidden break-words"
|
||||
>
|
||||
<div class="tip text-lg font-bold">随机因子</div>
|
||||
<div class="body mt-2 text-gray-600">{{ detail?.options?.seed }}</div>
|
||||
<div class="text-lg font-bold">随机因子</div>
|
||||
<div class="mt-2 text-gray-600">{{ detail?.options?.seed }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Dall3 专属 -->
|
||||
|
@ -176,8 +176,8 @@ watch(
|
|||
v-if="detail.platform === AiPlatformEnum.OPENAI && detail?.options?.style"
|
||||
class="mb-5 w-full overflow-hidden break-words"
|
||||
>
|
||||
<div class="tip text-lg font-bold">风格选择</div>
|
||||
<div class="body mt-2 text-gray-600">
|
||||
<div class="text-lg font-bold">风格选择</div>
|
||||
<div class="mt-2 text-gray-600">
|
||||
{{
|
||||
Dall3StyleList.find((item) => item.key === detail?.options?.style)?.name
|
||||
}}
|
||||
|
@ -191,8 +191,8 @@ watch(
|
|||
"
|
||||
class="mb-5 w-full overflow-hidden break-words"
|
||||
>
|
||||
<div class="tip text-lg font-bold">模型版本</div>
|
||||
<div class="body mt-2 text-gray-600">{{ detail?.options?.version }}</div>
|
||||
<div class="text-lg font-bold">模型版本</div>
|
||||
<div class="mt-2 text-gray-600">{{ detail?.options?.version }}</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
@ -202,8 +202,8 @@ watch(
|
|||
"
|
||||
class="mb-5 w-full overflow-hidden break-words"
|
||||
>
|
||||
<div class="tip text-lg font-bold">参考图</div>
|
||||
<div class="body mt-2 text-gray-600">
|
||||
<div class="text-lg font-bold">参考图</div>
|
||||
<div class="mt-2 text-gray-600">
|
||||
<Image :src="detail.options.referImageUrl" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -170,11 +170,11 @@ onUnmounted(async () => {
|
|||
});
|
||||
</script>
|
||||
<template>
|
||||
<Drawer class="w-[600px]">
|
||||
<Drawer class="w-2/5">
|
||||
<ImageDetail :id="showImageDetailId" />
|
||||
</Drawer>
|
||||
<Card
|
||||
class="dr-task flex h-full w-full flex-col"
|
||||
class="flex h-full w-full flex-col"
|
||||
:body-style="{
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
|
@ -190,7 +190,7 @@ onUnmounted(async () => {
|
|||
</template>
|
||||
|
||||
<div
|
||||
class="task-image-list flex flex-1 flex-wrap content-start overflow-y-auto p-5 pb-[140px] pt-5"
|
||||
class="flex flex-1 flex-wrap content-start overflow-y-auto p-5 pb-28 pt-5"
|
||||
ref="imageListRef"
|
||||
>
|
||||
<ImageCard
|
||||
|
@ -204,7 +204,7 @@ onUnmounted(async () => {
|
|||
</div>
|
||||
|
||||
<div
|
||||
class="task-image-pagination sticky bottom-0 z-50 flex h-[60px] items-center justify-center bg-white shadow-[0_-2px_8px_rgba(0,0,0,0.1)]"
|
||||
class="sticky bottom-0 z-50 flex h-16 items-center justify-center bg-white shadow-sm"
|
||||
>
|
||||
<Pagination
|
||||
:total="pageTotal"
|
||||
|
|
|
@ -113,20 +113,20 @@ defineExpose({ settingValues });
|
|||
v-model:value="prompt"
|
||||
:maxlength="1024"
|
||||
:rows="5"
|
||||
class="mt-[15px] w-full"
|
||||
class="mt-4 w-full"
|
||||
placeholder="例如:童话里的小屋应该是什么样子?"
|
||||
show-count
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="hot-words mt-[30px] flex flex-col">
|
||||
<div class="mt-8 flex flex-col">
|
||||
<div>
|
||||
<b>随机热词</b>
|
||||
</div>
|
||||
<Space wrap class="word-list mt-[15px] flex flex-wrap justify-start">
|
||||
<Space wrap class="mt-4 flex flex-col flex-wrap justify-start">
|
||||
<Button
|
||||
shape="round"
|
||||
class="btn m-0"
|
||||
class="m-0"
|
||||
:type="selectHotWord === hotWord ? 'primary' : 'default'"
|
||||
v-for="hotWord in ImageHotWords"
|
||||
:key="hotWord"
|
||||
|
@ -137,16 +137,16 @@ defineExpose({ settingValues });
|
|||
</Space>
|
||||
</div>
|
||||
|
||||
<div class="group-item mt-[30px]">
|
||||
<div class="mt-8">
|
||||
<div>
|
||||
<b>平台</b>
|
||||
</div>
|
||||
<Space wrap class="group-item-body mt-[15px] w-full">
|
||||
<Space wrap class="mt-4 w-full">
|
||||
<Select
|
||||
v-model:value="otherPlatform"
|
||||
placeholder="Select"
|
||||
size="large"
|
||||
class="!important w-[330px]"
|
||||
class="!w-80"
|
||||
@change="handlerPlatformChange"
|
||||
>
|
||||
<Select.Option
|
||||
|
@ -160,16 +160,16 @@ defineExpose({ settingValues });
|
|||
</Space>
|
||||
</div>
|
||||
|
||||
<div class="group-item mt-[30px]">
|
||||
<div class="mt-8">
|
||||
<div>
|
||||
<b>模型</b>
|
||||
</div>
|
||||
<Space wrap class="group-item-body mt-[15px] w-full">
|
||||
<Space wrap class="mt-4 w-full">
|
||||
<Select
|
||||
v-model:value="modelId"
|
||||
placeholder="Select"
|
||||
size="large"
|
||||
class="!important w-[330px]"
|
||||
class="!w-80"
|
||||
>
|
||||
<Select.Option
|
||||
v-for="item in platformModels"
|
||||
|
@ -182,25 +182,29 @@ defineExpose({ settingValues });
|
|||
</Space>
|
||||
</div>
|
||||
|
||||
<div class="group-item mt-[30px]">
|
||||
<div class="mt-8">
|
||||
<div>
|
||||
<b>图片尺寸</b>
|
||||
</div>
|
||||
<Space wrap class="group-item-body mt-[15px] flex flex-wrap gap-x-[20px]">
|
||||
<Space wrap class="mt-4 flex flex-wrap gap-x-5">
|
||||
<InputNumber
|
||||
v-model:value="width"
|
||||
class="mt-[10px] w-[170px]"
|
||||
class="w-40"
|
||||
placeholder="图片宽度"
|
||||
addon-before="宽"
|
||||
addon-after="px"
|
||||
/>
|
||||
<InputNumber
|
||||
v-model:value="height"
|
||||
class="w-[170px]"
|
||||
class="w-40"
|
||||
placeholder="图片高度"
|
||||
addon-before="高"
|
||||
addon-after="px"
|
||||
/>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
<div class="btns mt-[50px] flex justify-center">
|
||||
<div class="mt-12 flex justify-center">
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
|
|
|
@ -151,18 +151,18 @@ defineExpose({ settingValues });
|
|||
v-model:value="prompt"
|
||||
:maxlength="1024"
|
||||
:rows="5"
|
||||
class="mt-[15px] w-full"
|
||||
class="mt-4 w-full"
|
||||
placeholder="例如:童话里的小屋应该是什么样子?"
|
||||
show-count
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="hot-words mt-[30px] flex flex-col">
|
||||
<div class="mt-8 flex flex-col">
|
||||
<div><b>随机热词</b></div>
|
||||
<Space wrap class="word-list mt-[15px] flex flex-wrap justify-start">
|
||||
<Space wrap class="mt-4 flex flex-wrap justify-start">
|
||||
<Button
|
||||
shape="round"
|
||||
class="btn m-0"
|
||||
class="m-0"
|
||||
:type="selectHotWord === hotWord ? 'primary' : 'default'"
|
||||
v-for="hotWord in ImageHotWords"
|
||||
:key="hotWord"
|
||||
|
@ -173,15 +173,13 @@ defineExpose({ settingValues });
|
|||
</Space>
|
||||
</div>
|
||||
|
||||
<div class="model mt-[30px]">
|
||||
<div class="mt-8">
|
||||
<div><b>模型选择</b></div>
|
||||
<Space wrap class="model-list mt-[15px] flex flex-wrap gap-[10px]">
|
||||
<Space wrap class="mt-4 flex flex-wrap gap-2">
|
||||
<div
|
||||
class="modal-item flex w-[110px] cursor-pointer flex-col items-center overflow-hidden rounded-[5px] border-[3px]"
|
||||
class="flex w-28 cursor-pointer flex-col items-center overflow-hidden rounded-lg border-2"
|
||||
:class="[
|
||||
selectModel === model.key
|
||||
? 'border-[#1293ff!important]'
|
||||
: 'border-transparent',
|
||||
selectModel === model.key ? '!border-blue-500' : 'border-transparent',
|
||||
]"
|
||||
v-for="model in Dall3Models"
|
||||
:key="model.key"
|
||||
|
@ -192,20 +190,20 @@ defineExpose({ settingValues });
|
|||
fit="contain"
|
||||
@click="handleModelClick(model)"
|
||||
/>
|
||||
<div class="model-font text-[14px] font-bold text-[#3e3e3e]">
|
||||
<div class="text-sm font-bold text-gray-600">
|
||||
{{ model.name }}
|
||||
</div>
|
||||
</div>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
<div class="image-style mt-[30px]">
|
||||
<div class="mt-8">
|
||||
<div><b>风格选择</b></div>
|
||||
<Space wrap class="image-style-list mt-[15px] flex flex-wrap gap-[10px]">
|
||||
<Space wrap class="mt-4 flex flex-wrap gap-2">
|
||||
<div
|
||||
class="image-style-item flex w-[110px] cursor-pointer flex-col items-center overflow-hidden rounded-[5px] border-[3px]"
|
||||
class="flex w-28 cursor-pointer flex-col items-center overflow-hidden rounded-lg border-2"
|
||||
:class="[
|
||||
style === imageStyle.key ? 'border-[#1293ff]' : 'border-transparent',
|
||||
style === imageStyle.key ? 'border-blue-500' : 'border-transparent',
|
||||
]"
|
||||
v-for="imageStyle in Dall3StyleList"
|
||||
:key="imageStyle.key"
|
||||
|
@ -216,41 +214,38 @@ defineExpose({ settingValues });
|
|||
fit="contain"
|
||||
@click="handleStyleClick(imageStyle)"
|
||||
/>
|
||||
<div class="style-font text-[14px] font-bold text-[#3e3e3e]">
|
||||
<div class="text-sm font-bold text-gray-600">
|
||||
{{ imageStyle.name }}
|
||||
</div>
|
||||
</div>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
<div class="image-size mt-[30px] w-full">
|
||||
<div class="mt-8 w-full">
|
||||
<div><b>画面比例</b></div>
|
||||
<Space
|
||||
wrap
|
||||
class="size-list mt-[20px] flex w-full flex-row justify-between"
|
||||
>
|
||||
<Space wrap class="mt-5 flex w-full flex-wrap gap-2">
|
||||
<div
|
||||
class="size-item flex cursor-pointer flex-col items-center"
|
||||
class="flex cursor-pointer flex-col items-center"
|
||||
v-for="imageSize in Dall3SizeList"
|
||||
:key="imageSize.key"
|
||||
@click="handleSizeClick(imageSize)"
|
||||
>
|
||||
<div
|
||||
class="size-wrapper flex h-[50px] w-[50px] flex-col items-center justify-center rounded-[7px] border bg-white p-[4px]"
|
||||
class="flex h-12 w-12 flex-col items-center justify-center rounded-lg border bg-white p-0"
|
||||
:class="[
|
||||
selectSize === imageSize.key ? 'border-[#1293ff]' : 'border-white',
|
||||
selectSize === imageSize.key ? 'border-blue-500' : 'border-white',
|
||||
]"
|
||||
>
|
||||
<div :style="imageSize.style"></div>
|
||||
</div>
|
||||
<div class="size-font text-[14px] font-bold text-[#3e3e3e]">
|
||||
<div class="text-sm font-bold text-gray-600">
|
||||
{{ imageSize.name }}
|
||||
</div>
|
||||
</div>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
<div class="btns mt-[50px] flex justify-center">
|
||||
<div class="mt-12 flex justify-center">
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
|
|
|
@ -150,7 +150,7 @@ defineExpose({ settingValues });
|
|||
v-model:value="prompt"
|
||||
:maxlength="1024"
|
||||
:rows="5"
|
||||
class="mt-[15px] w-full"
|
||||
class="mt-4 w-full"
|
||||
placeholder="例如:童话里的小屋应该是什么样子?"
|
||||
show-count
|
||||
/>
|
||||
|
@ -172,38 +172,38 @@ defineExpose({ settingValues });
|
|||
</Space>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 w-full">
|
||||
<div class="mt-8">
|
||||
<div><b>尺寸</b></div>
|
||||
<Space wrap class="mt-5 flex w-full flex-row justify-between">
|
||||
<Space wrap class="mt-4 flex w-full flex-wrap gap-2">
|
||||
<div
|
||||
class="flex cursor-pointer flex-col items-center"
|
||||
class="flex cursor-pointer flex-col items-center overflow-hidden"
|
||||
v-for="imageSize in MidjourneySizeList"
|
||||
:key="imageSize.key"
|
||||
@click="handleSizeClick(imageSize)"
|
||||
>
|
||||
<div
|
||||
class="flex h-[50px] w-[50px] items-center justify-center rounded-[7px] border bg-white p-1"
|
||||
class="flex h-12 w-12 items-center justify-center rounded-lg border bg-white p-0"
|
||||
:class="[
|
||||
selectSize === imageSize.key ? 'border-[#1293ff]' : 'border-white',
|
||||
selectSize === imageSize.key ? 'border-blue-500' : 'border-white',
|
||||
]"
|
||||
>
|
||||
<div :style="imageSize.style"></div>
|
||||
</div>
|
||||
<div class="text-sm font-bold text-[#3e3e3e]">{{ imageSize.key }}</div>
|
||||
<div class="text-sm font-bold text-gray-600">{{ imageSize.key }}</div>
|
||||
</div>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
<div class="mt-8">
|
||||
<div><b>模型</b></div>
|
||||
<Space wrap class="mt-4 flex flex-wrap gap-4">
|
||||
<Space wrap class="mt-4 flex flex-wrap gap-2">
|
||||
<div
|
||||
v-for="model in MidjourneyModels"
|
||||
:key="model.key"
|
||||
class="flex w-[150px] cursor-pointer flex-col items-center overflow-hidden border-[3px]"
|
||||
class="flex max-w-40 cursor-pointer flex-col items-center overflow-hidden"
|
||||
:class="[
|
||||
selectModel === model.key
|
||||
? 'rounded border-[#1293ff]'
|
||||
? 'rounded border-blue-500'
|
||||
: 'border-transparent',
|
||||
]"
|
||||
>
|
||||
|
@ -213,17 +213,17 @@ defineExpose({ settingValues });
|
|||
fit="contain"
|
||||
@click="handleModelClick(model)"
|
||||
/>
|
||||
<div class="text-sm font-bold text-[#3e3e3e]">{{ model.name }}</div>
|
||||
<div class="text-sm font-bold text-gray-600">{{ model.name }}</div>
|
||||
</div>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<div class="mt-8">
|
||||
<div><b>版本</b></div>
|
||||
<Space wrap class="mt-5 w-full">
|
||||
<Space wrap class="mt-5 flex w-full flex-wrap gap-2">
|
||||
<Select
|
||||
v-model:value="selectVersion"
|
||||
class="!w-[330px]"
|
||||
class="!w-80"
|
||||
clearable
|
||||
placeholder="请选择版本"
|
||||
>
|
||||
|
@ -245,7 +245,7 @@ defineExpose({ settingValues });
|
|||
</Space>
|
||||
</div>
|
||||
|
||||
<div class="mt-[50px] flex justify-center">
|
||||
<div class="mt-8 flex justify-center">
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
|
|
|
@ -140,16 +140,16 @@ defineExpose({ settingValues });
|
|||
v-model:value="prompt"
|
||||
:maxlength="1024"
|
||||
:rows="5"
|
||||
class="mt-[15px] w-full"
|
||||
class="mt-4 w-full"
|
||||
placeholder="例如:童话里的小屋应该是什么样子?"
|
||||
show-count
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 热词区域 -->
|
||||
<div class="mt-[30px] flex flex-col">
|
||||
<div class="mt-8 flex flex-col">
|
||||
<div><b>随机热词</b></div>
|
||||
<Space wrap class="mt-[15px] flex flex-wrap justify-start">
|
||||
<Space wrap class="mt-4 flex flex-wrap gap-2">
|
||||
<Button
|
||||
shape="round"
|
||||
class="m-0"
|
||||
|
@ -164,14 +164,14 @@ defineExpose({ settingValues });
|
|||
</div>
|
||||
|
||||
<!-- 参数项:采样方法 -->
|
||||
<div class="mt-[30px]">
|
||||
<div class="mt-8">
|
||||
<div><b>采样方法</b></div>
|
||||
<Space wrap class="mt-[15px] w-full">
|
||||
<Space wrap class="mt-4 w-full">
|
||||
<Select
|
||||
v-model:value="sampler"
|
||||
placeholder="Select"
|
||||
size="large"
|
||||
class="!w-[330px]"
|
||||
class="!w-80"
|
||||
>
|
||||
<Select.Option
|
||||
v-for="item in StableDiffusionSamplers"
|
||||
|
@ -185,14 +185,14 @@ defineExpose({ settingValues });
|
|||
</div>
|
||||
|
||||
<!-- CLIP -->
|
||||
<div class="mt-[30px]">
|
||||
<div class="mt-8">
|
||||
<div><b>CLIP</b></div>
|
||||
<Space wrap class="mt-[15px] w-full">
|
||||
<Space wrap class="mt-4 w-full">
|
||||
<Select
|
||||
v-model:value="clipGuidancePreset"
|
||||
placeholder="Select"
|
||||
size="large"
|
||||
class="!w-[330px]"
|
||||
class="!w-80"
|
||||
>
|
||||
<Select.Option
|
||||
v-for="item in StableDiffusionClipGuidancePresets"
|
||||
|
@ -206,14 +206,14 @@ defineExpose({ settingValues });
|
|||
</div>
|
||||
|
||||
<!-- 风格 -->
|
||||
<div class="mt-[30px]">
|
||||
<div class="mt-8">
|
||||
<div><b>风格</b></div>
|
||||
<Space wrap class="mt-[15px] w-full">
|
||||
<Space wrap class="mt-4 w-full">
|
||||
<Select
|
||||
v-model:value="stylePreset"
|
||||
placeholder="Select"
|
||||
size="large"
|
||||
class="!w-[330px]"
|
||||
class="!w-80"
|
||||
>
|
||||
<Select.Option
|
||||
v-for="item in StableDiffusionStylePresets"
|
||||
|
@ -228,64 +228,68 @@ defineExpose({ settingValues });
|
|||
</div>
|
||||
|
||||
<!-- 图片尺寸 -->
|
||||
<div class="mt-[30px]">
|
||||
<div class="mt-8">
|
||||
<div><b>图片尺寸</b></div>
|
||||
<Space wrap class="mt-[15px] w-full">
|
||||
<Space wrap class="mt-4 w-full">
|
||||
<InputNumber
|
||||
v-model:value="width"
|
||||
class="w-[170px]"
|
||||
class="w-40"
|
||||
placeholder="图片宽度"
|
||||
addon-before="宽"
|
||||
addon-after="px"
|
||||
/>
|
||||
<InputNumber
|
||||
v-model:value="height"
|
||||
class="w-[170px]"
|
||||
class="w-40"
|
||||
placeholder="图片高度"
|
||||
addon-before="高"
|
||||
addon-after="px"
|
||||
/>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
<!-- 迭代步数 -->
|
||||
<div class="mt-[30px]">
|
||||
<div class="mt-8">
|
||||
<div><b>迭代步数</b></div>
|
||||
<Space wrap class="mt-[15px] w-full">
|
||||
<Space wrap class="mt-4 w-full">
|
||||
<InputNumber
|
||||
v-model:value="steps"
|
||||
size="large"
|
||||
class="!w-[330px]"
|
||||
class="!w-80"
|
||||
placeholder="Please input"
|
||||
/>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
<!-- 引导系数 -->
|
||||
<div class="mt-[30px]">
|
||||
<div class="mt-8">
|
||||
<div><b>引导系数</b></div>
|
||||
<Space wrap class="mt-[15px] w-full">
|
||||
<Space wrap class="mt-4 w-full">
|
||||
<InputNumber
|
||||
v-model:value="scale"
|
||||
type="number"
|
||||
size="large"
|
||||
class="!w-[330px]"
|
||||
class="!w-80"
|
||||
placeholder="Please input"
|
||||
/>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
<!-- 随机因子 -->
|
||||
<div class="mt-[30px]">
|
||||
<div class="mt-8">
|
||||
<div><b>随机因子</b></div>
|
||||
<Space wrap class="mt-[15px] w-full">
|
||||
<Space wrap class="mt-4 w-full">
|
||||
<InputNumber
|
||||
v-model:value="seed"
|
||||
size="large"
|
||||
class="!w-[330px]"
|
||||
class="!w-80"
|
||||
placeholder="Please input"
|
||||
/>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
<!-- 生成按钮 -->
|
||||
<div class="mt-[50px] flex justify-center">
|
||||
<div class="mt-12 flex justify-center">
|
||||
<Button
|
||||
type="primary"
|
||||
size="large"
|
||||
|
|
|
@ -90,16 +90,16 @@ onMounted(async () => {
|
|||
|
||||
<template>
|
||||
<Page auto-content-height>
|
||||
<div class="ai-image absolute inset-0 flex h-full w-full flex-row">
|
||||
<div class="left flex w-[390px] flex-col p-5">
|
||||
<div class="absolute inset-0 flex h-full w-full flex-row bg-gray-50">
|
||||
<div class="left-0 flex w-96 flex-col p-4">
|
||||
<div class="segmented flex justify-center">
|
||||
<Segmented
|
||||
v-model:value="selectPlatform"
|
||||
:options="platformOptions"
|
||||
class="bg-[#ececec]"
|
||||
class="bg-gray-100"
|
||||
/>
|
||||
</div>
|
||||
<div class="modal-switch-container mt-[30px] h-full overflow-y-auto">
|
||||
<div class="mt-8 h-full overflow-y-auto">
|
||||
<Common
|
||||
v-if="selectPlatform === 'common'"
|
||||
ref="commonRef"
|
||||
|
@ -126,7 +126,7 @@ onMounted(async () => {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main flex-1 bg-white">
|
||||
<div class="ml-4 flex-1 bg-white">
|
||||
<ImageList ref="imageListRef" @on-regeneration="handleRegeneration" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -100,7 +100,7 @@ onMounted(async () => {
|
|||
<TableAction :actions="[]" />
|
||||
</template>
|
||||
<template #picUrl="{ row }">
|
||||
<Image :src="row.picUrl" class="h-80px w-80px" />
|
||||
<Image :src="row.picUrl" class="h-20 w-20" />
|
||||
</template>
|
||||
<template #userId="{ row }">
|
||||
<span>
|
||||
|
|
|
@ -6,7 +6,7 @@ import { onMounted, reactive, ref } from 'vue';
|
|||
import { Page } from '@vben/common-ui';
|
||||
|
||||
import { useDebounceFn } from '@vueuse/core';
|
||||
import { Input, Pagination } from 'ant-design-vue';
|
||||
import { Image, Input, Pagination } from 'ant-design-vue';
|
||||
|
||||
import { getImagePageMy } from '#/api/ai/image';
|
||||
|
||||
|
@ -45,32 +45,28 @@ onMounted(async () => {
|
|||
</script>
|
||||
<template>
|
||||
<Page auto-content-height>
|
||||
<div class="bg-white p-[20px]">
|
||||
<!-- TODO @fan:Search 可以换成 Icon 组件么? -->
|
||||
<div class="bg-white p-5">
|
||||
<Input.Search
|
||||
v-model="queryParams.prompt"
|
||||
class="mb-[20px] w-full"
|
||||
class="mb-5 w-full"
|
||||
size="large"
|
||||
placeholder="请输入要搜索的内容"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
<div
|
||||
class="grid gap-[10px] bg-white shadow-[0_0_10px_rgba(0,0,0,0.1)]"
|
||||
style="grid-template-columns: repeat(auto-fill, minmax(200px, 1fr))"
|
||||
class="grid grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-2.5 bg-white shadow-sm"
|
||||
>
|
||||
<!-- TODO @fan:这个图片的风格,要不和 ImageCard.vue 界面一致?(只有卡片,没有操作);因为看着更有相框的感觉~~~ -->
|
||||
<div
|
||||
v-for="item in list"
|
||||
:key="item.id"
|
||||
class="relative cursor-pointer overflow-hidden bg-white transition-transform duration-300 hover:scale-[1.05]"
|
||||
class="relative cursor-pointer overflow-hidden bg-white transition-transform duration-300 hover:scale-105"
|
||||
>
|
||||
<img
|
||||
<Image
|
||||
:src="item.picUrl"
|
||||
class="block h-auto w-full transition-transform duration-300 hover:scale-[1.1]"
|
||||
class="block h-auto w-full transition-transform duration-300 hover:scale-110"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- TODO @fan:缺少翻页 -->
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
|
@ -81,7 +77,7 @@ onMounted(async () => {
|
|||
v-model:page-size="queryParams.pageSize"
|
||||
@change="debounceGetList"
|
||||
@show-size-change="debounceGetList"
|
||||
class="mt-[20px]"
|
||||
class="mt-5"
|
||||
/>
|
||||
</div>
|
||||
</Page>
|
||||
|
|
|
@ -114,16 +114,16 @@ onBeforeUnmount(() => {
|
|||
<template>
|
||||
<div>
|
||||
<!-- 文件处理列表 -->
|
||||
<div class="mt-[15px] grid grid-cols-1 gap-2">
|
||||
<div class="mt-4 grid grid-cols-1 gap-2">
|
||||
<div
|
||||
v-for="(file, index) in modelValue.list"
|
||||
:key="index"
|
||||
class="flex items-center rounded-sm border-l-4 border-l-[#409eff] px-[12px] py-[4px] shadow-sm transition-all duration-300 hover:bg-[#ecf5ff]"
|
||||
class="flex items-center rounded-sm border-l-4 border-l-blue-500 px-3 py-1 shadow-sm transition-all duration-300 hover:bg-blue-50"
|
||||
>
|
||||
<!-- 文件图标和名称 -->
|
||||
<div class="mr-[10px] flex min-w-[200px] items-center">
|
||||
<IconifyIcon icon="lucide:file-text" class="mr-8px text-[#409eff]" />
|
||||
<span class="break-all text-[13px] text-[#303133]">
|
||||
<div class="mr-2 flex min-w-48 items-center">
|
||||
<IconifyIcon icon="lucide:file-text" class="mr-2 text-blue-500" />
|
||||
<span class="break-all text-sm text-gray-600">
|
||||
{{ file.name }}
|
||||
</span>
|
||||
</div>
|
||||
|
@ -138,14 +138,14 @@ onBeforeUnmount(() => {
|
|||
</div>
|
||||
|
||||
<!-- 分段数量 -->
|
||||
<div class="ml-[10px] text-[13px] text-[#606266]">
|
||||
<div class="ml-2 text-sm text-gray-400">
|
||||
分段数量:{{ file.count ? file.count : '-' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部完成按钮 -->
|
||||
<div class="mt-[20px] flex justify-end">
|
||||
<div class="mt-5 flex justify-end">
|
||||
<Button
|
||||
:type="allProcessComplete ? 'primary' : 'default'"
|
||||
:disabled="!allProcessComplete"
|
||||
|
|
|
@ -168,9 +168,9 @@ onMounted(async () => {
|
|||
<template>
|
||||
<div>
|
||||
<!-- 上部分段设置部分 -->
|
||||
<div class="mb-[20px]">
|
||||
<div class="mb-[20px] flex items-center justify-between">
|
||||
<div class="flex items-center text-[16px] font-bold">
|
||||
<div class="mb-5">
|
||||
<div class="mb-5 flex items-center justify-between">
|
||||
<div class="flex items-center text-base font-bold">
|
||||
分段设置
|
||||
<Tooltip placement="top">
|
||||
<template #title>
|
||||
|
@ -178,7 +178,7 @@ onMounted(async () => {
|
|||
</template>
|
||||
<IconifyIcon
|
||||
icon="lucide:circle-alert"
|
||||
class="ml-[5px] text-gray-400"
|
||||
class="ml-1 text-gray-400"
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
@ -188,7 +188,7 @@ onMounted(async () => {
|
|||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="segment-settings mb-[20px]">
|
||||
<div class="mb-5">
|
||||
<Form :label-col="{ span: 5 }">
|
||||
<Form.Item label="最大 Token 数">
|
||||
<InputNumber
|
||||
|
@ -200,24 +200,24 @@ onMounted(async () => {
|
|||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-[10px]">
|
||||
<div class="mb-[10px] text-[16px] font-bold">分段预览</div>
|
||||
<div class="mb-2.5">
|
||||
<div class="mb-2.5 text-base font-bold">分段预览</div>
|
||||
<!-- 文件选择器 -->
|
||||
<div class="file-selector mb-[10px]">
|
||||
<div class="mb-2.5">
|
||||
<Dropdown
|
||||
v-if="modelData.list && modelData.list.length > 0"
|
||||
trigger="click"
|
||||
>
|
||||
<div class="flex cursor-pointer items-center">
|
||||
<IconifyIcon icon="lucide:file-text" class="text-danger mr-[5px]" />
|
||||
<IconifyIcon icon="lucide:file-text" class="mr-1" />
|
||||
<span>{{ currentFile?.name || '请选择文件' }}</span>
|
||||
<span
|
||||
v-if="currentFile?.segments"
|
||||
class="ml-5px text-[12px] text-gray-500"
|
||||
class="ml-1 text-sm text-gray-500"
|
||||
>
|
||||
({{ currentFile.segments.length }}个分片)
|
||||
</span>
|
||||
<IconifyIcon icon="lucide:chevron-down" class="ml-[5px]" />
|
||||
<IconifyIcon icon="lucide:chevron-down" class="ml-1" />
|
||||
</div>
|
||||
<template #overlay>
|
||||
<Menu>
|
||||
|
@ -227,10 +227,7 @@ onMounted(async () => {
|
|||
@click="selectFile(index)"
|
||||
>
|
||||
{{ file.name }}
|
||||
<span
|
||||
v-if="file.segments"
|
||||
class="ml-[5px] text-[12px] text-gray-500"
|
||||
>
|
||||
<span v-if="file.segments" class="ml-1 text-sm text-gray-500">
|
||||
({{ file.segments.length }}个分片)
|
||||
</span>
|
||||
</Menu.Item>
|
||||
|
@ -240,15 +237,10 @@ onMounted(async () => {
|
|||
<div v-else class="text-gray-400">暂无上传文件</div>
|
||||
</div>
|
||||
<!-- 文件内容预览 -->
|
||||
<div
|
||||
class="file-preview max-h-[600px] overflow-y-auto rounded-md bg-gray-50 p-[15px]"
|
||||
>
|
||||
<div
|
||||
v-if="splitLoading"
|
||||
class="flex items-center justify-center py-[20px]"
|
||||
>
|
||||
<div class="max-h-[600px] overflow-y-auto rounded-md bg-gray-50 p-4">
|
||||
<div v-if="splitLoading" class="flex items-center justify-center py-5">
|
||||
<IconifyIcon icon="lucide:loader" class="is-loading" />
|
||||
<span class="ml-[10px]">正在加载分段内容...</span>
|
||||
<span class="ml-2.5">正在加载分段内容...</span>
|
||||
</div>
|
||||
<template
|
||||
v-else-if="
|
||||
|
@ -260,13 +252,13 @@ onMounted(async () => {
|
|||
<div
|
||||
v-for="(segment, index) in currentFile.segments"
|
||||
:key="index"
|
||||
class="mb-[10px]"
|
||||
class="mb-2.5"
|
||||
>
|
||||
<div class="mb-[5px] text-[12px] text-gray-500">
|
||||
<div class="mb-1 text-sm text-gray-500">
|
||||
分片-{{ index + 1 }} · {{ segment.contentLength || 0 }} 字符数 ·
|
||||
{{ segment.tokens || 0 }} Token
|
||||
</div>
|
||||
<div class="rounded-md bg-white p-[10px]">
|
||||
<div class="rounded-md bg-white p-2">
|
||||
{{ segment.content }}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -275,7 +267,7 @@ onMounted(async () => {
|
|||
</div>
|
||||
</div>
|
||||
<!-- 添加底部按钮 -->
|
||||
<div class="mt-[20px] flex justify-between">
|
||||
<div class="mt-5 flex justify-between">
|
||||
<div>
|
||||
<Button v-if="!modelData.id" @click="handlePrevStep">上一步</Button>
|
||||
</div>
|
||||
|
|
|
@ -186,11 +186,11 @@ onMounted(() => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Form ref="formRef" :model="modelData" label-width="0" class="mt-[20px]">
|
||||
<Form.Item class="mb-[20px]">
|
||||
<Form ref="formRef" :model="modelData" label-width="0" class="mt-5">
|
||||
<Form.Item class="mb-5">
|
||||
<div class="w-full">
|
||||
<div
|
||||
class="w-full rounded-md border-2 border-dashed border-[#dcdfe6] p-[20px] text-center hover:border-[#409eff]"
|
||||
class="w-full rounded-md border-2 border-dashed border-gray-200 p-5 text-center hover:border-blue-500"
|
||||
>
|
||||
<UploadDragger
|
||||
ref="uploadRef"
|
||||
|
@ -203,18 +203,18 @@ onMounted(() => {
|
|||
:custom-request="customRequest"
|
||||
:multiple="true"
|
||||
>
|
||||
<div class="flex flex-col items-center justify-center py-[20px]">
|
||||
<div class="flex flex-col items-center justify-center py-5">
|
||||
<IconifyIcon
|
||||
icon="ep:upload-filled"
|
||||
class="mb-[10px] text-[48px] text-[#c0c4cc]"
|
||||
class="mb-2.5 text-xs text-gray-400"
|
||||
/>
|
||||
<div class="ant-upload-text text-[16px] text-[#606266]">
|
||||
<div class="ant-upload-text text-base text-gray-400">
|
||||
拖拽文件至此,或者
|
||||
<em class="cursor-pointer not-italic text-[#409eff]">
|
||||
<em class="cursor-pointer not-italic text-blue-500">
|
||||
选择文件
|
||||
</em>
|
||||
</div>
|
||||
<div class="ant-upload-tip mt-10px text-[12px] text-[#909399]">
|
||||
<div class="mt-2.5 text-sm text-gray-400">
|
||||
已支持 {{ supportedFileTypes.join('、') }},每个文件不超过
|
||||
{{ maxFileSize }} MB。
|
||||
</div>
|
||||
|
@ -223,19 +223,16 @@ onMounted(() => {
|
|||
</div>
|
||||
<div
|
||||
v-if="modelData.list && modelData.list.length > 0"
|
||||
class="mt-[15px] grid grid-cols-1 gap-2"
|
||||
class="mt-4 grid grid-cols-1 gap-2"
|
||||
>
|
||||
<div
|
||||
v-for="(file, index) in modelData.list"
|
||||
:key="index"
|
||||
class="flex items-center justify-between rounded-sm border-l-4 border-l-[#409eff] px-[12px] py-[4px] shadow-sm transition-all duration-300 hover:bg-[#ecf5ff]"
|
||||
class="flex items-center justify-between rounded-sm border-l-4 border-l-blue-500 px-3 py-1 shadow-sm transition-all duration-300 hover:bg-blue-50"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<IconifyIcon
|
||||
icon="lucide:file-text"
|
||||
class="mr-[8px] text-[#409eff]"
|
||||
/>
|
||||
<span class="break-all text-[13px] text-[#303133]">{{
|
||||
<IconifyIcon icon="lucide:file-text" class="mr-2 text-blue-500" />
|
||||
<span class="break-all text-sm text-gray-600">{{
|
||||
file.name
|
||||
}}</span>
|
||||
</div>
|
||||
|
@ -246,7 +243,7 @@ onMounted(() => {
|
|||
@click="removeFile(index)"
|
||||
class="ml-2"
|
||||
>
|
||||
<IconifyIcon icon="lucide:trash" />
|
||||
<IconifyIcon icon="lucide:trash-2" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -131,26 +131,26 @@ defineExpose({
|
|||
<div class="mx-auto">
|
||||
<!-- 头部导航栏 -->
|
||||
<div
|
||||
class="border-bottom absolute left-0 right-0 top-0 z-10 flex h-[50px] items-center bg-white px-[20px]"
|
||||
class="absolute left-0 right-0 top-0 z-10 flex h-12 items-center border-b bg-white px-4"
|
||||
>
|
||||
<!-- 左侧标题 -->
|
||||
<div class="flex w-[200px] items-center overflow-hidden">
|
||||
<div class="flex w-48 items-center overflow-hidden">
|
||||
<ArrowLeft
|
||||
class="size-5 flex-shrink-0 cursor-pointer"
|
||||
@click="handleBack"
|
||||
/>
|
||||
<span class="ml-10px text-16px truncate">
|
||||
<span class="ml-2.5 truncate text-base">
|
||||
{{ formData.id ? '编辑知识库文档' : '创建知识库文档' }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 步骤条 -->
|
||||
<div class="flex h-full flex-1 items-center justify-center">
|
||||
<div class="flex h-full w-[400px] items-center justify-between">
|
||||
<div class="flex h-full w-96 items-center justify-between">
|
||||
<div
|
||||
v-for="(step, index) in steps"
|
||||
:key="index"
|
||||
class="relative mx-[15px] flex h-full cursor-pointer items-center"
|
||||
class="relative mx-4 flex h-full cursor-pointer items-center"
|
||||
:class="[
|
||||
currentStep === index
|
||||
? 'border-b-2 border-solid border-blue-500 text-blue-500'
|
||||
|
@ -158,7 +158,7 @@ defineExpose({
|
|||
]"
|
||||
>
|
||||
<div
|
||||
class="mr-2 flex h-7 w-7 items-center justify-center rounded-full border-2 border-solid text-[15px]"
|
||||
class="mr-2 flex h-7 w-7 items-center justify-center rounded-full border-2 border-solid text-base"
|
||||
:class="[
|
||||
currentStep === index
|
||||
? 'border-blue-500 bg-blue-500 text-white'
|
||||
|
@ -176,7 +176,7 @@ defineExpose({
|
|||
</div>
|
||||
<!-- 主体内容 -->
|
||||
<Card :body-style="{ padding: '10px' }" class="mb-4">
|
||||
<div class="mt-[50px]">
|
||||
<div class="mt-12">
|
||||
<!-- 第一步:上传文档 -->
|
||||
<div v-if="currentStep === 0" class="mx-auto w-[560px]">
|
||||
<UploadStep v-model="formData" ref="uploadDocumentRef" />
|
||||
|
|
|
@ -83,7 +83,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal class="w-[600px]" :title="getTitle">
|
||||
<Modal class="w-2/5" :title="getTitle">
|
||||
<Form class="mx-4" />
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -94,12 +94,11 @@ onMounted(() => {
|
|||
<Card class="min-w-300 flex-1">
|
||||
<div class="mb-15">
|
||||
<h3
|
||||
class="m-0 mb-2 font-semibold leading-none tracking-tight"
|
||||
style="font-size: 18px"
|
||||
class="m-0 mb-2 text-lg font-semibold leading-none tracking-tight"
|
||||
>
|
||||
召回测试
|
||||
</h3>
|
||||
<div class="text-14 text-gray-500">
|
||||
<div class="text-sm text-gray-500">
|
||||
根据给定的查询文本测试召回效果。
|
||||
</div>
|
||||
</div>
|
||||
|
@ -110,7 +109,7 @@ onMounted(() => {
|
|||
:rows="8"
|
||||
placeholder="请输入文本"
|
||||
/>
|
||||
<div class="text-12 absolute bottom-2 right-2 text-gray-400">
|
||||
<div class="absolute bottom-2 right-2 text-sm text-gray-400">
|
||||
{{ queryParams.content?.length }} / 200
|
||||
</div>
|
||||
</div>
|
||||
|
@ -148,7 +147,7 @@ onMounted(() => {
|
|||
<Card class="min-w-300 flex-1">
|
||||
<!-- 加载中状态 -->
|
||||
<template v-if="loading">
|
||||
<div class="flex h-[300px] items-center justify-center">
|
||||
<div class="flex h-72 items-center justify-center">
|
||||
<Empty description="正在检索中..." />
|
||||
</div>
|
||||
</template>
|
||||
|
@ -162,19 +161,19 @@ onMounted(() => {
|
|||
:key="index"
|
||||
class="p-15 mb-20 rounded border border-solid border-gray-200"
|
||||
>
|
||||
<div class="text-12 mb-5 flex justify-between text-gray-500">
|
||||
<div class="mb-5 flex justify-between text-sm text-gray-500">
|
||||
<span>
|
||||
分段({{ segment.id }}) · {{ segment.contentLength }} 字符数 ·
|
||||
{{ segment.tokens }} Token
|
||||
</span>
|
||||
<span
|
||||
class="-8 text-12 rounded-full bg-blue-50 py-4 font-bold text-blue-500"
|
||||
class="rounded-full bg-blue-50 py-4 text-sm font-bold text-blue-500"
|
||||
>
|
||||
score: {{ segment.score }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="text-13 mb-10 overflow-hidden whitespace-pre-wrap rounded bg-gray-50 p-10 transition-all duration-100"
|
||||
class="mb-10 overflow-hidden whitespace-pre-wrap rounded bg-gray-50 p-10 text-sm transition-all duration-100"
|
||||
:class="{
|
||||
'max-h-50 line-clamp-2': !segment.expanded,
|
||||
'max-h-500': segment.expanded,
|
||||
|
@ -183,7 +182,7 @@ onMounted(() => {
|
|||
{{ segment.content }}
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-13 flex items-center text-gray-500">
|
||||
<div class="flex items-center text-sm text-gray-500">
|
||||
<IconifyIcon icon="lucide:file-text" class="mr-5" />
|
||||
<span>{{ segment.documentName || '未知文档' }}</span>
|
||||
</div>
|
||||
|
@ -205,7 +204,7 @@ onMounted(() => {
|
|||
|
||||
<!-- 无召回结果 -->
|
||||
<template v-else>
|
||||
<div class="flex h-[300px] items-center justify-center">
|
||||
<div class="flex h-72 items-center justify-center">
|
||||
<Empty description="暂无召回结果" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -147,27 +147,9 @@ onMounted(() => {
|
|||
</template>
|
||||
<template #expand_content="{ row }">
|
||||
<div
|
||||
class="content-expand"
|
||||
style="
|
||||
padding: 10px 20px;
|
||||
line-height: 1.5;
|
||||
white-space: pre-wrap;
|
||||
background-color: #f9f9f9;
|
||||
border-left: 3px solid #409eff;
|
||||
border-radius: 4px;
|
||||
"
|
||||
class="whitespace-pre-wrap border-l-4 border-blue-500 bg-gray-100 px-2.5 py-5 leading-5"
|
||||
>
|
||||
<div
|
||||
class="content-title"
|
||||
style="
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #606266;
|
||||
"
|
||||
>
|
||||
完整内容:
|
||||
</div>
|
||||
<div class="mb-2 text-sm font-bold text-gray-600">完整内容:</div>
|
||||
{{ row.content }}
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -84,7 +84,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal class="w-[600px]" :title="getTitle">
|
||||
<Modal class="w-2/5" :title="getTitle">
|
||||
<Form class="mx-4" />
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -75,9 +75,10 @@ onMounted(() => {
|
|||
|
||||
<template>
|
||||
<Page auto-content-height>
|
||||
<div class="absolute bottom-0 left-0 right-0 top-0 flex">
|
||||
<div class="absolute bottom-0 left-0 right-0 top-0 m-4 flex">
|
||||
<Left
|
||||
ref="leftRef"
|
||||
class="mr-4"
|
||||
:is-generating="isGenerating"
|
||||
@submit="submit"
|
||||
@direct-generate="directGenerate"
|
||||
|
|
|
@ -23,10 +23,8 @@ defineExpose({
|
|||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="flex w-[350px] flex-col bg-[#f5f7f9] p-5">
|
||||
<h3
|
||||
class="h-[1.75rem] w-full text-center text-[1.25rem] leading-[28px] text-[hsl(var(--primary))]"
|
||||
>
|
||||
<div class="flex w-80 flex-col bg-gray-50 p-5">
|
||||
<h3 class="text-primary h-7 w-full text-center text-xl leading-7">
|
||||
思维导图创作中心
|
||||
</h3>
|
||||
<div class="flex-grow overflow-y-auto">
|
||||
|
@ -36,12 +34,12 @@ defineExpose({
|
|||
v-model:value="formData.prompt"
|
||||
:maxlength="1024"
|
||||
:rows="8"
|
||||
class="w-100% mt-15px"
|
||||
class="mt-4 w-full"
|
||||
placeholder="请输入提示词,让AI帮你完善"
|
||||
show-count
|
||||
/>
|
||||
<Button
|
||||
class="mt-[15px] !w-full"
|
||||
class="mt-4 !w-full"
|
||||
type="primary"
|
||||
:loading="isGenerating"
|
||||
@click="emits('submit', formData)"
|
||||
|
@ -49,18 +47,18 @@ defineExpose({
|
|||
智能生成思维导图
|
||||
</Button>
|
||||
</div>
|
||||
<div class="mt-[30px]">
|
||||
<div class="mt-7">
|
||||
<b>使用已有内容生成?</b>
|
||||
<Textarea
|
||||
v-model:value="generatedContent"
|
||||
:maxlength="1024"
|
||||
:rows="8"
|
||||
class="w-100% mt-15px"
|
||||
class="mt-4 w-full"
|
||||
placeholder="例如:童话里的小屋应该是什么样子?"
|
||||
show-count
|
||||
/>
|
||||
<Button
|
||||
class="mt-[15px] !w-full"
|
||||
class="mt-4 !w-full"
|
||||
type="primary"
|
||||
@click="emits('directGenerate', generatedContent)"
|
||||
:disabled="isGenerating"
|
||||
|
|
|
@ -153,7 +153,7 @@ defineExpose({
|
|||
:style="{ height: `${contentAreaHeight}px` }"
|
||||
class="w-full"
|
||||
/>
|
||||
<div ref="toolBarRef" class="absolute bottom-[10px] right-5"></div>
|
||||
<div ref="toolBarRef" class="absolute bottom-2.5 right-5"></div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
|
|
@ -93,7 +93,7 @@ onMounted(async () => {
|
|||
<template #doc>
|
||||
<DocAlert title="AI 思维导图" url="https://doc.iocoder.cn/ai/mindmap/" />
|
||||
</template>
|
||||
<Drawer class="w-[800px]">
|
||||
<Drawer class="w-3/5">
|
||||
<Right
|
||||
v-if="previewVisible"
|
||||
:generated-content="previewContent"
|
||||
|
|
|
@ -76,7 +76,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal class="w-[600px]" :title="getTitle">
|
||||
<Modal class="w-2/5" :title="getTitle">
|
||||
<Form class="mx-4" />
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -110,7 +110,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||
<span v-else>引用 {{ row.toolIds.length }} 个</span>
|
||||
</template>
|
||||
<template #avatar="{ row }">
|
||||
<Image :src="row.avatar" class="w-32px h-32px" />
|
||||
<Image :src="row.avatar" class="h-8 w-8" />
|
||||
</template>
|
||||
<template #actions="{ row }">
|
||||
<TableAction
|
||||
|
|
|
@ -82,7 +82,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal class="w-[600px]" :title="getTitle">
|
||||
<Modal class="w-2/5" :title="getTitle">
|
||||
<Form class="mx-4" />
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -77,7 +77,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal class="w-[600px]" :title="getTitle">
|
||||
<Modal class="w-2/5" :title="getTitle">
|
||||
<Form class="mx-4" />
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -76,7 +76,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal class="w-[600px]" :title="getTitle">
|
||||
<Modal class="w-2/5" :title="getTitle">
|
||||
<Form class="mx-4" />
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -18,7 +18,7 @@ function generateMusic(args: { formData: Recordable<any> }) {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Page>
|
||||
<Page auto-content-height>
|
||||
<div class="flex h-full items-stretch">
|
||||
<!-- 模式 -->
|
||||
<Mode class="flex-none" @generate-music="generateMusic" />
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
<script lang="ts" setup>
|
||||
import type { Nullable } from '@vben/types';
|
||||
|
||||
import { inject, reactive, ref } from 'vue';
|
||||
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
@ -10,9 +8,9 @@ import { Image, Slider } from 'ant-design-vue';
|
|||
|
||||
defineOptions({ name: 'AiMusicAudioBarIndex' });
|
||||
|
||||
const currentSong = inject('currentSong', {});
|
||||
const currentSong = inject<any>('currentSong', {});
|
||||
|
||||
const audioRef = ref<Nullable<HTMLElement>>(null);
|
||||
const audioRef = ref<HTMLAudioElement | null>(null);
|
||||
// 音频相关属性https://www.runoob.com/tags/ref-av-dom.html
|
||||
const audioProps = reactive<any>({
|
||||
autoplay: true,
|
||||
|
@ -42,26 +40,24 @@ function audioTimeUpdate(args: any) {
|
|||
|
||||
<template>
|
||||
<div
|
||||
class="b-solid b-1 b-l-none flex h-[72px] items-center justify-between px-2"
|
||||
style="background-color: #fffffd; border-color: #dcdfe6"
|
||||
class="b-1 b-l-none h-18 flex items-center justify-between border border-solid border-rose-100 bg-white px-2"
|
||||
>
|
||||
<!-- 歌曲信息 -->
|
||||
<div class="flex gap-[10px]">
|
||||
<div class="flex gap-2.5">
|
||||
<Image
|
||||
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
|
||||
:width="45"
|
||||
/>
|
||||
<div>
|
||||
<div>{{ currentSong.name }}</div>
|
||||
<div class="text-[12px] text-gray-400">{{ currentSong.singer }}</div>
|
||||
<div class="text-xs text-gray-400">{{ currentSong.singer }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 音频controls -->
|
||||
<div class="flex items-center gap-[12px]">
|
||||
<div class="flex items-center gap-3">
|
||||
<IconifyIcon
|
||||
icon="majesticons:back-circle"
|
||||
:size="20"
|
||||
class="cursor-pointer text-gray-300"
|
||||
class="size-5 cursor-pointer text-gray-300"
|
||||
/>
|
||||
<IconifyIcon
|
||||
:icon="
|
||||
|
@ -69,21 +65,19 @@ function audioTimeUpdate(args: any) {
|
|||
? 'mdi:arrow-right-drop-circle'
|
||||
: 'solar:pause-circle-bold'
|
||||
"
|
||||
:size="30"
|
||||
class="cursor-pointer"
|
||||
class="size-7 cursor-pointer"
|
||||
@click="toggleStatus('paused')"
|
||||
/>
|
||||
<IconifyIcon
|
||||
icon="majesticons:next-circle"
|
||||
:size="20"
|
||||
class="cursor-pointer text-gray-300"
|
||||
class="size-5 cursor-pointer text-gray-300"
|
||||
/>
|
||||
<div class="flex items-center gap-[16px]">
|
||||
<div class="flex items-center gap-4">
|
||||
<span>{{ audioProps.currentTime }}</span>
|
||||
<Slider
|
||||
v-model:value="audioProps.duration"
|
||||
color="#409eff"
|
||||
class="w-[160px!important]"
|
||||
class="!w-40"
|
||||
/>
|
||||
<span>{{ audioProps.duration }}</span>
|
||||
</div>
|
||||
|
@ -98,18 +92,13 @@ function audioTimeUpdate(args: any) {
|
|||
<!-- <source :src="audioUrl" /> -->
|
||||
</audio>
|
||||
</div>
|
||||
<div class="flex items-center gap-[16px]">
|
||||
<div class="flex items-center gap-4">
|
||||
<IconifyIcon
|
||||
:icon="audioProps.muted ? 'tabler:volume-off' : 'tabler:volume'"
|
||||
:size="20"
|
||||
class="cursor-pointer"
|
||||
class="size-5 cursor-pointer"
|
||||
@click="toggleStatus('muted')"
|
||||
/>
|
||||
<Slider
|
||||
v-model:value="audioProps.volume"
|
||||
color="#409eff"
|
||||
class="w-[160px!important]"
|
||||
/>
|
||||
<Slider v-model:value="audioProps.volume" color="#409eff" class="!w-40" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -74,7 +74,7 @@ provide('currentSong', currentSong);
|
|||
<div class="flex flex-auto overflow-hidden">
|
||||
<Tabs
|
||||
v-model:active-key="currentType"
|
||||
class="flex-auto px-[20px]"
|
||||
class="flex-auto px-5"
|
||||
tab-position="bottom"
|
||||
>
|
||||
<!-- 我的创作 -->
|
||||
|
|
|
@ -16,7 +16,7 @@ defineProps({
|
|||
|
||||
const emits = defineEmits(['play']);
|
||||
|
||||
const currentSong = inject('currentSong', {});
|
||||
const currentSong = inject<any>('currentSong', {});
|
||||
|
||||
function playSong() {
|
||||
emits('play');
|
||||
|
@ -24,11 +24,11 @@ function playSong() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="rounded-1 mb-[12px] flex p-[12px]">
|
||||
<div class="mb-3 flex rounded p-3">
|
||||
<div class="relative" @click="playSong">
|
||||
<Image :src="songInfo.imageUrl" class="w-80px flex-none" />
|
||||
<Image :src="songInfo.imageUrl" class="w-20 flex-none" />
|
||||
<div
|
||||
class="bg-op-40 absolute left-0 top-0 flex h-full w-full cursor-pointer items-center justify-center bg-black"
|
||||
class="absolute left-0 top-0 flex h-full w-full cursor-pointer items-center justify-center bg-black bg-opacity-40"
|
||||
>
|
||||
<IconifyIcon
|
||||
:icon="
|
||||
|
@ -40,9 +40,9 @@ function playSong() {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ml-[8px]">
|
||||
<div class="ml-2">
|
||||
<div>{{ songInfo.title }}</div>
|
||||
<div class="mt-[8px] line-clamp-2 text-[12px]">
|
||||
<div class="mt-2 line-clamp-2 text-xs">
|
||||
{{ songInfo.desc }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,21 +5,21 @@ import { Button, Card, Image } from 'ant-design-vue';
|
|||
|
||||
defineOptions({ name: 'AiMusicSongInfoIndex' });
|
||||
|
||||
const currentSong = inject('currentSong', {});
|
||||
const currentSong = inject<any>('currentSong', {});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Card class="line-height-24px mb-[0!important] w-[300px]">
|
||||
<Image :src="currentSong.imageUrl" style="width: 100%; height: 100%" />
|
||||
<Card class="!mb-0 w-40 leading-6">
|
||||
<Image :src="currentSong.imageUrl" class="h-full w-full" />
|
||||
|
||||
<div class="">{{ currentSong.title }}</div>
|
||||
<div class="line-clamp-1 text-[12px]">
|
||||
<div class="line-clamp-1 text-xs">
|
||||
{{ currentSong.desc }}
|
||||
</div>
|
||||
<div class="text-[12px]">
|
||||
<div class="text-xs">
|
||||
{{ currentSong.date }}
|
||||
</div>
|
||||
<Button size="small" shape="round" class="my-[6px]">信息复用</Button>
|
||||
<div class="text-[12px]" v-html="currentSong.lyric"></div>
|
||||
<Button size="small" shape="round" class="my-2">信息复用</Button>
|
||||
<div class="text-xs" v-html="currentSong.lyric"></div>
|
||||
</Card>
|
||||
</template>
|
||||
|
|
|
@ -33,7 +33,7 @@ defineExpose({
|
|||
/>
|
||||
</Title>
|
||||
|
||||
<Title title="纯音乐" class="mt-[20px]" desc="创建一首没有歌词的歌曲">
|
||||
<Title title="纯音乐" class="mt-5" desc="创建一首没有歌词的歌曲">
|
||||
<template #extra>
|
||||
<Switch v-model:checked="formData.pure" size="small" />
|
||||
</template>
|
||||
|
|
|
@ -27,8 +27,8 @@ function generateMusic() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Card class="mb-[0!important] h-full w-[300px]">
|
||||
<Radio.Group v-model:value="generateMode" class="mb-[15px]">
|
||||
<Card class="!mb-0 h-full w-80">
|
||||
<Radio.Group v-model:value="generateMode" class="mb-4">
|
||||
<Radio.Button value="desc"> 描述模式 </Radio.Button>
|
||||
<Radio.Button value="lyric"> 歌词模式 </Radio.Button>
|
||||
</Radio.Group>
|
||||
|
|
|
@ -37,7 +37,7 @@ defineExpose({
|
|||
|
||||
<Title title="音乐风格">
|
||||
<Space class="flex-wrap">
|
||||
<Tag v-for="tag in tags" :key="tag" class="mb-[8px]">
|
||||
<Tag v-for="tag in tags" :key="tag" class="mb-2">
|
||||
{{ tag }}
|
||||
</Tag>
|
||||
</Space>
|
||||
|
@ -46,7 +46,7 @@ defineExpose({
|
|||
:type="showCustom ? 'primary' : 'default'"
|
||||
shape="round"
|
||||
size="small"
|
||||
class="mb-[6px]"
|
||||
class="mb-2"
|
||||
@click="showCustom = !showCustom"
|
||||
>
|
||||
自定义风格
|
||||
|
@ -56,7 +56,7 @@ defineExpose({
|
|||
<Title
|
||||
v-show="showCustom"
|
||||
desc="描述您想要的音乐风格,Suno无法识别艺术家的名字,但可以理解流派和氛围"
|
||||
class="mt-[12px]"
|
||||
class="mt-3"
|
||||
>
|
||||
<Textarea
|
||||
v-model="formData.style"
|
||||
|
|
|
@ -14,12 +14,12 @@ defineProps({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mb-[12px]">
|
||||
<div class="flex items-center justify-between" style="color: #303133">
|
||||
<div class="mb-3">
|
||||
<div class="flex items-center justify-between text-gray-600">
|
||||
<span>{{ title }}</span>
|
||||
<slot name="extra"></slot>
|
||||
</div>
|
||||
<div class="my-[8px] text-[12px]" style="color: #909399">
|
||||
<div class="my-2 text-xs text-gray-400">
|
||||
{{ desc }}
|
||||
</div>
|
||||
<slot></slot>
|
||||
|
|
|
@ -111,7 +111,7 @@ onMounted(async () => {
|
|||
v-if="row.audioUrl?.length > 0"
|
||||
:href="row.audioUrl"
|
||||
target="_blank"
|
||||
style="padding: 0"
|
||||
class="p-0"
|
||||
>
|
||||
音乐
|
||||
</Button>
|
||||
|
@ -120,8 +120,7 @@ onMounted(async () => {
|
|||
v-if="row.videoUrl?.length > 0"
|
||||
:href="row.videoUrl"
|
||||
target="_blank"
|
||||
class="!pl-5px"
|
||||
style="padding: 0"
|
||||
class="p-0 !pl-1"
|
||||
>
|
||||
视频
|
||||
</Button>
|
||||
|
@ -130,8 +129,7 @@ onMounted(async () => {
|
|||
v-if="row.imageUrl?.length > 0"
|
||||
:href="row.imageUrl"
|
||||
target="_blank"
|
||||
class="!pl-5px"
|
||||
style="padding: 0"
|
||||
class="p-0 !pl-1"
|
||||
>
|
||||
封面
|
||||
</Button>
|
||||
|
@ -144,7 +142,7 @@ onMounted(async () => {
|
|||
/>
|
||||
</template>
|
||||
<template #tags="{ row }">
|
||||
<Tag v-for="tag in row.tags" :key="tag" class="ml-2px">
|
||||
<Tag v-for="tag in row.tags" :key="tag" class="ml-1">
|
||||
{{ tag }}
|
||||
</Tag>
|
||||
</template>
|
||||
|
|
|
@ -210,7 +210,7 @@ onBeforeUnmount(() => {
|
|||
class="absolute inset-x-0 top-0 z-10 flex h-12 items-center border-b bg-white px-5"
|
||||
>
|
||||
<!-- 左侧标题 -->
|
||||
<div class="flex w-[200px] items-center overflow-hidden">
|
||||
<div class="flex w-48 items-center overflow-hidden">
|
||||
<ArrowLeft
|
||||
class="size-5 flex-shrink-0 cursor-pointer"
|
||||
@click="handleBack"
|
||||
|
@ -225,11 +225,11 @@ onBeforeUnmount(() => {
|
|||
|
||||
<!-- 步骤条 -->
|
||||
<div class="flex h-full flex-1 items-center justify-center">
|
||||
<div class="flex h-full w-[400px] items-center justify-between">
|
||||
<div class="flex h-full w-96 items-center justify-between">
|
||||
<div
|
||||
v-for="(step, index) in steps"
|
||||
:key="index"
|
||||
class="relative mx-[15px] flex h-full cursor-pointer items-center"
|
||||
class="relative mx-4 flex h-full cursor-pointer items-center"
|
||||
:class="[
|
||||
currentStep === index
|
||||
? 'border-b-2 border-solid border-blue-500 text-blue-500'
|
||||
|
@ -238,7 +238,7 @@ onBeforeUnmount(() => {
|
|||
@click="handleStepClick(index)"
|
||||
>
|
||||
<div
|
||||
class="mr-2 flex h-7 w-7 items-center justify-center rounded-full border-2 border-solid text-[15px]"
|
||||
class="mr-2 flex h-7 w-7 items-center justify-center rounded-full border-2 border-solid text-base"
|
||||
:class="[
|
||||
currentStep === index
|
||||
? 'border-blue-500 bg-blue-500 text-white'
|
||||
|
@ -255,7 +255,7 @@ onBeforeUnmount(() => {
|
|||
</div>
|
||||
|
||||
<!-- 右侧按钮 -->
|
||||
<div class="flex w-[200px] items-center justify-end gap-2">
|
||||
<div class="flex w-48 items-center justify-end gap-2">
|
||||
<Button
|
||||
v-if="actionType === 'update'"
|
||||
type="primary"
|
||||
|
@ -271,7 +271,7 @@ onBeforeUnmount(() => {
|
|||
</div>
|
||||
<!-- 主体内容 -->
|
||||
<Card :body-style="{ padding: '10px' }" class="mb-4">
|
||||
<div class="mt-[50px]">
|
||||
<div class="mt-12">
|
||||
<!-- 第一步:基本信息 -->
|
||||
<div v-if="currentStep === 0" class="mx-auto w-4/6">
|
||||
<BasicInfo v-model="formData" ref="basicInfoRef" />
|
||||
|
|
|
@ -4,6 +4,7 @@ import type { Ref } from 'vue';
|
|||
import { inject, ref } from 'vue';
|
||||
|
||||
import { useVbenDrawer } from '@vben/common-ui';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { isNumber } from '@vben/utils';
|
||||
|
||||
import { Button, Input, Select } from 'ant-design-vue';
|
||||
|
@ -181,20 +182,20 @@ defineExpose({ validate });
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative h-[700px] w-[100%]">
|
||||
<div class="relative h-[700px] w-full">
|
||||
<Tinyflow
|
||||
v-if="workflowData"
|
||||
ref="tinyflowRef"
|
||||
class-name="custom-class"
|
||||
:style="{ width: '100%', height: '100%' }"
|
||||
class="h-full w-full"
|
||||
:data="workflowData"
|
||||
:provider="provider"
|
||||
/>
|
||||
<div class="absolute right-[30px] top-[30px]">
|
||||
<div class="absolute right-8 top-8">
|
||||
<Button
|
||||
@click="testWorkflowModel"
|
||||
type="primary"
|
||||
v-hasPermi="['ai:workflow:test']"
|
||||
v-access:code="['ai:workflow:test']"
|
||||
>
|
||||
测试
|
||||
</Button>
|
||||
|
@ -202,20 +203,18 @@ defineExpose({ validate });
|
|||
|
||||
<Drawer title="工作流测试">
|
||||
<fieldset
|
||||
class="min-inline-size-auto m-0 rounded-[6px] border border-[#dcdfe6] p-[12px_16px]"
|
||||
class="min-inline-size-auto m-0 rounded-lg border border-gray-200 px-3 py-4"
|
||||
>
|
||||
<legend
|
||||
class="ml-[8px] px-[10px] text-[16px] font-semibold text-[#303133]"
|
||||
>
|
||||
<legend class="ml-2 px-2.5 text-base font-semibold text-gray-600">
|
||||
<h3>运行参数配置</h3>
|
||||
</legend>
|
||||
<div class="p-[8px]">
|
||||
<div class="p-2">
|
||||
<div
|
||||
class="mb-[4px] flex items-center justify-around"
|
||||
class="mb-1 flex items-center justify-around"
|
||||
v-for="(param, index) in params4Test"
|
||||
:key="index"
|
||||
>
|
||||
<Select class="w-[200px]" v-model="param.key" placeholder="参数名">
|
||||
<Select class="w-48" v-model="param.key" placeholder="参数名">
|
||||
<Select.Option
|
||||
v-for="(value, key) in paramsOfStartNode"
|
||||
:key="key"
|
||||
|
@ -226,45 +225,44 @@ defineExpose({ validate });
|
|||
</Select.Option>
|
||||
</Select>
|
||||
<Input
|
||||
class="mx-[8px] w-[200px]"
|
||||
class="mx-2 w-48"
|
||||
v-model:value="param.value"
|
||||
placeholder="参数值"
|
||||
/>
|
||||
<Button danger plain circle @click="removeParam(index)">
|
||||
<template #icon>
|
||||
<span class="icon-[ant-design--delete-outlined]"></span>
|
||||
<IconifyIcon icon="lucide:trash" />
|
||||
</template>
|
||||
</Button>
|
||||
</div>
|
||||
<Button type="primary" plain class="mt-[8px]" @click="addParam">
|
||||
<Button type="primary" plain class="mt-2" @click="addParam">
|
||||
添加参数
|
||||
</Button>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset
|
||||
class="min-inline-size-auto m-0 mt-[8px] rounded-[6px] border border-[#dcdfe6] bg-[#f8f9fa] p-[12px_16px]"
|
||||
class="m-0 mt-2 rounded-lg border border-gray-200 bg-gray-50 px-3 py-4"
|
||||
>
|
||||
<legend
|
||||
class="ml-[8px] px-[10px] text-[16px] font-semibold text-[#303133]"
|
||||
>
|
||||
<legend class="ml-2 px-2.5 text-base font-semibold text-gray-600">
|
||||
<h3>运行结果</h3>
|
||||
</legend>
|
||||
<div class="p-[8px]">
|
||||
<div class="p-2">
|
||||
<div v-if="loading" class="text-primary">执行中...</div>
|
||||
<div v-else-if="error" class="text-danger">{{ error }}</div>
|
||||
<pre
|
||||
v-else-if="testResult"
|
||||
class="max-h-[300px] overflow-auto whitespace-pre-wrap rounded-[4px] bg-white p-[12px] font-mono text-[14px] leading-[1.5]"
|
||||
>{{ JSON.stringify(testResult, null, 2) }}
|
||||
class="max-h-80 overflow-auto whitespace-pre-wrap rounded-lg bg-white p-3 font-mono text-sm leading-5"
|
||||
>
|
||||
{{ JSON.stringify(testResult, null, 2) }}
|
||||
</pre>
|
||||
<div v-else class="text-[#909399]">点击运行查看结果</div>
|
||||
<div v-else class="text-gray-400">点击运行查看结果</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<Button
|
||||
size="large"
|
||||
class="mt-[8px] w-[100%] bg-[#67c23a] text-white"
|
||||
class="mt-2 w-full bg-green-500 text-white"
|
||||
@click="goRun"
|
||||
>
|
||||
运行流程
|
||||
|
|
|
@ -3,6 +3,8 @@ import type { AiWriteApi } from '#/api/ai/write';
|
|||
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { createReusableTemplate } from '@vueuse/core';
|
||||
import { Button, message, Textarea } from 'ant-design-vue';
|
||||
|
||||
|
@ -121,8 +123,8 @@ function submit() {
|
|||
<template>
|
||||
<DefineTab v-slot="{ active, text, itemClick }">
|
||||
<span
|
||||
:class="active ? 'text-black shadow-md' : 'hover:bg-[#DDDFE3]'"
|
||||
class="z-1 relative inline-block w-1/2 cursor-pointer rounded-full text-center leading-[30px] text-[5C6370] hover:text-black"
|
||||
:class="active ? 'text-black shadow-md' : 'hover:bg-gray-200'"
|
||||
class="relative z-10 inline-block w-1/2 cursor-pointer rounded-full text-center leading-7 text-gray-400 hover:text-black"
|
||||
@click="itemClick"
|
||||
>
|
||||
{{ text }}
|
||||
|
@ -130,27 +132,27 @@ function submit() {
|
|||
</DefineTab>
|
||||
<!-- 定义 label 组件:长度/格式/语气/语言等 -->
|
||||
<DefineLabel v-slot="{ label, hint, hintClick }">
|
||||
<h3 class="mb-3 mt-5 flex items-center justify-between text-[14px]">
|
||||
<h3 class="mb-3 mt-5 flex items-center justify-between text-sm">
|
||||
<span>{{ label }}</span>
|
||||
<span
|
||||
v-if="hint"
|
||||
class="flex cursor-pointer select-none items-center text-[12px] text-[#846af7]"
|
||||
class="flex cursor-pointer select-none items-center text-xs text-purple-500"
|
||||
@click="hintClick"
|
||||
>
|
||||
<span class="icon-[ant-design--question-circle-outlined]"> </span>
|
||||
<IconifyIcon icon="lucide:circle-help" />
|
||||
{{ hint }}
|
||||
</span>
|
||||
</h3>
|
||||
</DefineLabel>
|
||||
<div class="flex flex-col" v-bind="$attrs">
|
||||
<div class="flex w-full justify-center bg-[#f5f7f9] pt-2">
|
||||
<div class="z-10 w-[303px] rounded-full bg-[#DDDFE3] p-1">
|
||||
<div class="flex w-full justify-center bg-gray-50 pt-2">
|
||||
<div class="z-10 w-72 rounded-full bg-gray-200 p-1">
|
||||
<div
|
||||
:class="
|
||||
selectedTab === AiWriteTypeEnum.REPLY &&
|
||||
'after:translate-x-[100%] after:transform'
|
||||
"
|
||||
class="relative flex items-center after:absolute after:left-0 after:top-0 after:block after:h-[30px] after:w-1/2 after:rounded-full after:bg-white after:transition-transform after:content-['']"
|
||||
class="relative flex items-center after:absolute after:left-0 after:top-0 after:block after:h-7 after:w-1/2 after:rounded-full after:bg-white after:transition-transform after:content-['']"
|
||||
>
|
||||
<ReuseTab
|
||||
v-for="tab in tabs"
|
||||
|
@ -164,7 +166,7 @@ function submit() {
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="box-border h-full w-[380px] flex-grow overflow-y-auto bg-[#f5f7f9] px-7 pb-2 lg:block"
|
||||
class="box-border h-full w-96 flex-grow overflow-y-auto bg-gray-50 px-7 pb-2 lg:block"
|
||||
>
|
||||
<div>
|
||||
<template v-if="selectedTab === 1">
|
||||
|
@ -233,7 +235,7 @@ function submit() {
|
|||
</Button>
|
||||
<Button
|
||||
:loading="isWriting"
|
||||
style="color: white; background-color: #846af7"
|
||||
class="bg-purple-500 text-white"
|
||||
@click="submit"
|
||||
>
|
||||
生成
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue';
|
||||
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { useClipboard } from '@vueuse/core';
|
||||
import { Button, Card, message, Textarea } from 'ant-design-vue';
|
||||
// 粘贴板
|
||||
|
@ -58,15 +60,14 @@ watch(copied, (val) => {
|
|||
<span>预览</span>
|
||||
<!-- 展示在右上角 -->
|
||||
<Button
|
||||
style="color: white; background-color: #846af7"
|
||||
class="flex bg-purple-500 text-white"
|
||||
v-show="showCopy"
|
||||
@click="copyContent"
|
||||
size="small"
|
||||
class="flex"
|
||||
>
|
||||
<template #icon>
|
||||
<div class="flex items-center justify-center">
|
||||
<span class="icon-[ant-design--copy-twotone]"></span>
|
||||
<IconifyIcon icon="lucide:copy" />
|
||||
</div>
|
||||
</template>
|
||||
复制
|
||||
|
@ -83,13 +84,13 @@ watch(copied, (val) => {
|
|||
<!-- 终止生成内容的按钮 -->
|
||||
<Button
|
||||
v-show="isWriting"
|
||||
class="z-36 absolute bottom-2 left-1/2 flex -translate-x-1/2 sm:bottom-5"
|
||||
class="absolute bottom-2 left-1/2 z-40 flex -translate-x-1/2 sm:bottom-5"
|
||||
@click="emits('stopStream')"
|
||||
size="small"
|
||||
>
|
||||
<template #icon>
|
||||
<div class="flex items-center justify-center">
|
||||
<span class="icon-[ant-design--stop-twotone]"></span>
|
||||
<IconifyIcon icon="lucide:ban" />
|
||||
</div>
|
||||
</template>
|
||||
终止生成
|
||||
|
|
|
@ -17,12 +17,12 @@ const emits = defineEmits<{
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-wrap gap-[8px]">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span
|
||||
v-for="tag in props.tags"
|
||||
:key="tag.value"
|
||||
class="tag mb-2 cursor-pointer rounded-[4px] border-[2px] border-solid border-[#DDDFE3] bg-[#DDDFE3] px-2 text-[12px] leading-6"
|
||||
:class="modelValue === tag.value && '!border-[#846af7] text-[#846af7]'"
|
||||
class="mb-2 cursor-pointer rounded border-2 border-solid border-gray-200 bg-gray-200 px-1 text-xs leading-6"
|
||||
:class="modelValue === tag.value && '!border-purple-500 !text-purple-500'"
|
||||
@click="emits('update:modelValue', tag.value)"
|
||||
>
|
||||
{{ tag.label }}
|
||||
|
|
|
@ -39,7 +39,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
|
||||
<template>
|
||||
<Modal
|
||||
class="w-[40%]"
|
||||
class="w-2/5"
|
||||
title="流程表单详情"
|
||||
:body-style="{
|
||||
maxHeight: '100px',
|
||||
|
|
|
@ -106,7 +106,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :title="getTitle" class="w-[40%]">
|
||||
<Modal :title="getTitle" class="w-2/5">
|
||||
<Form class="mx-4" />
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -84,7 +84,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :title="getTitle" class="w-[40%]">
|
||||
<Modal :title="getTitle" class="w-2/5">
|
||||
<Form class="mx-4" />
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -403,7 +403,7 @@ onBeforeUnmount(() => {
|
|||
class="absolute inset-x-0 top-0 z-10 flex h-12 items-center border-b bg-white px-5"
|
||||
>
|
||||
<!-- 左侧标题 -->
|
||||
<div class="flex w-[200px] items-center overflow-hidden">
|
||||
<div class="flex w-48 items-center overflow-hidden">
|
||||
<ArrowLeft
|
||||
class="size-5 flex-shrink-0 cursor-pointer"
|
||||
@click="handleBack"
|
||||
|
@ -431,7 +431,7 @@ onBeforeUnmount(() => {
|
|||
@click="handleStepClick(index)"
|
||||
>
|
||||
<div
|
||||
class="mr-2 flex h-7 w-7 items-center justify-center rounded-full border-2 border-solid text-[15px]"
|
||||
class="mr-2 flex h-7 w-7 items-center justify-center rounded-full border-2 border-solid text-base"
|
||||
:class="[
|
||||
currentStep === index
|
||||
? 'border-blue-500 bg-blue-500 text-white'
|
||||
|
@ -448,7 +448,7 @@ onBeforeUnmount(() => {
|
|||
</div>
|
||||
|
||||
<!-- 右侧按钮 -->
|
||||
<div class="flex w-[200px] items-center justify-end gap-2">
|
||||
<div class="flex w-48 items-center justify-end gap-2">
|
||||
<Button
|
||||
v-if="actionType === 'update'"
|
||||
type="primary"
|
||||
|
@ -464,7 +464,7 @@ onBeforeUnmount(() => {
|
|||
</div>
|
||||
<!-- 主体内容 -->
|
||||
<Card :body-style="{ padding: '10px' }" class="mb-4">
|
||||
<div class="mt-[50px]">
|
||||
<div class="mt-12">
|
||||
<!-- 第一步:基本信息 -->
|
||||
<div v-if="currentStep === 0" class="mx-auto w-4/6">
|
||||
<BasicInfo
|
||||
|
|
|
@ -11,7 +11,7 @@ import type { SystemUserApi } from '#/api/system/user';
|
|||
import { ref, watch } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { CircleHelp, IconifyIcon, Plus, X } from '@vben/icons';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import {
|
||||
Avatar,
|
||||
|
@ -254,7 +254,10 @@ defineExpose({ validate });
|
|||
"
|
||||
placement="top"
|
||||
>
|
||||
<CircleHelp class="ml-1 size-5 text-gray-900" />
|
||||
<IconifyIcon
|
||||
icon="lucide:circle-help"
|
||||
class="ml-1 size-5 text-gray-900"
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Form.Item>
|
||||
|
@ -343,7 +346,8 @@ defineExpose({ validate });
|
|||
{{ user.nickname?.substring(0, 1) }}
|
||||
</Avatar>
|
||||
{{ user.nickname }}
|
||||
<X
|
||||
<IconifyIcon
|
||||
icon="lucide:x"
|
||||
class="ml-2 size-4 cursor-pointer text-gray-400 hover:text-red-500"
|
||||
@click="handleRemoveStartUser(user)"
|
||||
/>
|
||||
|
@ -354,7 +358,7 @@ defineExpose({ validate });
|
|||
class="flex items-center"
|
||||
>
|
||||
<template #icon>
|
||||
<IconifyIcon icon="lucide:user-plus" class="size-[18px]" />
|
||||
<IconifyIcon icon="lucide:user-plus" class="size-4" />
|
||||
</template>
|
||||
选择人员
|
||||
</Button>
|
||||
|
@ -370,7 +374,8 @@ defineExpose({ validate });
|
|||
>
|
||||
<IconifyIcon icon="lucide:building" class="size-6 px-1" />
|
||||
{{ dept.name }}
|
||||
<X
|
||||
<IconifyIcon
|
||||
icon="lucide:x"
|
||||
class="ml-2 size-4 cursor-pointer text-gray-400 hover:text-red-500"
|
||||
@click="handleRemoveStartDept(dept)"
|
||||
/>
|
||||
|
@ -381,7 +386,7 @@ defineExpose({ validate });
|
|||
class="flex items-center"
|
||||
>
|
||||
<template #icon>
|
||||
<Plus class="size-[18px]" />
|
||||
<IconifyIcon icon="lucide:user-plus" class="size-4" />
|
||||
</template>
|
||||
选择部门
|
||||
</Button>
|
||||
|
@ -404,7 +409,8 @@ defineExpose({ validate });
|
|||
{{ user.nickname?.substring(0, 1) }}
|
||||
</Avatar>
|
||||
{{ user.nickname }}
|
||||
<X
|
||||
<IconifyIcon
|
||||
icon="lucide:x"
|
||||
class="ml-2 size-4 cursor-pointer text-gray-400 hover:text-red-500"
|
||||
@click="handleRemoveManagerUser(user)"
|
||||
/>
|
||||
|
@ -415,7 +421,7 @@ defineExpose({ validate });
|
|||
class="flex items-center"
|
||||
>
|
||||
<template #icon>
|
||||
<IconifyIcon icon="lucide:user-plus" class="size-[18px]" />
|
||||
<IconifyIcon icon="lucide:user-plus" class="size-4" />
|
||||
</template>
|
||||
选择人员
|
||||
</Button>
|
||||
|
@ -440,14 +446,3 @@ defineExpose({ validate });
|
|||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.upload-img-placeholder {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
border-color: #1890ff !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -173,9 +173,9 @@ defineExpose({ validate });
|
|||
"
|
||||
class="mb-5 mt-7 rounded-sm border border-solid border-gray-200 p-5"
|
||||
>
|
||||
<div class="mb-[15px] flex items-center">
|
||||
<div class="mr-[10px] h-[15px] w-[4px] bg-[#1890ff]"></div>
|
||||
<span class="text-[15px] font-bold">表单预览</span>
|
||||
<div class="mb-4 flex items-center">
|
||||
<div class="mr-2 h-4 w-1 bg-blue-500"></div>
|
||||
<span class="text-base font-bold">表单预览</span>
|
||||
</div>
|
||||
<FormCreate
|
||||
v-model:api="formPreview.formData"
|
||||
|
|
|
@ -437,9 +437,10 @@ const handleRenameSuccess = () => {
|
|||
:class="isExpand ? 'rotate-180' : 'rotate-0'"
|
||||
@click="isExpand = !isExpand"
|
||||
>
|
||||
<span
|
||||
class="icon-[ic--round-expand-more] text-3xl text-gray-400"
|
||||
></span>
|
||||
<IconifyIcon
|
||||
icon="lucide:chevron-down"
|
||||
class="text-3xl text-gray-400"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
@ -451,7 +452,7 @@ const handleRenameSuccess = () => {
|
|||
v-if="categoryInfo.modelList.length > 0"
|
||||
type="link"
|
||||
size="small"
|
||||
class="flex items-center text-[14px]"
|
||||
class="flex items-center text-sm"
|
||||
@click.stop="handleModelSort"
|
||||
>
|
||||
<template #icon>
|
||||
|
@ -463,7 +464,7 @@ const handleRenameSuccess = () => {
|
|||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
class="flex items-center text-[14px]"
|
||||
class="flex items-center text-sm"
|
||||
>
|
||||
<template #icon>
|
||||
<IconifyIcon icon="lucide:settings" />
|
||||
|
@ -514,15 +515,16 @@ const handleRenameSuccess = () => {
|
|||
title="拖动排序"
|
||||
placement="left"
|
||||
>
|
||||
<span
|
||||
class="icon-[ic--round-drag-indicator] drag-handle mr-2.5 cursor-move text-2xl text-gray-500"
|
||||
></span>
|
||||
<IconifyIcon
|
||||
icon="ic:round-drag-indicator"
|
||||
class="mr-2.5 cursor-move text-2xl text-gray-500"
|
||||
/>
|
||||
</Tooltip>
|
||||
<div
|
||||
v-if="!row.icon"
|
||||
class="mr-2.5 flex h-9 w-9 flex-shrink-0 items-center justify-center rounded bg-blue-500 text-white"
|
||||
>
|
||||
<span style="font-size: 12px">
|
||||
<span class="text-xs">
|
||||
{{ row.name.substring(0, 2) }}
|
||||
</span>
|
||||
</div>
|
||||
|
@ -589,7 +591,7 @@ const handleRenameSuccess = () => {
|
|||
</template>
|
||||
<template #deploymentTime="{ row }">
|
||||
<div class="flex items-center justify-center">
|
||||
<span v-if="row.processDefinition" class="w-[150px]">
|
||||
<span v-if="row.processDefinition" class="w-36">
|
||||
{{ formatDateTime(row.processDefinition.deploymentTime) }}
|
||||
</span>
|
||||
<Tag v-if="row.processDefinition">
|
||||
|
@ -599,7 +601,7 @@ const handleRenameSuccess = () => {
|
|||
<Tag
|
||||
v-if="row.processDefinition?.suspensionState === 2"
|
||||
color="warning"
|
||||
class="ml-[10px]"
|
||||
class="ml-2.5"
|
||||
>
|
||||
已停用
|
||||
</Tag>
|
||||
|
|
|
@ -25,8 +25,8 @@ const formLoading = ref(false); // 表单的加载中:1)修改时的数据
|
|||
// 审批相关:变量
|
||||
const processDefineKey = 'oa_leave'; // 流程定义 Key
|
||||
const startUserSelectTasks = ref<any>([]); // 发起人需要选择审批人的用户任务列表
|
||||
const startUserSelectAssignees = ref({}); // 发起人选择审批人的数据
|
||||
const tempStartUserSelectAssignees = ref({}); // 历史发起人选择审批人的数据,用于每次表单变更时,临时保存
|
||||
const startUserSelectAssignees = ref<any>({}); // 发起人选择审批人的数据
|
||||
const tempStartUserSelectAssignees = ref<any>({}); // 历史发起人选择审批人的数据,用于每次表单变更时,临时保存
|
||||
const activityNodes = ref<BpmProcessInstanceApi.ApprovalNodeInfo[]>([]); // 审批节点信息
|
||||
const processDefinitionId = ref('');
|
||||
|
||||
|
@ -191,7 +191,7 @@ watch(
|
|||
|
||||
// ============================== 生命周期 ==============================
|
||||
onMounted(async () => {
|
||||
const processDefinitionDetail = await getProcessDefinition(
|
||||
const processDefinitionDetail: any = await getProcessDefinition(
|
||||
undefined,
|
||||
processDefineKey,
|
||||
);
|
||||
|
@ -210,11 +210,11 @@ onMounted(async () => {
|
|||
|
||||
<template>
|
||||
<Page>
|
||||
<div class="w-80vw mx-auto max-w-[920px]">
|
||||
<div class="mx-auto w-[80vw] max-w-[920px]">
|
||||
<Card :title="getTitle" class="w-full">
|
||||
<template #extra>
|
||||
<Button type="default" @click="onBack">
|
||||
<IconifyIcon icon="mdi:arrow-left" />
|
||||
<IconifyIcon icon="lucide:arrow-left" />
|
||||
返回
|
||||
</Button>
|
||||
</template>
|
||||
|
|
|
@ -75,7 +75,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :title="getTitle" class="w-[40%]">
|
||||
<Modal :title="getTitle" class="w-2/5">
|
||||
<Form class="mx-4" />
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -243,7 +243,7 @@ onMounted(() => {
|
|||
<div class="flex items-end">
|
||||
<InputSearch
|
||||
v-model:value="searchName"
|
||||
class="!w-50% mb-15px"
|
||||
class="!w-50% mb-4"
|
||||
placeholder="请输入流程名称检索"
|
||||
allow-clear
|
||||
@input="handleQuery"
|
||||
|
@ -311,7 +311,7 @@ onMounted(() => {
|
|||
</Tabs.TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
<div v-else class="!py-200px text-center">
|
||||
<div v-else class="!py-48 text-center">
|
||||
<Space direction="vertical" size="large">
|
||||
<span class="text-gray-500">没有找到搜索结果</span>
|
||||
</Space>
|
||||
|
|
|
@ -253,14 +253,14 @@ onMounted(async () => {
|
|||
}"
|
||||
>
|
||||
<template #title>
|
||||
<span class="text-[#878c93]">编号:{{ id || '-' }}</span>
|
||||
<span class="text-gray-500">编号:{{ id || '-' }}</span>
|
||||
</template>
|
||||
|
||||
<div class="flex h-[100%] flex-col">
|
||||
<div class="flex h-full flex-col">
|
||||
<!-- 流程基本信息 -->
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="mb-10px h-40px flex items-center gap-5">
|
||||
<div class="mb-5px text-[26px] font-bold">
|
||||
<div class="mb-2.5 flex h-10 items-center gap-5">
|
||||
<div class="mb-1 text-2xl font-bold">
|
||||
{{ processInstance?.name }}
|
||||
</div>
|
||||
<DictTag
|
||||
|
@ -270,9 +270,9 @@ onMounted(async () => {
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div class="mb-10px text-13px h-35px flex items-center gap-5">
|
||||
<div class="mb-2.5 flex h-12 items-center gap-5 text-sm">
|
||||
<div
|
||||
class="flex items-center gap-2 rounded-3xl bg-gray-100 px-[10px] py-[4px] dark:bg-gray-600"
|
||||
class="flex items-center gap-2 rounded-3xl bg-gray-100 px-2.5 py-1 dark:bg-gray-600"
|
||||
>
|
||||
<Avatar
|
||||
:size="28"
|
||||
|
@ -285,11 +285,11 @@ onMounted(async () => {
|
|||
>
|
||||
{{ processInstance?.startUser?.nickname.substring(0, 1) }}
|
||||
</Avatar>
|
||||
<span class="text-12px">{{
|
||||
<span class="text-sm">{{
|
||||
processInstance?.startUser?.nickname
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="text-[#878c93]">
|
||||
<div class="text-gray-500">
|
||||
{{ formatDateTime(processInstance?.startTime) }} 提交
|
||||
</div>
|
||||
</div>
|
||||
|
@ -297,7 +297,7 @@ onMounted(async () => {
|
|||
<component
|
||||
v-if="processInstance?.status"
|
||||
:is="auditIconsMap[processInstance?.status]"
|
||||
class="absolute right-[20px] top-[10px] size-[150px]"
|
||||
class="absolute right-5 top-2.5 size-36"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -700,15 +700,12 @@ defineExpose({ loadTodoTask });
|
|||
"
|
||||
>
|
||||
<Button ghost type="primary" @click="openPopover('approve')">
|
||||
<IconifyIcon icon="icon-park-outline:check" />
|
||||
<IconifyIcon icon="lucide:check" />
|
||||
{{ getButtonDisplayName(BpmTaskOperationButtonTypeEnum.APPROVE) }}
|
||||
</Button>
|
||||
<template #content>
|
||||
<!-- 办理表单 -->
|
||||
<div
|
||||
class="flex flex-1 flex-col px-[20px] pt-[20px]"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<div class="flex flex-1 flex-col px-5 pt-5" v-loading="formLoading">
|
||||
<Form
|
||||
layout="vertical"
|
||||
class="mb-auto"
|
||||
|
@ -717,10 +714,7 @@ defineExpose({ loadTodoTask });
|
|||
:rules="approveReasonRule"
|
||||
label-width="100px"
|
||||
>
|
||||
<Card
|
||||
v-if="runningTask?.formId > 0"
|
||||
class="!-mt-[10px] mb-[15px]"
|
||||
>
|
||||
<Card v-if="runningTask?.formId > 0" class="!-mt-2.5 mb-3.5">
|
||||
<template #title>
|
||||
<span class="el-icon-picture-outline">
|
||||
填写表单【{{ runningTask?.formName }}】
|
||||
|
@ -739,7 +733,7 @@ defineExpose({ loadTodoTask });
|
|||
name="nextAssignees"
|
||||
v-if="nextAssigneesActivityNode.length > 0"
|
||||
>
|
||||
<div class="-mb-[35px] -mt-[15px] ml-[10px]">
|
||||
<div class="-mb-8 -mt-3.5 ml-2.5">
|
||||
<ProcessInstanceTimeline
|
||||
:activity-nodes="nextAssigneesActivityNode"
|
||||
:show-status-icon="false"
|
||||
|
@ -759,7 +753,7 @@ defineExpose({ loadTodoTask });
|
|||
|
||||
<div class="mt-2">
|
||||
<Image
|
||||
style="float: left; width: 326px; height: 150px"
|
||||
class="float-left h-40 w-80"
|
||||
v-if="approveReasonForm.signPicUrl"
|
||||
:src="approveReasonForm.signPicUrl"
|
||||
/>
|
||||
|
@ -815,10 +809,7 @@ defineExpose({ loadTodoTask });
|
|||
</Button>
|
||||
<template #content>
|
||||
<!-- 审批表单 -->
|
||||
<div
|
||||
class="pt-20px px-20px flex flex-1 flex-col"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<div class="flex flex-1 flex-col px-5 pt-5" v-loading="formLoading">
|
||||
<Form
|
||||
layout="vertical"
|
||||
class="mb-auto"
|
||||
|
@ -874,10 +865,7 @@ defineExpose({ loadTodoTask });
|
|||
{{ getButtonDisplayName(BpmTaskOperationButtonTypeEnum.COPY) }}
|
||||
</Button>
|
||||
<template #content>
|
||||
<div
|
||||
class="pt-20px px-20px flex flex-1 flex-col"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<div class="flex flex-1 flex-col px-5 pt-5" v-loading="formLoading">
|
||||
<Form
|
||||
layout="vertical"
|
||||
class="mb-auto"
|
||||
|
@ -949,10 +937,7 @@ defineExpose({ loadTodoTask });
|
|||
{{ getButtonDisplayName(BpmTaskOperationButtonTypeEnum.TRANSFER) }}
|
||||
</Button>
|
||||
<template #content>
|
||||
<div
|
||||
class="pt-20px px-20px flex flex-1 flex-col"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<div class="flex flex-1 flex-col px-5 pt-5" v-loading="formLoading">
|
||||
<Form
|
||||
layout="vertical"
|
||||
class="mb-auto"
|
||||
|
@ -1025,10 +1010,7 @@ defineExpose({ loadTodoTask });
|
|||
{{ getButtonDisplayName(BpmTaskOperationButtonTypeEnum.DELEGATE) }}
|
||||
</Button>
|
||||
<template #content>
|
||||
<div
|
||||
class="pt-20px px-20px flex flex-1 flex-col"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<div class="flex flex-1 flex-col px-5 pt-5" v-loading="formLoading">
|
||||
<Form
|
||||
layout="vertical"
|
||||
class="mb-auto"
|
||||
|
@ -1101,10 +1083,7 @@ defineExpose({ loadTodoTask });
|
|||
{{ getButtonDisplayName(BpmTaskOperationButtonTypeEnum.ADD_SIGN) }}
|
||||
</Button>
|
||||
<template #content>
|
||||
<div
|
||||
class="pt-20px px-20px flex flex-1 flex-col"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<div class="flex flex-1 flex-col px-5 pt-5" v-loading="formLoading">
|
||||
<Form
|
||||
layout="vertical"
|
||||
class="mb-auto"
|
||||
|
@ -1184,10 +1163,7 @@ defineExpose({ loadTodoTask });
|
|||
<IconifyIcon :size="14" icon="icon-park-outline:minus" /> 减签
|
||||
</Button>
|
||||
<template #content>
|
||||
<div
|
||||
class="pt-20px px-20px flex flex-1 flex-col"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<div class="flex flex-1 flex-col px-5 pt-5" v-loading="formLoading">
|
||||
<Form
|
||||
layout="vertical"
|
||||
class="mb-auto"
|
||||
|
@ -1258,10 +1234,7 @@ defineExpose({ loadTodoTask });
|
|||
{{ getButtonDisplayName(BpmTaskOperationButtonTypeEnum.RETURN) }}
|
||||
</Button>
|
||||
<template #content>
|
||||
<div
|
||||
class="pt-20px px-20px flex flex-1 flex-col"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<div class="flex flex-1 flex-col px-5 pt-5" v-loading="formLoading">
|
||||
<Form
|
||||
layout="vertical"
|
||||
class="mb-auto"
|
||||
|
@ -1334,7 +1307,7 @@ defineExpose({ loadTodoTask });
|
|||
</Button>
|
||||
<template #content>
|
||||
<div
|
||||
class="pt-20px px-20px flex w-[400px] flex-1 flex-col"
|
||||
class="flex w-96 flex-1 flex-col px-5 pt-5"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<Form
|
||||
|
@ -1347,7 +1320,7 @@ defineExpose({ loadTodoTask });
|
|||
>
|
||||
<FormItem label="取消理由" name="cancelReason">
|
||||
<Alert
|
||||
class="text-12px mb-2"
|
||||
class="mb-2 text-xs"
|
||||
type="warning"
|
||||
size="small"
|
||||
show-icon
|
||||
|
@ -1389,7 +1362,7 @@ defineExpose({ loadTodoTask });
|
|||
processDefinition?.formType === 10
|
||||
"
|
||||
>
|
||||
<IconifyIcon :size="14" icon="icon-park-outline:refresh" /> 再次提交
|
||||
<IconifyIcon :size="14" icon="lucide:refresh-cw" /> 再次提交
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
|
|
|
@ -41,13 +41,13 @@ const [Modal, modalApi] = useVbenModal({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal class="h-[40%] w-[60%]">
|
||||
<Modal class="h-2/5 w-3/5">
|
||||
<div class="mb-2 flex justify-end">
|
||||
<Space>
|
||||
<Tooltip title="撤销上一步操作">
|
||||
<Button @click="signature?.undo()">
|
||||
<template #icon>
|
||||
<IconifyIcon icon="lucide:undo" class="mb-[4px] size-[16px]" />
|
||||
<IconifyIcon icon="lucide:undo" class="mb-1 size-4" />
|
||||
</template>
|
||||
撤销
|
||||
</Button>
|
||||
|
@ -56,7 +56,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
<Tooltip title="清空画布">
|
||||
<Button @click="signature?.clear()">
|
||||
<template #icon>
|
||||
<IconifyIcon icon="lucide:trash" class="mb-[4px] size-[16px]" />
|
||||
<IconifyIcon icon="lucide:trash" class="mb-1 size-4" />
|
||||
</template>
|
||||
<span>清除</span>
|
||||
</Button>
|
||||
|
@ -65,7 +65,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
</div>
|
||||
|
||||
<Vue3Signature
|
||||
class="mx-auto border-[1px] border-solid border-gray-300"
|
||||
class="mx-auto border border-solid border-gray-300"
|
||||
ref="signature"
|
||||
w="874px"
|
||||
h="324px"
|
||||
|
|
|
@ -201,7 +201,7 @@ defineExpose({
|
|||
class="ml-1"
|
||||
>
|
||||
<IconifyIcon icon="lucide:file-text" />
|
||||
<span class="!ml-[2px] text-[12px]">查看表单</span>
|
||||
<span class="!ml-0.5 text-xs">查看表单</span>
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -217,7 +217,7 @@ function handleUserSelectCancel() {
|
|||
|
||||
<template>
|
||||
<div>
|
||||
<Timeline class="pt-20px">
|
||||
<Timeline class="pt-5">
|
||||
<!-- 遍历每个审批节点 -->
|
||||
<Timeline.Item
|
||||
v-for="(activity, index) in activityNodes"
|
||||
|
@ -227,17 +227,17 @@ function handleUserSelectCancel() {
|
|||
<template #dot>
|
||||
<div class="relative">
|
||||
<div
|
||||
class="position-absolute left--10px top--6px flex h-[32px] w-[32px] items-center justify-center rounded-full border border-solid border-[#dedede] bg-[#3f73f7] p-[6px]"
|
||||
class="position-absolute left--2.5 top--1.5 flex h-8 w-8 items-center justify-center rounded-full border border-solid border-gray-200 bg-blue-500 p-1.5"
|
||||
>
|
||||
<IconifyIcon
|
||||
:icon="getApprovalNodeTypeIcon(activity.nodeType)"
|
||||
class="size-[24px] text-white"
|
||||
class="size-6 text-white"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="showStatusIcon"
|
||||
class="absolute right-[-10px] top-[18px] flex size-[20px] items-center rounded-full border-[2px] border-solid border-white p-[2px]"
|
||||
class="absolute right--2.5 top-4 flex size-5 items-center rounded-full border-2 border-solid border-white p-0.5"
|
||||
:style="{
|
||||
backgroundColor: getApprovalNodeColor(activity.status),
|
||||
}"
|
||||
|
@ -261,7 +261,7 @@ function handleUserSelectCancel() {
|
|||
<!-- 信息:时间 -->
|
||||
<div
|
||||
v-if="activity.status !== BpmTaskStatusEnum.NOT_START"
|
||||
class="ml-auto mt-1 text-[13px] text-[#a5a5a5]"
|
||||
class="ml-auto mt-1 text-sm text-gray-500"
|
||||
>
|
||||
{{ getApprovalNodeTime(activity) }}
|
||||
</div>
|
||||
|
@ -294,10 +294,7 @@ function handleUserSelectCancel() {
|
|||
"
|
||||
>
|
||||
<template #icon>
|
||||
<IconifyIcon
|
||||
icon="mdi:account-plus-outline"
|
||||
class="size-[18px]"
|
||||
/>
|
||||
<IconifyIcon icon="lucide:user-plus" class="size-4" />
|
||||
</template>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
|
@ -305,19 +302,19 @@ function handleUserSelectCancel() {
|
|||
<div
|
||||
v-for="(user, userIndex) in customApproveUsers[activity.id]"
|
||||
:key="user.id || userIndex"
|
||||
class="relative flex h-[36px] items-center gap-2 rounded-3xl bg-gray-100 pr-[8px] dark:bg-gray-600"
|
||||
class="relative flex h-9 items-center gap-2 rounded-3xl bg-gray-100 pr-2 dark:bg-gray-600"
|
||||
>
|
||||
<Avatar
|
||||
class="!m-[5px]"
|
||||
class="!m-1"
|
||||
:size="28"
|
||||
v-if="user.avatar"
|
||||
:src="user.avatar"
|
||||
/>
|
||||
|
||||
<Avatar class="!m-[5px]" :size="28" v-else>
|
||||
<Avatar class="!m-1" :size="28" v-else>
|
||||
<span>{{ user.nickname.substring(0, 1) }}</span>
|
||||
</Avatar>
|
||||
<span class="text-[13px]">{{ user.nickname }}</span>
|
||||
<span class="text-sm">{{ user.nickname }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -326,7 +323,7 @@ function handleUserSelectCancel() {
|
|||
<div
|
||||
v-for="(task, idx) in activity.tasks"
|
||||
:key="idx"
|
||||
class="flex flex-col gap-2 pr-[8px]"
|
||||
class="flex flex-col gap-2 pr-2"
|
||||
>
|
||||
<div
|
||||
class="relative flex flex-wrap gap-2"
|
||||
|
@ -334,7 +331,7 @@ function handleUserSelectCancel() {
|
|||
>
|
||||
<!-- 信息:头像昵称 -->
|
||||
<div
|
||||
class="h-35px relative flex items-center rounded-3xl bg-gray-100 pr-[8px] dark:bg-gray-600"
|
||||
class="relative flex h-8 items-center rounded-3xl bg-gray-100 pr-2 dark:bg-gray-600"
|
||||
>
|
||||
<template
|
||||
v-if="
|
||||
|
@ -342,12 +339,12 @@ function handleUserSelectCancel() {
|
|||
"
|
||||
>
|
||||
<Avatar
|
||||
class="!m-[5px]"
|
||||
class="!m-1"
|
||||
:size="28"
|
||||
v-if="task.assigneeUser?.avatar"
|
||||
:src="task.assigneeUser?.avatar"
|
||||
/>
|
||||
<Avatar class="!m-[5px]" :size="28" v-else>
|
||||
<Avatar class="!m-1" :size="28" v-else>
|
||||
{{ task.assigneeUser?.nickname.substring(0, 1) }}
|
||||
</Avatar>
|
||||
{{ task.assigneeUser?.nickname }}
|
||||
|
@ -358,12 +355,12 @@ function handleUserSelectCancel() {
|
|||
"
|
||||
>
|
||||
<Avatar
|
||||
class="!m-[5px]"
|
||||
class="!m-1"
|
||||
:size="28"
|
||||
v-if="task.ownerUser?.avatar"
|
||||
:src="task.ownerUser?.avatar"
|
||||
/>
|
||||
<Avatar class="!m-[5px]" :size="28" v-else>
|
||||
<Avatar class="!m-1" :size="28" v-else>
|
||||
{{ task.ownerUser?.nickname.substring(0, 1) }}
|
||||
</Avatar>
|
||||
{{ task.ownerUser?.nickname }}
|
||||
|
@ -374,16 +371,14 @@ function handleUserSelectCancel() {
|
|||
v-if="
|
||||
showStatusIcon && onlyStatusIconShow.includes(task.status)
|
||||
"
|
||||
class="absolute left-[24px] top-[20px] flex items-center rounded-full border-2 border-solid border-white p-[2px]"
|
||||
class="absolute left-6 top-5 flex items-center rounded-full border-2 border-solid border-white p-1"
|
||||
:style="{
|
||||
backgroundColor: statusIconMap[task.status]?.color,
|
||||
}"
|
||||
>
|
||||
<IconifyIcon
|
||||
:icon="
|
||||
statusIconMap[task.status]?.icon || 'mdi:clock-outline'
|
||||
"
|
||||
class="size-[10px] text-white"
|
||||
:icon="statusIconMap[task.status]?.icon || 'lucide:clock'"
|
||||
class="size-2 text-white"
|
||||
:class="[statusIconMap[task.status]?.animation]"
|
||||
/>
|
||||
</div>
|
||||
|
@ -394,7 +389,7 @@ function handleUserSelectCancel() {
|
|||
<teleport defer :to="`#activity-task-${activity.id}-${index}`">
|
||||
<div
|
||||
v-if="shouldShowApprovalReason(task, activity.nodeType)"
|
||||
class="mt-1 w-full rounded-md bg-[#f8f8fa] p-2 text-[13px] text-[#a5a5a5]"
|
||||
class="mt-1 w-full rounded-md bg-gray-100 p-2 text-sm text-gray-500"
|
||||
>
|
||||
审批意见:{{ task.reason }}
|
||||
</div>
|
||||
|
@ -403,11 +398,11 @@ function handleUserSelectCancel() {
|
|||
task.signPicUrl &&
|
||||
activity.nodeType === BpmNodeTypeEnum.USER_TASK_NODE
|
||||
"
|
||||
class="mt-1 w-full rounded-md bg-[#f8f8fa] p-2 text-[13px] text-[#a5a5a5]"
|
||||
class="mt-1 w-full rounded-md bg-gray-100 p-2 text-sm text-gray-500"
|
||||
>
|
||||
签名:
|
||||
<Image
|
||||
class="ml-[5px] h-[40px] w-[90px]"
|
||||
class="ml-1 h-10 w-24"
|
||||
:src="task.signPicUrl"
|
||||
:preview="{ src: task.signPicUrl }"
|
||||
/>
|
||||
|
@ -419,30 +414,30 @@ function handleUserSelectCancel() {
|
|||
<div
|
||||
v-for="(user, userIndex) in activity.candidateUsers"
|
||||
:key="userIndex"
|
||||
class="relative flex h-[35px] items-center rounded-3xl bg-gray-100 pr-[8px] dark:bg-gray-600"
|
||||
class="relative flex h-8 items-center rounded-3xl bg-gray-100 pr-2 dark:bg-gray-600"
|
||||
>
|
||||
<Avatar
|
||||
class="!m-[5px]"
|
||||
class="!m-1"
|
||||
:size="28"
|
||||
v-if="user.avatar"
|
||||
:src="user.avatar"
|
||||
/>
|
||||
<Avatar class="!m-[5px]" :size="28" v-else>
|
||||
<Avatar class="!m-1" :size="28" v-else>
|
||||
{{ user.nickname.substring(0, 1) }}
|
||||
</Avatar>
|
||||
<span class="text-[13px]">
|
||||
<span class="text-sm">
|
||||
{{ user.nickname }}
|
||||
</span>
|
||||
|
||||
<!-- 候选任务状态图标 -->
|
||||
<div
|
||||
v-if="showStatusIcon"
|
||||
class="absolute left-[24px] top-[20px] flex items-center rounded-full border-2 border-solid border-white p-[1px]"
|
||||
class="absolute left-6 top-5 flex items-center rounded-full border-2 border-solid border-white p-1"
|
||||
:style="{ backgroundColor: statusIconMap['-1']?.color }"
|
||||
>
|
||||
<IconifyIcon
|
||||
class="text-[11px] text-white"
|
||||
:icon="statusIconMap['-1']?.icon || 'mdi:clock-outline'"
|
||||
class="text-xs text-white"
|
||||
:icon="statusIconMap['-1']?.icon || 'lucide:clock'"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -85,7 +85,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :title="getTitle" class="w-[40%]">
|
||||
<Modal :title="getTitle" class="w-2/5">
|
||||
<Form class="mx-4" />
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -132,7 +132,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal title="关联商机" class="w-[40%]">
|
||||
<Modal title="关联商机" class="w-2/5">
|
||||
<FormModal @success="onRefresh" />
|
||||
<Grid>
|
||||
<template #toolbar-tools>
|
||||
|
|
|
@ -106,7 +106,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :title="getTitle" class="w-[50%]">
|
||||
<Modal :title="getTitle" class="w-1/2">
|
||||
<Form class="mx-4">
|
||||
<template #product="slotProps">
|
||||
<ProductEditTable
|
||||
|
|
|
@ -134,7 +134,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal title="变更商机状态" class="w-[40%]">
|
||||
<Modal title="变更商机状态" class="w-2/5">
|
||||
<Form class="mx-4" />
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -76,7 +76,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :title="getTitle" class="w-[40%]">
|
||||
<Modal :title="getTitle" class="w-2/5">
|
||||
<Form class="mx-4" />
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue