editApplication.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. <template>
  2. <div>
  3. <a-modal
  4. title="编辑应用"
  5. :visible="application"
  6. @ok="handleOk"
  7. :confirmLoading="confirmLoading"
  8. @cancel="handleCancel"
  9. width="800px"
  10. >
  11. <a-card :body-style="{ padding: '24px 32px' }" :bordered="false">
  12. <a-form :form="form">
  13. <!-- <selectTable :projectId.sync="projectId" ref="selectTable" :requireCheck="true"></selectTable> -->
  14. <a-form-item
  15. label="项目名称"
  16. :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
  17. :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
  18. >
  19. <a-input
  20. disabled
  21. v-decorator="[
  22. 'projectName',
  23. {
  24. rules: [{ required: true }],
  25. },
  26. ]"
  27. />
  28. </a-form-item>
  29. <a-form-item
  30. label="设备类型"
  31. :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
  32. :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
  33. >
  34. <a-radio-group v-model="appType" @change="changePlatform" disabled>
  35. <a-radio-button value="android">安卓</a-radio-button>
  36. <a-radio-button value="ios">IOS</a-radio-button>
  37. </a-radio-group>
  38. </a-form-item>
  39. <!-- <a-form-item v-if="appType == 'android'"> -->
  40. <a-form-item
  41. label="推广类型"
  42. :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
  43. :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
  44. >
  45. <a-radio-group v-model="platform" disabled>
  46. <a-radio value="1">应用下载</a-radio>
  47. <a-radio value="2">网页游戏</a-radio>
  48. </a-radio-group>
  49. </a-form-item>
  50. <a-form-item
  51. label="上传应用"
  52. :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
  53. :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
  54. >
  55. <a-radio-group v-model="uploadType">
  56. <a-radio-button value="1" disabled>本地上传</a-radio-button>
  57. <a-radio-button value="2">填写链接</a-radio-button>
  58. </a-radio-group>
  59. </a-form-item>
  60. <a-form-item
  61. label="上传文件"
  62. v-if="uploadType == '1'"
  63. :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
  64. :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
  65. >
  66. <!-- <a-upload name="file" :file-list="fileList" :before-upload="beforeUpload" @change="handleChange">
  67. <a-button><a-icon type="upload" />文件上传</a-button>
  68. </a-upload> -->
  69. <a-upload
  70. name="file"
  71. :multiple="false"
  72. :action="uploadAction"
  73. :headers="tokenHeader"
  74. :file-list="fileList"
  75. :showUploadList="false"
  76. :beforeUpload="beforeUpload"
  77. @change="handleChange"
  78. style="margin-right: 20px"
  79. >
  80. <a-button :disabled="(!projectId && !fileUrl) || loadDisabled">
  81. <a-icon type="upload" />
  82. {{ loadDisabled ? '上传中,请稍后' : '文件上传' }}
  83. </a-button>
  84. </a-upload>
  85. <a @click="downLoadFile">文件格式下载</a>
  86. </a-form-item>
  87. <a-form-item
  88. v-if="uploadType == '2'"
  89. label="下载链接"
  90. :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
  91. :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
  92. >
  93. <a-input
  94. placeholder="请填写应用下载链接"
  95. v-decorator="[
  96. 'url',
  97. {
  98. rules: [{ required: true, validator: handleConfirmValue }],
  99. },
  100. ]"
  101. />
  102. </a-form-item>
  103. <a-form-item
  104. label="应用包名"
  105. v-if="uploadType == '2' && appType == 'android'"
  106. :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
  107. :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
  108. >
  109. <a-input
  110. v-decorator="[
  111. 'packageName',
  112. {
  113. rules: [{ required: true, message: '请填写正确的应用包名称' }],
  114. },
  115. ]"
  116. placeholder="请填写包名称,如com.smile.gifmaker"
  117. />
  118. </a-form-item>
  119. <a-form-item
  120. label="应用名称"
  121. v-if="uploadType == '2'"
  122. :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
  123. :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
  124. >
  125. <a-input
  126. v-decorator="[
  127. 'appName',
  128. {
  129. rules: [{ required: true, message: '请填写应用名称' }],
  130. },
  131. ]"
  132. placeholder="请填写应用名称"
  133. />
  134. </a-form-item>
  135. <a-form-item
  136. label="上传图标"
  137. :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
  138. :wrapperCol="{ xs: { span: 24 }, sm: { span: 19 } }"
  139. v-if="application"
  140. >
  141. <uploadFile
  142. v-if="application"
  143. :value.sync="fileUrl"
  144. :multiple="false"
  145. :fileCount="1"
  146. uploadType="image"
  147. @overUpload="overUpload"
  148. :size="100"
  149. ></uploadFile>
  150. <p class="upload-txt-rules">文件格式:支持上传png/jpg/jpeg图片,尺寸450*450,小于100kb</p>
  151. </a-form-item>
  152. <a-form-item
  153. label="应用标记"
  154. :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
  155. :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
  156. v-if="uploadType == '2'"
  157. >
  158. <a-input
  159. v-decorator="[
  160. 'appVersion',
  161. {
  162. rules: [{ required: true, message: ' ' }, { validator: checkAppVersion }],
  163. },
  164. ]"
  165. placeholder="请填写应用标记,必填且不可重复,如快手-5.6.1.66"
  166. />
  167. </a-form-item>
  168. <!-- <a-form-item>
  169. <a-form-item :wrapperCol="{ span: 24 }" style="text-align: center">
  170. <a-button htmlType="submit" type="primary">提交</a-button>
  171. <a-button style="margin-left: 8px">保存</a-button>
  172. </a-form-item>
  173. </a-form-item> -->
  174. <a-form-item
  175. label=""
  176. :labelCol="{ span: 5 }"
  177. :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 }, offset: 5 }"
  178. v-if="uploadType == '2' && appType == 'android'"
  179. >
  180. <a-checkbox-group v-decorator="['useSdk']">
  181. <a-checkbox :value="0"> 该应用已接入快手广告监测SDK </a-checkbox>
  182. </a-checkbox-group>
  183. </a-form-item>
  184. <a-form-item
  185. label="隐私政策链接"
  186. :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
  187. :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
  188. v-if="uploadType == '2' && appType == 'android'"
  189. >
  190. <a-input
  191. v-decorator="[
  192. 'appPrivacyUrl',
  193. {
  194. rules: [{ required: true, message: '请填写隐私政策链接' }, { validator: handleConfirmValue }],
  195. },
  196. ]"
  197. placeholder="请填写隐私政策链接"
  198. />
  199. </a-form-item>
  200. <a-form-item
  201. label="监测链接"
  202. :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
  203. :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
  204. v-if="uploadType == '2' && appType == 'android'"
  205. >
  206. <a-input v-decorator="['trackUrl']" placeholder="请填写监测链接" />
  207. </a-form-item>
  208. </a-form>
  209. </a-card>
  210. </a-modal>
  211. </div>
  212. </template>
  213. <script>
  214. import Vue from 'vue'
  215. import { ACCESS_TOKEN } from '@/store/mutation-types'
  216. import { deleteAction, postAction, getAction, downFilePost, downFile } from '@/api/manage'
  217. import uploadFile from './uploadFile.vue'
  218. import { mapActions, mapGetters } from 'vuex'
  219. import BMF from 'browser-md5-file'
  220. import selectTable from '@/views/modules/Statistics/components/selectPagination.vue'
  221. import pick from 'lodash.pick'
  222. const fileSuffix = ['xlsx', 'xls', 'zip']
  223. export default {
  224. name: 'BaseForm',
  225. components: {
  226. uploadFile,
  227. selectTable,
  228. },
  229. data() {
  230. return {
  231. loadDisabled: false,
  232. projectId: '',
  233. accountId: '',
  234. fileList: [],
  235. fileUrl: '',
  236. accountList: {},
  237. appType: 'android', //设备类型
  238. platform: '1', //应用类型 : 1 Android 应用下载,2: Android 网页游戏,3: iOS 应用下载, 4:iOS 网页游戏
  239. uploadType: '2', //上传类型 1 本地上传 2 填写链接
  240. appVersion: '', //应用标记
  241. appName: '', // 应用名称
  242. packageName: '', //应用包名
  243. file: '', // 上传文件
  244. imageUrl: '', // 上传图标链接链接
  245. downloadUrl: '', //下载链接
  246. showUploadFile: true,
  247. showDownLoad: false,
  248. showUpload: true,
  249. showAndroid: true,
  250. showIOS: false,
  251. customDomain: '',
  252. acceptVideo: '/*.apk,/*.png,/*.jpg,/*.jpeg,/*.mp4',
  253. accessKeyId: 'LTAIbNbqWzSOklQV',
  254. accessKeySecret: '1rkPz7JNoXk8sJevPaeYHWqfkQXBGh',
  255. region: 'oss-cn-beijing',
  256. bucket: 'ctop-media',
  257. form: this.$form.createForm(this),
  258. url: {
  259. insertTemplateUrl: '/kuaishouAppPackage/fillInLink',
  260. userAllocationList: '/ctop/userAllocation/list',
  261. },
  262. application: false,
  263. confirmLoading: false,
  264. imageToken: '',
  265. uploadAction: '/kuaishouAppPackage/importAppExcel',
  266. tokenHeader: { 'X-Access-Token': Vue.ls.get(ACCESS_TOKEN) },
  267. appId: null,
  268. }
  269. },
  270. methods: {
  271. checkAppVersion(rule, value, callback) {
  272. if (value != '') {
  273. if (this.projectId) {
  274. let params = {}
  275. params.projectId = this.projectId
  276. params.appVersion = value
  277. getAction('/kuaishouAppPackage/checkAppVersion', params).then((res) => {
  278. if (res.success) {
  279. callback()
  280. } else {
  281. callback(res.message)
  282. }
  283. })
  284. }
  285. } else {
  286. callback('应用标记必填')
  287. }
  288. },
  289. overUpload(file) {
  290. console.log(file)
  291. },
  292. downLoadFile() {
  293. downFile('/kuaishouAppPackage/exportAppTemplate').then((res) => {
  294. let blob = new Blob([res], {
  295. type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  296. })
  297. let downloadElement = document.createElement('a')
  298. let href = window.URL.createObjectURL(blob) //创建下载的链接
  299. downloadElement.href = href
  300. downloadElement.download = '应用模板' //下载后文件名
  301. document.body.appendChild(downloadElement)
  302. downloadElement.click() //点击下载
  303. document.body.removeChild(downloadElement) //下载完成移除元素
  304. window.URL.revokeObjectURL(href) //释放掉blob对象
  305. })
  306. },
  307. handleChange(info) {
  308. console.log(info)
  309. let fileList = [...info.fileList]
  310. // 1. Limit the number of uploaded files
  311. // Only to show two recent uploaded files, and old ones will be replaced by the new
  312. fileList = fileList.slice(-2)
  313. // 2. read from response and show file link
  314. fileList = fileList.map((file) => {
  315. if (file.response) {
  316. // Component will show file.url as link
  317. file.url = file.response.url
  318. }
  319. return file
  320. })
  321. if (fileList.length > 0) {
  322. this.fileList = [
  323. {
  324. ...fileList[fileList.length - 1],
  325. },
  326. ]
  327. } else {
  328. this.fileList = []
  329. }
  330. // this.loadDisabled = false
  331. // this.$message.success('文件导入成功,异步创建中,请稍后查看...')
  332. if (info.file.status !== 'uploading') {
  333. console.log(info.file, info.fileList)
  334. }
  335. if (info.file.status === 'done') {
  336. this.loadDisabled = false
  337. if (info.file.response.code == 200) {
  338. this.application = true
  339. this.$emit('getDataList')
  340. this.$message.success(info.file.response.message)
  341. } else {
  342. this.$message.error(info.file.response.message)
  343. }
  344. } else if (info.file.status === 'error') {
  345. this.$message.error(`${info.file.name}上传失败`)
  346. this.loadDisabled = false
  347. }
  348. // console.log(this.form)
  349. },
  350. beforeUpload(file) {
  351. // this.cosUpload(file)
  352. if (process.env.NODE_ENV == 'development') {
  353. this.uploadAction = `/jeecg-boot/kuaishouAppPackage/importAppExcel?projectId=${this.projectId}&platform=${
  354. this.appType == 'ios' ? +this.platform + 2 : +this.platform
  355. }&imageUrl=${this.fileUrl}`
  356. } else if (process.env.NODE_ENV == 'debug') {
  357. } else if (process.env.NODE_ENV == 'production') {
  358. this.uploadAction = `${this.axios.defaults.baseURL}/kuaishouAppPackage/importAppExcel?projectId=${
  359. this.projectId
  360. }&platform=${this.appType == 'ios' ? +this.platform + 2 : +this.platform}&imageUrl=${this.fileUrl}`
  361. }
  362. this.loadDisabled = true
  363. const size = (Number(file.size) / (1024 * 1024)).toFixed(2)
  364. const fileName = file.name
  365. const fileStrArr = fileName.split('.')
  366. const suffix = fileStrArr[fileStrArr.length - 1]
  367. let result = fileSuffix.some((item) => {
  368. return item === suffix
  369. })
  370. if (!result) {
  371. this.$message.error('不支持该文件类型')
  372. this.loadDisabled = false
  373. return false
  374. }
  375. },
  376. cosUpload(file) {
  377. let that = this
  378. let date = new Date()
  379. let y = date.getFullYear()
  380. let MM = date.getMonth() + 1
  381. MM = MM < 10 ? '0' + MM : MM
  382. let d = date.getDate()
  383. d = d < 10 ? '0' + d : d
  384. let timeElse = new Date().getTime()
  385. let arr = file.name.split('.')
  386. let str = ''
  387. for (let i = 0; i < arr.length; i++) {
  388. if (i === arr.length - 1) {
  389. } else {
  390. if (i === arr.length - 2) {
  391. str += arr[i]
  392. } else {
  393. str += arr[i] + '.'
  394. }
  395. }
  396. }
  397. cos.putObject(
  398. {
  399. Bucket: 'media-1301855440',
  400. Region: 'ap-chongqing',
  401. // 存储桶所在地域,必须字段
  402. Key: that.appType + '/' + y + '-' + MM + '-' + d + '/' + str + '-' + timeElse + '.' + arr[arr.length - 1],
  403. StorageClass: 'STANDARD',
  404. Body: file, // 上传文件对象
  405. },
  406. function (err, data) {
  407. if (err) {
  408. that.$message.error('上传失败!!!' + err)
  409. return
  410. }
  411. that.loadingElse = false
  412. that.fileList.push({
  413. uid: file.name,
  414. name: file.name,
  415. status: 'done',
  416. url: '//' + data.Location,
  417. })
  418. if (that.fileList.length > 1) {
  419. that.fileList = that.fileList.slice(-1)
  420. }
  421. const isZip = file.type.includes('zip') || file.type.includes('text')
  422. const fileOvesize = file.size > 1024 * 1024 * 1024
  423. if (!isZip) {
  424. that.$message.error('只能上传zip格式的文件或者txt文件')
  425. return
  426. }
  427. if (fileOvesize) {
  428. that.$message.error('文件大小不能超过1G')
  429. return
  430. }
  431. that.handleMd5(file)
  432. }
  433. )
  434. },
  435. handleMd5(file) {
  436. let bmf = new BMF()
  437. let that = this
  438. return new Promise(function (resolve, reject) {
  439. bmf.md5(file, (err, md5) => {
  440. // getAction('kuaishouPopulationPackage/checkPopulationPackage', { signature: md5 })
  441. // .then((result) => {
  442. // if (result.code === 200) {
  443. that.personNameDisabled = false
  444. that.personResourceDisabled = false
  445. resolve()
  446. // } else if (result.code === 201) {
  447. // that.$message.error(result.message)
  448. // that.personForm.name = result.result.orientationName
  449. // that.personForm.resource = result.result.type
  450. // that.personNameDisabled = true
  451. // that.personResourceDisabled = true
  452. // reject()
  453. // }
  454. // })
  455. // .catch((error) => {
  456. // console.log(error, 'eeee')
  457. // reject()
  458. // })
  459. })
  460. })
  461. },
  462. handleOk() {
  463. this.handleSubmit()
  464. },
  465. handleCancel() {
  466. this.form.resetFields()
  467. this.imageUrl = ''
  468. this.fileUrl = ''
  469. this.platform = '1'
  470. this.application = false
  471. this.uploadType = '2'
  472. },
  473. showApplication(val) {
  474. this.application = true
  475. this.appId = val.id
  476. getAction('/kuaishouAppPackage/queryById', { id: val.id }).then((res) => {
  477. // 'appIconUrl',
  478. if (res.success) {
  479. this.fileUrl = res.result.appIconUrl
  480. this.appType = res.result.platform > 2 ? 'ios' : 'android'
  481. this.platform = res.result.platform > 2 ? res.result.platform - 2 + '' : res.result.platform + ''
  482. res.result.useSdk = res.result.useSdk ? (res.result.useSdk == 0 ? [] : [0]) : null
  483. this.projectId = res.result.projectId
  484. if (this.appType == 'android') {
  485. this.$nextTick(() => {
  486. this.form.setFieldsValue(
  487. pick(res.result, 'url', 'packageName', 'appPrivacyUrl', 'useSdk', 'trackUrl', 'appName', 'projectName')
  488. )
  489. setTimeout(() => {
  490. this.form.setFieldsValue(pick(res.result, 'appVersion'))
  491. }, 150)
  492. })
  493. } else {
  494. setTimeout(() => {
  495. this.form.setFieldsValue(pick(res.result, 'url', 'appVersion', 'projectName'))
  496. }, 100)
  497. setTimeout(() => {
  498. this.form.setFieldsValue(pick(res.result, 'appName'))
  499. }, 150)
  500. }
  501. }
  502. })
  503. },
  504. handleConfirmValue(rule, value, callback) {
  505. if (/(http|https):\/\/([\w.]+\/?)\S*/.test(value) && value != '') {
  506. callback()
  507. } else {
  508. callback('链接不能为空且开头为http://或https://')
  509. }
  510. },
  511. ...mapGetters(['nickname', 'avatar', 'userInfo']),
  512. changePlatform() {
  513. // this.form.resetFields()
  514. // if (this.appType == 'android') {
  515. // this.showAndroid = true
  516. // this.showIOS = false
  517. // this.platform = '1'
  518. // } else {
  519. // this.showAndroid = false
  520. // this.showIOS = true
  521. // this.showDownLoad = true
  522. // this.platform = '1'
  523. // }
  524. },
  525. handleSubmit() {
  526. // console.log('设备类型:' + this.appType)
  527. // console.log('应用类型:' + this.platform)
  528. // console.log('上传类型:' + this.uploadType)
  529. // console.log('应用标记:' + this.appVersion)
  530. // console.log('应用名称:' + this.appName)
  531. // console.log('包名称:' + this.packageName)
  532. // console.log('文件地址:' + this.file)
  533. // console.log('图片地址:' + this.imageUrl)
  534. // e.preventDefault()
  535. this.form.validateFields((err, values) => {
  536. if (!err) {
  537. if (this.fileUrl && this.projectId) {
  538. this.confirmLoading = true
  539. let params = {}
  540. params.projectId = this.projectId
  541. if (this.uploadType == '1') {
  542. this.url.insertTemplateUrl = '/kuaishouAppPackage/importAppExcel'
  543. params.platform = this.appType == 'ios' ? +this.platform + 2 : +this.platform
  544. params.imageUrl = this.fileUrl
  545. } else {
  546. this.url.insertTemplateUrl = '/kuaishouAppPackage/fillInLink'
  547. params = { ...values }
  548. params.useSdk = params.useSdk ? (params.useSdk.length > 0 ? 1 : 0) : null
  549. params.id = this.appId
  550. params.projectId = this.projectId
  551. params.appIconUrl = this.fileUrl
  552. params.platform = this.appType == 'ios' ? +this.platform + 2 : +this.platform
  553. }
  554. postAction(this.url.insertTemplateUrl, params).then((res) => {
  555. this.confirmLoading = false
  556. if (res.success) {
  557. this.$message.success('修改成功')
  558. this.handleCancel()
  559. this.$emit('getDataList')
  560. } else {
  561. this.$message.error(res.message)
  562. }
  563. })
  564. } else {
  565. this.$message.error('请填写必填项')
  566. }
  567. }
  568. })
  569. },
  570. onChange(value) {
  571. console.log(value)
  572. },
  573. },
  574. created: function () {
  575. let params = {}
  576. params.pageSize = '1000'
  577. params.mediaId = '2'
  578. params.userId = this.userInfo().id
  579. getAction(this.url.userAllocationList, params).then((res) => {
  580. if (res.success) {
  581. this.accountList = res.result.records
  582. }
  583. })
  584. },
  585. }
  586. </script>