logs.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. <template>
  2. <view class="app-page flex flex-col">
  3. <view v-if="loading != 'success'" class="loading-wrap">
  4. <tm-skeleton model="list"></tm-skeleton>
  5. <tm-skeleton model="list"></tm-skeleton>
  6. <tm-skeleton model="list"></tm-skeleton>
  7. <tm-skeleton model="list"></tm-skeleton>
  8. </view>
  9. <view class="page-content pa-24 flex flex-col" v-else>
  10. <view v-if="dataList.length == 0" class="content-empty flex flex-center"><tm-empty icon="icon-shiliangzhinengduixiang-" label="暂无任何日志"></tm-empty></view>
  11. <block v-else>
  12. <block v-for="(item, index) in dataList" :key="index">
  13. <tm-translate animation-name="fadeUp" :wait="calcAniWait(index)">
  14. <view class="card mb-24 bg-white pa-24 round-3">
  15. <view class="border-b-1 pb-20 text-size-l text-weight-b">
  16. <tm-tags :dense="true" :shadow="0" color="bg-gradient-light-blue-accent" size="s" model="fill">ID:{{ item.id }}</tm-tags>
  17. <tm-tags class="ml-24" :shadow="0" :dense="true" color="bg-gradient-orange-accent" size="s" model="fill">
  18. 类型:{{ item.type | formatLogType }}
  19. </tm-tags>
  20. <tm-tags class="ml-24" v-if="false" :shadow="0" :dense="true" color="bg-gradient-blue-grey-accent" size="s" model="fill">
  21. 关键值:{{ item.logKey }}
  22. </tm-tags>
  23. </view>
  24. <view class="mt-20 text-size-m">
  25. <view v-if="false" class="desc-item flex ">
  26. <view class="desc-label text-grey-darken-2">日志类型</view>
  27. <view class="desc-value">{{ item.type | formatLogType }}</view>
  28. </view>
  29. <view class="desc-item flex mt-12">
  30. <view class="desc-label text-grey-darken-2">关键值</view>
  31. <view class="desc-value">{{ item.logKey }}</view>
  32. </view>
  33. <view class="desc-item flex flex-top-start mt-12">
  34. <view class="desc-label text-grey-darken-2">IP地址</view>
  35. <view class="desc-value">{{ item.ipAddress }}</view>
  36. </view>
  37. <view class="desc-item flex mt-12">
  38. <view class="desc-label text-grey-darken-2">日志内容</view>
  39. <view class="desc-value">{{ item.content }}</view>
  40. </view>
  41. <view class="desc-item flex mt-12">
  42. <view class="desc-label text-grey-darken-2">操作时间</view>
  43. <view class="desc-value">{{ item.time }}</view>
  44. </view>
  45. </view>
  46. </view>
  47. </tm-translate>
  48. </block>
  49. <tm-flotbutton @click="fnToTopPage" :offset="[16, 80]" color="bg-gradient-light-blue-accent" size="m" icon="icon-angle-up"></tm-flotbutton>
  50. <tm-flotbutton size="m" icon="icon-delete" color="bg-gradient-red-accent" @click="fnOnClear"></tm-flotbutton>
  51. <view class="load-text ">{{ loadMoreText }}</view>
  52. </block>
  53. </view>
  54. </view>
  55. </template>
  56. <script>
  57. import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
  58. import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
  59. import tmTags from '@/tm-vuetify/components/tm-tags/tm-tags.vue';
  60. import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
  61. import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
  62. import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
  63. export default {
  64. components: {
  65. tmSkeleton,
  66. tmEmpty,
  67. tmButton,
  68. tmTags,
  69. tmFlotbutton,
  70. tmTranslate
  71. },
  72. data() {
  73. return {
  74. loading: 'loading',
  75. queryParams: {
  76. size: 8,
  77. page: 0,
  78. sort: undefined
  79. },
  80. result: {},
  81. dataList: [],
  82. total: 0,
  83. isLoadMore: false,
  84. loadMoreText: '加载中...'
  85. };
  86. },
  87. filters: {
  88. formatLogType(val) {
  89. const logTypes = {
  90. BLOG_INITIALIZED: {
  91. value: 0,
  92. text: '博客初始化'
  93. },
  94. POST_PUBLISHED: {
  95. value: 5,
  96. text: '文章发布'
  97. },
  98. POST_EDITED: {
  99. value: 15,
  100. text: '文章修改'
  101. },
  102. POST_DELETED: {
  103. value: 20,
  104. text: '文章删除'
  105. },
  106. LOGGED_IN: {
  107. value: 25,
  108. text: '用户登录'
  109. },
  110. LOGGED_OUT: {
  111. value: 30,
  112. text: '注销登录'
  113. },
  114. LOGIN_FAILED: {
  115. value: 35,
  116. text: '登录失败'
  117. },
  118. PASSWORD_UPDATED: {
  119. value: 40,
  120. text: '修改密码'
  121. },
  122. PROFILE_UPDATED: {
  123. value: 45,
  124. text: '资料修改'
  125. },
  126. SHEET_PUBLISHED: {
  127. value: 50,
  128. text: '页面发布'
  129. },
  130. SHEET_EDITED: {
  131. value: 55,
  132. text: '页面修改'
  133. },
  134. SHEET_DELETED: {
  135. value: 60,
  136. text: '页面删除'
  137. },
  138. MFA_UPDATED: {
  139. value: 65,
  140. text: '两步验证'
  141. },
  142. LOGGED_PRE_CHECK: {
  143. value: 70,
  144. text: '登录验证'
  145. }
  146. };
  147. return logTypes[val].text;
  148. }
  149. },
  150. onLoad() {
  151. this.fnSetPageTitle('日志管理');
  152. },
  153. created() {
  154. this.fnGetData();
  155. },
  156. onPullDownRefresh() {
  157. this.queryParams.page = 0;
  158. this.dataList = [];
  159. this.fnGetData();
  160. },
  161. onReachBottom(e) {
  162. if (this.result.hasNext) {
  163. this.queryParams.page += 1;
  164. this.isLoadMore = true;
  165. this.fnGetData();
  166. } else {
  167. uni.showToast({
  168. icon: 'none',
  169. title: '没有更多数据了'
  170. });
  171. }
  172. },
  173. methods: {
  174. fnGetData() {
  175. uni.showLoading({
  176. mask: true,
  177. title: '加载中...'
  178. });
  179. // 设置状态为加载中
  180. if (!this.isLoadMore) {
  181. this.loading = 'loading';
  182. }
  183. this.loadMoreText = '加载中...';
  184. this.$httpApi.admin
  185. .getLogsListByPage(this.queryParams)
  186. .then(res => {
  187. if (res.status == 200) {
  188. this.loadMoreText = res.data.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
  189. this.result = res.data;
  190. this.total = res.data.total;
  191. const _tempDataList = res.data.content.map(item => {
  192. item['time'] = uni.$tm.dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss');
  193. return item;
  194. });
  195. if (this.isLoadMore) {
  196. this.dataList = this.dataList.concat(_tempDataList);
  197. } else {
  198. this.dataList = _tempDataList;
  199. }
  200. this.loading = 'success';
  201. } else {
  202. uni.$tm.toast('加载失败,请重试!');
  203. thi.loading = 'error';
  204. }
  205. })
  206. .catch(err => {
  207. console.error(err);
  208. uni.$tm.toast('加载失败,请重试!');
  209. this.loading = 'error';
  210. this.loadMoreText = '加载失败,请下拉刷新!';
  211. })
  212. .finally(() => {
  213. setTimeout(() => {
  214. uni.hideLoading();
  215. uni.stopPullDownRefresh();
  216. }, 300);
  217. });
  218. },
  219. // 删除
  220. fnOnClear() {
  221. uni.$eShowModal({
  222. title: '提示',
  223. content: `您确定要清空所有的日志记录吗?`,
  224. showCancel: true,
  225. cancelText: '否',
  226. cancelColor: '#999999',
  227. confirmText: '是',
  228. confirmColor: '#03a9f4'
  229. })
  230. .then(res => {
  231. uni.showLoading({
  232. mask: true,
  233. title: '正在清空...'
  234. });
  235. this.$httpApi.admin
  236. .deleteAllLogs()
  237. .then(res => {
  238. if (res.status == 200) {
  239. uni.$tm.toast('操作成功!');
  240. setTimeout(() => {
  241. this.queryParams.page = 0;
  242. this.dataList = [];
  243. this.fnGetData();
  244. }, 1000);
  245. } else {
  246. uni.$tm.toast('操作失败,请重试!');
  247. }
  248. })
  249. .catch(err => {
  250. console.error(err);
  251. uni.$tm.toast('操作失败,请重试!');
  252. });
  253. })
  254. .catch(err => {});
  255. }
  256. }
  257. };
  258. </script>
  259. <style lang="scss" scoped>
  260. .app-page {
  261. width: 100vw;
  262. min-height: 100vh;
  263. }
  264. .loading-wrap {
  265. padding: 24rpx;
  266. }
  267. .page-content {}
  268. .content-empty {
  269. width: 100vw;
  270. height: 65vh;
  271. }
  272. .card {
  273. box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.05);
  274. }
  275. .desc-item {
  276. .desc-label {
  277. width: 150rpx;
  278. position: relative;
  279. &::after {
  280. content: ':';
  281. position: absolute;
  282. right: 0px;
  283. top: 0rpx;
  284. }
  285. }
  286. .desc-value {
  287. word-wrap: break-word;
  288. word-break: break-all;
  289. padding-left: 6rpx;
  290. }
  291. }
  292. </style>