@sugarat/easypicker2-client 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/.env +6 -0
  2. package/.env.production +3 -0
  3. package/.env.test +4 -0
  4. package/.eslintignore +0 -0
  5. package/.eslintrc.json +57 -0
  6. package/.github/workflows/main.yml +61 -0
  7. package/.prettierrc.js +9 -0
  8. package/LICENSE +21 -0
  9. package/README.md +86 -0
  10. package/auto-imports.d.ts +6 -0
  11. package/components.d.ts +56 -0
  12. package/docker/ep_backup/easypicker2.sql +214 -0
  13. package/docker/ep_backup/mongodb/easypicker2/action.bson +0 -0
  14. package/docker/ep_backup/mongodb/easypicker2/action.metadata.json +1 -0
  15. package/docker/ep_backup/mongodb/easypicker2/log.bson +0 -0
  16. package/docker/ep_backup/mongodb/easypicker2/log.metadata.json +1 -0
  17. package/docker/ep_backup/user-config.json +176 -0
  18. package/docs/.env +1 -0
  19. package/docs/.env.production +2 -0
  20. package/docs/.vitepress/config.ts +204 -0
  21. package/docs/.vitepress/theme/bg.png +0 -0
  22. package/docs/.vitepress/theme/index.scss +41 -0
  23. package/docs/.vitepress/theme/index.ts +5 -0
  24. package/docs/author.md +24 -0
  25. package/docs/auto-imports.d.ts +6 -0
  26. package/docs/components.d.ts +17 -0
  27. package/docs/deploy/design/api.md +3 -0
  28. package/docs/deploy/design/db.md +3 -0
  29. package/docs/deploy/design/index.md +3 -0
  30. package/docs/deploy/design/shell.md +9 -0
  31. package/docs/deploy/faq.md +86 -0
  32. package/docs/deploy/index.md +9 -0
  33. package/docs/deploy/local.md +275 -0
  34. package/docs/deploy/online-new.md +610 -0
  35. package/docs/deploy/online.md +683 -0
  36. package/docs/deploy/qiniu.md +183 -0
  37. package/docs/index.md +40 -0
  38. package/docs/introduction/about/code.md +26 -0
  39. package/docs/introduction/about/index.md +33 -0
  40. package/docs/introduction/feature/index.md +3 -0
  41. package/docs/plan/log.md +333 -0
  42. package/docs/plan/todo.md +127 -0
  43. package/docs/plan/wish.md +29 -0
  44. package/docs/praise/index.md +45 -0
  45. package/docs/public/favicon.ico +0 -0
  46. package/docs/public/logo.png +0 -0
  47. package/docs/public/robots.txt +2 -0
  48. package/docs/src/apis/ajax.ts +66 -0
  49. package/docs/src/apis/index.ts +1 -0
  50. package/docs/src/apis/modules/wish.ts +20 -0
  51. package/docs/src/components/Avatar.vue +60 -0
  52. package/docs/src/components/Home.vue +85 -0
  53. package/docs/src/components/Picture.vue +13 -0
  54. package/docs/src/components/Praise.vue +52 -0
  55. package/docs/src/components/WishBtn.vue +98 -0
  56. package/docs/src/components/WishPanel.vue +170 -0
  57. package/docs/src/components/callme/index.vue +72 -0
  58. package/docs/vite.config.ts +42 -0
  59. package/index.html +127 -0
  60. package/package.json +52 -0
  61. package/public/favicon.ico +0 -0
  62. package/public/logo.png +0 -0
  63. package/scripts/deploy/docs.mjs +24 -0
  64. package/scripts/deploy/prod.mjs +24 -0
  65. package/scripts/deploy/test.mjs +26 -0
  66. package/src/@types/ajax.d.ts +5 -0
  67. package/src/@types/api.d.ts +305 -0
  68. package/src/@types/lib.d.ts +26 -0
  69. package/src/@types/page.d.ts +18 -0
  70. package/src/App.vue +36 -0
  71. package/src/apis/ajax.ts +70 -0
  72. package/src/apis/index.ts +20 -0
  73. package/src/apis/modules/action.ts +17 -0
  74. package/src/apis/modules/category.ts +20 -0
  75. package/src/apis/modules/config.ts +19 -0
  76. package/src/apis/modules/file.ts +150 -0
  77. package/src/apis/modules/people.ts +81 -0
  78. package/src/apis/modules/public.ts +49 -0
  79. package/src/apis/modules/super/overview.ts +56 -0
  80. package/src/apis/modules/super/user.ts +62 -0
  81. package/src/apis/modules/task.ts +67 -0
  82. package/src/apis/modules/user.ts +56 -0
  83. package/src/apis/modules/wish.ts +31 -0
  84. package/src/assets/i/EasyPicker.png +0 -0
  85. package/src/assets/logo.png +0 -0
  86. package/src/assets/styles/app.css +69 -0
  87. package/src/components/HomeFooter/index.vue +134 -0
  88. package/src/components/HomeHeader/index.vue +156 -0
  89. package/src/components/InfosForm/index.vue +73 -0
  90. package/src/components/MessageList/index.vue +155 -0
  91. package/src/components/MessagePanel/index.vue +42 -0
  92. package/src/components/Praise/index.vue +102 -0
  93. package/src/components/QrCode.vue +44 -0
  94. package/src/components/linkDialog.vue +104 -0
  95. package/src/components/loginPanel.vue +92 -0
  96. package/src/constants/index.ts +83 -0
  97. package/src/env.d.ts +8 -0
  98. package/src/main.ts +19 -0
  99. package/src/pages/404/index.vue +59 -0
  100. package/src/pages/about/index.vue +152 -0
  101. package/src/pages/callme/index.vue +155 -0
  102. package/src/pages/dashboard/config/index.vue +264 -0
  103. package/src/pages/dashboard/files/index.vue +1152 -0
  104. package/src/pages/dashboard/index.vue +335 -0
  105. package/src/pages/dashboard/manage/config/index.vue +97 -0
  106. package/src/pages/dashboard/manage/index.vue +105 -0
  107. package/src/pages/dashboard/manage/overview/index.vue +488 -0
  108. package/src/pages/dashboard/manage/user/index.vue +679 -0
  109. package/src/pages/dashboard/manage/wish/index.vue +257 -0
  110. package/src/pages/dashboard/tasks/components/CategoryPanel.vue +208 -0
  111. package/src/pages/dashboard/tasks/components/CreateTask.vue +93 -0
  112. package/src/pages/dashboard/tasks/components/TaskInfo.vue +129 -0
  113. package/src/pages/dashboard/tasks/components/infoPanel/ddl.vue +96 -0
  114. package/src/pages/dashboard/tasks/components/infoPanel/file.vue +175 -0
  115. package/src/pages/dashboard/tasks/components/infoPanel/info.vue +477 -0
  116. package/src/pages/dashboard/tasks/components/infoPanel/people.vue +567 -0
  117. package/src/pages/dashboard/tasks/components/infoPanel/template.vue +146 -0
  118. package/src/pages/dashboard/tasks/components/infoPanel/tip.vue +55 -0
  119. package/src/pages/dashboard/tasks/components/infoPanel/tipInfo.vue +196 -0
  120. package/src/pages/dashboard/tasks/index.vue +302 -0
  121. package/src/pages/dashboard/tasks/public.ts +32 -0
  122. package/src/pages/disabled/index.vue +47 -0
  123. package/src/pages/feedback/index.vue +5 -0
  124. package/src/pages/home/index.vue +72 -0
  125. package/src/pages/login/index.vue +270 -0
  126. package/src/pages/register/index.vue +211 -0
  127. package/src/pages/reset/index.vue +186 -0
  128. package/src/pages/task/index.vue +897 -0
  129. package/src/pages/wish/index.vue +152 -0
  130. package/src/router/Interceptor/index.ts +112 -0
  131. package/src/router/index.ts +13 -0
  132. package/src/router/routes/index.ts +197 -0
  133. package/src/shims-vue.d.ts +6 -0
  134. package/src/store/index.ts +17 -0
  135. package/src/store/modules/category.ts +44 -0
  136. package/src/store/modules/public.ts +27 -0
  137. package/src/store/modules/task.ts +55 -0
  138. package/src/store/modules/user.ts +57 -0
  139. package/src/utils/elementUI.ts +8 -0
  140. package/src/utils/networkUtil.ts +236 -0
  141. package/src/utils/other.ts +25 -0
  142. package/src/utils/regExp.ts +11 -0
  143. package/src/utils/stringUtil.ts +242 -0
  144. package/tsconfig.json +24 -0
  145. package/vite.config.ts +55 -0
