feat(dev): 添加开发模式专用指令和配置支持

- 在 config.json 中新增 dev 配置项用于区分开发与生产环境
- 实现 v-dev-only 指令,仅在开发模式下渲染元素
- 注册全局自定义指令 dev-only,支持通过 binding.value 控制启用状态
- 在 TaskSyllabus/Bg.vue 中使用 v-dev-only 指令隐藏生产环境下的加号区域
- 移除 card 样式中的固定 margin-bottom,改由容器控制间距
- 统一使用 CSS 变量 --color-border-separate 替代硬编码的分割线颜色
- 为 Task.vue 的搜索框添加 clearable 属性并移除弹出项的阴影效果
- Layout 组件名称规范化为首字母大写
- 在主题样式中定义深色与浅色模式下的 --color-border-separate 颜色值
- 覆盖 Element Plus 的 --el-fill-color-blank 以适配暗黑模式背景透明度需求
This commit is contained in:
zhaoweijie
2025-12-21 18:10:37 +08:00
parent f0db3c88e4
commit cc22655a1e
10 changed files with 70 additions and 6 deletions

View File

@@ -15,5 +15,6 @@
], ],
"agentRepository": { "agentRepository": {
"storageVersionIdentifier": "1" "storageVersionIdentifier": "1"
} },
"dev": true
} }

View File

@@ -0,0 +1,43 @@
import type { Directive, DirectiveBinding } from 'vue'
import { useConfigStoreHook } from '@/stores'
/**
* 开发模式专用指令
* 只在开发模式下显示元素,生产模式下会移除该元素
*
* \@param binding.value - 是否开启该功能,默认为 true
* @example
* \!-- 默认开启,开发模式显示 --
* \!div v-dev-only开发模式内容</div>
*
* \!-- 传入参数控制 --
* <div v-dev-only="true">开启指令</div>
* <div v-dev-only="false">取消指令</div>
*/
export const devOnly: Directive = {
mounted(el: HTMLElement, binding: DirectiveBinding) {
checkAndRemoveElement(el, binding)
},
updated(el: HTMLElement, binding: DirectiveBinding) {
checkAndRemoveElement(el, binding)
},
}
const configStore = useConfigStoreHook()
/**
* 检查并移除元素的逻辑
*/
function checkAndRemoveElement(el: HTMLElement, binding: DirectiveBinding) {
const isDev = typeof configStore.config.dev === 'boolean' ? configStore.config.dev : import.meta.env.DEV
// 默认值为 true如果没有传值或者传值为 true 都启用
const shouldEnable = binding.value !== false
// 如果不是开发模式或者明确禁用,移除该元素
if (!isDev && shouldEnable) {
console.log(1111)
if (el.parentNode) {
el.parentNode.removeChild(el)
}
}
}

View File

@@ -0,0 +1,9 @@
import type { App } from 'vue'
import { devOnly } from './devOnly'
// 全局注册 directive
export function setupDirective(app: App<Element>) {
app.directive('dev-only', devOnly)
}

View File

@@ -3,7 +3,7 @@ import Layout from './layout/index.vue'
</script> </script>
<template> <template>
<layout /> <Layout />
</template> </template>
<style lang="scss"> <style lang="scss">

View File

