information.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. <template>
  2. <div class="info-layout">
  3. <edit
  4. :name="'账号信息'"
  5. @clickOper="handleOper('infoStatus')"
  6. :oper="infoStatus?'编辑':'收起'"
  7. :isActive="infoStatus"
  8. >
  9. <div class="info" slot="show">
  10. <p>头像</p>
  11. <img class="avatar" :src="info.head" alt>
  12. <p>昵称</p>
  13. <div>{{info.nickName}}</div>
  14. </div>
  15. <div class="info edit-info" slot="edit">
  16. <div class="info-left">
  17. <p>头像</p>
  18. <img class="avatar" :src="info.head" alt>
  19. <p>昵称</p>
  20. <input
  21. autofocus
  22. v-model="editinfo.nickName"
  23. placeholder="输入昵称"
  24. class="nickname"
  25. type="text"
  26. >
  27. <div @click="saveNickName" class="btn parmary">保存</div>
  28. </div>
  29. <div>
  30. <div class="btn choose">
  31. <input class="el-upload" ref="uploadInput" name="file" type="file" @change="update">
  32. <span>选择图片</span>
  33. </div>
  34. <p class="p-desc">请选择一张新照片进行上传</p>
  35. <p class="p-desc">支持图片格式为:JPG/PNG</p>
  36. <p class="p-desc">推荐分辨率为:512*512px,大小不大于1MB</p>
  37. </div>
  38. </div>
  39. </edit>
  40. <edit
  41. :name="'我的收货地址'"
  42. @clickOper="handleOper('addressStatus')"
  43. :oper="addressStatus?'编辑':'收起'"
  44. :isActive="addressStatus"
  45. >
  46. <div class="address" slot="show">
  47. <template v-if="address.shipName">
  48. <p>
  49. <span>{{address.shipName}}</span>
  50. <span>{{address.shipMobile}}</span>
  51. </p>
  52. <p class="p-desc">{{`${address.shipAreaPath}${address.shipAddress}`}}</p>
  53. </template>
  54. <template v-else>
  55. <p class="p-desc">暂无信息</p>
  56. </template>
  57. </div>
  58. <div class="address edit-address" slot="edit">
  59. <div class="input-con">
  60. <input type="text" v-model="editAdd.shipName" :placeholder="'姓名'">
  61. <input type="text" v-model="editAdd.shipMobile" :placeholder="'电话'">
  62. </div>
  63. <div class="input-con">
  64. <citySelect :areaPath="editAdd.shipAreaPath" @currentVal="getCurrentSelect"/>
  65. </div>
  66. <div class="input-con address-input">
  67. <input
  68. type="text"
  69. v-model="editAdd.shipAddress"
  70. :placeholder="'详细地址'"
  71. >
  72. </div>
  73. <div class="btn parmary" @click="uAddress">保存</div>
  74. </div>
  75. </edit>
  76. <edit
  77. :name="'我的发票抬头'"
  78. @clickOper="handleOper('invoiceStatus')"
  79. :oper="invoiceStatus?'编辑':'收起'"
  80. :isActive="invoiceStatus"
  81. >
  82. <div class="invoice" slot="show">
  83. <p class="p-desc">{{invoice2.title||invoice3.title||'暂无信息'}}</p>
  84. </div>
  85. <div class="invoice edit-invoice" slot="edit">
  86. <div class="select-con">
  87. <div :class="{'tag-active':cInvoice==='normal'}" @click="cInvoice='normal'">
  88. <span>增值税普通发票</span>
  89. <img src="@/assets/images/tag-icon.png" alt>
  90. </div>
  91. <div :class="{'tag-active':cInvoice==='zengzhi'}" @click="cInvoice='zengzhi'">
  92. <span>增值税专用发票</span>
  93. <i></i>
  94. <img src="@/assets/images/tag-icon.png" alt>
  95. </div>
  96. </div>
  97. <div v-if="cInvoice==='normal'">
  98. <div class="input-con">
  99. <input type="text" placeholder="请输入发票抬头" v-model="editInvoice2.title">
  100. <input type="text" placeholder="请输入税务登记号(个人用户可不填)" v-model="editInvoice2.code">
  101. </div>
  102. </div>
  103. <div v-else>
  104. <div class="input-con">
  105. <input type="text" v-model="invoice3.title" placeholder="请输入发票抬头">
  106. <input type="text" v-model="invoice3.code" placeholder="请输入税务登记号(个人用户可不填)">
  107. </div>
  108. <div class="input-con">
  109. <input type="text" v-model="invoice3.organizedAddress" placeholder="注册地址">
  110. <input type="text" v-model="invoice3.registerPhone" placeholder="注册电话">
  111. </div>
  112. <div class="input-con">
  113. <input type="text" v-model="invoice3.bankName" placeholder="开户银行">
  114. <input type="text" v-model="invoice3.bankAccount" placeholder="银行账户">
  115. </div>
  116. </div>
  117. <div @click="saveInvoice(cInvoice)" class="btn parmary">保存</div>
  118. </div>
  119. </edit>
  120. </div>
  121. </template>
  122. <script>
  123. import { mapState } from 'vuex'
  124. import edit from '@/components/edit'
  125. import citySelect from '@/components/citySelect'
  126. var cloneObj = function (obj) {
  127. var newObj = {}
  128. if (obj instanceof Array) {
  129. newObj = []
  130. }
  131. for (var key in obj) {
  132. var val = obj[key] || ''
  133. newObj[key] = typeof val === 'object' ? cloneObj(val) : val
  134. }
  135. return newObj
  136. }
  137. export default {
  138. components: { edit, citySelect },
  139. computed: {
  140. ...mapState({
  141. info: state => state.user.info,
  142. editinfo: state => cloneObj(state.user.info),
  143. token: state => state.user.token,
  144. invoice2: state => {
  145. let type = Object.prototype.toString.call(state.user.invoice2)
  146. if (type === '[object Object]') {
  147. return state.user.invoice2
  148. }
  149. let condition = state.user.invoice2 && state.user.invoice2 !== 'null' && type !== '[object Array]'
  150. return (condition ? JSON.parse(state.user.invoice2) : {})
  151. },
  152. editInvoice2: state => {
  153. let type = Object.prototype.toString.call(state.user.invoice2)
  154. if (type === '[object Object]') {
  155. return state.user.invoice2
  156. }
  157. let condition = state.user.invoice2 && state.user.invoice2 !== 'null' && type !== '[object Array]'
  158. return cloneObj(condition ? JSON.parse(state.user.invoice2) : {})
  159. },
  160. invoice3: state => {
  161. let type = Object.prototype.toString.call(state.user.invoice3)
  162. if (type === '[object Object]') {
  163. return state.user.invoice3
  164. }
  165. let condition = state.user.invoice3 && state.user.invoice3 !== 'null' && type !== '[object Array]'
  166. return (condition ? JSON.parse(state.user.invoice3) : {})
  167. },
  168. editInvoice3: state => {
  169. let type = Object.prototype.toString.call(state.user.invoice3)
  170. if (type === '[object Object]') {
  171. return state.user.invoice3
  172. }
  173. let condition = state.user.invoice3 && state.user.invoice3 !== 'null' && type !== '[object Array]'
  174. return cloneObj(condition ? JSON.parse(state.user.invoice3) : {})
  175. },
  176. address: state => state.user.address || {},
  177. editAdd: state => cloneObj(state.user.address) || {}
  178. })
  179. },
  180. data () {
  181. return {
  182. infoStatus: true,
  183. addressStatus: true,
  184. invoiceStatus: true,
  185. cInvoice: 'normal',
  186. tempSelect: '',
  187. addre: []
  188. }
  189. },
  190. methods: {
  191. handleOper (type) {
  192. this[type] = !this[type]
  193. },
  194. getCurrentSelect (data) {
  195. this.tempSelect = data
  196. },
  197. async saveNickName () {
  198. if (this.editinfo.nickName.trim()) {
  199. let res = await this.$http
  200. .post(
  201. '/user/updateNickName',
  202. { nickName: this.editinfo.nickName },
  203. {
  204. headers: {
  205. token: this.token
  206. }
  207. }
  208. )
  209. let data = res.data
  210. if (data.code === 0) {
  211. this.infoStatus = true
  212. this.$store.dispatch('getInfo', {url: '/user/getUserInfo', name: 'info'})
  213. } else {
  214. this.$toast.show('warn', '修改失败')
  215. }
  216. } else {
  217. return this.$toast.show('warn', '昵称不能为空')
  218. }
  219. },
  220. saveInvoice (cInvoice) {
  221. let isObject = function (obj) {
  222. return JSON.stringify(obj) === '{}' ? '' : obj
  223. }
  224. let params = {}
  225. let invoiceType = ''
  226. if (cInvoice === 'normal') {
  227. invoiceType = 2
  228. params = {
  229. invoiceType,
  230. title: isObject(this.editInvoice2.title),
  231. code: isObject(this.editInvoice2.code)
  232. }
  233. } else {
  234. let {title, code, organizedAddress, registerPhone, bankName, bankAccount} = this.editInvoice3
  235. invoiceType = 3
  236. params = {
  237. invoiceType: isObject(invoiceType),
  238. title: isObject(title),
  239. code: isObject(code),
  240. organizedAddress: isObject(organizedAddress),
  241. registerPhone: isObject(registerPhone),
  242. bankName: isObject(bankName),
  243. bankAccount: isObject(bankAccount)
  244. }
  245. }
  246. this.$http
  247. .post('user/invoice/save', params, {
  248. headers: {
  249. token: this.token
  250. }
  251. })
  252. .then(data => {
  253. this.invoiceStatus = true
  254. this.$store.dispatch('getInvoice', {
  255. type: invoiceType,
  256. params: {
  257. invoiceType: invoiceType
  258. }
  259. })
  260. })
  261. },
  262. uAddress () {
  263. this.editAdd.province = this.tempSelect[0]
  264. this.editAdd.city = this.tempSelect[1]
  265. this.editAdd.shipAreaPath = this.tempSelect.join(',')
  266. let {
  267. shipAddress,
  268. shipAreaPath,
  269. province,
  270. city,
  271. shipMobile,
  272. shipName
  273. } = this.editAdd
  274. let params = {
  275. shipAddress,
  276. shipAreaPath,
  277. province,
  278. city,
  279. shipMobile,
  280. shipName
  281. }
  282. this.$http
  283. .post('/user/updateAddress', params, {
  284. headers: {
  285. token: this.token
  286. }
  287. })
  288. .then(data => {
  289. this.addressStatus = true
  290. this.$store.dispatch('getInfo', {
  291. url: '/user/getReceiverInfo',
  292. name: 'address'
  293. })
  294. })
  295. },
  296. update (e) {
  297. let file = e.target.files[0]
  298. let type = file.type.toLowerCase()
  299. if (type !== 'image/jpeg' && type !== 'image/png') {
  300. return this.$toast.show('warn', '上传的图片类型不正确,请重新上传')
  301. }
  302. let token = this.token
  303. let config = {
  304. headers: {
  305. token
  306. }
  307. } // 添加请求头
  308. var reader = new FileReader()
  309. reader.onload = async e => {
  310. let imgdata = e.target.result
  311. this.$http.post('/user/uploadHead', { imgdata }, config).then(data => {
  312. this.info.head = data.data.msg
  313. localStorage.setItem('info', JSON.stringify(this.info))
  314. })
  315. }
  316. reader.readAsDataURL(file)
  317. }
  318. },
  319. watch: {},
  320. mounted () {
  321. this.$store.dispatch('getInfo', {
  322. url: '/user/getReceiverInfo',
  323. name: 'address'
  324. })
  325. Object.keys(this.invoice2).length === 0 && this.$store.dispatch('getInvoice', {
  326. type: 2,
  327. params: {
  328. invoiceType: 2
  329. }
  330. })
  331. Object.keys(this.invoice3).length === 0 && this.$store.dispatch('getInvoice', {
  332. type: 3,
  333. params: {
  334. invoiceType: 3
  335. }
  336. })
  337. }
  338. }
  339. </script>
  340. <style lang="scss" scoped>
  341. .info-layout {
  342. $theme-color: #1fe4dc;
  343. $border-color: #e7e7e7;
  344. width: 90%;
  345. padding-bottom: 100px;
  346. input {
  347. appearance: none;
  348. line-height: 36px;
  349. height: 36px;
  350. border: solid 1px $border-color;
  351. padding-left: 10px;
  352. &:focus {
  353. border: solid 1px $theme-color;
  354. }
  355. }
  356. .btn {
  357. text-align: center;
  358. cursor: pointer;
  359. }
  360. .parmary {
  361. background-color: $theme-color;
  362. width: 126px;
  363. height: 36px;
  364. line-height: 36px;
  365. margin-top: 20px;
  366. }
  367. .choose {
  368. background-color: #ddd;
  369. color: #fff;
  370. width: 100px;
  371. line-height: 26px;
  372. height: 26px;
  373. font-size: 12px;
  374. margin: 12px 0 20px;
  375. }
  376. .info,
  377. .address,
  378. .invoice {
  379. margin-top: 20px;
  380. p {
  381. line-height: 36px;
  382. span {
  383. padding-right: 10px;
  384. }
  385. }
  386. .p-desc {
  387. color: #a0a0a0;
  388. line-height: 24px;
  389. }
  390. .avatar {
  391. width: 68px;
  392. height: 68px;
  393. box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4);
  394. margin: 5px 0;
  395. }
  396. .nickname {
  397. width: 126px;
  398. }
  399. }
  400. .edit-info {
  401. display: flex;
  402. .info-left {
  403. min-width: 210px;
  404. }
  405. .choose {
  406. cursor: pointer;
  407. position: relative;
  408. .el-upload {
  409. position: absolute;
  410. top: 0;
  411. left: 0;
  412. opacity: 0;
  413. line-height: 1;
  414. cursor: pointer;
  415. height: 100%;
  416. z-index: 10;
  417. width: 100%;
  418. padding: 0;
  419. margin: 0;
  420. font-size: 0;
  421. display: inline-block;
  422. }
  423. span {
  424. cursor: pointer;
  425. }
  426. }
  427. }
  428. .edit-address {
  429. .input-con {
  430. input {
  431. width: 200px;
  432. line-height: 36px;
  433. height: 36px;
  434. margin: 10px 25px 10px 0;
  435. }
  436. }
  437. .address-input {
  438. input {
  439. width: 660px;
  440. }
  441. }
  442. }
  443. .edit-invoice {
  444. .select-con {
  445. div {
  446. position: relative;
  447. cursor: pointer;
  448. width: 200px;
  449. line-height: 36px;
  450. height: 36px;
  451. margin: 10px 25px 10px 0;
  452. border: solid 1px $border-color;
  453. color: #a0a0a0;
  454. padding: 0 10px;
  455. display: inline-block;
  456. img {
  457. display: none;
  458. position: absolute;
  459. bottom: 0;
  460. right: 0;
  461. }
  462. }
  463. .tag-active {
  464. border: solid 1px $theme-color;
  465. color: #000;
  466. img {
  467. display: inline-block;
  468. }
  469. }
  470. }
  471. .input-con {
  472. input {
  473. width: 316px;
  474. line-height: 36px;
  475. height: 36px;
  476. margin: 10px 25px 10px 0;
  477. }
  478. }
  479. }
  480. }
  481. </style>