CreateCdkey.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. <template>
  2. <div class="manage-root cdkey-create">
  3. <Header />
  4. <div class="manage-root-contain">
  5. <nav-menu class="manage-root-contain-left" :activeMenuIndex="activeMenuIndex"></nav-menu>
  6. <div class="manage-root-contain-right">
  7. <breadcrumb :breadcrumbList="breadcrumbList" class="breadcrumb-box"></breadcrumb>
  8. <div class="create-top">
  9. <div class="common-title-box">
  10. <h3>{{id?'编辑兑换码':'创建兑换码'}}</h3>
  11. <div class="btn-box" v-if="id||!id&&stepIndex!==2">
  12. <el-button size="small" :disabled="true">上一步</el-button>
  13. <el-button type="primary" size="small" @click="handleStep('+')" :disabled="stepIndex===2" :loading="loading">下一步</el-button>
  14. </div>
  15. </div>
  16. <el-steps :active="stepIndex" align-center>
  17. <el-step title="基本信息" description="填写兑换码基本信息">
  18. <svg-icon icon-class="dot" slot="icon" class="svg-dot"></svg-icon>
  19. </el-step>
  20. <el-step :title="id?'编辑兑换内容':'添加兑换内容'" description="为兑换码添加内容">
  21. <svg-icon icon-class="dot" slot="icon" class="svg-dot"></svg-icon>
  22. </el-step>
  23. <el-step :title="id?'完成编辑':'完成创建'" :description="id?'兑换码编辑完成':'兑换码创建完成'">
  24. <svg-icon icon-class="dot" slot="icon" class="svg-dot"></svg-icon>
  25. </el-step>
  26. </el-steps>
  27. </div>
  28. <div class="create-bottom">
  29. <el-form :model="organizeForm" :rules="rulesOrganize" ref="organizeForm" label-width="100px" class="registerForm" v-if="stepIndex===0">
  30. <el-form-item label="兑换码名称" prop="name">
  31. <el-input v-model="organizeForm.name" placeholder="请输入兑换码名称" @blur="handleTrim('organizeForm','name')" maxlength="20"></el-input>
  32. <p class="tips">不超过20个字</p>
  33. </el-form-item>
  34. <el-form-item label="可使用人数" prop="person_count_max" class="price-box" v-if="type===0">
  35. <el-input-number v-model="organizeForm.person_count_max" @change="handleChange" :min="0" :max="500" size="small" class="personal-ceil"></el-input-number>
  36. <span class="append">人</span>
  37. <p class="tips">最多不超过 500 次</p>
  38. </el-form-item>
  39. <el-form-item label="有效期" prop="valid_day_count" class="validity-box">
  40. <el-input placeholder="请输入内容" v-model="organizeForm.valid_day_count" type="number" :min="1" maxlength="20">
  41. <template slot="append">天</template>
  42. </el-input>
  43. </el-form-item>
  44. <el-form-item label="兑换码" prop="subcode_import_file_id" v-if="type===1">
  45. <div class="article-mp3-box">
  46. <ul v-if="organizeForm.subcode_import_file_list&&organizeForm.subcode_import_file_list.length>0" class="article-mp3-list">
  47. <li v-for="(item,index) in organizeForm.subcode_import_file_list" :key="index">
  48. <a><svg-icon :icon-class="'txt'" class="icon-logo"></svg-icon><span>{{item.name}}</span></a>
  49. <i class="el-icon-error" @click="handleDelResource(index)"></i>
  50. </li>
  51. </ul>
  52. <upload :class="['article-mp3']" :datafileList="organizeForm.subcode_import_file_list" :changeFillId="handleAvatarSuccess" :fileName="'articleMp3'" uploadType="txt" tips=' ' :filleNumber="1" :showList="true" />
  53. </div>
  54. </el-form-item>
  55. <el-form-item label="备注" prop="memo">
  56. <el-input
  57. type="textarea"
  58. :rows="4"
  59. placeholder="请输入"
  60. v-model="organizeForm.memo"
  61. maxlength="200"
  62. show-word-limit>
  63. </el-input>
  64. </el-form-item>
  65. </el-form>
  66. <div v-if="stepIndex===1">
  67. <div class="issue-top">
  68. <h4 class="issue-top-left">
  69. 内容列表
  70. </h4>
  71. <el-button type="primary" size="small" @click="addGoods">添加内容</el-button>
  72. </div>
  73. <el-table
  74. class="search-table"
  75. :data="tableData"
  76. style="width: 100%"
  77. @sort-change="handleSort"
  78. :default-sort = dataSort
  79. :max-height="tableHeight"
  80. v-loading="tableLoading">
  81. <el-table-column
  82. type="index"
  83. label="#"
  84. sortable
  85. width="54"
  86. :index="(pageNumber-1)*pageSize+1">
  87. </el-table-column>
  88. <el-table-column
  89. prop="goods_name"
  90. label="名称"
  91. sortable="custom">
  92. </el-table-column>
  93. <el-table-column
  94. prop="goods_type"
  95. label="类型"
  96. sortable="custom"
  97. width="150" >
  98. <template slot-scope="scope">
  99. <span class="items-type" :style="{background:goodsTypeListCss[scope.row.goods_type]?goodsTypeListCss[scope.row.goods_type].bg:'', color:goodsTypeListCss[scope.row.goods_type]?goodsTypeListCss[scope.row.goods_type].color:''}">{{scope.row.goods_type_name}}</span>
  100. </template>
  101. </el-table-column>
  102. <el-table-column
  103. prop="goods_study_phase"
  104. label="学段"
  105. sortable="custom"
  106. width="120">
  107. <template slot-scope="scope">
  108. {{scope.row.goods_study_phase_name}}
  109. </template>
  110. </el-table-column>
  111. <el-table-column
  112. fixed="right"
  113. label="操作"
  114. width="180">
  115. <template slot-scope="scope">
  116. <el-button
  117. @click.native.prevent="handleDelete(scope.row, scope.$index)"
  118. type="text"
  119. size="small"
  120. class="red-btn">
  121. 删除
  122. </el-button>
  123. </template>
  124. </el-table-column>
  125. </el-table>
  126. <el-pagination
  127. background
  128. @size-change="handleSizeChange"
  129. @current-change="handleCurrentChange"
  130. :current-page="pageNumber"
  131. :page-sizes="[10, 20, 30, 40]"
  132. :page-size="pageSize"
  133. layout="total, prev, pager, next, sizes, jumper"
  134. :total="total_count">
  135. </el-pagination>
  136. </div>
  137. <div v-if="stepIndex===2">
  138. <el-result icon="success" :subTitle="id?'兑换码编辑成功':'兑换码创建成功'">
  139. <template slot="extra">
  140. <el-button size="small" @click="handleback">返回列表</el-button>
  141. <el-button type="primary" size="small" @click="handleCreate">继续创建</el-button>
  142. </template>
  143. </el-result>
  144. </div>
  145. </div>
  146. </div>
  147. </div>
  148. </div>
  149. </template>
  150. <script>
  151. //这里可以导入其它文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
  152. //例如:import 《组件名称》from ‘《组件路径》';
  153. import Header from "../../components/Header.vue";
  154. import NavMenu from "../../components/NavMenu.vue"
  155. import Breadcrumb from '../../components/Breadcrumb.vue';
  156. import { getLogin } from "@/api/ajax";
  157. import Upload from "../../components/Upload.vue"
  158. export default {
  159. //import引入的组件需要注入到对象中才能使用
  160. components: { Header, NavMenu, Breadcrumb, Upload },
  161. props: {},
  162. data() {
  163. //这里存放数据
  164. const validateValidity = (rule, value, callback) => {
  165. if (value === '') {
  166. callback(new Error('请输入有效期'));
  167. } else {
  168. if (value<1) {
  169. callback(new Error('请输入有效期'));
  170. } else {
  171. callback();
  172. }
  173. }
  174. };
  175. return {
  176. goodsTypeListCss:{
  177. 2:{
  178. text:'报纸',
  179. color:'#165DFF',
  180. bg:'#E8F7FF'
  181. },
  182. // '2':{
  183. // text:'画刊',
  184. // color:'#F53F3F',
  185. // bg:'#FFECE8'
  186. // },
  187. '3':{
  188. text:'精读',
  189. color:'#0FC6C2',
  190. bg:'#E8FFFB'
  191. },
  192. 0:{
  193. text:'课程',
  194. color:'#722ED1',
  195. bg:'#F5E8FF'
  196. },
  197. 1:{
  198. text:'课程',
  199. color:'#722ED1',
  200. bg:'#F5E8FF'
  201. },
  202. 10:{
  203. text:'课程',
  204. color:'#722ED1',
  205. bg:'#F5E8FF'
  206. },
  207. // '5':{
  208. // text:'报纸专辑',
  209. // color:'#165DFF',
  210. // bg:'#E8F7FF'
  211. // },
  212. // '6':{
  213. // text:'画刊专辑',
  214. // color:'#F53F3F',
  215. // bg:'#FFECE8'
  216. // }
  217. },
  218. activeMenuIndex: "cdkey_manage",
  219. breadcrumbList:[
  220. {
  221. icon:'barcode-line',
  222. url:'',
  223. text:''
  224. },
  225. {
  226. icon:'',
  227. url:'',
  228. text:'兑换码管理'
  229. }
  230. ],
  231. id:this.$route.query.id?this.$route.query.id:'',
  232. organizeForm:{
  233. name: '',
  234. person_count_max: 50,
  235. valid_day_count: 30,
  236. memo: '',
  237. subcode_import_file_list: [],
  238. subcode_import_file_id: '',
  239. type: this.$route.query.type?this.$route.query.type*1:0
  240. },
  241. rulesOrganize:{
  242. name:[
  243. { required: true, message: '请输入兑换码名称', trigger: 'blur' },
  244. { max: 20, message: '兑换码名称最多20位', trigger:'change' },
  245. ],
  246. person_count_max:[
  247. { required: true, message: '请输入可使用人数', trigger: 'blur' }
  248. ],
  249. valid_day_count:[
  250. { required: true, validator: validateValidity, trigger: 'blur' }
  251. ],
  252. subcode_import_file_id:[
  253. { required: true, message: '请上传兑换码文件', trigger: 'blur' }
  254. ],
  255. },
  256. stepIndex:window.localStorage.getItem('cdKeyId')?1:0, // 步骤索引
  257. loading: false,
  258. cdKeyId: window.localStorage.getItem('cdKeyId')?window.localStorage.getItem('cdKeyId'):'',
  259. tableLoading: false,
  260. pageSize: 10,
  261. pageNumber: 1,
  262. tableHeight: "", // 表格高度
  263. total_count: 0,
  264. dataSort: {},
  265. tableData: [],
  266. type: this.$route.query.type?this.$route.query.type*1:0,
  267. }
  268. },
  269. //计算属性 类似于data概念
  270. computed: {
  271. },
  272. //监控data中数据变化
  273. watch: {
  274. },
  275. //方法集合
  276. methods: {
  277. // 删除
  278. handleDelete(row){
  279. this.$confirm('确定删除吗?', '提示', {
  280. confirmButtonText: '确定',
  281. cancelButtonText: '取消',
  282. type: 'warning'
  283. }).then(() => {
  284. let Mname = "/ShopServer/Manager/DiscountCodeManager/DeleteGoodsFromDiscountCode";
  285. let data = {
  286. discount_code_id: this.cdKeyId,
  287. goods_type: row.goods_type,
  288. goods_id: row.goods_id
  289. };
  290. getLogin(Mname, data).then(res => {
  291. this.$message({
  292. type: 'success',
  293. message: '删除成功!'
  294. });
  295. this.getGoodsList()
  296. });
  297. }).catch(() => {
  298. });
  299. },
  300. // 删除资源文件
  301. handleDelResource(i){
  302. this.$confirm("确定删除吗?", "提示", {
  303. confirmButtonText: "确定",
  304. cancelButtonText: "取消",
  305. type: "warning",
  306. }).then(() => {
  307. this.organizeForm.subcode_import_file_list.splice(i, 1);
  308. this.organizeForm.subcode_import_file_id = ''
  309. this.$forceUpdate()
  310. });
  311. },
  312. handleAvatarSuccess(fileList,name) {
  313. this.organizeForm.subcode_import_file_list = fileList
  314. this.organizeForm.subcode_import_file_id = fileList[0]&&fileList[0].response&&fileList[0].response.file_info_list&&fileList[0].response.file_info_list[0]?fileList[0].response.file_info_list[0].file_id:''
  315. this.$forceUpdate()
  316. },
  317. handleSizeChange(val) {
  318. this.pageSize = val
  319. this.pageNumber = 1
  320. this.getGoodsList()
  321. },
  322. handleCurrentChange(val) {
  323. this.pageNumber = val
  324. this.getGoodsList()
  325. },
  326. handleSort(value){
  327. let dataSort = {
  328. prop: value.prop,
  329. order: value.order
  330. }
  331. this.dataSort = dataSort
  332. this.getGoodsList()
  333. },
  334. // 上一步下一步
  335. handleStep(type){
  336. if(type=='-'){
  337. // if(this.stepIndex>0) this.stepIndex--
  338. }else{
  339. if(this.stepIndex===0) {
  340. this.$refs['organizeForm'].validate((valid) => {
  341. if (valid) {
  342. this.handleCreateCdkey()
  343. } else {
  344. return false;
  345. }
  346. });
  347. }else if(this.stepIndex===1){
  348. this.stepIndex++
  349. }
  350. }
  351. },
  352. changeIcon(flag){
  353. this[flag] = !this[flag]
  354. },
  355. // 返回列表
  356. handleback(){
  357. localStorage.setItem("pageNumber",1)
  358. this.$router.push({
  359. path: "/cdkey_manage",
  360. query: {
  361. },
  362. });
  363. },
  364. //继续创建
  365. handleCreate(){
  366. window.localStorage.removeItem('cdKeyId')
  367. this.$router.replace('/createCdkey')
  368. location.reload()
  369. },
  370. handleChange(value) {
  371. // console.log(value)
  372. },
  373. handleCreateCdkey(){
  374. this.loading = true
  375. let MethodName = "/ShopServer/Manager/DiscountCodeManager/CreateDiscountCode";
  376. let form = this.organizeForm
  377. let data = form
  378. getLogin(MethodName, data)
  379. .then((res) => {
  380. this.loading = false
  381. if(res.status===1){
  382. this.cdKeyId = res.id
  383. this.stepIndex++
  384. window.localStorage.removeItem('cdKeyId')
  385. this.getGoodsList()
  386. }
  387. })
  388. .catch(() => {
  389. this.loading = false
  390. });
  391. },
  392. // 去掉前后空格
  393. handleTrim(form,fild){
  394. this[form][fild] = this[form][fild].trim()
  395. },
  396. getGoodsList(){
  397. this.tableLoading = true
  398. let MethodName = "/ShopServer/Manager/DiscountCodeManager/PageQueryDiscountCodeGoodsList";
  399. let order_column_list = []
  400. if(this.dataSort != {}){
  401. if(this.dataSort.order=='descending'){
  402. order_column_list = [this.dataSort.prop + ':desc']
  403. }else if(this.dataSort.order=='ascending'){
  404. // 升序不传值
  405. order_column_list = [this.dataSort.prop]
  406. }else{
  407. order_column_list = ['create_time:desc']
  408. }
  409. }else{
  410. order_column_list = ['create_time:desc']
  411. }
  412. let data = {
  413. discount_code_id: this.cdKeyId,
  414. page_capacity:this.pageSize,
  415. cur_page:this.pageNumber,
  416. order_column_list: order_column_list
  417. }
  418. getLogin(MethodName, data)
  419. .then((res) => {
  420. this.tableLoading = false
  421. if(res.status===1){
  422. this.tableData = res.goods_list
  423. this.total_count = res.total_count
  424. }
  425. })
  426. .catch(() => {
  427. this.tableLoading = false
  428. });
  429. },
  430. // 添加商品
  431. addGoods(){
  432. window.localStorage.setItem('cdKeyId',this.cdKeyId)
  433. this.$router.push({
  434. path:'/addGoods'
  435. })
  436. },
  437. //计算table高度(动态设置table高度)
  438. getTableHeight() {
  439. let tableH = 460; //距离页面下方的高度
  440. let tableHeightDetil = window.innerHeight - tableH;
  441. if (tableHeightDetil <= 300) {
  442. this.tableHeight = 300;
  443. } else {
  444. this.tableHeight = window.innerHeight - tableH;
  445. }
  446. },
  447. },
  448. //生命周期 - 创建完成(可以访问当前this实例)
  449. created() {
  450. let obj = {
  451. icon:'',
  452. url:'',
  453. text:'创建兑换码'
  454. }
  455. if(this.id){
  456. obj.text = '编辑兑换码'
  457. // this.getCourseInfo()
  458. }
  459. this.breadcrumbList.push(obj)
  460. this.getTableHeight()
  461. if(this.stepIndex===1){
  462. this.getGoodsList()
  463. }
  464. },
  465. //生命周期 - 挂载完成(可以访问DOM元素)
  466. mounted() {
  467. },
  468. //生命周期-创建之前
  469. beforeCreated() { },
  470. //生命周期-挂载之前
  471. beforeMount() { },
  472. //生命周期-更新之前
  473. beforUpdate() { },
  474. //生命周期-更新之后
  475. updated() { },
  476. //生命周期-销毁之前
  477. beforeDestory() { },
  478. //生命周期-销毁完成
  479. destoryed() { },
  480. //如果页面有keep-alive缓存功能,这个函数会触发
  481. activated() { }
  482. }
  483. </script>
  484. <style lang="scss" scoped>
  485. /* @import url(); 引入css类 */
  486. .create-top{
  487. background: #FFFFFF;
  488. border-radius: 4px;
  489. padding: 24px;
  490. .common-title-box{
  491. margin-bottom: 4px;
  492. }
  493. }
  494. .create-bottom{
  495. padding: 40px 40px;
  496. margin-top: 16px;
  497. background: #FFFFFF;
  498. border-radius: 4px;
  499. height: calc(100vh - 292px);
  500. overflow: auto;
  501. .tips{
  502. margin: 0;
  503. color: #86909C;
  504. font-size: 12px;
  505. line-height: 20px;
  506. }
  507. .issue-top{
  508. display: flex;
  509. justify-content: space-between;
  510. margin-bottom: 8px;
  511. &-left{
  512. margin: 0;
  513. color: #1D2129;
  514. font-size: 20px;
  515. font-weight: 500;
  516. line-height: 28px;
  517. span{
  518. margin-left: 4px;
  519. color: #86909C;
  520. font-size: 14px;
  521. font-weight: 400;
  522. line-height: 22px;
  523. }
  524. }
  525. }
  526. }
  527. .items-type{
  528. padding: 1px 8px;
  529. font-weight: 500;
  530. font-size: 14px;
  531. line-height: 22px;
  532. border-radius: 2px;
  533. }
  534. .article-mp3-box{
  535. display: flex;
  536. height: 32px;
  537. align-items: center;
  538. }
  539. .article-mp3{
  540. width: 82px;
  541. height: 32px;
  542. font-size: 0;
  543. &-has{
  544. width: 320px;
  545. }
  546. }
  547. .article-mp3-list{
  548. list-style: none;
  549. margin: 0;
  550. padding: 0;
  551. display: inline-block;
  552. width: 226px;
  553. li{
  554. padding: 5px 12px;
  555. height: 32px;
  556. border-radius: 2px 0px 0px 2px;
  557. background: #F2F3F5;
  558. display: flex;
  559. align-items: center;
  560. a{
  561. color: #1D2129;
  562. display: flex;
  563. align-items: center;
  564. flex: 1;
  565. span{
  566. overflow:hidden;
  567. text-overflow:ellipsis;
  568. white-space: nowrap;
  569. flex: 1;
  570. display: block;
  571. font-size: 14px;
  572. line-height: 22px;
  573. width: 163px;
  574. }
  575. .svg-icon{
  576. width: 16px;
  577. height: 16px;
  578. margin-right: 4px;
  579. color: #1D2129;
  580. }
  581. }
  582. .el-icon-error{
  583. color: #4E5969;
  584. cursor: pointer;
  585. margin-left: 4px;
  586. }
  587. }
  588. }
  589. </style>
  590. <style lang="scss">
  591. .cdkey-create{
  592. .personal-ceil{
  593. width: 200px;
  594. .el-input__inner{
  595. width: 200px;
  596. padding: 0 60px;
  597. }
  598. }
  599. .el-range-input{
  600. background: #F2F3F5;
  601. }
  602. .el-tag{
  603. background: #fff;
  604. }
  605. .validity-box{
  606. width: 350px;
  607. .el-input-group{
  608. width: 250px;
  609. }
  610. .el-input-group__append{
  611. border: none;
  612. border-left: 1px solid #E5E6EB;
  613. background: #F2F3F5;
  614. }
  615. }
  616. .price-box{
  617. width: 300px;
  618. display: inline-block;
  619. .el-form-item__content{
  620. position: relative;
  621. .prepend,.append{
  622. position: absolute;
  623. left: 44px;
  624. font-size: 14px;
  625. line-height: 22px;
  626. color: #1D2129;
  627. line-height: 34px;
  628. }
  629. .append{
  630. left: 142px;
  631. }
  632. }
  633. }
  634. }
  635. .el-date-picker__editor-wrap{
  636. .el-input, .el-textarea{
  637. width: auto;
  638. }
  639. }
  640. </style>