diff --git a/public/login-bg.jpg b/public/login-bg.jpg new file mode 100644 index 0000000..2aa303a Binary files /dev/null and b/public/login-bg.jpg differ diff --git a/src/components/editor/index.vue b/src/components/editor/index.vue index bcfc822..ea6857c 100644 --- a/src/components/editor/index.vue +++ b/src/components/editor/index.vue @@ -102,6 +102,44 @@ export default defineComponent({ } }; + // 应用禁用状态(只保留表情) + const applyDisableState = () => { + if (!state.editorToolbar || !props.disableExceptEmotion) return; + + nextTick(() => { + // 获取所有工具栏按钮容器 + const toolbarItems = state.editorToolbar!.querySelectorAll('.w-e-bar-item'); + toolbarItems.forEach((item: Element) => { + // 尝试找到按钮上的 tooltip + const button = item.querySelector('button'); + let isEmotionButton = false; + + if (button) { + // 检查 data-tooltip (新版) 或 data-title (旧版) + const tooltip = button.getAttribute('data-tooltip') || button.getAttribute('data-title') || ''; + // 也检查svg或者特定的class,如果有的话。通常表情按钮会有特定的icon + // 这里主要依靠 tooltip 文字匹配 + if (tooltip.includes('表情') || tooltip.toLowerCase().includes('emotion')) { + isEmotionButton = true; + } + } + + // 也可以尝试检查 menu key,但这通常不在 DOM 上直接体现,除非自己加了属性 + // 下面是一个补充策略:如果 item 内部有 emoji 的 svg 或者特定的结构 + + if (!isEmotionButton) { + (item as HTMLElement).style.opacity = '0.4'; + (item as HTMLElement).style.pointerEvents = 'none'; + (item as HTMLElement).style.cursor = 'not-allowed'; + } else { + (item as HTMLElement).style.opacity = '1'; + (item as HTMLElement).style.pointerEvents = 'auto'; + (item as HTMLElement).style.cursor = 'pointer'; + } + }); + }); + }; + // 初始化富文本 const initWangeditor = () => { destroyEditor(); @@ -124,35 +162,11 @@ export default defineComponent({ }); state.isInitialized = true; - - // 初始化后应用禁用状态 - applyDisableState(); - }); - }; - - // 应用禁用状态 - const applyDisableState = () => { - if (!state.editorToolbar || !props.disableExceptEmotion) return; - - nextTick(() => { - const toolbarItems = state.editorToolbar!.querySelectorAll('.w-e-bar-item'); - toolbarItems.forEach((item: Element) => { - const button = item.querySelector('button'); - if (button) { - const dataTitle = button.getAttribute('data-title') || ''; - const isEmotionButton = dataTitle.includes('表情') || dataTitle.toLowerCase().includes('emotion'); - - if (!isEmotionButton) { - (item as HTMLElement).style.opacity = '0.5'; - (item as HTMLElement).style.pointerEvents = 'none'; - (item as HTMLElement).style.cursor = 'not-allowed'; - } else { - (item as HTMLElement).style.opacity = '1'; - (item as HTMLElement).style.pointerEvents = 'auto'; - (item as HTMLElement).style.cursor = 'pointer'; - } - } - }); + + // 如果开启了特殊禁用模式,应用样式 + if (props.disableExceptEmotion) { + applyDisableState(); + } }); }; @@ -192,10 +206,11 @@ export default defineComponent({ // 监听禁用除表情外的状态变化 watch( () => props.disableExceptEmotion, - (disabled) => { - if (state.editor && state.isInitialized) { - applyDisableState(); - } + (val) => { + // 重新初始化或者直接应用样式 + // 为了稳妥,重新初始化以确保工具栏状态正确 + // 但也可以只调用 applyDisableState 如果只是切换禁用状态 + initWangeditor(); } ); @@ -211,39 +226,20 @@ export default defineComponent({ position: relative; } -/* 禁用除表情外的所有工具栏按钮 */ -.disabled-editor :deep(.w-e-bar-item) { - opacity: 0.5; - cursor: not-allowed !important; - pointer-events: none !important; +/* 仅在“只保留表情”模式下应用边框和样式修正 */ +.disabled-editor { + border: 1px solid #dcdfe6; + border-radius: 4px; } -/* 允许表情按钮正常使用 */ -.disabled-editor :deep(.w-e-bar-item[data-title*='表情']), -.disabled-editor :deep(.w-e-bar-item[data-title*='emotion']) { - opacity: 1 !important; - cursor: pointer !important; - pointer-events: auto !important; +.disabled-editor :deep(.w-e-toolbar) { + border-bottom: 1px solid #dcdfe6; + background-color: #f5f7fa; + border-radius: 4px 4px 0 0; } -/* 禁用编辑区域的所有操作(除了通过表情插入) */ .disabled-editor :deep(.w-e-text-container) { - cursor: not-allowed; - user-select: text; /* 允许选择文本 */ -} - -/* 禁用所有菜单项,除了表情相关的 */ -.disabled-editor :deep(.w-e-menu-tooltip:not([data-title*='表情']):not([data-title*='emotion'])) { - opacity: 0.5 !important; - cursor: not-allowed !important; - pointer-events: none !important; -} - -/* 允许表情菜单正常使用 */ -.disabled-editor :deep(.w-e-menu-tooltip[data-title*='表情']), -.disabled-editor :deep(.w-e-menu-tooltip[data-title*='emotion']) { - opacity: 1 !important; - cursor: pointer !important; - pointer-events: auto !important; + border-radius: 0 0 4px 4px; + background-color: #fff; } diff --git a/src/utils/request.ts b/src/utils/request.ts index d68abfc..36c5783 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -149,19 +149,19 @@ const responseErrorHandler = (error: any) => { handleTokenExpired(); break; case 403: - ElMessage.error('没有权限访问该资源'); + // ElMessage.error('没有权限访问该资源'); break; case 404: - ElMessage.error('请求的资源不存在'); + // ElMessage.error('请求的资源不存在'); break; case 500: - ElMessage.error('服务器内部错误'); + // ElMessage.error('服务器内部错误'); break; case 502: - ElMessage.error('网关错误'); + // ElMessage.error('网关错误'); break; case 503: - ElMessage.error('服务不可用'); + // ElMessage.error('服务不可用'); break; default: if (httpStatus >= 400) { diff --git a/src/views/customerService/account/index.vue b/src/views/customerService/account/index.vue index 8e530d2..15946be 100644 --- a/src/views/customerService/account/index.vue +++ b/src/views/customerService/account/index.vue @@ -286,7 +286,7 @@ const onOpenAddRole = () => { /** * 打开编辑客服对话框 */ -const onOpenEditRole = (row: TableDataItem) => { +const onOpenEditRole = (row: any) => { editRoleRef.value?.openDialog(row); }; diff --git a/src/views/customerService/product/component/editRole.vue b/src/views/customerService/product/component/editRole.vue index e5c1592..5eb2c96 100644 --- a/src/views/customerService/product/component/editRole.vue +++ b/src/views/customerService/product/component/editRole.vue @@ -81,7 +81,10 @@ const state = reactive({ // 表单验证规则 const rules: FormRules = { - name: [{ required: true, message: '产品名称不能为空', trigger: 'blur' }, { max: 64, message: '产品名称长度最多 64 个字符', trigger: 'blur' }, 1], + name: [ + { required: true, message: '产品名称不能为空', trigger: 'blur' }, + { max: 64, message: '产品名称长度最多 64 个字符', trigger: 'blur' }, + ], description: [ { required: true, message: '产品详情不能为空', trigger: 'blur' }, { max: 8126, message: '产品详情长度最多8126 个字符', trigger: 'blur' }, @@ -120,7 +123,7 @@ const openDialog = async (row?: ProductFormData) => { * 处理编辑模式的数据获取 * @param id - 产品ID */ -const handleEditMode = async (row) => { +const handleEditMode = async (row: ProductFormData) => { try { state.formData.id = row.id; state.formData.description = row.description; diff --git a/src/views/customerService/report/component/exportDialog.vue b/src/views/customerService/report/component/exportDialog.vue index 1a7e00f..fcba1be 100644 --- a/src/views/customerService/report/component/exportDialog.vue +++ b/src/views/customerService/report/component/exportDialog.vue @@ -1,22 +1,24 @@