优化修改
This commit is contained in:
@@ -38,10 +38,10 @@ module.exports = {
|
||||
'@typescript-eslint/no-redeclare': 'error',
|
||||
'@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
'warn',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_|props|watch',
|
||||
caughtErrorsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
@@ -64,6 +64,11 @@ module.exports = {
|
||||
'vue/no-parsing-error': 'off',
|
||||
'vue/no-deprecated-v-on-native-modifier': 'off',
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'vue/no-reserved-component-names': 'off',
|
||||
'vue/no-v-for-template-key': 'off',
|
||||
'vue/no-unused-vars': 'off',
|
||||
'vue/no-mutating-props': 'off',
|
||||
'no-mixed-spaces-and-tabs': 'off',
|
||||
'no-useless-escape': 'off',
|
||||
'no-sparse-arrays': 'off',
|
||||
'no-prototype-builtins': 'off',
|
||||
@@ -77,8 +82,8 @@ module.exports = {
|
||||
'no-unused-vars': 'off',
|
||||
'no-v-model-argument': 'off',
|
||||
'no-case-declarations': 'off',
|
||||
'no-console': 'error',
|
||||
'no-debugger': 'error',
|
||||
'no-console': 'off',
|
||||
'no-debugger': 'warn',
|
||||
'no-redeclare': 'off',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -32,22 +32,12 @@
|
||||
<div class="table-body">
|
||||
<div v-for="(attr, index) in ruleForm.attrs" :key="index" class="table-row">
|
||||
<div class="col col-name">
|
||||
<el-input
|
||||
v-if="!isDictType(attr.type)"
|
||||
v-model="attr.name"
|
||||
placeholder="请输入属性名称"
|
||||
clearable
|
||||
/>
|
||||
<el-input v-if="!isDictType(attr.type)" v-model="attr.name" placeholder="请输入属性名称" clearable />
|
||||
<span v-else class="dict-name">{{ attr.name || '请选择字典' }}</span>
|
||||
</div>
|
||||
<div class="col col-type">
|
||||
<el-select v-model="attr.type" placeholder="属性类型" class="w100" @change="onAttrTypeChange(attr)">
|
||||
<el-option
|
||||
v-for="item in attrTypeOptions"
|
||||
:key="item.key"
|
||||
:label="item.value"
|
||||
:value="item.key"
|
||||
/>
|
||||
<el-option v-for="item in attrTypeOptions" :key="item.key" :label="item.value" :value="item.key" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="col col-required">
|
||||
@@ -155,13 +145,6 @@ interface DictInfo {
|
||||
remark: string;
|
||||
}
|
||||
|
||||
interface DictValue {
|
||||
key: string;
|
||||
value: string;
|
||||
isDefault: number;
|
||||
remark: string;
|
||||
}
|
||||
|
||||
interface RuleForm {
|
||||
id: string | '';
|
||||
parentId: string;
|
||||
@@ -219,15 +202,11 @@ const fetchDictTypeOptions = () => {
|
||||
.then((res: any) => {
|
||||
const list = res.data?.list ?? [];
|
||||
// 提取所有字典类型信息
|
||||
dictTypeOptions.value = list
|
||||
.map((item: any) => item.info)
|
||||
.filter((info: DictInfo) => info && info.name);
|
||||
dictTypeOptions.value = list.map((item: any) => item.info).filter((info: DictInfo) => info && info.name);
|
||||
// 保存完整的字典数据列表(包含info和values)
|
||||
dictValueOptions.value = list;
|
||||
|
||||
})
|
||||
.catch((err: any) => {
|
||||
|
||||
dictTypeOptions.value = [];
|
||||
dictValueOptions.value = [];
|
||||
})
|
||||
@@ -270,7 +249,9 @@ const isDictOptionDisabled = (dictName: string, currentAttr: CustomAttr) => {
|
||||
const dictInfo = dictTypeOptions.value.find((item) => item.name === dictName);
|
||||
const dictType = dictInfo?.type || '';
|
||||
// 检查该字典是否已被其他属性使用(使用 dictType 判断)
|
||||
return ruleForm.attrs.some((attr) => attr !== currentAttr && isDictType(attr.type) && (attr.dictType === dictType || (!attr.dictType && attr.name === dictName)));
|
||||
return ruleForm.attrs.some(
|
||||
(attr) => attr !== currentAttr && isDictType(attr.type) && (attr.dictType === dictType || (!attr.dictType && attr.name === dictName))
|
||||
);
|
||||
};
|
||||
|
||||
// 添加自定义属性
|
||||
@@ -325,16 +306,16 @@ const openDialog = (row?: CategoryRow | string, edit?: boolean) => {
|
||||
// 获取分类树数据
|
||||
getCategoryTree().then((res: any) => {
|
||||
const tree = res.data?.tree ?? [];
|
||||
|
||||
|
||||
// 递归函数,将所有id字段转换为字符串
|
||||
const convertIdsToString = (items: any[]): any[] => {
|
||||
return items.map(item => ({
|
||||
return items.map((item) => ({
|
||||
...item,
|
||||
id: item.id?.toString(),
|
||||
children: item.children && item.children.length > 0 ? convertIdsToString(item.children) : []
|
||||
children: item.children && item.children.length > 0 ? convertIdsToString(item.children) : [],
|
||||
}));
|
||||
};
|
||||
|
||||
|
||||
categoryData.value = convertIdsToString(tree);
|
||||
});
|
||||
|
||||
@@ -472,7 +453,7 @@ const onSubmit = () => {
|
||||
...submitData,
|
||||
_originalData: originalData,
|
||||
};
|
||||
|
||||
|
||||
updateCategory(requestData)
|
||||
.then(() => {
|
||||
ElMessage.success('修改成功');
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</div>
|
||||
|
||||
<div v-if="msg.isUser" class="avatar-wrap">
|
||||
<el-avatar :size="36" src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" />
|
||||
<div class="user-avatar">你</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -111,6 +111,23 @@ const messages = ref<Message[]>([
|
||||
0 2px 8px rgba(59, 130, 246, 0.15);
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
|
||||
border: 1px solid #f59e0b;
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.25),
|
||||
0 2px 8px rgba(245, 158, 11, 0.2);
|
||||
}
|
||||
|
||||
.bubble-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
<div class="sidebar-header">
|
||||
<div class="brand-dot"></div>
|
||||
<div class="user-info">
|
||||
<el-avatar :size="42" src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" />
|
||||
<div class="ai-avatar">
|
||||
<span class="ai-icon">AI</span>
|
||||
</div>
|
||||
<div class="user-details">
|
||||
<div class="user-name">助手</div>
|
||||
<div class="user-status">在线</div>
|
||||
<div class="user-name">AI 助手</div>
|
||||
<div class="user-status"><span class="status-dot"></span>在线</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-button class="new-chat-btn" @click="handleNewChat">
|
||||
@@ -124,12 +126,13 @@ const handleDeleteHistory = (id: number) => {
|
||||
<style scoped lang="scss">
|
||||
.sidebar {
|
||||
width: 252px;
|
||||
background: linear-gradient(180deg, #ffffff 0%, #f9fbff 100%);
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.95) 0%, rgba(249, 251, 255, 0.92) 100%);
|
||||
border-right: 1px solid #e7edf7;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
box-shadow: 6px 0 20px rgba(15, 23, 42, 0.04);
|
||||
box-shadow: 8px 0 30px rgba(15, 23, 42, 0.06);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
@@ -139,20 +142,24 @@ const handleDeleteHistory = (id: number) => {
|
||||
}
|
||||
|
||||
.new-chat-btn {
|
||||
margin-top: 10px;
|
||||
margin-top: 12px;
|
||||
width: 100%;
|
||||
height: 34px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #dbe7f7;
|
||||
background: linear-gradient(135deg, #f8fbff 0%, #eff6ff 100%);
|
||||
color: #1f4db8;
|
||||
height: 40px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(59, 130, 246, 0.28);
|
||||
background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
|
||||
color: #ffffff;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.2px;
|
||||
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.26);
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
color: #1e40af;
|
||||
border-color: #bfdbfe;
|
||||
background: linear-gradient(135deg, #eff6ff 0%, #e0eeff 100%);
|
||||
transform: translateY(-1px);
|
||||
color: #ffffff;
|
||||
border-color: rgba(59, 130, 246, 0.4);
|
||||
background: linear-gradient(135deg, #60a5fa 0%, #3b82f6 100%);
|
||||
box-shadow: 0 6px 16px rgba(37, 99, 235, 0.32);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,10 +178,32 @@ const handleDeleteHistory = (id: number) => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 8px 8px 6px;
|
||||
border-radius: 12px;
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.86) 0%, rgba(248, 251, 255, 0.92) 100%);
|
||||
border: 1px solid #e7edf7;
|
||||
padding: 10px 10px 8px;
|
||||
border-radius: 16px;
|
||||
background: linear-gradient(135deg, rgba(59, 130, 246, 0.08) 0%, rgba(147, 197, 253, 0.04) 100%);
|
||||
border: 1px solid rgba(59, 130, 246, 0.18);
|
||||
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
.ai-avatar {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #60a5fa 0%, #3b82f6 50%, #1d4ed8 100%);
|
||||
box-shadow:
|
||||
inset 0 2px 8px rgba(255, 255, 255, 0.35),
|
||||
0 4px 12px rgba(37, 99, 235, 0.28);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ai-icon {
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.user-details {
|
||||
@@ -193,6 +222,23 @@ const handleDeleteHistory = (id: number) => {
|
||||
font-size: 12px;
|
||||
color: #10b981;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.status-dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background: #10b981;
|
||||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.2);
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.5; }
|
||||
}
|
||||
|
||||
.sidebar-menu {
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { Clock, Plus, Delete } from '@element-plus/icons-vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import Sidebar from './components/Sidebar.vue';
|
||||
import MainContent from './components/MainContent.vue';
|
||||
@@ -87,8 +86,10 @@ const handleDeleteHistory = (id: number) => {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
background:
|
||||
radial-gradient(1200px 460px at 65% -140px, rgba(59, 130, 246, 0.1) 0%, rgba(59, 130, 246, 0) 68%),
|
||||
linear-gradient(180deg, #f7faff 0%, #f4f7fc 100%);
|
||||
radial-gradient(1000px 500px at 70% -180px, rgba(59, 130, 246, 0.12) 0%, rgba(59, 130, 246, 0) 65%),
|
||||
radial-gradient(800px 400px at 10% 10%, rgba(139, 92, 246, 0.06) 0%, rgba(139, 92, 246, 0) 60%),
|
||||
radial-gradient(600px 300px at 90% 110%, rgba(16, 185, 129, 0.05) 0%, rgba(16, 185, 129, 0) 60%),
|
||||
linear-gradient(180deg, #f8fbff 0%, #f0f4fa 100%);
|
||||
}
|
||||
|
||||
.main-wrapper {
|
||||
@@ -105,8 +106,8 @@ const handleDeleteHistory = (id: number) => {
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.45) 0%, rgba(255, 255, 255, 0) 28%),
|
||||
radial-gradient(1000px 380px at 10% 110%, rgba(99, 102, 241, 0.08) 0%, rgba(99, 102, 241, 0) 72%);
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.35) 0%, rgba(255, 255, 255, 0) 32%),
|
||||
radial-gradient(900px 360px at 15% 115%, rgba(99, 102, 241, 0.06) 0%, rgba(99, 102, 241, 0) 70%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -724,11 +724,15 @@ const parseFieldsUnified = (raw: unknown): Array<{ key: string; value: string }>
|
||||
}));
|
||||
}
|
||||
|
||||
// 如果是对象格式 { key: value }
|
||||
// 如果是对象格式 { key: value } 或者 { key: { value: value } }
|
||||
if (typeof raw === 'object') {
|
||||
const fields: Array<{ key: string; value: string }> = [];
|
||||
Object.keys(raw as Record<string, unknown>).forEach((key) => {
|
||||
const v = (raw as Record<string, unknown>)[key];
|
||||
let v = (raw as Record<string, unknown>)[key];
|
||||
// 处理 { key: { value: "value" } } 格式(后端可能返回这种结构)
|
||||
if (v && typeof v === 'object' && !Array.isArray(v) && 'value' in v) {
|
||||
v = (v as { value: unknown }).value;
|
||||
}
|
||||
const value = String(v ?? '');
|
||||
fields.push({ key, value });
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user