setting.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. <template>
  2. <view class="app-page" :class="{ 'is-balck grey-darken-6': isBlackTheme }">
  3. <tm-form v-if="!loading" ref="formData">
  4. <!-- <tm-sheet :shadow="24" :padding="[12, 24]" :margin="[24, 24]">
  5. <view class="py-12 px-24 mx-12 round-3 border-b-1 grey text">
  6. <text class="text-size-n text-weight-b ">标题</text>
  7. <text class="text-grey text-size-xs px-10">副标题/描述</text>
  8. </view>
  9. <view class="sheet-content">内容区域</view>
  10. </tm-sheet> -->
  11. <tm-sheet :shadow="6" :padding="[12, 24]" :margin="[24, 24]">
  12. <view class="py-12 px-24 mx-12 round-3 grey text">
  13. <text class="text-size-n text-weight-b text-grey-darken-3">布局</text>
  14. <text class="text-grey text-size-xs px-10 ml-12">应用以及文章列表布局设置</text>
  15. </view>
  16. <view class="sheet-content">
  17. <tm-pickers
  18. title="请选择首页布局"
  19. btn-color="light-blue"
  20. :default-value.sync="homeLayout.selectDefault"
  21. rang-key="name"
  22. :list="homeLayout.list"
  23. @confirm="fnOnHomeLayoutConfirm"
  24. >
  25. <tm-input
  26. name="status"
  27. required
  28. title="首页布局"
  29. placeholder="请选择首页布局"
  30. disabled
  31. :value="homeLayout.selectLabel"
  32. right-icon="icon-angle-right"
  33. ></tm-input>
  34. </tm-pickers>
  35. <tm-pickers
  36. title="请选择文章卡片样式"
  37. btn-color="light-blue"
  38. :default-value.sync="articleCardStyle.selectDefault"
  39. rang-key="name"
  40. :list="articleCardStyle.list"
  41. @confirm="fnOnArticleCardStyleConfirm"
  42. >
  43. <tm-input
  44. name="status"
  45. required
  46. title="卡片样式"
  47. placeholder="请选择文章卡片样式"
  48. disabled
  49. :value="articleCardStyle.selectLabel"
  50. right-icon="icon-angle-right"
  51. ></tm-input>
  52. </tm-pickers>
  53. </view>
  54. </tm-sheet>
  55. <tm-sheet v-if="false" :shadow="24" :padding="[12, 24]" :margin="[24, 24]">
  56. <view class="py-12 px-24 mx-12 round-3 grey text">
  57. <text class="text-size-n text-weight-b ">外观</text>
  58. <text class="text-grey text-size-xs px-10">设置应用主题色/暗黑模式等</text>
  59. </view>
  60. <view class="sheet-content">
  61. <!-- 内容区域 -->
  62. <text class="ma-24">todo</text>
  63. </view>
  64. </tm-sheet>
  65. <tm-sheet :shadow="6" :padding="[12, 24]" :margin="[24, 24]">
  66. <view class="py-12 px-24 mx-12 round-3 grey text">
  67. <text class="text-size-n text-weight-b text-grey-darken-3">功能</text>
  68. <text class="text-grey text-size-xs px-10 ml-12">一些常用的功能性设置</text>
  69. </view>
  70. <view class="sheet-content">
  71. <view class="mx-32 my-24 border-b-1 pb-24 flex-between">
  72. <text class="text-size-m ">图库瀑布流模式</text>
  73. <tm-switch v-model="appSettings.gallery.useWaterfull" color="light-blue" :text="['是', '否']"></tm-switch>
  74. </view>
  75. <view class="mx-32 my-24 border-b-1 pb-24 flex-between">
  76. <text class="text-size-m ">友链简洁模式</text>
  77. <tm-switch v-model="appSettings.links.useSimple" color="light-blue" :text="['是', '否']"></tm-switch>
  78. </view>
  79. <view class="mx-32 my-24 border-b-1 pb-24 flex-between">
  80. <text class="text-size-m">是否圆形头像</text>
  81. <tm-switch v-model="appSettings.isAvatarRadius" color="light-blue" :text="['是', '否']"></tm-switch>
  82. </view>
  83. <view class="mx-32 my-24 border-b-1 pb-24 flex-between">
  84. <text class="text-size-m ">轮播图指示器</text>
  85. <tm-switch v-model="appSettings.banner.useDot" color="light-blue" :text="['是', '否']"></tm-switch>
  86. </view>
  87. <view v-if="appSettings.banner.useDot" class="mx-32 my-24 border-b-1 pb-24 flex-between">
  88. <text class="text-size-m ">轮播图指示器位置</text>
  89. <tm-groupradio name="dotPosition" @change="fnOnBannerDotChange">
  90. <tm-radio
  91. :name="item.name"
  92. :size="28"
  93. color="light-blue"
  94. v-for="(item, index) in dotPositionList"
  95. :key="index"
  96. v-model="item.checked"
  97. :label="item.name"
  98. ></tm-radio>
  99. </tm-groupradio>
  100. </view>
  101. <view class="mx-32 my-24 border-b-1 pb-24 flex-between">
  102. <text class="text-size-m">显示完整统计</text>
  103. <tm-switch v-model="appSettings.about.showAllCount" color="light-blue" :text="['是', '否']"></tm-switch>
  104. </view>
  105. <view class="mx-32 my-24 border-b-1 pb-24 flex-between">
  106. <text class="text-size-m ">链接直接打开</text>
  107. <tm-switch v-model="appSettings.contact.isLinkCopy" color="light-blue" :text="['是', '否']"></tm-switch>
  108. </view>
  109. <view class="mx-32 my-24 border-b-1 pb-24 flex-between">
  110. <text class="text-size-m ">显示后台入口</text>
  111. <tm-switch v-model="appSettings.about.showAdmin" color="light-blue" :text="['是', '否']"></tm-switch>
  112. </view>
  113. </view>
  114. </tm-sheet>
  115. </tm-form>
  116. <!-- 操作区域 -->
  117. <view v-if="!loading" class="btn-bar flex flex-center bg-white">
  118. <tm-button theme="light-blue" :shadow="0" block :height="70" @click="fnOnSave()">保存设置</tm-button>
  119. <tm-button theme="red" :shadow="0" block :height="70" @click="fnOnSaveDefault()">恢复默认设置</tm-button>
  120. <tm-button theme="blue-grey" :shadow="0" block :height="70" @click="fnOnBack()">返回</tm-button>
  121. </view>
  122. </view>
  123. </template>
  124. <script>
  125. import { _DefaultAppSettings } from '@/utils/app.js';
  126. import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
  127. import tmForm from '@/tm-vuetify/components/tm-form/tm-form.vue';
  128. import tmPickers from '@/tm-vuetify/components/tm-pickers/tm-pickers.vue';
  129. import tmInput from '@/tm-vuetify/components/tm-input/tm-input.vue';
  130. import tmSwitch from '@/tm-vuetify/components/tm-switch/tm-switch.vue';
  131. import tmSheet from '@/tm-vuetify/components/tm-sheet/tm-sheet.vue';
  132. import tmGroupradio from '@/tm-vuetify/components/tm-groupradio/tm-groupradio.vue';
  133. import tmRadio from '@/tm-vuetify/components/tm-radio/tm-radio.vue';
  134. export default {
  135. components: {
  136. tmButton,
  137. tmForm,
  138. tmPickers,
  139. tmInput,
  140. tmSwitch,
  141. tmSheet,
  142. tmGroupradio,
  143. tmRadio
  144. },
  145. data() {
  146. return {
  147. isBlackTheme: false,
  148. loading: true,
  149. appSettings: {},
  150. isSaved: true,
  151. firstLoad: true,
  152. homeLayout: {
  153. list: [{ name: '一行一列', value: 'h_row_col1' }, { name: '一行两列', value: 'h_row_col2' }],
  154. selectDefault: ['一行一列'],
  155. selectLabel: '一行一列',
  156. selectValue: 'h_row_col1'
  157. },
  158. articleCardStyle: {
  159. list: [
  160. { name: '左图右文', value: 'lr_image_text' },
  161. { name: '左文右图', value: 'lr_text_image' },
  162. { name: '上图下文', value: 'tb_image_text' },
  163. { name: '上文下图', value: 'tb_text_image' },
  164. { name: '只有文字', value: 'only_text' }
  165. ],
  166. selectDefault: ['左图右文'],
  167. selectLabel: '左图右文',
  168. selectValue: 'lr_image_text'
  169. },
  170. dotPositionList: [{ name: '右边', value: 'right', checked: true }, { name: '下边', value: 'bottom', checked: false }]
  171. };
  172. },
  173. watch: {
  174. appSettings: {
  175. deep: true,
  176. handler() {
  177. if (this.firstLoad) {
  178. this.firstLoad = false;
  179. } else {
  180. this.isSaved = false;
  181. }
  182. }
  183. }
  184. },
  185. onLoad(e) {
  186. this.fnSetPageTitle('应用设置');
  187. },
  188. created() {
  189. this.appSettings = Object.assign({}, _DefaultAppSettings, uni.$tm.vx.getters().getSettings);
  190. this.fnHandleFormatSelect();
  191. uni.showLoading({
  192. title: '加载中...',
  193. mask: true
  194. });
  195. setTimeout(() => {
  196. this.loading = false;
  197. uni.hideLoading();
  198. }, 500);
  199. },
  200. methods: {
  201. // 统一处理选择框的内容
  202. fnHandleFormatSelect() {
  203. // 首页布局
  204. const _homeLayout = this.fnFindObjInList(this.homeLayout.list, 'value', this.appSettings.layout.home);
  205. this.homeLayout.selectDefault = [_homeLayout.name];
  206. this.homeLayout.selectLabel = _homeLayout.name;
  207. this.homeLayout.selectValue = _homeLayout.value;
  208. const _articleCardStyle = this.fnFindObjInList(this.articleCardStyle.list, 'value', this.appSettings.layout.cardType);
  209. this.articleCardStyle.selectDefault = [_articleCardStyle.name];
  210. this.articleCardStyle.selectLabel = _articleCardStyle.name;
  211. this.articleCardStyle.selectValue = _articleCardStyle.value;
  212. },
  213. // 在集合中找匹配的对象
  214. fnFindObjInList(list, key, value) {
  215. return list.find(x => x[key] == value);
  216. },
  217. fnOnBannerDotChange(e) {
  218. const _select = e[0];
  219. if (_select.index == 0 && _select.checked) {
  220. this.appSettings.banner.dotPosition = 'right';
  221. }
  222. if (_select.index == 1 && _select.checked) {
  223. this.appSettings.banner.dotPosition = 'bottom';
  224. }
  225. },
  226. // 首页布局
  227. fnOnHomeLayoutConfirm(e) {
  228. const _select = e[0].data;
  229. this.homeLayout.selectDefault = [_select.name];
  230. this.homeLayout.selectLabel = _select.name;
  231. this.homeLayout.selectValue = _select.value;
  232. this.appSettings.layout.home = _select.value;
  233. },
  234. // 文章卡片样式
  235. fnOnArticleCardStyleConfirm(e) {
  236. const _select = e[0].data;
  237. this.articleCardStyle.selectDefault = [_select.name];
  238. this.articleCardStyle.selectLabel = _select.name;
  239. this.articleCardStyle.selectValue = _select.value;
  240. this.appSettings.layout.cardType = _select.value;
  241. },
  242. // 保存
  243. fnOnSave() {
  244. this.isSaved = true;
  245. console.log('this.appSettings', this.appSettings);
  246. this.$tm.vx.commit('setting/setSettings', this.appSettings);
  247. uni.$tm.toast('保存成功,部分设置在重启后生效!');
  248. },
  249. // 使用默认配置
  250. fnOnSaveDefault() {
  251. uni.$eShowModal({
  252. title: '提示',
  253. content: '您确定要恢复为默认的设置吗?',
  254. showCancel: true,
  255. cancelText: '否',
  256. cancelColor: '#999999',
  257. confirmText: '是',
  258. confirmColor: '#03a9f4'
  259. })
  260. .then(res => {
  261. this.isSaved = true;
  262. uni.$tm.vx.actions('setting/updateDefaultAppSettings');
  263. uni.$tm.toast('系统设置已恢复为默认配置,部分设置在重启后生效!');
  264. })
  265. .catch(err => {});
  266. },
  267. fnOnBack() {
  268. if (this.isSaved) {
  269. uni.navigateBack();
  270. return;
  271. }
  272. uni.$eShowModal({
  273. title: '提示',
  274. content: '您当前可能有未保存的数据,确定返回吗?',
  275. showCancel: true,
  276. cancelText: '否',
  277. cancelColor: '#999999',
  278. confirmText: '是',
  279. confirmColor: '#03a9f4'
  280. })
  281. .then(res => {
  282. uni.navigateBack();
  283. this.isSaved = true;
  284. })
  285. .catch(err => {});
  286. }
  287. }
  288. };
  289. </script>
  290. <style scoped lang="scss">
  291. .app-page {
  292. box-sizing: border-box;
  293. padding-bottom: 120rpx;
  294. .btn-bar {
  295. width: 100vw;
  296. position: fixed;
  297. left: 0;
  298. bottom: 0;
  299. box-sizing: border-box;
  300. padding: 24rpx;
  301. gap: 0 24rpx;
  302. box-shadow: 0rpx -6rpx 24rpx rgba(0, 0, 0, 0.03);
  303. }
  304. }
  305. .required {
  306. position: relative;
  307. padding-left: 18rpx;
  308. &:before {
  309. content: '*';
  310. position: absolute;
  311. left: -4rpx;
  312. top: 50%;
  313. transform: translateY(-50%);
  314. font-size: 34rpx;
  315. color: rgba(244, 67, 54, 1);
  316. }
  317. }
  318. </style>