8
0

app.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. <template>
  2. <hc-new-card>
  3. <template #header>
  4. <div class="w-60">
  5. <hc-search-input v-model="searchForm.name" placeholder="请输入名称关键词" @search="searchClick" />
  6. </div>
  7. </template>
  8. <template #extra>
  9. <el-button hc-btn type="primary" @click="addClick">新增</el-button>
  10. </template>
  11. <hc-table :column="tableColumn" :datas="tableData" :loading="tableLoading" is-new :index-style="{ width: 60 }">
  12. <template #action="{ row }">
  13. <el-link type="warning" @click="editRowClick(row)">修改</el-link>
  14. <el-link type="primary" @click="updateRowClick(row)">升级</el-link>
  15. <el-link type="danger" @click="delRowClick(row)">删除</el-link>
  16. </template>
  17. </hc-table>
  18. <template #action>
  19. <hc-pages :pages="searchForm" @change="pageChange" />
  20. </template>
  21. <!-- 新增/修改 -->
  22. <hc-new-dialog v-model="isDialogShow" widths="44rem" is-footer-center :title="dialogTitle" @close="dialogClose">
  23. <el-form ref="formRef" :model="formModel" :rules="formRules" label-position="top" label-width="auto">
  24. <el-row :gutter="20">
  25. <el-col :span="12">
  26. <el-form-item label="应用平台:" prop="platform">
  27. <el-input v-model="formModel.platform" clearable placeholder="请输入应用平台" />
  28. </el-form-item>
  29. <el-form-item label="应用名称:" prop="name">
  30. <el-input v-model="formModel.name" clearable placeholder="请输入应用名称" />
  31. </el-form-item>
  32. <el-form-item label="当前版本:" prop="currentVersion">
  33. <el-input v-model="formModel.currentVersion" clearable placeholder="请输入当前版本号" />
  34. </el-form-item>
  35. </el-col>
  36. <el-col :span="12">
  37. <el-form-item label="应用说明:">
  38. <el-input v-model="formModel.appExplain" :autosize="{ minRows: 9, maxRows: 9 }" type="textarea" placeholder="请输入应用说明" />
  39. </el-form-item>
  40. </el-col>
  41. </el-row>
  42. </el-form>
  43. <template #footer>
  44. <el-button hc-btn @click="dialogClose">取消</el-button>
  45. <el-button hc-btn type="primary" :loading="submitLoading" @click="dialogSubmit">提交</el-button>
  46. </template>
  47. </hc-new-dialog>
  48. <!-- APP升级列表 -->
  49. <hc-new-dialog v-model="isUpdateDialog" ui="hc-app-update-dialog" widths="700px" is-table @close="updateDialogClose">
  50. <template #header>
  51. <el-button hc-btn type="primary" @click="addUpdateClick">新增版本</el-button>
  52. <div class="hc-update-dialog-title">{{ updateDialogTitle }}</div>
  53. </template>
  54. <hc-table :column="tableUpdateColumn" :datas="tableUpdateData" :loading="tableUpdateLoading" is-new :index-style="{ width: 60 }">
  55. <template #softwareType="{ row }">
  56. {{ row.softwareType === 1 ? '安卓' : 'IOS' }}
  57. </template>
  58. <template #fileType="{ row }">
  59. {{ row.fileType === 0 ? '完整' : 'wgt' }}
  60. </template>
  61. <template #constraintUpdate="{ row }">
  62. {{ row.fileType === 1 ? '是' : '否' }}
  63. </template>
  64. <template #action="{ row }">
  65. <el-link type="warning" @click="editUpdateRow(row)">修改</el-link>
  66. <el-link type="danger" @click="delUpdateRow(row)">删除</el-link>
  67. </template>
  68. </hc-table>
  69. <template #footer>
  70. <hc-pages :pages="searchUpdateForm" @change="pageUpdateChange" />
  71. </template>
  72. </hc-new-dialog>
  73. <!-- 新增/修改 APP升级 -->
  74. <hc-new-dialog v-model="isUpdateFormDialog" widths="550px" is-footer-center :title="updateFormTitle" @close="updateFormDialogClose">
  75. <el-form ref="formUpdateRef" :model="formUpdateModel" :rules="formUpdateRules" label-position="left" label-width="auto">
  76. <el-form-item label="当前版本:" prop="versionNumber">
  77. <el-input v-model="formUpdateModel.versionNumber" clearable placeholder="请输入当前版本号" />
  78. </el-form-item>
  79. <el-form-item label="软件类型:" prop="softwareType">
  80. <el-radio-group v-model="formUpdateModel.softwareType">
  81. <el-radio :label="1">安卓</el-radio>
  82. <el-radio :label="2">ios</el-radio>
  83. <el-radio :label="3">win</el-radio>
  84. <el-radio :label="4">mac</el-radio>
  85. </el-radio-group>
  86. </el-form-item>
  87. <el-form-item v-if="formUpdateModel.softwareType <= 2" label="文件类型:" prop="fileType">
  88. <el-radio-group v-model="formUpdateModel.fileType">
  89. <el-radio :label="0">完整安装包</el-radio>
  90. <el-radio :label="1">wgt热更新包</el-radio>
  91. </el-radio-group>
  92. </el-form-item>
  93. <el-form-item v-if="formUpdateModel.softwareType === 3" label="文件类型:" prop="fileType">
  94. <el-radio-group v-model="formUpdateModel.fileType">
  95. <el-radio :label="0">win</el-radio>
  96. <el-radio :label="1">arm</el-radio>
  97. </el-radio-group>
  98. </el-form-item>
  99. <el-form-item v-if="formUpdateModel.softwareType === 4" label="文件类型:" prop="fileType">
  100. <el-radio-group v-model="formUpdateModel.fileType">
  101. <el-radio :label="0">intel</el-radio>
  102. <el-radio :label="1">M系列</el-radio>
  103. </el-radio-group>
  104. </el-form-item>
  105. <el-form-item label="更新内容:" prop="updateContent">
  106. <el-input v-model="formUpdateModel.updateContent" :autosize="{ minRows: 4, maxRows: 8 }" type="textarea" placeholder="请输入更新内容" />
  107. </el-form-item>
  108. <el-form-item label="文件地址:" prop="fileUrl">
  109. <el-input v-model="formUpdateModel.fileUrl" clearable>
  110. <template #append>
  111. <el-button @click="uploadFile">上传文件</el-button>
  112. </template>
  113. </el-input>
  114. </el-form-item>
  115. <el-form-item label="强制更新:" prop="constraintUpdate">
  116. <el-radio-group v-model="formUpdateModel.constraintUpdate">
  117. <el-radio :label="1">是</el-radio>
  118. <el-radio :label="0">否</el-radio>
  119. </el-radio-group>
  120. </el-form-item>
  121. </el-form>
  122. <template #footer>
  123. <el-button hc-btn @click="updateFormDialogClose">取消</el-button>
  124. <el-button hc-btn type="primary" :loading="submitUpdateLoading" @click="dialogUpdateSubmit">提交</el-button>
  125. </template>
  126. </hc-new-dialog>
  127. <!-- 上传文件 -->
  128. <hc-upload-file ref="uploadRef" :options="uploadOptions" @success="uploadSuccess" />
  129. </hc-new-card>
  130. </template>
  131. <script setup>
  132. import { nextTick, onActivated, ref } from 'vue'
  133. import { formValidate, getArrValue } from 'js-fast-way'
  134. import { delMessage } from '~uti/tools'
  135. import mainApi from '~api/system/app'
  136. import { getHeader } from 'hc-vue3-ui'
  137. //激活
  138. onActivated(() => {
  139. searchForm.value.current = 1
  140. getTableData()
  141. })
  142. //搜索表单
  143. const searchForm = ref({ current: 1, size: 30, total: 0 })
  144. //搜索
  145. const searchClick = () => {
  146. searchForm.value.current = 1
  147. getTableData()
  148. }
  149. //分页
  150. const pageChange = ({ current, size }) => {
  151. searchForm.value.current = current
  152. searchForm.value.size = size
  153. getTableData()
  154. }
  155. //表格数据
  156. const tableColumn = ref([
  157. { key: 'platform', name: '应用平台' },
  158. { key: 'name', name: '应用名称' },
  159. { key: 'currentVersion', name: '当前版本' },
  160. { key: 'updateTime', name: '更新时间' },
  161. { key: 'action', name: '操作', width: 120, align: 'center' },
  162. ])
  163. //获取表格数据
  164. const tableLoading = ref(true)
  165. const tableData = ref([])
  166. const getTableData = async () => {
  167. tableData.value = []
  168. tableLoading.value = true
  169. const { error, code, data } = await mainApi.page({
  170. ...searchForm.value,
  171. total: null,
  172. })
  173. tableLoading.value = false
  174. if (!error && code === 200) {
  175. tableData.value = getArrValue(data['records'])
  176. searchForm.value.total = data['total']
  177. } else {
  178. tableData.value = []
  179. searchForm.value.total = 0
  180. }
  181. }
  182. //新增/修改 弹窗
  183. const isDialogShow = ref(false)
  184. const dialogTitle = ref('')
  185. //菜单表单
  186. const formRef = ref(null)
  187. const formModel = ref({})
  188. const formRules = {
  189. platform: {
  190. required: true,
  191. trigger: 'blur',
  192. message: '请输入应用平台',
  193. },
  194. name: {
  195. required: true,
  196. trigger: 'blur',
  197. message: '请输入应用名称',
  198. },
  199. currentVersion: {
  200. required: true,
  201. trigger: 'blur',
  202. message: '请输入当前版本号',
  203. },
  204. }
  205. //新增
  206. const addClick = () => {
  207. dialogTitle.value = '新增APP'
  208. formModel.value = {}
  209. //显示表单弹窗
  210. nextTick(() => {
  211. isDialogShow.value = true
  212. })
  213. }
  214. //修改
  215. const editRowClick = (row) => {
  216. formModel.value = {}
  217. dialogTitle.value = '修改APP'
  218. formModel.value = { ...row }
  219. //显示表单弹窗
  220. nextTick(() => {
  221. isDialogShow.value = true
  222. })
  223. }
  224. //删除
  225. const delRowClick = (row) => {
  226. delMessage(async () => {
  227. const { code, msg } = await mainApi.del(row.id)
  228. if (code === 200) {
  229. window.$message.success('删除成功')
  230. dialogClose()
  231. getTableData().then()
  232. } else {
  233. window.$message.error(msg ?? '删除失败')
  234. }
  235. })
  236. }
  237. //提交表单
  238. const submitLoading = ref(false)
  239. const dialogSubmit = async () => {
  240. const formRes = await formValidate(formRef.value)
  241. if (!formRes) return false
  242. submitLoading.value = true
  243. //发起请求
  244. let res = {}
  245. if (formModel.value.id) {
  246. res = await mainApi.update(formModel.value)
  247. } else {
  248. res = await mainApi.add(formModel.value)
  249. }
  250. //处理结果
  251. const { error, code, msg } = res
  252. if (!error && code === 200) {
  253. submitLoading.value = false
  254. window?.$message?.success('操作成功')
  255. dialogClose()
  256. getTableData().then()
  257. } else {
  258. window?.$message?.error(msg ?? '操作失败')
  259. }
  260. }
  261. //关闭弹窗
  262. const dialogClose = () => {
  263. isDialogShow.value = false
  264. submitLoading.value = false
  265. formModel.value = {}
  266. }
  267. //升级APP
  268. const isUpdateDialog = ref(false)
  269. const updateDialogTitle = ref('')
  270. const appRowInfo = ref({})
  271. //显示升级弹窗
  272. const updateRowClick = (row) => {
  273. updateDialogTitle.value = `升级 - ${row.name}`
  274. appRowInfo.value = { ...row }
  275. searchUpdateForm.value.current = 1
  276. searchUpdateForm.value.versionId = row.id
  277. nextTick(() => {
  278. isUpdateDialog.value = true
  279. getUpdateTableData()
  280. })
  281. }
  282. //搜索表单
  283. const searchUpdateForm = ref({
  284. current: 1, size: 30, total: 0,
  285. })
  286. //分页
  287. const pageUpdateChange = ({ current, size }) => {
  288. searchUpdateForm.value.current = current
  289. searchUpdateForm.value.size = size
  290. getUpdateTableData()
  291. }
  292. //表格数据
  293. const tableUpdateColumn = ref([
  294. { key: 'softwareType', name: '软件类型', width: 80 },
  295. { key: 'versionNumber', name: '当前版本', width: 100 },
  296. { key: 'fileType', name: '文件类型', width: 80 },
  297. { key: 'constraintUpdate', name: '强制更新', width: 80 },
  298. { key: 'updateDate', name: '更新时间' },
  299. { key: 'action', name: '操作', width: 100, align: 'center' },
  300. ])
  301. //获取表格数据
  302. const tableUpdateLoading = ref(false)
  303. const tableUpdateData = ref([{}])
  304. const getUpdateTableData = async () => {
  305. tableUpdateData.value = []
  306. tableUpdateLoading.value = true
  307. const { error, code, data } = await mainApi.getDetailList({
  308. ...searchUpdateForm.value,
  309. total: null,
  310. })
  311. tableUpdateLoading.value = false
  312. if (!error && code === 200) {
  313. tableUpdateData.value = getArrValue(data['records'])
  314. searchUpdateForm.value.total = data['total']
  315. } else {
  316. tableUpdateData.value = []
  317. searchUpdateForm.value.total = 0
  318. }
  319. }
  320. //新增/修改 弹窗
  321. const isUpdateFormDialog = ref(false)
  322. const updateFormTitle = ref('')
  323. //菜单表单
  324. const formUpdateRef = ref(null)
  325. const formUpdateModel = ref({})
  326. const formUpdateRules = {
  327. versionNumber: {
  328. required: true,
  329. trigger: 'blur',
  330. message: '请输入当前版本号',
  331. },
  332. softwareType: {
  333. required: true,
  334. trigger: 'blur',
  335. message: '请选择软件类型',
  336. },
  337. fileType: {
  338. required: true,
  339. trigger: 'blur',
  340. message: '请选择文件类型',
  341. },
  342. updateContent: {
  343. required: true,
  344. trigger: 'blur',
  345. message: '请输入更新内容',
  346. },
  347. fileUrl: {
  348. required: true,
  349. trigger: 'blur',
  350. message: '请上传文件',
  351. },
  352. constraintUpdate: {
  353. required: true,
  354. trigger: 'blur',
  355. message: '请选择强制更新',
  356. },
  357. }
  358. //新增
  359. const addUpdateClick = () => {
  360. updateFormTitle.value = '新增 - ' + updateDialogTitle.value
  361. formUpdateModel.value = { softwareType: 1, fileType: 0, constraintUpdate: 0, versionId: appRowInfo.value.id }
  362. //显示表单弹窗
  363. nextTick(() => {
  364. isUpdateFormDialog.value = true
  365. })
  366. }
  367. //修改
  368. const editUpdateRow = (row) => {
  369. formUpdateModel.value = {}
  370. updateFormTitle.value = '修改 - ' + updateDialogTitle.value
  371. formUpdateModel.value = { ...row }
  372. //显示表单弹窗
  373. nextTick(() => {
  374. isUpdateFormDialog.value = true
  375. })
  376. }
  377. //删除
  378. const delUpdateRow = (row) => {
  379. delMessage(async () => {
  380. const { code, msg } = await mainApi.removeDetail(row.id)
  381. if (code === 200) {
  382. window.$message.success('删除成功')
  383. updateDialogClose()
  384. getUpdateTableData().then()
  385. } else {
  386. window.$message.error(msg ?? '删除失败')
  387. }
  388. })
  389. }
  390. //关闭升级弹窗
  391. const updateDialogClose = () => {
  392. isUpdateDialog.value = false
  393. tableUpdateLoading.value = false
  394. tableUpdateData.value = []
  395. getTableData()
  396. }
  397. //上传文件
  398. const uploadRef = ref(null)
  399. const uploadOptions = ref({
  400. url: '/api/blade-resource/oss/endpoint/put-file2',
  401. accept: '.apk,.wgt,.exe,.dmg',
  402. accept_tip: '只能上传apk、wgt、exe、dmg文件',
  403. headers: getHeader(),
  404. multiple: false,
  405. })
  406. //上传文件
  407. const uploadFile = () => {
  408. uploadRef.value?.selectFile()
  409. }
  410. // 文件上传成功的回调
  411. const uploadSuccess = ({ resData }) => {
  412. formUpdateModel.value.fileUrl = resData
  413. uploadRef.value?.setModalShow(false)
  414. }
  415. //提交APP升级表单
  416. const submitUpdateLoading = ref(false)
  417. const dialogUpdateSubmit = async () => {
  418. const formRes = await formValidate(formUpdateRef.value)
  419. if (!formRes) return false
  420. submitUpdateLoading.value = true
  421. //发起请求
  422. let res = {}
  423. if (formUpdateModel.value.id) {
  424. res = await mainApi.updateDetail(formUpdateModel.value)
  425. } else {
  426. res = await mainApi.addDetail(formUpdateModel.value)
  427. }
  428. submitUpdateLoading.value = false
  429. //处理结果
  430. const { error, code, msg } = res
  431. if (!error && code === 200) {
  432. window?.$message?.success('操作成功')
  433. updateFormDialogClose()
  434. getUpdateTableData().then()
  435. } else {
  436. window?.$message?.error(msg ?? '操作失败')
  437. }
  438. }
  439. //关闭升级表单弹窗
  440. const updateFormDialogClose = () => {
  441. isUpdateFormDialog.value = false
  442. submitUpdateLoading.value = false
  443. formUpdateModel.value = {}
  444. }
  445. </script>
  446. <style lang="scss">
  447. .hc-app-update-dialog .el-dialog__headerbtn {
  448. top: 0;
  449. width: 48px;
  450. height: 48px;
  451. }
  452. .hc-update-dialog-title {
  453. position: absolute;
  454. top: 15px;
  455. left: 200px;
  456. right: 200px;
  457. text-align: center;
  458. }
  459. </style>