list.vue 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. <template>
  2. <view class="main">
  3. <view v-if="loaded">
  4. <view class="uni-header">
  5. <view class="uni-group">
  6. <view class="uni-sub-title">当前应用:</view>
  7. <view class="uni-title app-list">
  8. <picker @change="(e) => showAppIndex = e.detail.value" :value="showAppIndex"
  9. :range="appNameList">
  10. <view class="uni-input" style="font-size: 14px;">
  11. {{appNameList[showAppIndex]}}
  12. <uni-icons type="bottom"></uni-icons>
  13. </view>
  14. </picker>
  15. </view>
  16. </view>
  17. <view class="uni-group">
  18. <input class="uni-search" type="text" v-model="query" @confirm="search" placeholder="请输入搜索内容" />
  19. <button class="uni-button" type="default" size="mini" @click="search">搜索</button>
  20. <button class="uni-button publish" type="primary" size="mini" @click="publish">发布新版</button>
  21. <button class="uni-button" type="warn" size="mini" :disabled="!selectedIndexs.length"
  22. @click="delTable">批量删除</button>
  23. </view>
  24. </view>
  25. <view class="uni-container">
  26. <unicloud-db ref="udb" :collection="appVersionListDbName"
  27. field="store_list,appid,contents,platform,type,version,min_uni_version,url,stable_publish,create_date,title,name"
  28. :where="where" page-data="replace" :orderby="orderby" :getcount="true" :page-size="options.pageSize"
  29. :page-current="options.pageCurrent" v-slot:default="{data,pagination,loading,error,options}"
  30. :options="options">
  31. <uni-table style="overflow-y: hidden;" :loading="loading" :emptyText="error.message || '没有更多数据'"
  32. border stripe type="selection" @selection-change="selectionChange">
  33. <uni-tr>
  34. <uni-th align="center">AppID</uni-th>
  35. <uni-th align="center">更新标题</uni-th>
  36. <uni-th align="center">安装包类型</uni-th>
  37. <uni-th align="center">平台</uni-th>
  38. <uni-th align="center">已上架应用市场</uni-th>
  39. <uni-th align="center">版本号</uni-th>
  40. <uni-th align="center">安装包状态</uni-th>
  41. <uni-th align="center">上传时间</uni-th>
  42. <uni-th align="center">操作</uni-th>
  43. </uni-tr>
  44. <uni-tr v-for="(item,index) in data" :key="index" :disabled="item.stable_publish">
  45. <uni-td align="center"> {{item.appid}} </uni-td>
  46. <uni-td align="center"> {{item.title || '-'}} </uni-td>
  47. <uni-td align="center">
  48. <text :style="{
  49. padding: '5px 8px',
  50. backgroundColor: item.type === 'wgt' ? '#f0f9eb' : '#ecf5ff',
  51. color: item.type === 'wgt' ? '#67c23a' : '#409eff',
  52. border: `1px solid ${item.type === 'wgt' ? '#e1f3d8' : '#d9ecff'}`,
  53. borderRadius: '4px'
  54. }">{{options.type_valuetotext[item.type]}}</text>
  55. </uni-td>
  56. <uni-td align="center">
  57. <uni-data-picker :localdata="options.platform_valuetotext" :value="item.platform"
  58. :border="false" :readonly="true" split="," />
  59. </uni-td>
  60. <uni-td align="center">
  61. <text>{{store_list_key(item.store_list)}}</text>
  62. </uni-td>
  63. <uni-td align="center"> {{item.version}} </uni-td>
  64. <uni-td align="center"> {{item.stable_publish == true ? '已上线' : '已下线'}} </uni-td>
  65. <uni-td align="center">
  66. <uni-dateformat format="yyyy-MM-dd hh:mm:ss" :date="item.create_date"
  67. :threshold="[0, 0]" />
  68. </uni-td>
  69. <uni-td align="center">
  70. <button @click="navigateTo('./detail?id='+item._id, false)" class="uni-button" size="mini" type="primary">详情</button>
  71. </uni-td>
  72. </uni-tr>
  73. </uni-table>
  74. <view class="uni-pagination-box">
  75. <uni-pagination show-icon :page-size="pagination.size" v-model="pagination.current"
  76. :total="pagination.count" @change="onPageChanged" />
  77. </view>
  78. </unicloud-db>
  79. </view>
  80. </view>
  81. <view v-else class="page-loading" :style="containerTop">
  82. <i class="uni-icon_toast uni-loading"></i>
  83. </view>
  84. </view>
  85. </template>
  86. <script>
  87. import {
  88. enumConverter
  89. } from '@/js_sdk/validator/opendb-app-versions.js';
  90. import {
  91. appListDbName,
  92. appVersionListDbName,
  93. defaultDisplayApp
  94. } from '../utils.js'
  95. import {
  96. mapState
  97. } from 'vuex'
  98. const db = uniCloud.database()
  99. const dbCmd = db.command
  100. // 表查询配置
  101. const dbOrderBy = 'stable_publish desc,create_date desc' // 排序字段
  102. const dbSearchFields = ['name', 'title', 'stable_publish', 'type'] // 模糊搜索字段,支持模糊搜索的字段列表
  103. // 分页配置
  104. const pageSize = 20
  105. const pageCurrent = 1
  106. const appidKey = '__app_version_appid'
  107. const nameKey = '__app_version_name'
  108. function getScreenHeight() {
  109. return document.documentElement ? document.documentElement.clientHeight : window.innerHeight;
  110. }
  111. function createListQuery(condition = {}) {
  112. return {
  113. create_env: dbCmd.neq("uni-stat"),
  114. ...condition
  115. }
  116. }
  117. export default {
  118. data() {
  119. return {
  120. backButtonHover: false,
  121. appVersionListDbName,
  122. currentAppid: '',
  123. currentAppName: '',
  124. query: '',
  125. where: '',
  126. orderby: dbOrderBy,
  127. selectedIndexs: [],
  128. options: {
  129. pageSize,
  130. pageCurrent,
  131. ...enumConverter
  132. },
  133. imageStyles: {
  134. width: 64,
  135. height: 64
  136. },
  137. loaded: false,
  138. containerTop: {},
  139. appList: [],
  140. showAppIndex: 0
  141. }
  142. },
  143. async onLoad({
  144. appid
  145. }) {
  146. await this.getAppList()
  147. if (!this.appList.length) {
  148. this.showModalToAppManager()
  149. return
  150. }
  151. this.loaded = true
  152. this.appList.forEach((item, index) => {
  153. if (item.appid === appid || defaultDisplayApp) {
  154. this.showAppIndex = index
  155. }
  156. })
  157. this.setAppInfo(this.showAppIndex)
  158. this.where = createListQuery({
  159. appid: this.currentAppid
  160. })
  161. },
  162. computed: {
  163. ...mapState('app', ['appid']),
  164. appNameList() {
  165. return this.appList.map(item => item.name)
  166. }
  167. },
  168. watch: {
  169. showAppIndex(val) {
  170. this.setAppInfo(val)
  171. this.where = createListQuery({
  172. appid: this.currentAppid
  173. })
  174. }
  175. },
  176. onReady() {
  177. this.containerTop.height = `${getScreenHeight()}px`
  178. },
  179. methods: {
  180. setAppInfo(index) {
  181. this.currentAppid = this.appList[index].appid
  182. this.currentAppName = this.appList[index].name
  183. },
  184. navigateBack() {
  185. uni.navigateBack()
  186. },
  187. getWhere() {
  188. const query = this.query.trim()
  189. if (!query) {
  190. return ''
  191. }
  192. const queryRe = new RegExp(query, 'i')
  193. return dbSearchFields.map(name => queryRe + '.test(' + name + ')').join(' || ')
  194. },
  195. search() {
  196. const newWhere = this.getWhere()
  197. const isSameWhere = newWhere === this.where
  198. this.where = newWhere
  199. if (this.where) {
  200. this.where = `(${this.where}) && `
  201. }
  202. this.where += `${new RegExp(this.currentAppid, 'i')}.test(appid)`
  203. if (isSameWhere) { // 相同条件时,手动强制刷新
  204. this.loadData()
  205. }
  206. },
  207. loadData(clear = true) {
  208. this.$refs.udb.loadData({
  209. clear
  210. })
  211. },
  212. onPageChanged(e) {
  213. this.$refs.udb.loadData({
  214. current: e.current
  215. })
  216. },
  217. navigateTo(url, clear) {
  218. // clear 表示刷新列表时是否清除页码,true 表示刷新并回到列表第 1 页,默认为 true
  219. uni.navigateTo({
  220. url,
  221. events: {
  222. refreshData: () => {
  223. this.loadData(clear)
  224. }
  225. }
  226. })
  227. },
  228. // 多选处理
  229. selectedItems() {
  230. let dataList = this.$refs.udb.dataList
  231. return this.selectedIndexs.map(i => dataList[i]._id)
  232. },
  233. // 批量删除
  234. delTable() {
  235. this.$refs.udb.remove(this.selectedItems())
  236. },
  237. // 多选
  238. selectionChange(e) {
  239. this.selectedIndexs = e.detail.index
  240. },
  241. confirmDelete(id) {
  242. this.$refs.udb.remove(id)
  243. },
  244. publish(e) {
  245. // #ifdef H5
  246. const {
  247. top,
  248. left,
  249. width,
  250. height
  251. } = document.querySelector('.uni-button.publish').getBoundingClientRect()
  252. // #endif
  253. const platforms = Object.keys(this.options.type_valuetotext)
  254. uni.showActionSheet({
  255. itemList: Object.values(this.options.type_valuetotext),
  256. // #ifdef H5
  257. popover: {
  258. top: top + height,
  259. left,
  260. width
  261. },
  262. // #endif
  263. success: async (res) => {
  264. this.navigateTo(
  265. `./add?appid=${this.currentAppid}&name=${this.currentAppName}&type=${platforms[res.tapIndex]}`
  266. )
  267. }
  268. });
  269. },
  270. async getAppList() {
  271. try {
  272. const {
  273. result
  274. } = await db.collection(appListDbName).get()
  275. if (result && result.data && result.data.length > 0) {
  276. this.appList = result.data.filter(item => item.appid !== this.appid)
  277. } else {
  278. this.showModalToAppManager()
  279. }
  280. } catch (e) {
  281. const arr = ['TOKEN_INVALID_TOKEN_EXPIRED', 'TOKEN_INVALID_ANONYMOUS_USER']
  282. if (arr.indexOf(e.code) === -1)
  283. this.showModalToAppManager()
  284. }
  285. },
  286. showModalToAppManager() {
  287. let timer = null
  288. let second = 3
  289. function jump() {
  290. uni.navigateTo({
  291. url: '/pages/system/app/list'
  292. })
  293. clearInterval(timer)
  294. }
  295. timer = setInterval(() => {
  296. if (--second <= 0) {
  297. jump()
  298. }
  299. }, 1000)
  300. uni.showModal({
  301. title: '请先添加应用',
  302. content: '即将跳转至应用管理……',
  303. showCancel: false,
  304. confirmText: '立即跳转',
  305. success: (res) => jump()
  306. })
  307. },
  308. store_list_key(store_list) {
  309. const arr = store_list ? store_list.filter(item => item.enable) : []
  310. return arr.length ?
  311. arr.sort((a, b) => b.priority - a.priority)
  312. .map(item => item.name).join(',') :
  313. '-'
  314. }
  315. }
  316. }
  317. </script>
  318. <style lang="scss">
  319. .page-loading {
  320. display: flex;
  321. justify-content: center;
  322. align-items: center;
  323. flex-direction: column;
  324. flex: 1;
  325. i {
  326. $icon-size: 80rpx;
  327. width: $icon-size;
  328. height: $icon-size;
  329. }
  330. }
  331. page,
  332. page .main,
  333. .page-loading {
  334. height: 100%;
  335. }
  336. .app-list {
  337. display: flex;
  338. justify-content: space-between;
  339. align-items: center;
  340. padding: 5px 10px;
  341. border-radius: 4px;
  342. border: 1px solid #2e76ba;
  343. color: #3A8EE6;
  344. uni-text {
  345. margin-left: 10px;
  346. }
  347. }
  348. </style>