index.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. <template>
  2. <div>
  3. <el-button
  4. round
  5. type="primary"
  6. size="mini"
  7. @click.stop="showConfigurator"
  8. >{{getActionDisplayName("theme-editor")}}</el-button>
  9. <transition name="fade">
  10. <div v-show="visible" class="configurator" ref="configurator">
  11. <div
  12. class="main-configurator"
  13. ref="mainConfigurator"
  14. >
  15. <div v-if="currentConfig">
  16. <main-panel
  17. :currentConfig="currentConfig"
  18. :defaultConfig="defaultConfig"
  19. :userConfig="userConfig"
  20. :globalValue="globalValue"
  21. @onChange="userConfigChange"
  22. ></main-panel>
  23. </div>
  24. <div v-if="init && !currentConfig" class="no-config">
  25. <img src="../../assets/images/theme-no-config.png" alt>
  26. <span>{{getActionDisplayName("no-config")}}</span>
  27. </div>
  28. <download-area></download-area>
  29. </div>
  30. </div>
  31. </transition>
  32. </div>
  33. </template>
  34. <style>
  35. .configurator {
  36. height: 100%;
  37. width: 24%;
  38. max-width: 400px;
  39. position: fixed;
  40. overflow-y: auto;
  41. top: 79px;
  42. right: 0;
  43. bottom: 0;
  44. background: #fff;
  45. color: #666;
  46. line-height: 24px;
  47. padding-right: 1%;
  48. }
  49. .configurator .main-configurator {
  50. height: 100%;
  51. overflow: auto;
  52. background: #F5F7FA;
  53. border: 1px solid #EBEEF5;
  54. box-shadow: 0 2px 10px 0 rgba(0,0,0,0.06);
  55. border-radius: 8px;
  56. width: 97%;
  57. box-sizing: border-box;
  58. margin: 0 .5% 0 5%;
  59. }
  60. .no-config {
  61. margin-top: 130px;
  62. text-align: center;
  63. img {
  64. width: 50%;
  65. display: block;
  66. margin: 0 auto;
  67. }
  68. span {
  69. margin-top: 10px;
  70. display: block;
  71. color: #909399;
  72. font-size: 14px;
  73. }
  74. }
  75. .fade-enter,.fade-leave-to {
  76. transform:translateX(100%);
  77. }
  78. .fade-enter-active ,.fade-leave-active {
  79. transition:all 0.3s ease;
  80. }
  81. @media (min-width: 1600px) {
  82. .configurator {
  83. padding-right: calc((100% - 1600px) / 2);
  84. }
  85. }
  86. </style>
  87. <script>
  88. import bus from '../../bus';
  89. import { getVars, updateVars } from './utils/api.js';
  90. import mainPanel from './main';
  91. import {
  92. filterConfigType,
  93. filterGlobalValue,
  94. updateDomHeadStyle,
  95. getActionDisplayName
  96. } from './utils/utils.js';
  97. import DocStyle from './docStyle';
  98. import Loading from './loading';
  99. import DownloadArea from './download';
  100. export default {
  101. components: {
  102. mainPanel,
  103. DownloadArea
  104. },
  105. data() {
  106. return {
  107. init: false,
  108. visible: false,
  109. defaultConfig: null,
  110. currentConfig: null,
  111. userConfig: {
  112. global: {},
  113. local: {}
  114. },
  115. lastApply: 0
  116. };
  117. },
  118. mixins: [DocStyle, Loading],
  119. computed: {
  120. globalValue() {
  121. return filterGlobalValue(this.defaultConfig, this.userConfig);
  122. }
  123. },
  124. methods: {
  125. getActionDisplayName(key) {
  126. return getActionDisplayName(key);
  127. },
  128. showConfigurator() {
  129. this.visible = !this.visible;
  130. bus.$emit('user-theme-config-visible', this.visible);
  131. window.userThemeConfigVisible = Boolean(this.visible);
  132. if (this.init) return;
  133. this.$nextTick(() => {
  134. const loading = this.$loading({
  135. target: this.$refs.configurator
  136. });
  137. let defaultConfig;
  138. getVars()
  139. .then((res) => {
  140. defaultConfig = res;
  141. })
  142. .catch((err) => {
  143. this.onError(err);
  144. })
  145. .then(() => {
  146. setTimeout(() => {
  147. if (defaultConfig) {
  148. this.defaultConfig = defaultConfig;
  149. this.filterCurrentConfig();
  150. this.init = true;
  151. }
  152. loading.close();
  153. }, 300); // action after transition
  154. });
  155. });
  156. },
  157. filterCurrentConfig() {
  158. this.currentConfig = this.defaultConfig.find((config) => {
  159. return config.name === this.$route.path.split('/').pop().toLowerCase();
  160. });
  161. },
  162. userConfigChange(e) {
  163. this.$set(this.userConfig[filterConfigType(this.currentConfig.name)], e.key, e.value);
  164. this.onAction();
  165. },
  166. applyStyle(res, time) {
  167. if (time < this.lastApply) return;
  168. this.updateDocs();
  169. updateDomHeadStyle('chalk-style', res);
  170. this.lastApply = time;
  171. },
  172. onDownload() {
  173. return updateVars(Object.assign({}, this.userConfig, {download: true}), (xhr) => {
  174. xhr.responseType = 'blob';
  175. });
  176. },
  177. onReset() {
  178. this.userConfig = {
  179. global: {},
  180. local: {}
  181. };
  182. this.onAction();
  183. },
  184. onAction() {
  185. this.triggerComponentLoading(true);
  186. const time = +new Date();
  187. updateVars(this.userConfig)
  188. .then((res) => {
  189. this.applyStyle(res, time);
  190. })
  191. .catch((err) => {
  192. this.onError(err);
  193. })
  194. .then(() => {
  195. this.triggerComponentLoading(false);
  196. });
  197. },
  198. onError(err) {
  199. let message;
  200. try {
  201. message = JSON.parse(err).message;
  202. } catch (e) {
  203. message = err;
  204. }
  205. this.$message.error(message);
  206. },
  207. triggerComponentLoading(val) {
  208. bus.$emit('user-theme-config-loading', val);
  209. },
  210. updateDocs() {
  211. window.userThemeConfig = JSON.parse(JSON.stringify(this.userConfig));
  212. bus.$emit('user-theme-config-update', this.userConfig);
  213. this.updateDocStyle(this.userConfig);
  214. }
  215. },
  216. watch: {
  217. '$route.path'() {
  218. this.defaultConfig && this.filterCurrentConfig();
  219. if (!this.$refs.mainConfigurator) return;
  220. this.$nextTick(() => {
  221. this.$refs.mainConfigurator.scrollTop = 0;
  222. });
  223. }
  224. }
  225. };
  226. </script>