form.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <template>
  2. <el-drawer :title="titleMap[mode]" :append-to-body="true" v-model="visible" :size="1000" destroy-on-close :close-on-click-modal="false" @closed="$emit('closed')" :with-header="false">
  3. <el-container class="flex-column" v-loading="loading">
  4. <div class="drawer-detail-main">
  5. <div class="drawer-detail-header">
  6. <div class="drawer-detail-header-body">
  7. <div class="drawer-detail-header-left">{{ titleMap[mode] }}</div>
  8. <div class="drawer-detail-header-left">
  9. <el-button type="default" icon="el-icon-close" @click="visible=false"></el-button>
  10. </div>
  11. </div>
  12. </div>
  13. </div>
  14. <el-main>
  15. <el-form ref="dialogForm" :model="formData" :rules="rules" label-width="100px" label-position="top">
  16. <fieldset>
  17. <legend><el-tag>基础信息</el-tag></legend>
  18. <el-row :gutter="15">
  19. <el-col :span="24">
  20. <el-form-item label="所属店铺" prop="store_id">
  21. <el-input v-model="formData.store_id" placeholder="所属店铺" clearable readonly :style="{ width: '100%' }" @click="selectUser">
  22. <template #append>
  23. <el-tooltip
  24. effect="dark"
  25. content="点这里,清除选择"
  26. placement="top-start"
  27. >
  28. <div class="remove-a" @click="clearUser">清除</div>
  29. </el-tooltip>
  30. </template>
  31. </el-input>
  32. </el-form-item>
  33. </el-col>
  34. <el-col :span="12">
  35. <el-form-item label="商品标题" prop="product_name">
  36. <el-input v-model="formData.product_name" clearable placeholder="请输入"></el-input>
  37. <div class="el-form-item-msg"></div>
  38. </el-form-item>
  39. </el-col>
  40. <el-col :span="12">
  41. <el-form-item label="快递面单名称" prop="express_name">
  42. <el-input v-model="formData.express_name" clearable placeholder="请输入"></el-input>
  43. <div class="el-form-item-msg">不填写默认使用商品标题名称</div>
  44. </el-form-item>
  45. </el-col>
  46. <el-col :span="8">
  47. <el-form-item label="来客团单ID" prop="out_id">
  48. <el-input v-model="formData.out_id" clearable placeholder="请输入"></el-input>
  49. <div class="el-form-item-msg"></div>
  50. </el-form-item>
  51. </el-col>
  52. <el-col :span="8">
  53. <el-form-item label="商品价格" prop="product_price">
  54. <el-input v-model="formData.product_price" clearable placeholder="请输入">
  55. <template #append>元</template>
  56. </el-input>
  57. <div class="el-form-item-msg"></div>
  58. </el-form-item>
  59. </el-col>
  60. <el-col :span="8">
  61. <el-form-item label="商品划线价格" prop="product_origin">
  62. <el-input v-model="formData.product_origin" clearable placeholder="请输入">
  63. <template #append>元</template>
  64. </el-input>
  65. <div class="el-form-item-msg"></div>
  66. </el-form-item>
  67. </el-col>
  68. <el-col :span="24">
  69. <el-form-item label="商品图片" prop="product_img">
  70. <sc-upload v-model="formData.product_img" tip="最多上传100个文件,单个文件不要超过10M,请上传图像格式文件"></sc-upload>
  71. <div class="el-form-item-msg">选填</div>
  72. </el-form-item>
  73. </el-col>
  74. </el-row>
  75. </fieldset>
  76. <fieldset>
  77. <legend><el-tag>商品附加规格</el-tag></legend>
  78. <el-button type="primary" size="small" @click="addSpecs" v-if="specs.length<5">添加规格分组</el-button>
  79. <div class="specs" v-for="(item,indx) in specs" :key="indx">
  80. <div class="specs-header">
  81. <div class="specs-left">
  82. <el-input v-model="item.name" placeholder="组名称" clearable>
  83. <template #prepend>组名称</template>
  84. </el-input>
  85. <el-select v-model="item.num" clearable placeholder="请选择数量" v-if="item.list.length > 1">
  86. <el-option :value="len" :label="item.list.length+'选'+len" v-for="len in item.list.length"></el-option>
  87. </el-select>
  88. </div>
  89. <div class="specs-right">
  90. <el-button type="primary" @click="addItem(indx)">增加</el-button>
  91. <el-button type="danger" @click="removeSpec(indx)">删除</el-button>
  92. </div>
  93. </div>
  94. <div class="specs-body">
  95. <div class="body-item" v-for="(its,ind) in item.list" :key="ind">
  96. <div class="item-img"><sc-upload v-model="its.img"></sc-upload></div>
  97. <el-input placeholder="输入规格属性名" v-model="its.name" clearable>
  98. <template #append>
  99. <el-button type="danger" @click="removeItem(indx,ind)" icon="el-icon-delete" size="small"></el-button>
  100. </template>
  101. </el-input>
  102. </div>
  103. </div>
  104. </div>
  105. </fieldset>
  106. </el-form>
  107. </el-main>
  108. <el-footer style="text-align: right;">
  109. <el-button @click="visible=false" >取 消</el-button>
  110. <el-button v-if="mode!='show'" type="primary" :loading="isSaveing" @click="submit()">保 存</el-button>
  111. </el-footer>
  112. </el-container>
  113. </el-drawer>
  114. <storeData ref="storeData" :multiple="false" @success="handleSuccess"></storeData>
  115. </template>
  116. <script>
  117. import storeData from "@/views/manage/components/store";
  118. export default {
  119. components: {
  120. storeData
  121. },
  122. data(){
  123. return {
  124. loading: false,
  125. mode:"add",
  126. titleMap:{
  127. add:"新增商品",
  128. edit:"编辑商品"
  129. },
  130. visible: false,
  131. isSaveing: false,
  132. specs:[],
  133. formData:{},
  134. rules:{
  135. store_id: [
  136. {required: true, message: '请选择'}
  137. ],
  138. out_id: [
  139. {required: true, message: '请输入'}
  140. ],
  141. product_name: [
  142. {required: true, message: '请输入'}
  143. ],
  144. product_price: [
  145. {required: true, message: '请输入'}
  146. ],
  147. product_origin: [
  148. {required: true, message: '请输入'}
  149. ],
  150. }
  151. }
  152. },
  153. methods:{
  154. addSpecs(){
  155. if (this.specs.length >= 5) {
  156. return this.$message.error("最多只能添加三组规格")
  157. }
  158. this.specs.push({"name":"","num":1,"list":[ {"name":"","img":"","check":true} ]});
  159. },
  160. addItem(index){
  161. if (this.specs[index].list.length >= 20) {
  162. return this.$message.error("最多只能添加20个")
  163. }
  164. this.specs[index].list.push({"name":"","img":"","check":true})
  165. },
  166. removeSpec(index){
  167. this.specs.splice(index,1)
  168. },
  169. removeItem(index,sub){
  170. this.specs[index].list.splice(sub,1)
  171. },
  172. handleSuccess(data){
  173. this.formData.store_id = data.store_id;
  174. },
  175. clearUser(){
  176. this.formData.store_id = "";
  177. },
  178. selectUser(){
  179. this.$nextTick(() => {
  180. this.$refs.storeData.open()
  181. })
  182. },
  183. open(mode = 'add'){
  184. this.mode = mode;
  185. this.visible = true;
  186. return this
  187. },
  188. //表单注入数据
  189. setData(data){
  190. this.formData = JSON.parse(JSON.stringify(data));
  191. if (this.mode == 'edit') {
  192. this.specs = data.data_specs?data.data_specs:[];
  193. }
  194. },
  195. async submit(){
  196. var validate = await this.$refs.dialogForm.validate().catch(()=>{});
  197. if(!validate){ return false }
  198. this.isSaveing = true;
  199. let submitData = JSON.parse(JSON.stringify(this.formData));
  200. if (this.specs.length > 0) {
  201. submitData.data_specs = JSON.stringify(this.specs);
  202. }
  203. var resp = await this.$API.goods.save.post(submitData);
  204. this.isSaveing = false;
  205. if (resp.code == 0) {
  206. return this.$message.error(resp.msg);
  207. }
  208. this.$message.success(resp.msg);
  209. this.visible = false;
  210. this.formData = {};
  211. this.specs = [];
  212. this.submitState = false;
  213. this.$emit("success");
  214. }
  215. }
  216. }
  217. </script>
  218. <style>
  219. .specs{margin-top: 15px;background-color: #f8f8f8;}
  220. .specs-header{
  221. display: flex;
  222. margin-bottom: 10px;
  223. border-bottom: 1px solid #f8f8f8;
  224. background-color: #ddd;
  225. padding: 10px;
  226. }
  227. .specs-header .specs-left{
  228. display: flex;
  229. align-items: center;
  230. gap: 10px;
  231. }
  232. .specs-header .specs-right{
  233. display: flex;
  234. margin-left: auto;
  235. margin-right: 0;
  236. }
  237. .specs-body{display: flex;align-items: center;gap: 10px;padding: 10px;flex-direction: row;flex-wrap: wrap;}
  238. .specs-body .body-item{width: calc(25% - 10px);border: 1px solid #ddd;padding: 5px;display: flex;align-items: center;justify-content: center;flex-direction: column;}
  239. .item-img{margin-bottom: 5px;}
  240. </style>