156 lines
5.9 KiB
Vue
156 lines
5.9 KiB
Vue
<template>
|
|
<ElConfigProvider
|
|
size="default"
|
|
:locale="locales[language]"
|
|
:z-index="3000"
|
|
:card="{
|
|
shadow: 'never'
|
|
}"
|
|
:dialog="{ alignCenter: true }"
|
|
>
|
|
<RouterView></RouterView>
|
|
</ElConfigProvider>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { onBeforeMount, onMounted, onBeforeUnmount } from 'vue'
|
|
import { storeToRefs } from 'pinia'
|
|
import { useUserStore } from './store/modules/user'
|
|
import zh from 'element-plus/es/locale/lang/zh-cn'
|
|
import en from 'element-plus/es/locale/lang/en'
|
|
import { systemUpgrade } from './utils/sys'
|
|
import { toggleTransition } from './utils/ui/animation'
|
|
import { checkStorageCompatibility } from './utils/storage'
|
|
import { initializeTheme } from './hooks/core/useTheme'
|
|
|
|
const userStore = useUserStore()
|
|
const { language } = storeToRefs(userStore)
|
|
|
|
const locales = {
|
|
zh: zh,
|
|
en: en
|
|
}
|
|
|
|
let buttonIconObserver: MutationObserver | null = null
|
|
let panelTitleObserver: MutationObserver | null = null
|
|
|
|
const iconClassByText: Array<[RegExp, string]> = [
|
|
[/(新增|新建|创建|添加)/, 'auto-icon-plus'],
|
|
[/(删除|移除|清空|关闭)/, 'auto-icon-delete'],
|
|
[/(导入|上传)/, 'auto-icon-upload'],
|
|
[/(导出|下载)/, 'auto-icon-download'],
|
|
[/(搜索|查询|筛选)/, 'auto-icon-search'],
|
|
[/(重置|刷新)/, 'auto-icon-refresh'],
|
|
[/(编辑|修改|配置|设置)/, 'auto-icon-edit'],
|
|
[/(查看|详情)/, 'auto-icon-view'],
|
|
[/(保存|提交|确定|确认)/, 'auto-icon-check']
|
|
]
|
|
|
|
const autoIconClassList = iconClassByText.map(([, cls]) => cls)
|
|
|
|
const refreshButtonAutoIcons = () => {
|
|
const selectors = [
|
|
'.page-container .el-button:not(.is-circle):not(.el-button--text):not(:has(.el-icon))',
|
|
'.console-container .el-button:not(.is-circle):not(.el-button--text):not(:has(.el-icon))'
|
|
]
|
|
const buttons = document.querySelectorAll<HTMLElement>(selectors.join(','))
|
|
buttons.forEach((button) => {
|
|
autoIconClassList.forEach((className) => button.classList.remove(className))
|
|
// 区域/状态 Tab 仅展示文案,不参与按钮自动图标
|
|
if (button.classList.contains('region-tab-btn')) return
|
|
const text = (button.textContent || '').replace(/\s+/g, '')
|
|
const matched = iconClassByText.find(([rule]) => rule.test(text))
|
|
if (matched) button.classList.add(matched[1])
|
|
})
|
|
}
|
|
|
|
const panelTitleIconByText: Array<[RegExp, string]> = [
|
|
[/(任务|调度)/, 'auto-title-operation'],
|
|
[/(区域)/, 'auto-title-location'],
|
|
[/(用户|账号)/, 'auto-title-user'],
|
|
[/(参数|配置)/, 'auto-title-settings'],
|
|
[/(分类)/, 'auto-title-category'],
|
|
[/(商品|产品)/, 'auto-title-box'],
|
|
[/(订单)/, 'auto-title-receipt'],
|
|
[/(发票)/, 'auto-title-file'],
|
|
[/(询价|报价)/, 'auto-title-quote'],
|
|
[/(结算)/, 'auto-title-calc']
|
|
]
|
|
|
|
const panelTitleClassList = panelTitleIconByText.map(([, cls]) => cls)
|
|
const panelTitleBarClass = 'title-bar-heading'
|
|
const panelTitleBarTextRules: RegExp[] = [
|
|
/(数据概览|快捷菜单|分类列表|单位列表|商品列表|参数列表|用户列表|租户列表|区域列表|区域与询报价概览|报价管理|订单列表|最新订单|待结算订单|结算单记录|配送任务列表|预警列表|订单设置|客服设置|请求列表|近30日趋势|今日各区域|组织|组织管理|角色列表|菜单列表|字典类型|字典数据|站点列表|职位列表|快递公司列表|流程配置|流程列表|待办列表|已办列表|申请列表|客户列表|细胞样本类型列表|采集地区列表|采集协议号列表|样本编码列表|医院列表|协议单列表|审核记录列表|缴费确认列表|退费确认列表|分期预警列表|请假列表|洁净室列表|库位树|预约列表|缴费信息列表|样本接收列表|接收检查项列表|公司列表|项目列表|工单列表|任务列表|类型列表|规格列表|价格列表|体系列表|渠道列表|机构列表|耗材列表|试剂列表|SOP列表|工艺列表|路线列表|耗材包列表)/
|
|
]
|
|
|
|
const refreshPanelTitleIcons = () => {
|
|
const headings = document.querySelectorAll<HTMLHeadingElement>(
|
|
'.page-container .panel-top h2, .console-container .panel-top h2'
|
|
)
|
|
|
|
headings.forEach((h2) => {
|
|
const text = (h2.textContent || '').replace(/\s+/g, '')
|
|
const useBar = panelTitleBarTextRules.some((rule) => rule.test(text))
|
|
|
|
if (useBar) {
|
|
h2.querySelector('.title-ic')?.remove()
|
|
panelTitleClassList.forEach((className) => h2.classList.remove(className))
|
|
h2.classList.add(panelTitleBarClass)
|
|
return
|
|
}
|
|
|
|
h2.classList.remove(panelTitleBarClass)
|
|
|
|
// 已手写 title-ic(例如 delivery-demo)则不干预
|
|
if (h2.querySelector('.title-ic')) return
|
|
|
|
// 确保存在容器
|
|
const span = document.createElement('span')
|
|
span.className = 'title-ic'
|
|
span.setAttribute('aria-hidden', 'true')
|
|
h2.prepend(span)
|
|
|
|
// 根据标题文本匹配图标类型
|
|
panelTitleClassList.forEach((className) => h2.classList.remove(className))
|
|
const matched = panelTitleIconByText.find(([rule]) => rule.test(text))
|
|
if (matched) h2.classList.add(matched[1])
|
|
})
|
|
}
|
|
|
|
onBeforeMount(() => {
|
|
toggleTransition(true)
|
|
initializeTheme()
|
|
})
|
|
|
|
onMounted(() => {
|
|
checkStorageCompatibility()
|
|
toggleTransition(false)
|
|
systemUpgrade()
|
|
refreshButtonAutoIcons()
|
|
refreshPanelTitleIcons()
|
|
|
|
buttonIconObserver = new MutationObserver(() => {
|
|
refreshButtonAutoIcons()
|
|
})
|
|
buttonIconObserver.observe(document.body, {
|
|
childList: true,
|
|
subtree: true
|
|
})
|
|
|
|
panelTitleObserver = new MutationObserver(() => {
|
|
refreshPanelTitleIcons()
|
|
})
|
|
panelTitleObserver.observe(document.body, {
|
|
childList: true,
|
|
subtree: true
|
|
})
|
|
})
|
|
|
|
onBeforeUnmount(() => {
|
|
buttonIconObserver?.disconnect()
|
|
buttonIconObserver = null
|
|
panelTitleObserver?.disconnect()
|
|
panelTitleObserver = null
|
|
})
|
|
</script>
|