Edit.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. <!--
  2. * @Description:
  3. * @Version: 1.0
  4. * @Autor: zhuyijun
  5. * @Date: 2021-11-29 22:13:51
  6. * @LastEditTime: 2022-02-20 18:54:19
  7. -->
  8. <template>
  9. <div>
  10. <!-- 面包屑导航区 -->
  11. <el-breadcrumb separator-class="el-icon-arrow-right">
  12. <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
  13. <el-breadcrumb-item>商品管理</el-breadcrumb-item>
  14. <el-breadcrumb-item :to="{path:'/goods'}">商品列表</el-breadcrumb-item>
  15. <el-breadcrumb-item>编辑商品</el-breadcrumb-item>
  16. </el-breadcrumb>
  17. <!-- 卡片区 -->
  18. <el-card>
  19. <!-- 提示区域 -->
  20. <el-alert title="添加商品信息"
  21. center
  22. show-icon
  23. :closable="false"
  24. type="info">
  25. </el-alert>
  26. <!-- 步骤条 -->
  27. <el-steps :space="200"
  28. :active="activeIndex - 0"
  29. finish-status="success"
  30. align-center>
  31. <el-step title="基本信息"></el-step>
  32. <el-step title="商品参数"></el-step>
  33. <el-step title="商品属性"></el-step>
  34. <el-step title="商品图片"></el-step>
  35. <el-step title="商品内容"></el-step>
  36. <el-step title="完成"></el-step>
  37. </el-steps>
  38. <el-form :model="editForm"
  39. :rules="editFormRules"
  40. ref="editFormRef"
  41. label-width="100px"
  42. label-position="top">
  43. <!-- tab栏区域 -->
  44. <el-tabs v-model="activeIndex"
  45. :tab-position="tabPosition"
  46. :before-leave="beforeTabLeave"
  47. @tab-click="tabClicked">
  48. <el-tab-pane label="基本信息"
  49. name="0">
  50. <el-form-item label="商品名称"
  51. prop="goods_name">
  52. <el-input v-model="editForm.goods_name"></el-input>
  53. </el-form-item>
  54. <el-form-item label="商品价格"
  55. prop="goods_price">
  56. <el-input v-model="editForm.goods_price"></el-input>
  57. </el-form-item>
  58. <el-form-item label="商品重量"
  59. prop="goods_weight">
  60. <el-input v-model="editForm.goods_weight"></el-input>
  61. </el-form-item>
  62. <el-form-item label="商品数量"
  63. prop="goods_number">
  64. <el-input v-model="editForm.goods_number"></el-input>
  65. </el-form-item>
  66. <el-form-item label="商品分类"
  67. prop="goods_cat">
  68. <el-cascader v-model="editForm.goods_cat"
  69. :options="cateList"
  70. :props="cateProps"
  71. @change="handleChange"></el-cascader>
  72. </el-form-item>
  73. </el-tab-pane>
  74. <el-tab-pane label="商品参数"
  75. name="1">
  76. <!-- 渲染表单的Item项 -->
  77. <el-form-item v-for="item in manyTableData"
  78. :key="item.attr_id+''"
  79. :label="item.attr_name">
  80. <el-checkbox-group v-model="item.attr_vals">
  81. <el-checkbox :label="cb"
  82. v-for="(cb, i) in item.attr_vals"
  83. :key="i+''"></el-checkbox>
  84. </el-checkbox-group>
  85. </el-form-item>
  86. </el-tab-pane>
  87. <el-tab-pane label="商品属性"
  88. name="2">
  89. <!-- 渲染表单的Item项 -->
  90. <el-form-item v-for="item in onlyTableData"
  91. :key="item.attr_id +''"
  92. :label="item.attr_name">
  93. <el-input v-model="item.attr_vals"></el-input>
  94. </el-form-item>
  95. </el-tab-pane>
  96. <el-tab-pane label="商品图片"
  97. name="3">
  98. <!-- 上传图片
  99. action: 表示上传api地址
  100. list-type: 指定预览组件呈现方式
  101. -->
  102. <el-upload :action="uploadURL"
  103. :on-preview="handlePreview"
  104. :on-remove="handleRemove"
  105. list-type="picture"
  106. :headers="headerObj"
  107. :on-success="handleSuccess"
  108. v-model="editForm.pics">
  109. <el-button size="small"
  110. type="primary">点击上传</el-button>
  111. </el-upload>
  112. </el-tab-pane>
  113. <el-tab-pane label="商品内容"
  114. name="4">
  115. <!-- 富文本编辑器 -->
  116. <quill-editor v-model="editForm.goods_introduce">
  117. </quill-editor>
  118. <!-- <editor v-model="editForm.goods_introduce"
  119. :upload-url='uploadURL'></editor> -->
  120. </el-tab-pane>
  121. <el-tab-pane label="完成"
  122. name="5">
  123. <!-- 添加商品按钮 -->
  124. <el-button type="primary"
  125. class="btnedit"
  126. @click="edit">编辑商品</el-button>
  127. </el-tab-pane>
  128. </el-tabs>
  129. </el-form>
  130. </el-card>
  131. <el-dialog title="图片预览"
  132. :visible.sync="previewVisible"
  133. width="75%"
  134. @close="previewClosed">
  135. <img :src="previewPath"
  136. class="previewImg">
  137. </el-dialog>
  138. </div>
  139. </template>
  140. <script>
  141. // import editor from '../markdown/markdown.vue'
  142. export default {
  143. components: {
  144. // editor
  145. },
  146. data () {
  147. return {
  148. activeIndex: 0,
  149. tabPosition: 'left',
  150. editForm: {
  151. goods_id: '',
  152. goods_name: '',
  153. goods_price: 0,
  154. goods_weight: 0,
  155. goods_number: 0,
  156. //商品所属分类数组
  157. goods_cat: [],
  158. // 图片数组
  159. pics: [],
  160. //商品详情描述
  161. goods_introduce: '',
  162. attrs: []
  163. },
  164. editFormRules: {
  165. goods_name: [
  166. { required: true, message: '请输入商品名称', trigger: 'blur' }
  167. ],
  168. goods_price: [
  169. { required: true, message: '请输入商品价格', trigger: 'blur' }
  170. ],
  171. goods_weight: [
  172. { required: true, message: '请输入商品重量', trigger: 'blur' }
  173. ],
  174. goods_number: [
  175. { required: true, message: '请输入商品数量', trigger: 'blur' }
  176. ],
  177. goods_cat: [
  178. { required: true, message: '请选择商品分类', trigger: 'blur' }
  179. ]
  180. },
  181. cateList: [],
  182. cateProps: {
  183. expandTrigger: 'hover',
  184. label: 'cat_name',
  185. value: 'cat_id',
  186. children: 'children'
  187. },
  188. manyTableData: [],
  189. onlyTableData: [],
  190. // 上传图片的url地址
  191. uploadURL: 'http://localhost:8888/api/private/v1/upload',
  192. headerObj: {
  193. Authorization: window.localStorage.getItem('token')
  194. },
  195. previewPath: '',
  196. previewVisible: false,
  197. quillOption: {
  198. }
  199. }
  200. },
  201. created () {
  202. const id = this.$route.query.id
  203. if (id) {
  204. this.editForm.goods_id = id
  205. }
  206. this.getCateList()
  207. this.getGoodById(id)
  208. },
  209. methods: {
  210. async getCateList () {
  211. const { data: res } = await this.$http.get('categories')
  212. if (res.meta.status !== 200) {
  213. this.$message.error(res.meta.msg)
  214. }
  215. this.cateList = res.data
  216. // console.log(res.data)
  217. },
  218. //TODO 商品分类回显代写
  219. //递归设置分类
  220. handlerCate (list, id) {
  221. }
  222. ,
  223. async getGoodById (id) {
  224. const { data: res } = await this.$http.get(`goods/${id}`)
  225. if (res.meta.status !== 200) {
  226. this.$message.error(res.meta.msg)
  227. }
  228. // console.log(res.data)
  229. this.editForm = res.data
  230. },
  231. handleChange () {
  232. if (this.editForm.goods_cat.length !== 3) {
  233. this.editForm.goods_cat.length = []
  234. this.$message.info('请选择三级分类')
  235. }
  236. },
  237. // 监听标签切换
  238. beforeTabLeave (activeName, oldActiveName) {
  239. if (oldActiveName === '0' && this.editForm.goods_cat.length !== 3) {
  240. this.$message.error('请选择商品分类')
  241. return false
  242. }
  243. return true
  244. },
  245. async getManyAttribute () {
  246. const { data: res } = await this.$http.get(`categories/${this.cateId}/attributes`, {
  247. params: { sel: 'many' }
  248. })
  249. if (res.meta.status !== 200) {
  250. this.$message.error(res.meta.msg)
  251. }
  252. res.data.forEach(item => {
  253. let vals = item.attr_vals
  254. item.attr_vals = vals.length === 0 ? [] : vals.split(' ')
  255. })
  256. this.manyTableData = res.data
  257. },
  258. async getOnlyAttribute () {
  259. const { data: res } = await this.$http.get(`categories/${this.cateId}/attributes`, {
  260. params: { sel: 'only' }
  261. })
  262. if (res.meta.status !== 200) {
  263. this.$message.error(res.meta.msg)
  264. }
  265. // res.data.forEach(item => {
  266. // let vals = item.attr_vals
  267. // item.attr_vals = vals.length === 0 ? [] : vals.split(' ')
  268. // })
  269. this.onlyTableData = res.data
  270. // console.log(res.data)
  271. },
  272. tabClicked () {
  273. switch (this.activeIndex) {
  274. case '1':
  275. this.getManyAttribute()
  276. break
  277. case '2':
  278. this.getOnlyAttribute()
  279. break
  280. case '3': break
  281. case '4': break
  282. default:
  283. }
  284. },
  285. // 处理图片预览效果
  286. handlePreview (file) {
  287. this.previewPath = file.response.data.url
  288. this.previewVisible = true
  289. },
  290. // 处理已出图片操作
  291. handleRemove (file) {
  292. // 1、获取将要删除的图片的临时路径
  293. const filePath = file.response.data.tmp_path
  294. // 2、从pics素组中,找到这个图片的索引值
  295. const i = this.editForm.pics.findIndex(item => item.pic === filePath)
  296. // 3、调用数组的splice方法,把图片信息对象,从pics数组中移除
  297. this.editForm.pics.splice(i, 1)
  298. },
  299. // 监听上传成功的事件
  300. handleSuccess (response) {
  301. //1、拼接得到一个图片信息对象
  302. const picInfo = { pic: response.data.tmp_path }
  303. // 2、将图片信息对象 push到pics数组中
  304. this.editForm.pics.push(picInfo)
  305. },
  306. previewClosed () {
  307. this.previewPath = ''
  308. },
  309. // 编辑商品函数
  310. edit () {
  311. this.$refs.editFormRef.validate(async (valid) => {
  312. if (!valid) return this.$message.error('请填写必要的表单项!')
  313. // 深拷贝
  314. let form = JSON.parse(JSON.stringify(this.editForm))
  315. form.goods_cat = form.goods_cat.join(',')
  316. // 处理动态参数
  317. this.manyTableData.forEach(item => {
  318. const attrInfo = {
  319. attr_id: item.attr_id,
  320. attr_value: item.attr_vals.join(' ')
  321. }
  322. form.attrs.push(attrInfo)
  323. })
  324. // 处理静态属性
  325. this.onlyTableData.forEach(item => {
  326. const attrInfo = {
  327. attr_id: item.attr_id,
  328. attr_value: item.attr_vals
  329. }
  330. form.attrs.push(attrInfo)
  331. })
  332. // 商品名称唯一
  333. // 执行添加逻辑
  334. const { data: res } = await this.$http.put(`goods/${form.goods_id}`, form)
  335. if (res.meta.status !== 201) {
  336. this.$message.error(res.meta.msg)
  337. }
  338. this.$message.success(res.meta.msg)
  339. })
  340. }
  341. },
  342. computed: {
  343. cateId () {
  344. if (this.editForm.goods_cat.length === 3) {
  345. return this.editForm.goods_cat[2]
  346. }
  347. return null
  348. }
  349. }
  350. }
  351. </script>
  352. <style lang="less" scoped>
  353. .el-checkbox {
  354. margin: 0 10px 0 0 !important;
  355. }
  356. .previewImg {
  357. width: 100%;
  358. }
  359. .btnedit {
  360. margin-top: 15px;
  361. }
  362. </style>