Greasyfork Beautify

优化导航栏样式 / 脚本列表改为卡片布局 / 代码高亮(atom-one-dark + vscode 风格) 等……融入式美化,自然、优雅,没有突兀感,仿佛页面原本就是如此……(更多优化逐步完善中!)

目前为 2022-07-22 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Greasyfork Beautify
  3. // @namespace https://github.com/kiccer
  4. // @version 1.6.1
  5. // @description 优化导航栏样式 / 脚本列表改为卡片布局 / 代码高亮(atom-one-dark + vscode 风格) 等……融入式美化,自然、优雅,没有突兀感,仿佛页面原本就是如此……(更多优化逐步完善中!)
  6. // @description:en Optimize the navigation bar style / script list to card layout / code highlighting (atom-one-dark + vscode style), etc. Into the style of beautification, more natural, more elegant, no sense of abruptness, as if the page is originally so. (more optimization in progress!)
  7. // @author kiccer<1072907338@qq.com>
  8. // @supportURL https://github.com/kiccer/TampermonkeyScripts/issues
  9. // @license MIT
  10. // @match https://greasyfork.org/*
  11. // @match https://sleazyfork.org/*
  12. // @icon https://greasyfork.org/packs/media/images/blacklogo96-b2384000fca45aa17e45eb417cbcbb59.png
  13. // @require https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js
  14. // @require https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.9/index.min.js
  15. // @require https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js
  16. // @require https://cdn.bootcdn.net/ajax/libs/javascript-detect-element-resize/0.5.3/jquery.resize.min.js
  17. // @require https://cdn.bootcdn.net/ajax/libs/less.js/4.1.3/less.min.js
  18. // @require https://cdn.bootcdn.net/ajax/libs/highlight.js/11.5.1/highlight.min.js
  19. // @require https://cdn.bootcdn.net/ajax/libs/highlight.js/11.5.1/languages/javascript.min.js
  20. // @require https://greasyfork.org/scripts/447149-checkversion/code/checkVersion.js?version=1065242
  21. // @resource normalize.css https://cdn.bootcdn.net/ajax/libs/normalize/8.0.1/normalize.min.css
  22. // @resource element-ui.css https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.9/theme-chalk/index.min.css
  23. // @resource element-icons https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.9/theme-chalk/fonts/element-icons.ttf
  24. // @resource atom-one-dark.css https://cdn.bootcdn.net/ajax/libs/highlight.js/11.5.1/styles/atom-one-dark.min.css
  25. // @run-at document-start
  26. // @grant GM_info
  27. // @grant GM_setValue
  28. // @grant GM_getValue
  29. // @grant GM_addStyle
  30. // @grant GM_getResourceURL
  31. // @grant GM_getResourceText
  32. // @grant GM_registerMenuCommand
  33. // ==/UserScript==
  34.  
  35. /* globals $ less Vue hljs checkVersion ELEMENT */
  36.  
  37. Vue.use(ELEMENT)
  38.  
  39. if (/\(Development\)$/i.test(GM_info.script.name)) {
  40. Vue.config.devtools = true
  41. }
  42.  
  43. // 默认设置
  44. const defaultSettings = {
  45. script_list_columns_num: 2,
  46. show_install_button_in_card: true,
  47. show_version_info_in_card: true
  48. }
  49.  
  50. // 获取设置
  51. const getSettings = () => {
  52. return Object.assign(
  53. {},
  54. defaultSettings,
  55. JSON.parse(GM_getValue('formData') || '{}')
  56. )
  57. }
  58.  
  59. const VERSION = GM_info.script.version
  60. const settings = getSettings()
  61.  
  62. // 样式注入
  63. GM_addStyle(GM_getResourceText('normalize.css'))
  64. GM_addStyle(GM_getResourceText('element-ui.css'))
  65. GM_addStyle(GM_getResourceText('atom-one-dark.css'))
  66.  
  67. const lessOptions = {}
  68.  
  69. const lessInput = `
  70. // --------------------------------------------- 变量
  71.  
  72. @nav_height: 60px;
  73. @user_container_height: 24px;
  74.  
  75. // --------------------------------------------- 混合宏
  76.  
  77. .ellipsis (@lines) {
  78. display: -webkit-box;
  79. -webkit-box-orient: vertical;
  80. overflow: hidden;
  81. line-height: 1.5;
  82. -webkit-line-clamp: @lines;
  83. }
  84.  
  85. // --------------------------------------------- 通用样式
  86.  
  87. * {
  88. box-sizing: border-box;
  89. outline: none;
  90. }
  91.  
  92. body {
  93. line-height: 1.5;
  94. min-height: 100vh;
  95. background-color: #f7f7f7;
  96.  
  97. > .width-constraint {
  98. min-height: 100vh;
  99. background-color: #fff;
  100. padding: 20px;
  101. padding-top: calc(@nav_height + @user_container_height + 20px);
  102. .text-content {
  103. border: 0;
  104. box-shadow: none;
  105. padding: 0;
  106. }
  107. }
  108. }
  109.  
  110. a {
  111. color: rgb(38, 38, 38);
  112. text-decoration: none;
  113.  
  114. &:hover {
  115. text-decoration: underline;
  116. }
  117.  
  118. &:visited {
  119. color: rgb(38, 38, 38);
  120. }
  121. }
  122.  
  123. // --------------------------------------------- element-ui
  124.  
  125. // 解决 element-icons 图标引用不到问题
  126. @font-face {
  127. font-family: element-icons;
  128. src: url(${GM_getResourceURL('element-icons')}),
  129. }
  130.  
  131. // --------------------------------------------- 代码高亮
  132.  
  133. .code-container {
  134. background-color: #282c34;
  135. border-radius: 8px;
  136. max-height: 100%;
  137. overflow: visible;
  138.  
  139. // 定义滚动条
  140. ::-webkit-scrollbar {
  141. width: 14px;
  142. height: 14px;
  143. background-color: transparent;
  144. }
  145.  
  146. // 定义滚动条轨道
  147. ::-webkit-scrollbar-track {
  148. background-color: transparent;
  149. }
  150.  
  151. // 定义滑块
  152. ::-webkit-scrollbar-thumb {
  153. background-color: rgba(78, 86, 102, 0);
  154. }
  155.  
  156. // 定义边角
  157. ::-webkit-scrollbar-corner {
  158. background-color: transparent;
  159. }
  160.  
  161. &:hover {
  162. ::-webkit-scrollbar-thumb {
  163. background-color: rgba(78, 86, 102, .5);
  164. }
  165. }
  166.  
  167. ::selection {
  168. background-color: rgb(51, 56, 66);
  169. }
  170.  
  171. pre {
  172. code {
  173. padding: 0;
  174. font-family: Consolas;
  175. cursor: text;
  176. overflow: auto;
  177.  
  178. .marker {
  179. display: inline-block;
  180. color: #636d83;
  181. text-align: right;
  182. padding-right: 20px;
  183. user-select: none;
  184. cursor: auto;
  185. }
  186. }
  187. }
  188. }
  189.  
  190. // --------------------------------------------- 页码
  191.  
  192. .pagination {
  193. margin-top: 20px !important;
  194. user-select: none;
  195.  
  196. > * {
  197. padding: 0 .5em !important;
  198. min-width: 2em;
  199. height: 2em;
  200. line-height: 2;
  201. text-align: center;
  202. text-decoration: none !important;
  203. }
  204.  
  205. > a {
  206. background-color: #f7f7f7 !important;
  207.  
  208. &:hover {
  209. background-color: #e1e1e1 !important;
  210. }
  211. }
  212. }
  213.  
  214. // --------------------------------------------- 输入框
  215.  
  216. input[type=search] {
  217. padding: 3px 6px;
  218. padding-right: 2.4em !important;
  219. border: 1px solid #bfbfbf;
  220. border-radius: 4px;
  221. }
  222.  
  223. form {
  224. input.search-submit {
  225. top: 50% !important;
  226. transform: translateY(-50%);
  227. cursor: pointer;
  228. }
  229. }
  230.  
  231. .home-search {
  232. margin-bottom: 20px;
  233. }
  234.  
  235. .sidebar-search {
  236. margin-bottom: 20px;
  237.  
  238. input[type="search"] {
  239. margin: 0;
  240. }
  241. }
  242.  
  243. // --------------------------------------------- header
  244.  
  245. #main-header {
  246. background-color: #000;
  247. background-image: none;
  248. width: 100%;
  249. padding: 0;
  250. position: fixed;
  251. top: 0;
  252. z-index: 1;
  253. user-select: none;
  254. box-shadow: 0 0 5px 2px rgb(0 0 0 / 50%);
  255.  
  256. .width-constraint {
  257. display: flex;
  258. justify-content: space-between;
  259. height: 100%;
  260. padding: 0;
  261.  
  262. #site-name {
  263. display: flex;
  264. align-items: center;
  265. a {
  266. display: block;
  267. }
  268.  
  269. img {
  270. width: auto;
  271. height: 50px;
  272. }
  273.  
  274. #site-name-text {
  275. margin-left: 10px;
  276.  
  277. h1 {
  278. font-size: 36px;
  279. }
  280. }
  281. }
  282. }
  283.  
  284. #user-container {
  285. width: 100%;
  286. height: @user_container_height;
  287. background-color: #343434;
  288.  
  289. .user-main {
  290. display: flex;
  291. justify-content: space-between;
  292. align-items: center;
  293. margin: auto;
  294. max-width: 1200px;
  295. height: @user_container_height;
  296. padding-right: 10px;
  297.  
  298. @media screen and (max-width: 1228px) {
  299. margin: auto 1.2vw;
  300. }
  301.  
  302. .script-version {
  303. font-size: 12px;
  304. letter-spacing: 1px;
  305. font-family: "微软雅黑";
  306. font-weight: 200;
  307. color: rgba(255, 255, 255, .3);
  308.  
  309. .has-new-version {
  310. color: lime;
  311. margin-left: 5px;
  312. }
  313. }
  314.  
  315. .login-info {
  316. font-size: 14px;
  317. }
  318. }
  319. }
  320. }
  321.  
  322. #site-nav {
  323. width: 0;
  324. height: 0;
  325. border: 0;
  326. padding: 0;
  327. overflow: hidden;
  328. position: relative;
  329. }
  330.  
  331. #site-nav-vue {
  332. display: flex;
  333. .nav-item {
  334. line-height: @nav_height;
  335. padding: 0 10px;
  336. transition: all .2s ease;
  337. text-decoration: none;
  338. position: relative;
  339. white-space: nowrap;
  340.  
  341. &:hover {
  342. background-color: rgba(255, 255, 255, .2);
  343.  
  344. .sub-nav {
  345. display: flex;
  346. }
  347. }
  348.  
  349. .sub-nav {
  350. display: none;
  351. flex-direction: column;
  352. position: absolute;
  353. top: 100%;
  354. right: 0;
  355. background-color: rgba(0, 0, 0, .8);
  356.  
  357. .nav-item {
  358. line-height: 40px;
  359. }
  360. }
  361. }
  362. }
  363.  
  364. // --------------------------------------------- 脚本列表
  365.  
  366. #user-library-script-list,
  367. #user-script-list,
  368. #user-deleted-script-list,
  369. #browse-script-list {
  370. display: grid;
  371. grid-template-columns: repeat(${settings.script_list_columns_num}, 1fr);
  372. grid-gap: 20px;
  373. border: 0;
  374. box-shadow: none;
  375.  
  376. @media screen and (max-width: 1228px) {
  377. grid-template-columns: repeat(1, 1fr);
  378. }
  379.  
  380. li {
  381. border: 1px solid #bbb;
  382. box-shadow: 0 0 5px #ddd;
  383. border-radius: 5px;
  384. padding: 10px;
  385. position: relative;
  386. word-break: break-all;
  387.  
  388. a.script-link {
  389. .ellipsis(2);
  390. height: calc(3em + 8px);
  391. font-size: 16px;
  392. margin: 4px -10px 4px -14px;
  393. padding: 4px 10px;
  394. background: linear-gradient(#fff, #eee);
  395. border-left: 7px solid #800;
  396. box-shadow: inset 0 1px rgb(0 0 0 / 10%), inset 0 -1px rgb(0 0 0 / 10%);
  397. }
  398.  
  399. & > article {
  400. & > h2 {
  401. & > .badge,
  402. & > .name-description-separator,
  403. & > strong {
  404. display: none; // 兼容 “大人的Greasyfork”
  405. }
  406.  
  407. .script-description {
  408. .ellipsis(3);
  409. text-indent: 2em;
  410. margin: 10px 0 10px;
  411. height: 4.5em;
  412. font-size: 14px;
  413. strong,
  414. #install-area {
  415. display: none; // 兼容 “大人的Greasyfork”
  416. }
  417. }
  418. }
  419. }
  420.  
  421. .inline-script-stats {
  422. padding: 10px 0;
  423. // margin-bottom: 10px;
  424. border-top: 1px solid #ebebeb;
  425. // border-bottom: 1px solid #ebebeb;
  426.  
  427. dt {
  428. width: 40%;
  429. }
  430.  
  431. dd {
  432. width: 60%;
  433. }
  434. }
  435.  
  436. .install-link {
  437. float: right;
  438. font-size: 12px;
  439.  
  440. &:hover {
  441. transition: box-shadow .2s;
  442. box-shadow: 0 8px 16px 0 rgb(0 0 0 / 20%), 0 6px 20px 0 rgb(0 0 0 / 19%);
  443. }
  444.  
  445. &.lum-lightbox-loader {
  446. border-left: 10px solid #005200;
  447. border-right: 10px solid #005200;
  448. position: relative;
  449. min-height: 30px;
  450. min-width: 70px;
  451.  
  452. &::before,
  453. &::after {
  454. width: 1em;
  455. height: 1em;
  456. margin-top: -0.5em;
  457. border-radius: 1em;
  458. background: hsla(0, 0%, 100%, .5);
  459. }
  460. }
  461. }
  462. }
  463. }
  464.  
  465. // --------------------------------------------- 列表右侧选项组
  466.  
  467. .list-option-groups {
  468. #language-selector {
  469. + * {
  470. margin-top: 10px;
  471. }
  472. #language-selector-locale {
  473. width: 100%;
  474. border: 1px solid #bfbfbf;
  475. border-radius: 4px;
  476. }
  477. }
  478. }
  479. `
  480.  
  481. less.render(lessInput, lessOptions).then(output => {
  482. // output.css = string of css
  483. // output.map = string of sourcemap
  484. // output.imports = array of string filenames of the imports referenced
  485.  
  486. GM_addStyle(output.css)
  487. }, err => {
  488. console.error(err)
  489. })
  490.  
  491. // 查看代码页面简化,隐藏信息
  492. if (/https:\/\/greasyfork\.org\/[a-zA-Z-]+\/scripts\/\d+-.+\/code/.test(location.href)) {
  493. GM_addStyle(`
  494. #script-info header,
  495. #install-area,
  496. #script-feedback-suggestion {
  497. display: none;
  498. }
  499.  
  500. #script-content {
  501. margin-top: 16px;
  502. }
  503.  
  504. .code-container pre code {
  505. max-height: calc(100vh - 267px);
  506. }
  507. `)
  508. }
  509.  
  510. // 脚本卡片美化
  511. function scriptCardBeautify () {
  512. $(`
  513. #user-script-list li[data-script-id],
  514. #user-deleted-script-list li[data-script-id],
  515. #browse-script-list li[data-script-id]
  516. `).each((i, n) => {
  517. const card = $(n)
  518. const href = card.find('> article a.script-link').attr('href')
  519.  
  520. // TODO 显示脚本图标 (看情况,如果加了图标不好布局就算了)
  521.  
  522. // 判断这个卡片是否已经美化过了
  523. const hasVersionTag = card.find('.script-show-version').length > 0
  524. const hasDownloadBtn = card.find('.install-link-copy').length > 0
  525.  
  526. if (!(hasVersionTag && hasDownloadBtn)) {
  527. // 信息占位
  528. if (settings.show_version_info_in_card) {
  529. card.find('.inline-script-stats').append(`
  530. <dt class="script-show-version"><span>...</span></dt>
  531. <dd class="script-show-version"><span></span></dd>
  532. `)
  533. }
  534.  
  535. // 下载按钮占位
  536. if (settings.show_install_button_in_card) {
  537. card.append(`
  538. <a class="install-link lum-lightbox-loader"></a>
  539. `)
  540. }
  541.  
  542. $.ajax({
  543. type: 'get',
  544. url: href,
  545. success: res => {
  546. const html = $(res)
  547.  
  548. if (settings.show_version_info_in_card) {
  549. // 删除占位元素
  550. card.find('.script-show-version').remove()
  551.  
  552. // 版本
  553. card.find('.inline-script-stats').append(
  554. html.find('.script-show-version')
  555. )
  556. }
  557.  
  558. if (settings.show_install_button_in_card) {
  559. // 删除占位元素
  560. card.find('.install-link.lum-lightbox-loader').remove()
  561.  
  562. // 下载按钮
  563. card.append(
  564. html.find('#install-area .install-link').eq(0).addClass('install-link-copy')
  565. )
  566.  
  567. // 下载按钮文案根据已安装的版本号调整
  568. setTimeout(() => {
  569. const btn = card.find('.install-link-copy')[0]
  570. if (btn) checkVersion.checkForUpdatesJS(btn, true)
  571. })
  572. }
  573. }
  574. })
  575. }
  576. })
  577. }
  578.  
  579. // 页面获得焦点时
  580. window.addEventListener('focus', e => {
  581. // 自动更新安装状态
  582. $('.script-list li[data-script-id] a.install-link-copy').each((i, n) => {
  583. checkVersion.checkForUpdatesJS(n, true)
  584. })
  585. })
  586.  
  587. // 页面加载完成后执行
  588. $(() => {
  589. // 导航
  590. const navContainer = document.createElement('div')
  591. navContainer.id = 'site-nav-vue'
  592. document.querySelector('.width-constraint').appendChild(navContainer)
  593.  
  594. // eslint-disable-next-line no-unused-vars
  595. const navApp = new Vue({
  596. el: '#site-nav-vue',
  597.  
  598. template: `
  599. <div id="site-nav-vue">
  600. <a
  601. class="nav-item"
  602. v-for="(nav, nav_i) in navList"
  603. :key="nav_i"
  604. :href="nav.url"
  605. >
  606. <span>{{ nav.label }}</span>
  607.  
  608. <div class="sub-nav" v-if="nav.list?.length">
  609. <a
  610. class="nav-item"
  611. v-for="(sub, sub_i) in nav.list"
  612. :key="sub_i"
  613. :href="sub.url"
  614. >
  615. <span>{{ sub.label }}</span>
  616. </a>
  617. </div>
  618. </a>
  619. </div>
  620. `,
  621.  
  622. data () {
  623. return {
  624. navList: [...$('#site-nav > nav > li')].map(n => {
  625. const a = $(n).find('> a')
  626. const subNav = [...$(n).find('> nav > li')]
  627.  
  628. return {
  629. label: a.text() || $(n).text(),
  630. url: a.attr('href'),
  631. list: subNav.map(m => {
  632. const subA = $(m).find('> a')
  633.  
  634. return {
  635. label: subA.text(),
  636. url: subA.attr('href')
  637. }
  638. })
  639. }
  640. })
  641. }
  642. }
  643. })
  644.  
  645. // 用户
  646. const userContainer = document.createElement('div')
  647. userContainer.id = 'user-container'
  648. document.querySelector('#main-header').appendChild(userContainer)
  649.  
  650. // eslint-disable-next-line no-unused-vars
  651. const userApp = new Vue({
  652. el: '#user-container',
  653. template: `
  654. <div id="user-container">
  655. <div class="user-main">
  656. <div class="script-version">
  657. Greasyfork Beautify v${VERSION}
  658. <a
  659. class="has-new-version"
  660. href="https://greasyfork.org/scripts/446849-greasyfork-beautify/code/Greasyfork%20Beautify.user.js"
  661. v-if="lastVersion !== '${VERSION}'"
  662. >Update to v{{ lastVersion }}</a>
  663. </div>
  664.  
  665. <div class="login-info">
  666. <a
  667. :href="dom.attr('href')"
  668. >{{ dom.text() }}</a>
  669.  
  670. <template v-if="isLogin">
  671. [<a :href="logoutDom.attr('href')">{{ logoutDom.text() }}</a>]
  672. </template>
  673. </div>
  674. </div>
  675. </div>
  676. `,
  677.  
  678. data () {
  679. return {
  680. lastVersion: VERSION,
  681. dom: $('#nav-user-info .user-profile-link a, #nav-user-info .sign-in-link a'),
  682. logoutDom: $('.sign-out-link a'),
  683. isLogin: $('.sign-out-link').length > 0 // 存在登出按钮则表示已登录
  684. }
  685. },
  686.  
  687. created () {
  688. this.versionCheck()
  689. },
  690.  
  691. methods: {
  692. versionCheck () {
  693. $.ajax({
  694. url: 'https://greasyfork.org/zh-CN/scripts/446849-greasyfork-beautify',
  695. success: res => {
  696. const html = $(res)
  697. this.lastVersion = html.find('dd.script-show-version span').text()
  698. }
  699. })
  700. }
  701. }
  702. })
  703.  
  704. // 代码高亮
  705. $('pre.lang-js').each((pre_i, pre) => {
  706. // 调整代码,给一些压缩代码增加换行
  707. $(pre).find('li').append('\n')
  708. const code = $('<code class="language-javascript">').html(
  709. pre.innerHTML
  710. )
  711.  
  712. // 清空原始代码容器,放置新容器
  713. $(pre)
  714. .removeClass()
  715. .html('')
  716. .append(code)
  717.  
  718. // 高亮
  719. hljs.highlightElement(pre.querySelector('code'))
  720.  
  721. // 增加行号
  722. const html = $(pre).find('code').html()
  723. const htmlSplit = html.split('\n')
  724. const totalLines = htmlSplit.length
  725.  
  726. $(pre).find('code').html(
  727. htmlSplit.map((n, i) => `<span class="marker" style="width: calc(${String(totalLines).length * 0.5}em + 20px);">${i + 1}</span>${n}`).join('\n')
  728. )
  729. })
  730.  
  731. // 卡片数量记录
  732. let cardCountRecord = 0
  733. // 脚本列表页面,卡片
  734. if (settings.show_install_button_in_card || settings.show_version_info_in_card) {
  735. // 兼容翻页插件
  736. $('.script-list ').resize(e => {
  737. const cardCount = $('.script-list li[data-script-id]').length
  738.  
  739. if (cardCountRecord !== cardCount) {
  740. cardCountRecord = cardCount
  741. scriptCardBeautify()
  742. }
  743. })
  744. }
  745.  
  746. // 列表右侧选项组
  747. $('.list-option-groups > *:eq(0)').before(
  748. // 设置语言
  749. $('#language-selector')
  750. )
  751.  
  752. // 注册菜单
  753. $('body').append($('<div id="greasyfork-beautify-settings">'))
  754.  
  755. const settingsApp = new Vue({
  756. el: '#greasyfork-beautify-settings',
  757.  
  758. template: `
  759. <el-dialog
  760. width="600px"
  761. title="Greasyfork Beautify v${VERSION}"
  762. :visible.sync="show"
  763. @closed="onClosed"
  764. >
  765. <el-form
  766. size="mini"
  767. label-width="120px"
  768. :model="formData"
  769. >
  770. <el-form-item label="脚本列表列数">
  771. <el-input-number
  772. label="描述文字"
  773. v-model="formData.script_list_columns_num"
  774. :min="1"
  775. :max="2"
  776. />
  777. </el-form-item>
  778.  
  779. <el-form-item label="显示安装按钮">
  780. <el-switch
  781. v-model="formData.show_install_button_in_card"
  782. />
  783. </el-form-item>
  784.  
  785. <el-form-item label="显示版本信息">
  786. <el-switch
  787. v-model="formData.show_version_info_in_card"
  788. />
  789. </el-form-item>
  790. </el-form>
  791.  
  792. <span slot="footer" class="dialog-footer">
  793. <el-button @click="onReset">重 置</el-button>
  794. <el-button type="primary" @click="onSubmit">确 定</el-button>
  795. </span>
  796. </el-dialog>
  797. `,
  798.  
  799. data () {
  800. return {
  801. show: false,
  802. formData: getSettings()
  803. }
  804. },
  805.  
  806. methods: {
  807. onClosed () {
  808. Object.assign(this.formData, getSettings())
  809. },
  810.  
  811. onReset () {
  812. Object.assign(this.formData, defaultSettings)
  813. },
  814.  
  815. onSubmit () {
  816. GM_setValue('formData', JSON.stringify(this.formData))
  817. location.reload()
  818. }
  819. }
  820. })
  821.  
  822. GM_registerMenuCommand('美化设置', e => {
  823. settingsApp.show = true
  824. })
  825. })