list.vue 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  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. <!-- <view class="uni-group"> -->
  71. <button @click="navigateTo('./detail?id='+item._id, false)" class="uni-button"
  72. size="mini" type="primary">详情</button>
  73. <!-- <button @click="confirmDelete(item._id)" class="uni-button" size="mini" type="warn">删除</button> -->
  74. <!-- </view> -->
  75. </uni-td>
  76. </uni-tr>
  77. </uni-table>
  78. <view class="uni-pagination-box">
  79. <uni-pagination show-icon :page-size="pagination.size" v-model="pagination.current"
  80. :total="pagination.count" @change="onPageChanged" />
  81. </view>
  82. </unicloud-db>
  83. </view>
  84. </view>
  85. <view v-else class="page-loading" :style="containerTop">
  86. <i class="uni-icon_toast uni-loading"></i>
  87. </view>
  88. </view>
  89. </template>
  90. <script>
  91. import {
  92. enumConverter
  93. } from '@/js_sdk/validator/opendb-app-versions.js';
  94. import {
  95. appListDbName,
  96. appVersionListDbName,
  97. defaultDisplayApp
  98. } from '../utils.js'
  99. import {
  100. mapState
  101. } from 'vuex'
  102. const db = uniCloud.database()
  103. const dbCmd = db.command
  104. // 表查询配置
  105. const dbOrderBy = 'stable_publish desc,create_date desc' // 排序字段
  106. const dbSearchFields = ['name', 'title', 'stable_publish', 'type'] // 模糊搜索字段,支持模糊搜索的字段列表
  107. // 分页配置
  108. const pageSize = 20
  109. const pageCurrent = 1
  110. const appidKey = '__app_version_appid'
  111. const nameKey = '__app_version_name'
  112. function getScreenHeight() {
  113. return document.documentElement ? document.documentElement.clientHeight : window.innerHeight;
  114. }
  115. function createListQuery(condition = {}) {
  116. return {
  117. create_env: dbCmd.neq("uni-stat"),
  118. ...condition
  119. }
  120. }
  121. export default {
  122. data() {
  123. return {
  124. backButtonHover: false,
  125. appVersionListDbName,
  126. currentAppid: '',
  127. currentAppName: '',
  128. query: '',
  129. where: '',
  130. orderby: dbOrderBy,
  131. selectedIndexs: [],
  132. options: {
  133. pageSize,
  134. pageCurrent,
  135. ...enumConverter
  136. },
  137. imageStyles: {
  138. width: 64,
  139. height: 64
  140. },
  141. loaded: false,
  142. containerTop: {},
  143. appList: [],
  144. showAppIndex: 0
  145. }
  146. },
  147. async onLoad({
  148. appid
  149. }) {
  150. await this.getAppList()
  151. if (!this.appList.length) {
  152. this.showModalToAppManager()
  153. return
  154. }
  155. this.loaded = true
  156. this.appList.forEach((item, index) => {
  157. if (item.appid === appid || defaultDisplayApp) {
  158. this.showAppIndex = index
  159. }
  160. })
  161. this.setAppInfo(this.showAppIndex)
  162. this.where = createListQuery({
  163. appid: this.currentAppid
  164. })
  165. },
  166. computed: {
  167. ...mapState('app', ['appid']),
  168. appNameList() {
  169. return this.appList.map(item => item.name)
  170. }
  171. },
  172. watch: {
  173. showAppIndex(val) {
  174. this.setAppInfo(val)
  175. this.where = createListQuery({
  176. appid: this.currentAppid
  177. })
  178. }
  179. },
  180. onReady() {
  181. this.containerTop.height = `${getScreenHeight()}px`
  182. },
  183. methods: {
  184. setAppInfo(index) {
  185. this.currentAppid = this.appList[index].appid
  186. this.currentAppName = this.appList[index].name
  187. },
  188. navigateBack() {
  189. uni.navigateBack()
  190. },
  191. getWhere() {
  192. const query = this.query.trim()
  193. if (!query) {
  194. return ''
  195. }
  196. const queryRe = new RegExp(query, 'i')
  197. return dbSearchFields.map(name => queryRe + '.test(' + name + ')').join(' || ')
  198. },
  199. search() {
  200. const newWhere = this.getWhere()
  201. const isSameWhere = newWhere === this.where
  202. this.where = newWhere
  203. if (this.where) {
  204. this.where = `(${this.where}) && `
  205. }
  206. this.where += `${new RegExp(this.currentAppid, 'i')}.test(appid)`
  207. if (isSameWhere) { // 相同条件时,手动强制刷新
  208. this.loadData()
  209. }
  210. },
  211. loadData(clear = true) {
  212. this.$refs.udb.loadData({
  213. clear
  214. })
  215. },
  216. onPageChanged(e) {
  217. this.$refs.udb.loadData({
  218. current: e.current
  219. })
  220. },
  221. navigateTo(url, clear) {
  222. // clear 表示刷新列表时是否清除页码,true 表示刷新并回到列表第 1 页,默认为 true
  223. uni.navigateTo({
  224. url,
  225. events: {
  226. refreshData: () => {
  227. this.loadData(clear)
  228. }
  229. }
  230. })
  231. },
  232. // 多选处理
  233. selectedItems() {
  234. var dataList = this.$refs.udb.dataList
  235. return this.selectedIndexs.map(i => dataList[i]._id)
  236. },
  237. // 批量删除
  238. delTable() {
  239. this.$refs.udb.remove(this.selectedItems())
  240. },
  241. // 多选
  242. selectionChange(e) {
  243. this.selectedIndexs = e.detail.index
  244. },
  245. confirmDelete(id) {
  246. this.$refs.udb.remove(id)
  247. },
  248. publish(e) {
  249. // #ifdef H5
  250. const {
  251. top,
  252. left,
  253. width,
  254. height
  255. } = document.querySelector('.uni-button.publish').getBoundingClientRect()
  256. // #endif
  257. const platforms = Object.keys(this.options.type_valuetotext)
  258. uni.showActionSheet({
  259. itemList: Object.values(this.options.type_valuetotext),
  260. // #ifdef H5
  261. popover: {
  262. top: top + height,
  263. left,
  264. width
  265. },
  266. // #endif
  267. success: async (res) => {
  268. this.navigateTo(
  269. `./add?appid=${this.currentAppid}&name=${this.currentAppName}&type=${platforms[res.tapIndex]}`
  270. )
  271. }
  272. });
  273. },
  274. async getAppList() {
  275. try {
  276. const {
  277. result
  278. } = await db.collection(appListDbName).get()
  279. if (result && result.data && result.data.length > 0) {
  280. this.appList = result.data.filter(item => item.appid !== this.appid)
  281. } else {
  282. this.showModalToAppManager()
  283. }
  284. } catch (e) {
  285. const arr = ['TOKEN_INVALID_TOKEN_EXPIRED', 'TOKEN_INVALID_ANONYMOUS_USER']
  286. if (arr.indexOf(e.code) === -1)
  287. this.showModalToAppManager()
  288. }
  289. },
  290. showModalToAppManager() {
  291. let timer = null
  292. let second = 3
  293. function jump() {
  294. uni.navigateTo({
  295. url: '/pages/system/app/list'
  296. })
  297. clearInterval(timer)
  298. }
  299. timer = setInterval(() => {
  300. if (--second <= 0) {
  301. jump()
  302. }
  303. }, 1000)
  304. uni.showModal({
  305. title: '请先添加应用',
  306. content: '即将跳转至应用管理……',
  307. showCancel: false,
  308. confirmText: '立即跳转',
  309. success: (res) => jump()
  310. })
  311. },
  312. store_list_key(store_list) {
  313. const arr = store_list ? store_list.filter(item => item.enable) : []
  314. return arr.length ?
  315. arr.sort((a, b) => b.priority - a.priority)
  316. .map(item => item.name).join(',') :
  317. '-'
  318. }
  319. }
  320. }
  321. </script>
  322. <style lang="scss">
  323. .page-loading {
  324. display: flex;
  325. justify-content: center;
  326. align-items: center;
  327. flex-direction: column;
  328. flex: 1;
  329. i {
  330. $icon-size: 80rpx;
  331. width: $icon-size;
  332. height: $icon-size;
  333. }
  334. }
  335. page,
  336. page .main,
  337. .page-loading {
  338. height: 100%;
  339. }
  340. .app-list {
  341. display: flex;
  342. justify-content: space-between;
  343. align-items: center;
  344. padding: 5px 10px;
  345. border-radius: 4px;
  346. border: 1px solid #2e76ba;
  347. color: #3A8EE6;
  348. uni-text {
  349. margin-left: 10px;
  350. }
  351. }
  352. </style>