setings.vue 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932
  1. <template>
  2. <div class="layout-breadcrumb-seting">
  3. <el-drawer
  4. :title="$t('message.layout.configTitle')"
  5. v-model="getThemeConfig.isDrawer"
  6. direction="rtl"
  7. destroy-on-close
  8. size="260px"
  9. @close="onDrawerClose"
  10. >
  11. <el-scrollbar class="layout-breadcrumb-seting-bar">
  12. <!-- 全局主题 -->
  13. <el-divider content-position="left">{{ $t('message.layout.oneTitle') }}</el-divider>
  14. <div class="layout-breadcrumb-seting-bar-flex">
  15. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.primary') }}</div>
  16. <div class="layout-breadcrumb-seting-bar-flex-value">
  17. <el-color-picker v-model="getThemeConfig.primary" :predefine="predefinePrimaryColors" size="default" @change="onColorPickerChange">
  18. </el-color-picker>
  19. </div>
  20. </div>
  21. <div class="layout-breadcrumb-seting-bar-flex mt15">
  22. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsDark') }}</div>
  23. <div class="layout-breadcrumb-seting-bar-flex-value">
  24. <el-switch v-model="getThemeConfig.isIsDark" size="small" @change="onAddDarkChange"></el-switch>
  25. </div>
  26. </div>
  27. <!-- 顶栏设置 -->
  28. <el-divider content-position="left">{{ $t('message.layout.twoTopTitle') }}</el-divider>
  29. <div class="layout-breadcrumb-seting-bar-flex">
  30. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoTopBar') }}</div>
  31. <div class="layout-breadcrumb-seting-bar-flex-value">
  32. <el-color-picker
  33. v-model="getThemeConfig.topBar"
  34. :predefine="predefineTopBarBgColors"
  35. size="default"
  36. @change="onBgColorPickerChange('topBar')"
  37. >
  38. </el-color-picker>
  39. </div>
  40. </div>
  41. <div class="layout-breadcrumb-seting-bar-flex">
  42. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoTopBarColor') }}</div>
  43. <div class="layout-breadcrumb-seting-bar-flex-value">
  44. <el-color-picker
  45. v-model="getThemeConfig.topBarColor"
  46. :predefine="predefineFontColors"
  47. size="default"
  48. @change="onBgColorPickerChange('topBarColor')"
  49. >
  50. </el-color-picker>
  51. </div>
  52. </div>
  53. <div class="layout-breadcrumb-seting-bar-flex mt10">
  54. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoIsTopBarColorGradual') }}</div>
  55. <div class="layout-breadcrumb-seting-bar-flex-value">
  56. <el-switch v-model="getThemeConfig.isTopBarColorGradual" size="small" @change="onTopBarGradualChange"></el-switch>
  57. </div>
  58. </div>
  59. <!-- 菜单设置 -->
  60. <el-divider content-position="left">{{ $t('message.layout.twoMenuTitle') }}</el-divider>
  61. <div class="layout-breadcrumb-seting-bar-flex">
  62. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoMenuBar') }}</div>
  63. <div class="layout-breadcrumb-seting-bar-flex-value">
  64. <el-color-picker
  65. v-model="getThemeConfig.menuBar"
  66. :predefine="predefineMenuBarBgColors"
  67. size="default"
  68. @change="onBgColorPickerChange('menuBar')"
  69. >
  70. </el-color-picker>
  71. </div>
  72. </div>
  73. <div class="layout-breadcrumb-seting-bar-flex">
  74. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoMenuBarColor') }}</div>
  75. <div class="layout-breadcrumb-seting-bar-flex-value">
  76. <el-color-picker
  77. v-model="getThemeConfig.menuBarColor"
  78. :predefine="predefineFontColors"
  79. size="default"
  80. @change="onBgColorPickerChange('menuBarColor')"
  81. >
  82. </el-color-picker>
  83. </div>
  84. </div>
  85. <div class="layout-breadcrumb-seting-bar-flex">
  86. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoMenuBarActiveColor') }}</div>
  87. <div class="layout-breadcrumb-seting-bar-flex-value">
  88. <el-color-picker
  89. v-model="getThemeConfig.menuBarActiveColor"
  90. size="default"
  91. show-alpha
  92. :predefine="predefineActiveBgColors"
  93. @change="onBgColorPickerChange('menuBarActiveColor')"
  94. />
  95. </div>
  96. </div>
  97. <div class="layout-breadcrumb-seting-bar-flex mt14">
  98. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoIsMenuBarColorGradual') }}</div>
  99. <div class="layout-breadcrumb-seting-bar-flex-value">
  100. <el-switch v-model="getThemeConfig.isMenuBarColorGradual" size="small" @change="onMenuBarGradualChange"></el-switch>
  101. </div>
  102. </div>
  103. <!-- 分栏设置 -->
  104. <el-divider content-position="left" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }">{{
  105. $t('message.layout.twoColumnsTitle')
  106. }}</el-divider>
  107. <div class="layout-breadcrumb-seting-bar-flex" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }">
  108. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoColumnsMenuBar') }}</div>
  109. <div class="layout-breadcrumb-seting-bar-flex-value">
  110. <el-color-picker
  111. v-model="getThemeConfig.columnsMenuBar"
  112. :predefine="predefineColumnsMenuBarBgColors"
  113. size="default"
  114. @change="onBgColorPickerChange('columnsMenuBar')"
  115. :disabled="getThemeConfig.layout !== 'columns'"
  116. >
  117. </el-color-picker>
  118. </div>
  119. </div>
  120. <div class="layout-breadcrumb-seting-bar-flex" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }">
  121. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoColumnsMenuBarColor') }}</div>
  122. <div class="layout-breadcrumb-seting-bar-flex-value">
  123. <el-color-picker
  124. v-model="getThemeConfig.columnsMenuBarColor"
  125. :predefine="predefineFontColors"
  126. size="default"
  127. @change="onBgColorPickerChange('columnsMenuBarColor')"
  128. :disabled="getThemeConfig.layout !== 'columns'"
  129. >
  130. </el-color-picker>
  131. </div>
  132. </div>
  133. <div class="layout-breadcrumb-seting-bar-flex mt14" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }">
  134. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoIsColumnsMenuBarColorGradual') }}</div>
  135. <div class="layout-breadcrumb-seting-bar-flex-value">
  136. <el-switch
  137. v-model="getThemeConfig.isColumnsMenuBarColorGradual"
  138. size="small"
  139. @change="onColumnsMenuBarGradualChange"
  140. :disabled="getThemeConfig.layout !== 'columns'"
  141. ></el-switch>
  142. </div>
  143. </div>
  144. <div class="layout-breadcrumb-seting-bar-flex mt14" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }">
  145. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoIsColumnsMenuHoverPreload') }}</div>
  146. <div class="layout-breadcrumb-seting-bar-flex-value">
  147. <el-switch
  148. v-model="getThemeConfig.isColumnsMenuHoverPreload"
  149. size="small"
  150. @change="onColumnsMenuHoverPreloadChange"
  151. :disabled="getThemeConfig.layout !== 'columns'"
  152. ></el-switch>
  153. </div>
  154. </div>
  155. <!-- 界面设置 -->
  156. <el-divider content-position="left">{{ $t('message.layout.threeTitle') }}</el-divider>
  157. <div class="layout-breadcrumb-seting-bar-flex" :style="{ opacity: getThemeConfig.layout === 'transverse' ? 0.5 : 1 }">
  158. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsCollapse') }}</div>
  159. <div class="layout-breadcrumb-seting-bar-flex-value">
  160. <el-switch
  161. v-model="getThemeConfig.isCollapse"
  162. :disabled="getThemeConfig.layout === 'transverse'"
  163. size="small"
  164. @change="onThemeConfigChange"
  165. ></el-switch>
  166. </div>
  167. </div>
  168. <div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: getThemeConfig.layout === 'transverse' ? 0.5 : 1 }">
  169. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsUniqueOpened') }}</div>
  170. <div class="layout-breadcrumb-seting-bar-flex-value">
  171. <el-switch
  172. v-model="getThemeConfig.isUniqueOpened"
  173. :disabled="getThemeConfig.layout === 'transverse'"
  174. size="small"
  175. @change="setLocalThemeConfig"
  176. ></el-switch>
  177. </div>
  178. </div>
  179. <div class="layout-breadcrumb-seting-bar-flex mt15">
  180. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsFixedHeader') }}</div>
  181. <div class="layout-breadcrumb-seting-bar-flex-value">
  182. <el-switch v-model="getThemeConfig.isFixedHeader" size="small" @change="onIsFixedHeaderChange"></el-switch>
  183. </div>
  184. </div>
  185. <div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: getThemeConfig.layout !== 'classic' ? 0.5 : 1 }">
  186. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsClassicSplitMenu') }}</div>
  187. <div class="layout-breadcrumb-seting-bar-flex-value">
  188. <el-switch
  189. v-model="getThemeConfig.isClassicSplitMenu"
  190. :disabled="getThemeConfig.layout !== 'classic'"
  191. size="small"
  192. @change="onClassicSplitMenuChange"
  193. >
  194. </el-switch>
  195. </div>
  196. </div>
  197. <div class="layout-breadcrumb-seting-bar-flex mt15">
  198. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsLockScreen') }}</div>
  199. <div class="layout-breadcrumb-seting-bar-flex-value">
  200. <el-switch v-model="getThemeConfig.isLockScreen" size="small" @change="setLocalThemeConfig"></el-switch>
  201. </div>
  202. </div>
  203. <div class="layout-breadcrumb-seting-bar-flex mt11">
  204. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeLockScreenTime') }}</div>
  205. <div class="layout-breadcrumb-seting-bar-flex-value">
  206. <el-input-number
  207. v-model="getThemeConfig.lockScreenTime"
  208. controls-position="right"
  209. :min="1"
  210. :max="9999"
  211. @change="setLocalThemeConfig"
  212. size="default"
  213. style="width: 90px"
  214. >
  215. </el-input-number>
  216. </div>
  217. </div>
  218. <!-- 界面显示 -->
  219. <el-divider content-position="left">{{ $t('message.layout.fourTitle') }}</el-divider>
  220. <div class="layout-breadcrumb-seting-bar-flex mt15">
  221. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsShowLogo') }}</div>
  222. <div class="layout-breadcrumb-seting-bar-flex-value">
  223. <el-switch v-model="getThemeConfig.isShowLogo" size="small" @change="onIsShowLogoChange"></el-switch>
  224. </div>
  225. </div>
  226. <div
  227. class="layout-breadcrumb-seting-bar-flex mt15"
  228. :style="{ opacity: getThemeConfig.layout === 'classic' || getThemeConfig.layout === 'transverse' ? 0.5 : 1 }"
  229. >
  230. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsBreadcrumb') }}</div>
  231. <div class="layout-breadcrumb-seting-bar-flex-value">
  232. <el-switch
  233. v-model="getThemeConfig.isBreadcrumb"
  234. :disabled="getThemeConfig.layout === 'classic' || getThemeConfig.layout === 'transverse'"
  235. size="small"
  236. @change="onIsBreadcrumbChange"
  237. ></el-switch>
  238. </div>
  239. </div>
  240. <div class="layout-breadcrumb-seting-bar-flex mt15">
  241. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsBreadcrumbIcon') }}</div>
  242. <div class="layout-breadcrumb-seting-bar-flex-value">
  243. <el-switch v-model="getThemeConfig.isBreadcrumbIcon" size="small" @change="setLocalThemeConfig"></el-switch>
  244. </div>
  245. </div>
  246. <div class="layout-breadcrumb-seting-bar-flex mt15">
  247. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsTagsview') }}</div>
  248. <div class="layout-breadcrumb-seting-bar-flex-value">
  249. <el-switch v-model="getThemeConfig.isTagsview" size="small" @change="setLocalThemeConfig"></el-switch>
  250. </div>
  251. </div>
  252. <div class="layout-breadcrumb-seting-bar-flex mt15">
  253. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsTagsviewIcon') }}</div>
  254. <div class="layout-breadcrumb-seting-bar-flex-value">
  255. <el-switch v-model="getThemeConfig.isTagsviewIcon" size="small" @change="setLocalThemeConfig"></el-switch>
  256. </div>
  257. </div>
  258. <div class="layout-breadcrumb-seting-bar-flex mt15">
  259. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsCacheTagsView') }}</div>
  260. <div class="layout-breadcrumb-seting-bar-flex-value">
  261. <el-switch v-model="getThemeConfig.isCacheTagsView" size="small" @change="setLocalThemeConfig"></el-switch>
  262. </div>
  263. </div>
  264. <div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: state.isMobile ? 0.5 : 1 }">
  265. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsSortableTagsView') }}</div>
  266. <div class="layout-breadcrumb-seting-bar-flex-value">
  267. <el-switch
  268. v-model="getThemeConfig.isSortableTagsView"
  269. :disabled="state.isMobile ? true : false"
  270. size="small"
  271. @change="onSortableTagsViewChange"
  272. ></el-switch>
  273. </div>
  274. </div>
  275. <div class="layout-breadcrumb-seting-bar-flex mt15">
  276. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsShareTagsView') }}</div>
  277. <div class="layout-breadcrumb-seting-bar-flex-value">
  278. <el-switch v-model="getThemeConfig.isShareTagsView" size="small" @change="onShareTagsViewChange"></el-switch>
  279. </div>
  280. </div>
  281. <div class="layout-breadcrumb-seting-bar-flex mt15">
  282. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsFooter') }}</div>
  283. <div class="layout-breadcrumb-seting-bar-flex-value">
  284. <el-switch v-model="getThemeConfig.isFooter" size="small" @change="setLocalThemeConfig"></el-switch>
  285. </div>
  286. </div>
  287. <div class="layout-breadcrumb-seting-bar-flex mt15">
  288. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsGrayscale') }}</div>
  289. <div class="layout-breadcrumb-seting-bar-flex-value">
  290. <el-switch v-model="getThemeConfig.isGrayscale" size="small" @change="onAddFilterChange('grayscale')"></el-switch>
  291. </div>
  292. </div>
  293. <div class="layout-breadcrumb-seting-bar-flex mt15">
  294. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsInvert') }}</div>
  295. <div class="layout-breadcrumb-seting-bar-flex-value">
  296. <el-switch v-model="getThemeConfig.isInvert" size="small" @change="onAddFilterChange('invert')"></el-switch>
  297. </div>
  298. </div>
  299. <div class="layout-breadcrumb-seting-bar-flex mt15">
  300. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsWatermark') }}</div>
  301. <div class="layout-breadcrumb-seting-bar-flex-value">
  302. <el-switch v-model="getThemeConfig.isWatermark" size="small" @change="onWatermarkChange"></el-switch>
  303. </div>
  304. </div>
  305. <div class="layout-breadcrumb-seting-bar-flex mt14">
  306. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourWatermarkText') }}</div>
  307. <div class="layout-breadcrumb-seting-bar-flex-value">
  308. <el-input v-model="getThemeConfig.watermarkText" size="default" style="width: 90px" @input="onWatermarkTextInput"></el-input>
  309. </div>
  310. </div>
  311. <!-- 其它设置 -->
  312. <el-divider content-position="left">{{ $t('message.layout.fiveTitle') }}</el-divider>
  313. <div class="layout-breadcrumb-seting-bar-flex mt15">
  314. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveTagsStyle') }}</div>
  315. <div class="layout-breadcrumb-seting-bar-flex-value">
  316. <el-select v-model="getThemeConfig.tagsStyle" placeholder="请选择" size="default" style="width: 90px" @change="setLocalThemeConfig">
  317. <el-option label="卡片" value="tags-style-one"></el-option>
  318. <el-option label="简约" value="tags-style-four"></el-option>
  319. <el-option label="圆滑" value="tags-style-five"></el-option>
  320. </el-select>
  321. </div>
  322. </div>
  323. <div class="layout-breadcrumb-seting-bar-flex mt15">
  324. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveAnimation') }}</div>
  325. <div class="layout-breadcrumb-seting-bar-flex-value">
  326. <el-select
  327. v-model="getThemeConfig.animation"
  328. placeholder="请选择"
  329. placement="bottom-end"
  330. size="default"
  331. style="width: 90px"
  332. @change="setLocalThemeConfig"
  333. >
  334. <el-option label="右滑动" value="slide-right"></el-option>
  335. <el-option label="左滑动" value="slide-left"></el-option>
  336. <el-option label="淡入淡出" value="opacitys"></el-option>
  337. </el-select>
  338. </div>
  339. </div>
  340. <div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }">
  341. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveColumnsAsideStyle') }}</div>
  342. <div class="layout-breadcrumb-seting-bar-flex-value">
  343. <el-select
  344. v-model="getThemeConfig.columnsAsideStyle"
  345. placeholder="请选择"
  346. size="default"
  347. style="width: 90px"
  348. :disabled="getThemeConfig.layout !== 'columns' ? true : false"
  349. @change="setLocalThemeConfig"
  350. >
  351. <el-option label="圆角" value="columns-round"></el-option>
  352. <el-option label="卡片" value="columns-card"></el-option>
  353. </el-select>
  354. </div>
  355. </div>
  356. <div class="layout-breadcrumb-seting-bar-flex mt15 mb27" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }">
  357. <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveColumnsAsideLayout') }}</div>
  358. <div class="layout-breadcrumb-seting-bar-flex-value">
  359. <el-select
  360. v-model="getThemeConfig.columnsAsideLayout"
  361. placeholder="请选择"
  362. size="default"
  363. style="width: 90px"
  364. :disabled="getThemeConfig.layout !== 'columns' ? true : false"
  365. @change="setLocalThemeConfig"
  366. >
  367. <el-option label="水平" value="columns-horizontal"></el-option>
  368. <el-option label="垂直" value="columns-vertical"></el-option>
  369. </el-select>
  370. </div>
  371. </div>
  372. <!-- 布局切换 -->
  373. <el-divider content-position="left">{{ $t('message.layout.sixTitle') }}</el-divider>
  374. <div class="layout-drawer-content-flex">
  375. <!-- defaults 布局 -->
  376. <div class="layout-drawer-content-item" @click="onSetLayout('defaults')">
  377. <section class="el-container el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'defaults' }">
  378. <aside class="el-aside" style="width: 20px"></aside>
  379. <section class="el-container is-vertical">
  380. <header class="el-header" style="height: 10px"></header>
  381. <main class="el-main"></main>
  382. </section>
  383. </section>
  384. <div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'defaults' }">
  385. <div class="layout-tips-box">
  386. <p class="layout-tips-txt">{{ $t('message.layout.sixDefaults') }}</p>
  387. </div>
  388. </div>
  389. </div>
  390. <!-- classic 布局 -->
  391. <div class="layout-drawer-content-item" @click="onSetLayout('classic')">
  392. <section class="el-container is-vertical el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'classic' }">
  393. <header class="el-header" style="height: 10px"></header>
  394. <section class="el-container">
  395. <aside class="el-aside" style="width: 20px"></aside>
  396. <section class="el-container is-vertical">
  397. <main class="el-main"></main>
  398. </section>
  399. </section>
  400. </section>
  401. <div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'classic' }">
  402. <div class="layout-tips-box">
  403. <p class="layout-tips-txt">{{ $t('message.layout.sixClassic') }}</p>
  404. </div>
  405. </div>
  406. </div>
  407. <!-- transverse 布局 -->
  408. <div class="layout-drawer-content-item" @click="onSetLayout('transverse')">
  409. <section class="el-container is-vertical el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'transverse' }">
  410. <header class="el-header" style="height: 10px"></header>
  411. <section class="el-container">
  412. <section class="el-container is-vertical">
  413. <main class="el-main"></main>
  414. </section>
  415. </section>
  416. </section>
  417. <div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'transverse' }">
  418. <div class="layout-tips-box">
  419. <p class="layout-tips-txt">{{ $t('message.layout.sixTransverse') }}</p>
  420. </div>
  421. </div>
  422. </div>
  423. <!-- columns 布局 -->
  424. <div class="layout-drawer-content-item" @click="onSetLayout('columns')">
  425. <section class="el-container el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'columns' }">
  426. <aside class="el-aside-dark" style="width: 10px"></aside>
  427. <aside class="el-aside" style="width: 20px"></aside>
  428. <section class="el-container is-vertical">
  429. <header class="el-header" style="height: 10px"></header>
  430. <main class="el-main"></main>
  431. </section>
  432. </section>
  433. <div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'columns' }">
  434. <div class="layout-tips-box">
  435. <p class="layout-tips-txt">{{ $t('message.layout.sixColumns') }}</p>
  436. </div>
  437. </div>
  438. </div>
  439. </div>
  440. <div class="copy-config">
  441. <el-alert :title="$t('message.layout.tipText')" type="warning" :closable="false"> </el-alert>
  442. <el-button size="default" class="copy-config-btn" type="primary" ref="copyConfigBtnRef" @click="onCopyConfigClick">
  443. <el-icon class="mr5">
  444. <ele-CopyDocument />
  445. </el-icon>
  446. {{ $t('message.layout.copyText') }}
  447. </el-button>
  448. <el-button size="default" class="copy-config-btn-reset" type="info" @click="onResetConfigClick">
  449. <el-icon class="mr5">
  450. <ele-RefreshRight />
  451. </el-icon>
  452. {{ $t('message.layout.resetText') }}
  453. </el-button>
  454. </div>
  455. </el-scrollbar>
  456. </el-drawer>
  457. </div>
  458. </template>
  459. <script setup lang="ts" name="layoutBreadcrumbSeting">
  460. import { ref, nextTick, onUnmounted, onMounted, computed, reactive } from 'vue'
  461. import { ElMessage } from 'element-plus'
  462. import { useI18n } from 'vue-i18n'
  463. import { storeToRefs } from 'pinia'
  464. import { useThemeConfig } from '/@/stores/themeConfig'
  465. import { useChangeColor } from '/@/utils/theme'
  466. import { verifyAndSpace } from '/@/utils/toolsValidate'
  467. import { Local } from '/@/utils/storage'
  468. import Watermark from '/@/utils/watermark'
  469. import commonFunction from '/@/utils/commonFunction'
  470. import other from '/@/utils/other'
  471. import mittBus from '/@/utils/mitt'
  472. import { getToken, setToken } from '/@/api/admin/http-client'
  473. // 定义变量内容
  474. // 预定义主要颜色
  475. const predefinePrimaryColors = ref([
  476. '#F34D37', //红色
  477. '#409eff', //蓝色
  478. '#6954f0', //紫色
  479. '#41b584', //绿色
  480. ])
  481. // 预定义顶栏背景颜色
  482. const predefineTopBarBgColors = ref([
  483. '#ffffff', //白色
  484. '#323233', //黑色
  485. ])
  486. // 预定义菜单背景颜色
  487. const predefineMenuBarBgColors = ref([
  488. '#ffffff', //白色
  489. '#252526', //黑色
  490. ])
  491. // 预定义分栏背景颜色
  492. const predefineColumnsMenuBarBgColors = ref([
  493. '#ffffff', //白色
  494. '#333333', //黑色
  495. ])
  496. const grayWhiteColor = '#eaeaea' //灰白色
  497. const grayBlackColor = '#606266' //灰黑色
  498. // 预定义字体颜色
  499. const predefineFontColors = ref([
  500. grayWhiteColor, //灰白色
  501. grayBlackColor, //灰黑色
  502. ])
  503. const { locale } = useI18n()
  504. const storesThemeConfig = useThemeConfig()
  505. const { themeConfig } = storeToRefs(storesThemeConfig)
  506. const { copyText } = commonFunction()
  507. const { getLightColor, getDarkColor } = useChangeColor()
  508. const state = reactive({
  509. isMobile: false,
  510. })
  511. const GrayWhiteBgColor = 'rgba(0, 0, 0, 0.2)' //浅灰黑色
  512. // 预定义高亮背景颜色
  513. const predefineActiveBgColors = ref([
  514. GrayWhiteBgColor, //浅灰黑色
  515. getLightColor(predefinePrimaryColors.value[0], 9 / 10), //浅红色
  516. getLightColor(predefinePrimaryColors.value[1], 9 / 10), //浅蓝色
  517. getLightColor(predefinePrimaryColors.value[2], 9 / 10), //浅紫色
  518. getLightColor(predefinePrimaryColors.value[3], 9 / 10), //浅绿色
  519. ])
  520. // 获取布局配置信息
  521. const getThemeConfig = computed(() => {
  522. return themeConfig.value
  523. })
  524. // 1、全局主题
  525. const onColorPickerChange = () => {
  526. if (!getThemeConfig.value.primary) return ElMessage.warning('全局主题 primary 颜色值不能为空')
  527. // 颜色加深
  528. document.documentElement.style.setProperty('--el-color-primary-dark-2', `${getDarkColor(getThemeConfig.value.primary, 0.1)}`)
  529. document.documentElement.style.setProperty('--el-color-primary', getThemeConfig.value.primary)
  530. // 颜色变浅
  531. for (let i = 1; i <= 9; i++) {
  532. document.documentElement.style.setProperty(`--el-color-primary-light-${i}`, `${getLightColor(getThemeConfig.value.primary, i / 10)}`)
  533. }
  534. setDispatchThemeConfig()
  535. onBgColorPickerChange('menuBar')
  536. }
  537. // 2、菜单 / 顶栏
  538. const onBgColorPickerChange = (bg: string) => {
  539. const bgColor = themeConfig.value[bg]
  540. document.documentElement.style.setProperty(`--next-bg-${bg}`, bgColor)
  541. if (bg === 'menuBar') {
  542. document.documentElement.style.setProperty(`--next-bg-menuBar-light-1`, getLightColor(getThemeConfig.value.menuBar, 0.05))
  543. }
  544. onTopBarGradualChange()
  545. onMenuBarGradualChange()
  546. onColumnsMenuBarGradualChange()
  547. setDispatchThemeConfig()
  548. if (bg === 'topBar' || bg === 'menuBar' || bg === 'columnsMenuBar') {
  549. const whiteTheme = ['#FFFFFF', '#FFF', '#fff', '#ffffff']
  550. const colorName = bg + 'Color'
  551. if (whiteTheme.includes(bgColor)) {
  552. if (bg === 'menuBar') {
  553. const activeColorName = bg + 'ActiveColor'
  554. getThemeConfig.value[activeColorName] = getLightColor(getThemeConfig.value.primary, 9 / 10)
  555. onBgColorPickerChange(activeColorName)
  556. }
  557. getThemeConfig.value[colorName] = grayBlackColor
  558. } else {
  559. if (bg === 'menuBar') {
  560. const activeColorName = bg + 'ActiveColor'
  561. getThemeConfig.value[activeColorName] = GrayWhiteBgColor
  562. onBgColorPickerChange(activeColorName)
  563. }
  564. getThemeConfig.value[colorName] = grayWhiteColor
  565. }
  566. onBgColorPickerChange(colorName)
  567. }
  568. }
  569. // 设置激活颜色
  570. const onActiveColorPickerChange = (name: string) => {
  571. document.documentElement.style.setProperty(`--next-color-${name}`, themeConfig.value[name])
  572. }
  573. // 2、菜单 / 顶栏 --> 顶栏背景渐变
  574. const onTopBarGradualChange = () => {
  575. setGraduaFun('.layout-navbars-breadcrumb-index', getThemeConfig.value.isTopBarColorGradual, getThemeConfig.value.topBar)
  576. }
  577. // 2、菜单 / 顶栏 --> 菜单背景渐变
  578. const onMenuBarGradualChange = () => {
  579. setGraduaFun('.layout-container .el-aside', getThemeConfig.value.isMenuBarColorGradual, getThemeConfig.value.menuBar)
  580. }
  581. // 2、菜单 / 顶栏 --> 分栏菜单背景渐变
  582. const onColumnsMenuBarGradualChange = () => {
  583. setGraduaFun('.layout-container .layout-columns-aside', getThemeConfig.value.isColumnsMenuBarColorGradual, getThemeConfig.value.columnsMenuBar)
  584. }
  585. // 2、菜单 / 顶栏 --> 背景渐变函数
  586. const setGraduaFun = (el: string, bool: boolean, color: string) => {
  587. setTimeout(() => {
  588. let els = document.querySelector(el)
  589. if (!els) return false
  590. document.documentElement.style.setProperty('--el-menu-bg-color', document.documentElement.style.getPropertyValue('--next-bg-menuBar'))
  591. if (bool) els.setAttribute('style', `background:linear-gradient(to bottom left , ${color}, ${getLightColor(color, 0.6)}) !important;`)
  592. else els.setAttribute('style', ``)
  593. setLocalThemeConfig()
  594. }, 200)
  595. }
  596. // 2、分栏设置 ->
  597. const onColumnsMenuHoverPreloadChange = () => {
  598. setLocalThemeConfig()
  599. }
  600. // 3、界面设置 --> 菜单水平折叠
  601. const onThemeConfigChange = () => {
  602. setDispatchThemeConfig()
  603. }
  604. // 3、界面设置 --> 固定 Header
  605. const onIsFixedHeaderChange = () => {
  606. getThemeConfig.value.isFixedHeaderChange = getThemeConfig.value.isFixedHeader ? false : true
  607. setLocalThemeConfig()
  608. }
  609. // 3、界面设置 --> 经典布局分割菜单
  610. const onClassicSplitMenuChange = () => {
  611. // getThemeConfig.value.isBreadcrumb = false
  612. setLocalThemeConfig()
  613. mittBus.emit('getBreadcrumbIndexSetFilterRoutes')
  614. }
  615. // 4、界面显示 --> 侧边栏 Logo
  616. const onIsShowLogoChange = () => {
  617. getThemeConfig.value.isShowLogoChange = getThemeConfig.value.isShowLogo ? false : true
  618. setLocalThemeConfig()
  619. }
  620. // 4、界面显示 --> 面包屑 Breadcrumb
  621. const onIsBreadcrumbChange = () => {
  622. if (getThemeConfig.value.layout === 'classic') {
  623. getThemeConfig.value.isClassicSplitMenu = false
  624. }
  625. setLocalThemeConfig()
  626. }
  627. // 4、界面显示 --> 开启 TagsView 拖拽
  628. const onSortableTagsViewChange = () => {
  629. mittBus.emit('openOrCloseSortable')
  630. setLocalThemeConfig()
  631. }
  632. // 4、界面显示 --> 开启 TagsView 共用
  633. const onShareTagsViewChange = () => {
  634. mittBus.emit('openShareTagsView')
  635. setLocalThemeConfig()
  636. }
  637. // 4、界面显示 --> 灰色模式/色弱模式
  638. const onAddFilterChange = (attr: string) => {
  639. if (attr === 'grayscale') {
  640. if (getThemeConfig.value.isGrayscale) getThemeConfig.value.isInvert = false
  641. } else {
  642. if (getThemeConfig.value.isInvert) getThemeConfig.value.isGrayscale = false
  643. }
  644. const cssAttr =
  645. attr === 'grayscale' ? `grayscale(${getThemeConfig.value.isGrayscale ? 1 : 0})` : `invert(${getThemeConfig.value.isInvert ? '80%' : '0%'})`
  646. const appEle = document.body
  647. appEle.setAttribute('style', `filter: ${cssAttr}`)
  648. setLocalThemeConfig()
  649. }
  650. // 4、界面显示 --> 深色模式
  651. const onAddDarkChange = () => {
  652. const body = document.documentElement as HTMLElement
  653. if (getThemeConfig.value.isIsDark) body.setAttribute('data-theme', 'dark')
  654. else body.setAttribute('data-theme', '')
  655. }
  656. // 4、界面显示 --> 开启水印
  657. const onWatermarkChange = () => {
  658. getThemeConfig.value.isWatermark ? Watermark.set(getThemeConfig.value.watermarkText) : Watermark.del()
  659. setLocalThemeConfig()
  660. }
  661. // 4、界面显示 --> 水印文案
  662. const onWatermarkTextInput = (val: string) => {
  663. getThemeConfig.value.watermarkText = verifyAndSpace(val)
  664. if (getThemeConfig.value.watermarkText === '') return false
  665. if (getThemeConfig.value.isWatermark) Watermark.set(getThemeConfig.value.watermarkText)
  666. setLocalThemeConfig()
  667. }
  668. // 5、布局切换
  669. const onSetLayout = (layout: string) => {
  670. Local.set('oldLayout', layout)
  671. if (getThemeConfig.value.layout === layout) return false
  672. if (layout === 'transverse') getThemeConfig.value.isCollapse = false
  673. getThemeConfig.value.layout = layout
  674. getThemeConfig.value.isDrawer = false
  675. initLayoutChangeFun()
  676. }
  677. // 设置布局切换函数
  678. const initLayoutChangeFun = () => {
  679. onBgColorPickerChange('menuBar')
  680. onBgColorPickerChange('menuBarColor')
  681. onBgColorPickerChange('menuBarActiveColor')
  682. onBgColorPickerChange('topBar')
  683. onBgColorPickerChange('topBarColor')
  684. onBgColorPickerChange('columnsMenuBar')
  685. onBgColorPickerChange('columnsMenuBarColor')
  686. onActiveColorPickerChange('columnsMenuBarActiveColor')
  687. }
  688. // 关闭弹窗时,初始化变量。变量用于处理 layoutScrollbarRef.value.update() 更新滚动条高度
  689. const onDrawerClose = () => {
  690. getThemeConfig.value.isFixedHeaderChange = false
  691. getThemeConfig.value.isShowLogoChange = false
  692. getThemeConfig.value.isDrawer = false
  693. setLocalThemeConfig()
  694. }
  695. // 布局配置弹窗打开
  696. const openDrawer = () => {
  697. getThemeConfig.value.isDrawer = true
  698. }
  699. // 触发 store 布局配置更新
  700. const setDispatchThemeConfig = () => {
  701. setLocalThemeConfig()
  702. setLocalThemeConfigStyle()
  703. }
  704. // 存储布局配置
  705. const setLocalThemeConfig = () => {
  706. Local.remove('themeConfig')
  707. Local.set('themeConfig', getThemeConfig.value)
  708. }
  709. // 存储布局配置全局主题样式(html根标签)
  710. const setLocalThemeConfigStyle = () => {
  711. Local.set('themeConfigStyle', document.documentElement.style.cssText)
  712. }
  713. // 一键复制配置
  714. const onCopyConfigClick = () => {
  715. let copyThemeConfig = Local.get('themeConfig')
  716. copyThemeConfig.isDrawer = false
  717. copyText(JSON.stringify(copyThemeConfig)).then(() => {
  718. getThemeConfig.value.isDrawer = false
  719. })
  720. }
  721. // 一键恢复默认
  722. const onResetConfigClick = () => {
  723. const token = getToken()
  724. Local.clear()
  725. setToken(token)
  726. window.location.reload()
  727. // @ts-ignore
  728. Local.set('version', __NEXT_VERSION__)
  729. }
  730. // 初始化菜单样式等
  731. const initSetStyle = () => {
  732. // 2、菜单 / 顶栏 --> 顶栏背景渐变
  733. onTopBarGradualChange()
  734. // 2、菜单 / 顶栏 --> 菜单背景渐变
  735. onMenuBarGradualChange()
  736. // 2、菜单 / 顶栏 --> 分栏菜单背景渐变
  737. onColumnsMenuBarGradualChange()
  738. }
  739. onMounted(() => {
  740. nextTick(() => {
  741. // 判断当前布局是否不相同,不相同则初始化当前布局的样式,防止监听窗口大小改变时,布局配置logo、菜单背景等部分布局失效问题
  742. if (!Local.get('frequency')) initLayoutChangeFun()
  743. Local.set('frequency', 1)
  744. // 监听窗口大小改变,非默认布局,设置成默认布局(适配移动端)
  745. mittBus.on('layoutMobileResize', (res: LayoutMobileResize) => {
  746. getThemeConfig.value.layout = res.layout
  747. getThemeConfig.value.isDrawer = false
  748. initLayoutChangeFun()
  749. state.isMobile = other.isMobile()
  750. })
  751. setTimeout(() => {
  752. // 默认样式
  753. onColorPickerChange()
  754. // 灰色模式
  755. if (getThemeConfig.value.isGrayscale) onAddFilterChange('grayscale')
  756. // 色弱模式
  757. if (getThemeConfig.value.isInvert) onAddFilterChange('invert')
  758. // 深色模式
  759. if (getThemeConfig.value.isIsDark) onAddDarkChange()
  760. // 开启水印
  761. onWatermarkChange()
  762. // 语言国际化
  763. if (Local.get('themeConfig')) locale.value = Local.get('themeConfig').globalI18n
  764. // 初始化菜单样式等
  765. initSetStyle()
  766. }, 100)
  767. })
  768. })
  769. onUnmounted(() => {
  770. mittBus.off('layoutMobileResize', () => {})
  771. })
  772. // 暴露变量
  773. defineExpose({
  774. openDrawer,
  775. })
  776. </script>
  777. <style scoped lang="scss">
  778. .layout-breadcrumb-seting-bar {
  779. height: calc(100vh - 50px);
  780. padding: 0 15px;
  781. :deep(.el-scrollbar__view) {
  782. overflow-x: hidden !important;
  783. }
  784. .layout-breadcrumb-seting-bar-flex {
  785. display: flex;
  786. align-items: center;
  787. margin-bottom: 5px;
  788. &-label {
  789. flex: 1;
  790. color: var(--el-text-color-primary);
  791. }
  792. }
  793. .layout-drawer-content-flex {
  794. overflow: hidden;
  795. display: flex;
  796. flex-wrap: wrap;
  797. align-content: flex-start;
  798. margin: 0 -5px;
  799. .layout-drawer-content-item {
  800. width: 50%;
  801. height: 70px;
  802. cursor: pointer;
  803. border: 1px solid transparent;
  804. position: relative;
  805. padding: 5px;
  806. .el-container {
  807. height: 100%;
  808. .el-aside-dark {
  809. background-color: var(--next-color-seting-header);
  810. }
  811. .el-aside {
  812. background-color: var(--next-color-seting-aside);
  813. }
  814. .el-header {
  815. background-color: var(--next-color-seting-header);
  816. }
  817. .el-main {
  818. background-color: var(--next-color-seting-main);
  819. }
  820. }
  821. .el-circular {
  822. border-radius: 2px;
  823. overflow: hidden;
  824. border: 1px solid transparent;
  825. transition: all 0.3s ease-in-out;
  826. }
  827. .drawer-layout-active {
  828. border: 1px solid;
  829. border-color: var(--el-color-primary);
  830. }
  831. .layout-tips-warp,
  832. .layout-tips-warp-active {
  833. transition: all 0.3s ease-in-out;
  834. position: absolute;
  835. left: 50%;
  836. top: 50%;
  837. transform: translate(-50%, -50%);
  838. border: 1px solid;
  839. border-color: var(--el-color-primary-light-5);
  840. border-radius: 100%;
  841. padding: 4px;
  842. .layout-tips-box {
  843. transition: inherit;
  844. width: 30px;
  845. height: 30px;
  846. z-index: 9;
  847. border: 1px solid;
  848. border-color: var(--el-color-primary-light-5);
  849. border-radius: 100%;
  850. .layout-tips-txt {
  851. transition: inherit;
  852. position: relative;
  853. top: 5px;
  854. font-size: 12px;
  855. line-height: 1;
  856. letter-spacing: 2px;
  857. white-space: nowrap;
  858. color: var(--el-color-primary-light-5);
  859. text-align: center;
  860. transform: rotate(30deg);
  861. left: -1px;
  862. background-color: var(--next-color-seting-main);
  863. width: 32px;
  864. height: 17px;
  865. line-height: 17px;
  866. }
  867. }
  868. }
  869. .layout-tips-warp-active {
  870. border: 1px solid;
  871. border-color: var(--el-color-primary);
  872. .layout-tips-box {
  873. border: 1px solid;
  874. border-color: var(--el-color-primary);
  875. .layout-tips-txt {
  876. color: var(--el-color-primary) !important;
  877. background-color: var(--next-color-seting-main) !important;
  878. }
  879. }
  880. }
  881. &:hover {
  882. .el-circular {
  883. transition: all 0.3s ease-in-out;
  884. border: 1px solid;
  885. border-color: var(--el-color-primary);
  886. }
  887. .layout-tips-warp {
  888. transition: all 0.3s ease-in-out;
  889. border-color: var(--el-color-primary);
  890. .layout-tips-box {
  891. transition: inherit;
  892. border-color: var(--el-color-primary);
  893. .layout-tips-txt {
  894. transition: inherit;
  895. color: var(--el-color-primary) !important;
  896. background-color: var(--next-color-seting-main) !important;
  897. }
  898. }
  899. }
  900. }
  901. }
  902. }
  903. .copy-config {
  904. margin: 10px 0;
  905. .copy-config-btn {
  906. width: 100%;
  907. margin-top: 15px;
  908. }
  909. .copy-config-btn-reset {
  910. width: 100%;
  911. margin: 10px 0 0;
  912. }
  913. }
  914. }
  915. </style>