@@ -144,6 +144,7 @@ onMounted(() => {
@change="agentsStore.setSearchValue" @change="agentsStore.setSearchValue"
:disabled="!(agentsStore.agents.length > 0)" :disabled="!(agentsStore.agents.length > 0)"
:debounce="0" :debounce="0"
:clearable="true"
:trigger-on-focus="triggerOnFocus" :trigger-on-focus="triggerOnFocus"
@focus="handleFocus" @focus="handleFocus"
@blur="handleBlur" @blur="handleBlur"
@@ -228,6 +229,7 @@ onMounted(() => {
transition: height 0s ease-in-out; transition: height 0s ease-in-out;
border-top: 1px solid var(--color-border); border-top: 1px solid var(--color-border);
border-radius: 0; border-radius: 0;
box-shadow: none;
li { li {
height: 45px; height: 45px;

View File

@@ -27,6 +27,7 @@ defineEmits<{
<!-- 顶部加号区域 --> <!-- 顶部加号区域 -->
<div <div
v-if="!isAdding" v-if="!isAdding"
v-dev-only
class="plus-area mt-[35px] ml-[-15px] w-[34px] h-[34px] flex items-center justify-center cursor-pointer rounded-full" class="plus-area mt-[35px] ml-[-15px] w-[34px] h-[34px] flex items-center justify-center cursor-pointer rounded-full"
@click="$emit('start-add-output')" @click="$emit('start-add-output')"
> >

View File

@@ -278,7 +278,7 @@ defineExpose({
<div <div
v-for="item in collaborationProcess" v-for="item in collaborationProcess"
:key="item.Id" :key="item.Id"
class="card-it w-full flex items-center gap-[14%] bg-[var(--color-card-bg)]" class="card-it w-full flex items-center gap-[14%] bg-[var(--color-card-bg)] mb-[100px]"
> >
<!-- 流程卡片 --> <!-- 流程卡片 -->
<el-card <el-card
@@ -291,7 +291,7 @@ defineExpose({
<MultiLineTooltip placement="right" :text="item.StepName" :lines="2"> <MultiLineTooltip placement="right" :text="item.StepName" :lines="2">
<div class="text-[18px] font-bold text-center">{{ item.StepName }}</div> <div class="text-[18px] font-bold text-center">{{ item.StepName }}</div>
</MultiLineTooltip> </MultiLineTooltip>
<div class="h-[1px] w-full bg-[#d6d6d6] my-[8px]"></div> <div class="h-[1px] w-full bg-[var(--color-border-separate)] my-[8px]"></div>
<!-- 任务内容区域 - 支持双击编辑 --> <!-- 任务内容区域 - 支持双击编辑 -->
<div v-if="editingTaskId === item.Id" class="w-full"> <div v-if="editingTaskId === item.Id" class="w-full">
@@ -321,7 +321,7 @@ defineExpose({
</MultiLineTooltip> </MultiLineTooltip>
</div> </div>
<div class="h-[1px] w-full bg-[#d6d6d6] my-[8px]"></div> <div class="h-[1px] w-full bg-[var(--color-border-separate)] my-[8px]"></div>
<div <div
class="flex items-center gap-2 overflow-y-auto flex-wrap relative w-full max-h-[72px]" class="flex items-center gap-2 overflow-y-auto flex-wrap relative w-full max-h-[72px]"
> >
@@ -384,7 +384,6 @@ defineExpose({
border: 1px solid var(--color-card-border-task); border: 1px solid var(--color-card-border-task);
box-sizing: border-box; box-sizing: border-box;
transition: border-color 0.2s ease; transition: border-color 0.2s ease;
margin-bottom: 100px;
&:hover { &:hover {
background-color: var(--color-card-bg-task-hover); background-color: var(--color-card-bg-task-hover);
border-color: var(--color-card-border-hover); border-color: var(--color-card-border-hover);

View File

@@ -8,10 +8,12 @@ import 'element-plus/theme-chalk/dark/css-vars.css'
import 'virtual:svg-icons-register' import 'virtual:svg-icons-register'
import { initService } from '@/utils/request.ts' import { initService } from '@/utils/request.ts'
import { setupStore, useConfigStore } from '@/stores' import { setupStore, useConfigStore } from '@/stores'
import { setupDirective } from '@/ directive'
async function init() { async function init() {
const app = createApp(App) const app = createApp(App)
setupStore(app) setupStore(app)
setupDirective(app)
initService() initService()
const configStore = useConfigStore() const configStore = useConfigStore()
await configStore.initConfig() await configStore.initConfig()

View File

@@ -11,6 +11,7 @@ export interface Config {
agentRepository: { agentRepository: {
storageVersionIdentifier: string storageVersionIdentifier: string
} }
dev?: boolean
} }

View File

@@ -100,6 +100,8 @@
--color-text-result-detail: rgba(0,0,0,0.6); --color-text-result-detail: rgba(0,0,0,0.6);
// 结果卡片运行后颜色 // 结果卡片运行后颜色
--color-text-result-detail-run: #000; --color-text-result-detail-run: #000;
// 分割线
--color-border-separate: #D6D6D6;
} }
// 深色模式 // 深色模式
@@ -204,4 +206,8 @@ html.dark {
--color-text-result-detail: #6c6e72; --color-text-result-detail: #6c6e72;
// 结果卡片运行后颜色 // 结果卡片运行后颜色
--color-text-result-detail-run: #fff; --color-text-result-detail-run: #fff;
// 分割线
--color-border-separate: rgba(255,255,255,0.18);
--el-fill-color-blank: transparent !important;
} }