@@ -0,0 +1,156 @@
1
+ <template>
2
+ <div>
3
+ <nav class="navbar">
4
+ <div class="right-menu">
5
+ <label for="nav-open">
6
+ <span class="menu-icon">
7
+ <el-icon :size="28">
8
+ <Fold />
9
+ </el-icon>
10
+ </span>
11
+ </label>
12
+ </div>
13
+ <input type="checkbox" id="nav-open" />
14
+ <div id="miniMenu">
15
+ <ul class="nav-list">
16
+ <li v-for="({ href, text }, idx) in links" :key="idx">
17
+ <router-link :to="href">{{ text }}</router-link>
18
+ </li>
19
+ <li>
20
+ <a
21
+ href="https://docs.ep.sugarat.top/plan/wish.html"
22
+ target="_blank"
23
+ rel="noopener noreferrer"
24
+ >需求墙</a
25
+ >
26
+ </li>
27
+ <!-- <li>
28
+ <a
29
+ href="https://docs.ep.sugarat.top/introduction/about/index.html"
30
+ target="_blank"
31
+ rel="noopener noreferrer"
32
+ >关于</a
33
+ >
34
+ </li> -->
35
+ <!-- <li>
36
+ <a
37
+ href="https://github.com/ATQQ/easypicker2-client"
38
+ target="_blank"
39
+ rel="noopener noreferrer"
40
+ >GitHub</a
41
+ >
42
+ </li> -->
43
+ <li>
44
+ <a
45
+ href="https://docs.ep.sugarat.top/plan/todo.html"
46
+ target="_blank"
47
+ rel="noopener noreferrer"
48
+ >近期规划</a
49
+ >
50
+ </li>
51
+ <li>
52
+ <a
53
+ href="https://docs.ep.sugarat.top/plan/log.html"
54
+ target="_blank"
55
+ rel="noopener noreferrer"
56
+ >更新日志</a
57
+ >
58
+ </li>
59
+ </ul>
60
+ </div>
61
+ </nav>
62
+ </div>
63
+ </template>
64
+ <script lang="ts" setup>
65
+ import { onMounted, reactive } from 'vue'
66
+ import { useRoute } from 'vue-router'
67
+ import { Fold } from '@element-plus/icons-vue'
68
+
69
+ const $route = useRoute()
70
+ const links = reactive([])
71
+ onMounted(() => {
72
+ const { path } = $route
73
+ const navList = [
74
+ {
75
+ href: '/',
76
+ text: '首页'
77
+ },
78
+ {
79
+ href: '/login',
80
+ text: '登录'
81
+ },
82
+ {
83
+ href: '/register',
84
+ text: '快速注册'
85
+ }
86
+ ]
87
+ for (const nav of navList) {
88
+ if (nav.href !== path) {
89
+ links.push(nav)
90
+ }
91
+ }
92
+ })
93
+ </script>
94
+ <style lang="scss" scoped>
95
+ #nav-open {
96
+ position: absolute;
97
+ z-index: -1;
98
+ }
99
+ .navbar {
100
+ color: #fff;
101
+ padding: 12px 10px 10px 10px;
102
+
103
+ .right-menu {
104
+ margin-right: 15px;
105
+ display: none;
106
+ .menu-icon {
107
+ font-size: 28px;
108
+ }
109
+ }
110
+ .nav-list {
111
+ display: flex;
112
+ justify-content: left;
113
+ li {
114
+ text-align: center;
115
+ list-style: none;
116
+ color: #fff;
117
+ margin: 0 20px;
118
+ }
119
+ a {
120
+ color: #fff;
121
+ opacity: 0.8;
122
+ &:hover {
123
+ opacity: 1;
124
+ text-shadow: 0 0 3px #eee;
125
+ }
126
+ }
127
+ }
128
+ }
129
+
130
+ @media screen and (max-width: 600px) {
131
+ .navbar {
132
+ .right-menu {
133
+ display: block;
134
+ float: right;
135
+ font-size: 20px;
136
+ }
137
+ #nav-open:checked + #miniMenu {
138
+ .nav-list {
139
+ display: flex;
140
+ }
141
+ }
142
+ .nav-list {
143
+ display: none;
144
+ flex-direction: column;
145
+ li {
146
+ margin-top: 6px;
147
+ }
148
+ }
149
+ }
150
+ #miniMenu {
151
+ position: absolute;
152
+ right: 10px;
153
+ top: 40px;
154
+ }
155
+ }
156
+ </style>
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <el-form :disabled="disabled" :label-position="labelPosition || 'top'">
3
+ <el-form-item
4
+ class="ellipsis"
5
+ v-for="(info, idx) in infos"
6
+ :key="idx"
7
+ :label="info.type === 'text' ? '' : info.text"
8
+ >
9
+ <div class="fixed-text" v-if="info.type === 'text'">
10
+ {{ info.text }}
11
+ </div>
12
+ <el-input
13
+ v-if="info.type === 'input'"
14
+ :maxlength="maxInputLength"
15
+ clearable
16
+ show-word-limit
17
+ :placeholder="`请输入 ${info.text}`"
18
+ v-model="info.value"
19
+ ></el-input>
20
+ <el-radio-group v-if="info.type === 'radio'" v-model="info.value">
21
+ <el-radio
22
+ v-for="(r, idx) in info.children"
23
+ :key="idx"
24
+ :label="r.text"
25
+ >{{ r.text }}</el-radio
26
+ >
27
+ </el-radio-group>
28
+ <el-select
29
+ default-first-option
30
+ clearable
31
+ filterable
32
+ v-if="info.type === 'select'"
33
+ v-model="info.value"
34
+ :placeholder="`请选择 ${info.text}`"
35
+ >
36
+ <el-option
37
+ v-for="(r, idx) in info.children"
38
+ :key="idx"
39
+ :label="r.text"
40
+ :value="r.text"
41
+ />
42
+ </el-select>
43
+ </el-form-item>
44
+ </el-form>
45
+ </template>
46
+ <script setup lang="ts">
47
+ defineProps<{
48
+ infos: InfoItem[]
49
+ disabled: boolean
50
+ labelPosition?: 'left' | 'right' | 'top'
51
+ }>()
52
+
53
+ const maxInputLength = +import.meta.env.VITE_APP_INPUT_MAX_LENGTH || 10
54
+ </script>
55
+ <style scoped lang="scss">
56
+ :deep(div.el-form-item > label) {
57
+ font-weight: bold;
58
+ &::before {
59
+ content: '* ';
60
+ color: red;
61
+ }
62
+ }
63
+
64
+ :deep(div.el-form-item__content > .el-select) {
65
+ flex: 1;
66
+ }
67
+ .fixed-text {
68
+ background-color: #f5f7fa;
69
+ padding: 0 10px;
70
+ width: 100%;
71
+ text-align: left;
72
+ }
73
+ </style>
@@ -0,0 +1,155 @@
1
+ <script lang="ts" setup>
2
+ import { ref, reactive, onMounted, watch, computed } from 'vue'
3
+ import { useStore } from 'vuex'
4
+ import { formatDate } from '@/utils/stringUtil'
5
+ import { SuperUserApi } from '@/apis'
6
+
7
+ const props = defineProps<{
8
+ data: SuperUserApiTypes.MessageItem[]
9
+ autoShow?: boolean
10
+ }>()
11
+
12
+ const dialogMessage = reactive({
13
+ show: false,
14
+ title: '系统消息',
15
+ text: '内容'
16
+ })
17
+ const activeMessage = ref<SuperUserApiTypes.MessageItem>(null)
18
+ const handleViewDialogMessage = (v: SuperUserApiTypes.MessageItem) => {
19
+ activeMessage.value = v
20
+ dialogMessage.text = v.text
21
+ // TODO: 魔法数字问题
22
+ // TODO:支持更多的消息类型
23
+ dialogMessage.title = v.type === 0 ? '【系统消息】' : '【私信】'
24
+ dialogMessage.show = true
25
+ }
26
+
27
+ const readMessage = () => {
28
+ if (activeMessage.value.read) {
29
+ dialogMessage.show = false
30
+ return
31
+ }
32
+ SuperUserApi.readMessage(activeMessage.value.id).then(() => {
33
+ activeMessage.value.read = true
34
+ dialogMessage.show = false
35
+ })
36
+ }
37
+
38
+ watch(
39
+ () => props.data.length,
40
+ () => {
41
+ if (!props.autoShow) {
42
+ return
43
+ }
44
+ const showItem = props.data.find((v) => !v.read)
45
+ if (showItem) {
46
+ handleViewDialogMessage(showItem)
47
+ }
48
+ }
49
+ )
50
+
51
+ // TODO:换成自定义hook
52
+ const $store = useStore()
53
+ const isMobile = computed(() => $store.getters['public/isMobile'])
54
+ </script>
55
+ <template>
56
+ <div v-if="!data.length" class="empty">暂无更多消息 ღ( ´・ᴗ・` )比心</div>
57
+ <ul class="message-list">
58
+ <li
59
+ v-for="d in data"
60
+ :key="d.id"
61
+ :class="{
62
+ read: d.read
63
+ }"
64
+ @click="handleViewDialogMessage(d)"
65
+ >
66
+ <p class="text">{{ d.text }}</p>
67
+ <p class="date">{{ formatDate(new Date(d.date)) }}</p>
68
+ </li>
69
+ </ul>
70
+ <el-dialog
71
+ center
72
+ show-close
73
+ append-to-body
74
+ v-model="dialogMessage.show"
75
+ :close-on-click-modal="false"
76
+ :title="dialogMessage.title"
77
+ width="30%"
78
+ :fullscreen="isMobile"
79
+ >
80
+ <div class="message-text" v-html="dialogMessage.text"></div>
81
+ <template #footer>
82
+ <p class="dialog-date">
83
+ 时间:{{ formatDate(new Date(activeMessage.date)) }}
84
+ </p>
85
+ <span>
86
+ <el-button
87
+ type="default"
88
+ @click="
89
+ () => {
90
+ dialogMessage.show = false
91
+ }
92
+ "
93
+ >
94
+ 下次提醒
95
+ </el-button>
96
+ <el-button type="primary" @click="readMessage"> 确定 </el-button>
97
+ </span>
98
+ </template>
99
+ </el-dialog>
100
+ </template>
101
+
102
+ <style lang="scss" scoped>
103
+ .message-list {
104
+ list-style: none;
105
+ max-height: 500px;
106
+ overflow-y: scroll;
107
+ li {
108
+ border-bottom: 1px solid #ddd;
109
+ padding: 10px;
110
+ cursor: pointer;
111
+ &.read {
112
+ opacity: 0.5;
113
+ &:hover {
114
+ opacity: 0.9;
115
+ }
116
+ }
117
+ &:last-child {
118
+ border-bottom: none;
119
+ }
120
+
121
+ p.text {
122
+ font-size: 16px;
123
+ display: -webkit-box;
124
+ overflow: hidden;
125
+ -webkit-line-clamp: 2;
126
+ -webkit-box-orient: vertical;
127
+ }
128
+ p.date {
129
+ font-size: 14px;
130
+ margin-top: 4px;
131
+ }
132
+ }
133
+ }
134
+ .empty {
135
+ text-align: center;
136
+ padding: 10px;
137
+ }
138
+
139
+ .dialog-date {
140
+ font-size: 14px;
141
+ text-align: right;
142
+ padding: 10px;
143
+ color: grey;
144
+ }
145
+ </style>
146
+ <style lang="scss">
147
+ .message-text {
148
+ overflow-y: scroll;
149
+ max-height: 500px;
150
+ ul,
151
+ ol {
152
+ list-style: none;
153
+ }
154
+ }
155
+ </style>
@@ -0,0 +1,42 @@
1
+ <script lang="ts" setup>
2
+ import { Bell } from '@element-plus/icons-vue'
3
+ import { computed, reactive, onMounted, ref } from 'vue'
4
+ import { SuperUserApi } from '@/apis'
5
+ import MessageList from '@/components/MessageList/index.vue'
6
+
7
+ const activeTab = ref<'all' | 'no'>('all')
8
+ const messageData = reactive<SuperUserApiTypes.MessageItem[]>([])
9
+
10
+ const noReadMessage = computed(() => messageData.filter((v) => !v.read))
11
+ onMounted(() => {
12
+ SuperUserApi.getMessageList().then((v) => {
13
+ messageData.push(...v.data)
14
+ })
15
+ })
16
+ </script>
17
+ <template>
18
+ <div class="message-panel">
19
+ <el-popover placement="bottom-end" :width="375" trigger="hover">
20
+ <template #reference>
21
+ <el-badge :value="noReadMessage.length || ''" :max="99">
22
+ <el-button :icon="Bell" circle />
23
+ </el-badge>
24
+ </template>
25
+ <div>
26
+ <el-tabs v-model="activeTab">
27
+ <el-tab-pane :label="`未读 ${noReadMessage.length || ''}`" name="no">
28
+ <message-list auto-show :data="noReadMessage" />
29
+ </el-tab-pane>
30
+ <el-tab-pane :label="`全部 ${messageData.length || ''}`" name="all">
31
+ <message-list :data="messageData" />
32
+ </el-tab-pane>
33
+ </el-tabs>
34
+ </div>
35
+ </el-popover>
36
+ </div>
37
+ </template>
38
+ <style lang="scss" scoped>
39
+ .message-panel {
40
+ margin-right: 10px;
41
+ }
42
+ </style>
@@ -0,0 +1,102 @@
1
+ <template>
2
+ <span class="praise" @click="openPraise">
3
+ <!-- 赞赏弹窗 -->
4
+ <slot />
5
+ <el-dialog append-to-body v-model="showPraise" title="😄 嘻嘻 😄" :fullscreen="isMobile">
6
+ <p class="praise-line">目前的服务开销主要在 “文件存储” 与 "资源下载"两方面</p>
7
+ <p class="praise-line">存储 0.15 元/GB/月,下载0.29 元/GB</p>
8
+ <p class="praise-line">如果你觉得应用不错,可以支持一下👍🏻</p>
9
+ <div>
10
+ <table>
11
+ <thead>
12
+ <tr>
13
+ <th v-for="(v, idx) in praiseImg" :key="idx">{{ v.title }}</th>
14
+ </tr>
15
+ </thead>
16
+ <tbody>
17
+ <tr>
18
+ <td v-for="(v, idx) in praiseImg" :key="idx">
19
+ <el-image preview-teleported style="width: 100px; height: 100px" :src="v.url"
20
+ :preview-src-list="praiseImg.map(v => v.url)" :initial-index="idx" fit="cover" />
21
+ </td>
22
+ </tr>
23
+ </tbody>
24
+ </table>
25
+ </div>
26
+ <template #footer>
27
+ <span class="dialog-footer">
28
+ <el-button type="success" @click="Thanks">这次一定</el-button>
29
+ <el-button type="default" @click="NextPraise">下次一定</el-button>
30
+ </span>
31
+ </template>
32
+ </el-dialog>
33
+ </span>
34
+ </template>
35
+ <script setup lang="ts">
36
+ import { ElMessageBox, ElMessage } from 'element-plus'
37
+ import { computed, reactive, ref } from 'vue'
38
+ import { useStore } from 'vuex'
39
+
40
+ const $store = useStore()
41
+ const showPraise = ref(false)
42
+ const openPraise = () => {
43
+ showPraise.value = true
44
+ }
45
+
46
+ const praiseImg = reactive([
47
+ {
48
+ url: 'https://img.cdn.sugarat.top/mdImg/MTY1MTU0NzQ0MjMzNA==651547442334',
49
+ title: '微信',
50
+ },
51
+ {
52
+ url: 'https://img.cdn.sugarat.top/mdImg/MTY0Nzc1NTYyOTE5Mw==647755629193',
53
+ title: '微信赞赏',
54
+ },
55
+ {
56
+ url: 'https://img.cdn.sugarat.top/mdImg/MTY1MTU0NzQyOTg0OA==651547429848',
57
+ title: '支付宝',
58
+ },
59
+ ])
60
+ const Thanks = () => {
61
+ ElMessageBox.alert(`
62
+ <p class="tc">
63
+ <img width="140px" src="https://img.cdn.sugarat.top/mdImg/MTY1MTUwNjkwNDc4OQ==thanks.gif" />
64
+ </p>
65
+ <p class="tc">
66
+ <img width="240px" src="https://img.cdn.sugarat.top/mdImg/MTY0Nzc2MDE3MzM1NA==647760173354" />
67
+ </p>
68
+ `, '💐 谢谢老板 💐', {
69
+ confirmButtonText: '不客气',
70
+ dangerouslyUseHTMLString: true,
71
+ })
72
+ }
73
+ const NextPraise = () => {
74
+ showPraise.value = false
75
+ ElMessage.success('下次一定!下次一定!')
76
+ }
77
+
78
+ const isMobile = computed(() => $store.getters['public/isMobile'])
79
+
80
+ </script>
81
+ <style scoped>
82
+ .praise{
83
+ cursor: pointer;
84
+ }
85
+ .praise-line {
86
+ margin-bottom: 10px;
87
+ }
88
+
89
+ table{
90
+ display: block;
91
+ border-collapse: collapse;
92
+ margin: 1rem 0;
93
+ overflow-x: auto;
94
+ }
95
+ tr{
96
+ border:1px solid #dfe2e5;
97
+ }
98
+ th,td{
99
+ border:1px solid #8885;
100
+ padding: 0.6em 1em;
101
+ }
102
+ </style>
@@ -0,0 +1,44 @@
1
+ <template>
2
+ <el-image style="width: 150px; height: 150px" :src="src" :preview-src-list="srcList"/>
3
+ </template>
4
+ <script>
5
+ export default {
6
+ name: 'QrCode',
7
+ props: {
8
+ value: String,
9
+ },
10
+ data() {
11
+ return {
12
+ src: '',
13
+ srcList: [],
14
+ }
15
+ },
16
+ watch: {
17
+ value(to) {
18
+ if (!to) {
19
+ return
20
+ }
21
+ this.src = this.createEwm(to)
22
+ this.srcList = [this.src]
23
+ },
24
+ },
25
+ methods: {
26
+ createEwm(text, config) {
27
+ // eslint-disable-next-line no-undef
28
+ const canvasImg = new AraleQRCode({
29
+ text,
30
+ size: 400,
31
+ foreground: '#000',
32
+ ...config,
33
+ })
34
+ return canvasImg.toDataURL('image/png')
35
+ },
36
+ },
37
+ mounted() {
38
+ if (this.value) {
39
+ this.src = this.createEwm(this.value)
40
+ this.srcList = [this.src]
41
+ }
42
+ },
43
+ }
44
+ </script>
@@ -0,0 +1,104 @@
1
+ <template>
2
+ <div>
3
+ <el-dialog
4
+ :fullscreen="isMobile"
5
+ @close="handleClose"
6
+ :title="title"
7
+ v-model="showModel"
8
+ center
9
+ >
10
+ <!-- 链接 -->
11
+ <div>
12
+ <el-input placeholder="生成的链接" v-model="shareLink">
13
+ <template #prepend>
14
+ <el-button type="primary" @click="createShortLink"
15
+ >生成短链</el-button
16
+ >
17
+ </template>
18
+ <template #append>
19
+ <el-button type="primary" @click="copyLink">复制</el-button>
20
+ </template>
21
+ </el-input>
22
+ </div>
23
+ <!-- 二维码 -->
24
+ <div style="margin-top: 10px; text-align: center">
25
+ <qr-code :value="shareLink"></qr-code>
26
+ </div>
27
+ <!-- <template #footer>
28
+ <span class="dialog-footer">
29
+ <el-button type="primary" @click="$emit('update:value',false)">关闭</el-button>
30
+ </span>
31
+ </template>-->
32
+ </el-dialog>
33
+ </div>
34
+ </template>
35
+ <script lang="ts">
36
+ import { ElMessage } from 'element-plus'
37
+ import { computed, defineComponent, ref, watchEffect } from 'vue'
38
+ import QrCode from '@components/QrCode.vue'
39
+ import { useStore } from 'vuex'
40
+ import { copyRes, getShortUrl } from '@/utils/stringUtil'
41
+
42
+ export default defineComponent({
43
+ name: 'linkDialog',
44
+ components: {
45
+ QrCode
46
+ },
47
+ props: {
48
+ title: {
49
+ type: String,
50
+ default: '链接面板'
51
+ },
52
+ value: {
53
+ type: Boolean
54
+ },
55
+ link: {
56
+ type: String,
57
+ default: ''
58
+ },
59
+ download: {
60
+ type: Boolean,
61
+ default: true
62
+ }
63
+ },
64
+ setup(props, context) {
65
+ const shareLink = ref('')
66
+ const showModel = ref(false)
67
+ const copyLink = () => {
68
+ copyRes(shareLink.value)
69
+ }
70
+ watchEffect(() => {
71
+ shareLink.value = props.link
72
+ })
73
+ watchEffect(() => {
74
+ showModel.value = props.value
75
+ if (showModel.value && props.download) {
76
+ setTimeout(() => {
77
+ ElMessage.success('如未自动开始下载,请复制链接到浏览器中执行下载')
78
+ }, 200)
79
+ }
80
+ })
81
+ const handleClose = () => {
82
+ context.emit('update:value', false)
83
+ }
84
+ const createShortLink = () => {
85
+ getShortUrl(shareLink.value).then((v) => {
86
+ shareLink.value = v
87
+ ElMessage.success('短链生成成功')
88
+ })
89
+ }
90
+
91
+ const $store = useStore()
92
+ const isMobile = computed(() => $store.getters['public/isMobile'])
93
+
94
+ return {
95
+ shareLink,
96
+ createShortLink,
97
+ copyLink,
98
+ handleClose,
99
+ showModel,
100
+ isMobile
101
+ }
102
+ }
103
+ })
104
+ </script>