online-exam-form.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. <template>
  2. <el-form
  3. v-loading="loading"
  4. ref="ruleForm"
  5. :model="ruleForm"
  6. status-icon
  7. :rules="rulesThis"
  8. :label-width="labelWidth || '100px'"
  9. class="demo-ruleForm"
  10. :size="size || 'medium'"
  11. >
  12. <el-row>
  13. <el-col :span="24" style="padding: 0 0 20px 0">
  14. <el-row>
  15. <el-col :span="20">
  16. <el-alert
  17. title="特别关注:手动到对接平台修改商品信息,会被本系统强制覆盖,请谨慎操作!"
  18. type="error"
  19. show-icon
  20. description=""
  21. :size="'mini'"
  22. :closable="false"
  23. >
  24. </el-alert
  25. ></el-col>
  26. <el-col :span="4">
  27. <el-button
  28. v-if="!isDetail"
  29. :size="'mini'"
  30. type="primary"
  31. class="fr"
  32. @click="submitForm()"
  33. >保 存
  34. </el-button>
  35. </el-col>
  36. </el-row>
  37. </el-col>
  38. <el-col :span="6"
  39. ><el-form-item label="审核状态" prop="exam_status">
  40. <el-radio-group
  41. v-model="ruleForm.exam_status"
  42. placeholder="请选择审核状态"
  43. style="width: 100%"
  44. :size="size || 'medium'"
  45. @change="exam_statusChange"
  46. >
  47. <el-radio
  48. v-for="item in exam_statusList"
  49. :key="item.value"
  50. :label="item.value"
  51. >{{ item.label }}</el-radio
  52. >
  53. </el-radio-group>
  54. </el-form-item>
  55. </el-col>
  56. <el-col :span="18" v-if="String(ruleForm.exam_status) === '1'">
  57. <el-row>
  58. <el-col :span="24">
  59. <el-form-item label="有赞公用分类" prop="yz_cat_id" label-width="120px">
  60. <good-class-youzan
  61. :value="ruleForm.yz_cat_id"
  62. :placeholder="'请选择分类'"
  63. @handleChange="handleChange"
  64. />
  65. </el-form-item>
  66. </el-col>
  67. <!-- <el-col :span="11">
  68. <el-form-item label="是否可退货" prop="is_support_barter" label-width="120px">
  69. <el-radio-group
  70. v-model="ruleForm.is_support_barter"
  71. placeholder="请选择是否可退货"
  72. style="width: 100%"
  73. :size="'mini'"
  74. >
  75. <el-radio
  76. v-for="item in is_support_barter_list"
  77. :key="item.value"
  78. :label="item.value"
  79. >{{ item.label }}</el-radio
  80. >
  81. </el-radio-group>
  82. </el-form-item>
  83. </el-col> -->
  84. <!-- <el-col :span="24">
  85. <el-form-item label="允许购买用户标签" prop="tags" label-width="130px">
  86. <el-select
  87. v-model="ruleForm.tags"
  88. multiple
  89. placeholder="请选择"
  90. style="width: 100%"
  91. >
  92. <el-option
  93. v-for="item in tags_options"
  94. :key="item.name + item.tag_id"
  95. :label="item.name"
  96. :value="item.name"
  97. >
  98. </el-option>
  99. </el-select>
  100. </el-form-item>
  101. </el-col> -->
  102. </el-row>
  103. </el-col>
  104. <el-col
  105. :span="24"
  106. v-show="String(ruleForm.exam_status) === '1'"
  107. style="padding: 0 0 10px 0"
  108. >
  109. <el-row>
  110. <el-col :span="6">
  111. <el-form-item label="商品类型" prop="item_type">
  112. <el-select
  113. v-model="ruleForm.item_type"
  114. placeholder="请选择商品类型"
  115. style="width: 100%"
  116. >
  117. <el-option
  118. v-for="item in item_type_options"
  119. :key="item.label + item.value"
  120. :label="item.label"
  121. :value="item.value"
  122. :disabled="String(item.status) === '0'"
  123. >
  124. </el-option>
  125. </el-select>
  126. </el-form-item>
  127. </el-col>
  128. <el-col :span="10">
  129. <el-form-item label="开始出售时间" prop="time" label-width="120px">
  130. <ul class="item_auto_listing_time clearfix">
  131. <li class="fl" style="width: 100px">
  132. <el-radio
  133. v-model="ruleForm.item_auto_listing_time"
  134. label="0"
  135. @change="item_auto_change"
  136. >立即出售</el-radio
  137. >
  138. </li>
  139. <li class="fl">
  140. <el-date-picker
  141. v-model="ruleForm.auto_listing_time"
  142. type="datetime"
  143. style="width: 100%"
  144. value-format="yyyy-MM-dd HH:mm:ss"
  145. placeholder="选择开始出售时间"
  146. default-time="12:00:00"
  147. @change="time_change"
  148. :picker-options="pickerOptions"
  149. >
  150. </el-date-picker>
  151. </li>
  152. </ul>
  153. </el-form-item>
  154. </el-col>
  155. <el-col :span="8">
  156. <el-form-item label="划线价" prop="origin">
  157. <digital-input
  158. :values="ruleForm.origin"
  159. :placeholder="'起订量'"
  160. :min="0"
  161. :max="100000000000"
  162. :position="'right'"
  163. :precision="2"
  164. :controls="false"
  165. :append="''"
  166. :newTime="''"
  167. :size="''"
  168. :disabled="false"
  169. @reschange="num_change($event, 'origin', -1)"
  170. />
  171. </el-form-item>
  172. </el-col>
  173. <el-col :span="24">
  174. <el-form-item label-width="120px" prop="distribution" label="支持的配送方式">
  175. <el-checkbox-group v-model="ruleForm.distribution" @change="handleChange">
  176. <el-checkbox label="1" key="1">快递发货</el-checkbox>
  177. <el-checkbox label="2" key="2" >同城配送</el-checkbox>
  178. <el-checkbox label="3" key="3">到店自提</el-checkbox>
  179. </el-checkbox-group>
  180. </el-form-item>
  181. </el-col>
  182. </el-row>
  183. </el-col>
  184. <el-col
  185. :span="24"
  186. v-show="String(ruleForm.exam_status) === '1'"
  187. style="padding: 0 0 10px 0"
  188. >
  189. <!-- @current-change="handleCurrentChange" -->
  190. <el-table
  191. :data="nakelist"
  192. :size="'mini'"
  193. border
  194. stripe
  195. highlight-current-row
  196. ref="singleTable"
  197. >
  198. <el-table-column label="系统阶梯" width="80px">
  199. <template slot-scope="scope">
  200. <i
  201. v-if="currentRow && String(currentRow.id) === String(scope.row.id)"
  202. class="el-icon-check"
  203. style="color: #1890ff; font-size: 16px; font-weight: bolder"
  204. /> </template
  205. ></el-table-column>
  206. <el-table-column prop="min_num" label="采购起订量" />
  207. <el-table-column label="销售">
  208. <el-table-column prop="start_sale_num" label="起订量">
  209. <template slot-scope="scope">
  210. <span>
  211. {{ scope.row.start_sale_num }}
  212. </span>
  213. </template>
  214. </el-table-column>
  215. <el-table-column prop="sale_good_price" label="系统售价" />
  216. <el-table-column prop="sale_cost_fee" label="系统工艺费" />
  217. <el-table-column prop="final_price" label="最终售价">
  218. <template slot-scope="scope">
  219. <digital-input
  220. v-show="scope.row.edit"
  221. :values="scope.row.final_price"
  222. :placeholder="'最终售价'"
  223. :min="scope.row.sale_good_price"
  224. :max="9999999"
  225. :position="'right'"
  226. :precision="2"
  227. :controls="false"
  228. :append="''"
  229. :newTime="scope.row.newTime"
  230. :size="'mini'"
  231. :disabled="false"
  232. @reschange="num_change($event, 'final_price', scope.$index)"
  233. />
  234. <span v-show="!scope.row.edit">
  235. {{ scope.row.final_price }}
  236. </span>
  237. </template>
  238. </el-table-column>
  239. </el-table-column>
  240. </el-table>
  241. </el-col>
  242. <el-col :span="18" v-show="ruleForm.exam_status + '' !== '1'">
  243. <el-form-item label="审核备注" prop="reject_reason">
  244. <el-input
  245. type="textarea"
  246. placeholder="审核备注"
  247. v-model="ruleForm.reject_reason"
  248. :disabled="disabled"
  249. maxlength="250"
  250. show-word-limit
  251. :autosize="{ minRows: 3, maxRows: 3 }"
  252. />
  253. </el-form-item>
  254. </el-col>
  255. </el-row>
  256. </el-form>
  257. </template>
  258. <script>
  259. import asyncRequest from "@/apis/service/youzan/othgoodsOnline";
  260. import { item_type_options } from "../columns";
  261. export default {
  262. name: "exam-form",
  263. props: ["size", "statusList", "disabled", "isMust", "labelWidth", "time", "sitem"],
  264. /**
  265. * 属性集合
  266. * @param {String} size : 组件大小 非必填
  267. * @param {Array} statusList : 驳回至备选项 必填
  268. * @param {Boolean} disabled : 是否禁用 必填
  269. * @param {Boolean} isMust : 是否需要展示驳回节点 必填
  270. */
  271. /**
  272. * 事件集合
  273. * @searchChange : 选中值变化调用 抛出选中数据
  274. */
  275. data() {
  276. const validatetime = (rule, value, callback) => {
  277. const { item_auto_listing_time, auto_listing_time } = this.ruleForm;
  278. const type = item_auto_listing_time ?? "";
  279. const time = auto_listing_time ?? "";
  280. // console.log(item_auto_listing_time, auto_listing_time);
  281. if (type === "" && time === "") {
  282. callback(new Error("请选择开始出售时间!"));
  283. } else {
  284. callback();
  285. }
  286. };
  287. const validate_num_0 = (rule, value, callback) => {
  288. const val = value ?? "";
  289. const { required } = rule;
  290. if (required && val === "") {
  291. callback(new Error("不能为空!"));
  292. } else if (
  293. required &&
  294. (val === "0" ||
  295. val === "0." ||
  296. val === "0.0" ||
  297. val === "0.00" ||
  298. val === "0.000")
  299. ) {
  300. callback(new Error("不能为零!"));
  301. } else {
  302. callback();
  303. }
  304. };
  305. return {
  306. platform_id: "",
  307. spuCode: "",
  308. loading: true,
  309. currentRow: null,
  310. nakelist: [],
  311. tags_options: [],
  312. item_type_options,
  313. exam_statusList: [
  314. {
  315. value: "1",
  316. label: "通过",
  317. },
  318. {
  319. value: "2",
  320. label: "驳回",
  321. },
  322. ],
  323. is_support_barter_list: [
  324. {
  325. value: "1",
  326. label: "支持",
  327. },
  328. {
  329. value: "0",
  330. label: "不支持",
  331. },
  332. ],
  333. showModelThis: this.showModel,
  334. pickerOptions: {
  335. disabledDate: (time) => {
  336. return time.getTime() < new Date().valueOf() - 1000 * 60 * 60 * 24;
  337. },
  338. },
  339. ruleForm: {
  340. exam_status: "1", // 通过or驳回
  341. yz_cat_id: [],
  342. rebut: "", //驳回至
  343. reject_reason: "",
  344. tags: [],
  345. item_type: "0",
  346. item_auto_listing_time: "0",
  347. auto_listing_time: "",
  348. origin: "0",
  349. time: "0",
  350. distribution: ['1']
  351. },
  352. rulesThis: this.rules,
  353. rules: {
  354. exam_status: [
  355. {
  356. required: true,
  357. message: "请选择审核状态",
  358. trigger: "change",
  359. },
  360. ],
  361. is_support_barter: [
  362. {
  363. required: false,
  364. message: "请选择是否可退",
  365. trigger: "change",
  366. },
  367. ],
  368. tags: [
  369. {
  370. required: false,
  371. type: "array",
  372. trigger: "change",
  373. },
  374. ],
  375. yz_cat_id: [
  376. {
  377. required: true,
  378. type: "array",
  379. message: "请选择有赞公用分类",
  380. trigger: "change",
  381. },
  382. ],
  383. reject_reason: [
  384. { required: true, message: "请输入审核备注", trigger: "blur" },
  385. {
  386. min: 1,
  387. max: 250,
  388. message: "长度在 1 到 250 个字符",
  389. trigger: "blur",
  390. },
  391. ],
  392. origin: [
  393. {
  394. required: true,
  395. validator: validate_num_0,
  396. trigger: "blur",
  397. },
  398. ],
  399. time: [
  400. {
  401. required: true,
  402. validator: validatetime,
  403. trigger: "change,blur",
  404. },
  405. ],
  406. item_type: [
  407. {
  408. required: true,
  409. message: "请选择商品类型",
  410. trigger: "change",
  411. },
  412. ],
  413. },
  414. };
  415. },
  416. watch: {
  417. isDetail: function (val, old) {
  418. if (this.isDetail !== val) {
  419. this.options = [];
  420. this.selectLoading = false;
  421. }
  422. },
  423. newTime: function (val) {
  424. if (val) {
  425. this.initForm();
  426. }
  427. },
  428. },
  429. mounted() {
  430. this.initForm();
  431. },
  432. methods: {
  433. handleChange(values){
  434. console.log(values)
  435. },
  436. async initForm() {
  437. // this.loading = true;
  438. this.rulesThis = this.rules;
  439. await this.resetForm();
  440. this.exam_statusChange();
  441. await this.get_tags();
  442. const { nakelist, spuCode, platform_id } = this.sitem;
  443. this.spuCode = spuCode;
  444. this.platform_id = platform_id;
  445. console.log(this.sitem);
  446. this.nakelist = JSON.parse(JSON.stringify(nakelist));
  447. this.nakelist.forEach(async (si, sii) => {
  448. si.start_sale_num = si.min_num;
  449. let { isok, price, sale_cost_fee } = await this.get_new(sii);
  450. if (isok === 0) {
  451. this.nakelist[sii].sale_good_price = price;
  452. this.nakelist[sii].sale_cost_fee = sale_cost_fee;
  453. this.nakelist[sii].newTime = new Date().valueOf() + "";
  454. } else if (isok >= 100 && isok <= 104) {
  455. await this.logout();
  456. } else {
  457. this.nakelist[sii].sale_good_price = price;
  458. this.nakelist[sii].sale_cost_fee = sale_cost_fee;
  459. this.nakelist[sii].newTime = new Date().valueOf() + "";
  460. }
  461. this.$set(this.nakelist, sii, this.nakelist[sii]);
  462. });
  463. // this.setCurrent(this.nakelist[0]);
  464. let index = this.nakelist.findIndex((e) => e.min_num + "" === "1");
  465. if (index !== -1) {
  466. this.handleCurrentChange(this.nakelist[index]);
  467. }
  468. this.loading = false;
  469. },
  470. item_auto_change() {
  471. const { item_auto_listing_time } = this.ruleForm;
  472. if (String(item_auto_listing_time) === "0") {
  473. }
  474. this.ruleForm.auto_listing_time =
  475. String(item_auto_listing_time) === "0" ? "" : this.ruleForm.auto_listing_time;
  476. this.ruleForm.time =
  477. this.ruleForm.item_auto_listing_time || this.ruleForm.auto_listing_time;
  478. this.$refs.ruleForm.validateField("time");
  479. },
  480. time_change() {
  481. const { auto_listing_time } = this.ruleForm;
  482. this.ruleForm.item_auto_listing_time = String(auto_listing_time) === "" ? "0" : "";
  483. this.ruleForm.time =
  484. this.ruleForm.item_auto_listing_time || this.ruleForm.auto_listing_time;
  485. this.$refs.ruleForm.validateField("time");
  486. },
  487. async get_tags() {
  488. const { code, data, message } = await asyncRequest.tag_list({});
  489. if (code === 0) {
  490. this.tags_options = data;
  491. } else if (code >= 100 && code <= 104) {
  492. this.tags_options = [];
  493. await this.logout();
  494. } else {
  495. this.tags_options = [];
  496. this.$message.warning(message);
  497. }
  498. },
  499. exam_statusChange() {
  500. const { exam_status } = this.ruleForm;
  501. const isok = String(exam_status) === "1";
  502. // this.rulesThis.is_support_barter[0].required = isok;
  503. this.rulesThis.yz_cat_id[0].required = isok;
  504. this.rulesThis.item_type[0].required = isok;
  505. this.rulesThis.time[0].required = isok;
  506. this.rulesThis.origin[0].required = isok;
  507. this.rulesThis.reject_reason[0].required = !isok;
  508. },
  509. num_change(e, key, index) {
  510. if (index === -1) {
  511. // console.log(key, e);
  512. this.ruleForm[key] = e;
  513. this.$refs.ruleForm.validateField(key);
  514. } else {
  515. this.nakelist[index][key] = e;
  516. this.nakelist[index].newTime = new Date().valueOf() + "";
  517. // this.$set(this.nakelist, index, this.nakelist[index]);
  518. }
  519. },
  520. handleChange(e) {
  521. this.ruleForm.yz_cat_id = e;
  522. this.$refs.ruleForm.validateField("yz_cat_id");
  523. },
  524. // setCurrent(row) {
  525. // this.$refs.singleTable.setCurrentRow(row);
  526. // },
  527. async get_new(index) {
  528. console.log(index);
  529. const { min_num } = this.nakelist[index];
  530. const { code, data, message } = await asyncRequest.goodupprice({
  531. min_num: min_num,
  532. platform_id: this.platform_id,
  533. spuCode: this.spuCode,
  534. });
  535. const resModel = {
  536. isok: code,
  537. price: code === 0 ? data.sale_price : "0",
  538. sale_cost_fee: code === 0 ? data.new_cost_fee : "0",
  539. message: message,
  540. };
  541. return resModel;
  542. },
  543. handleCurrentChange(val) {
  544. this.currentRow = val;
  545. const { id } = val;
  546. this.nakelist.forEach((si, sii) => {
  547. this.nakelist[sii].edit = false;
  548. if (id && id === si.id) {
  549. this.nakelist[sii].edit = true;
  550. }
  551. this.$set(this.nakelist, sii, this.nakelist[sii]);
  552. });
  553. },
  554. async resetForm() {
  555. // 重置
  556. await this.$nextTick(() => {
  557. if (this.$refs.ruleForm) {
  558. this.$refs.ruleForm.resetFields();
  559. this.$refs.ruleForm.clearValidate();
  560. this.ruleForm = {
  561. exam_status: "1", // 通过or驳回
  562. yz_cat_id: [],
  563. is_support_barter: "1",
  564. reject_reason: "",
  565. tags: [],
  566. item_type: "0",
  567. item_auto_listing_time: "0",
  568. auto_listing_time: "",
  569. origin: "0",
  570. time: "0",
  571. };
  572. }
  573. });
  574. },
  575. async submitForm() {
  576. await this.$refs.ruleForm.validate(async (valid) => {
  577. if (valid) {
  578. if (this.loading) return;
  579. await this.$confirm(`确定要提交?`, {
  580. confirmButtonText: "确定",
  581. cancelButtonText: "取消",
  582. type: "warning",
  583. })
  584. .then(async () => {
  585. this.loading = true;
  586. let model = JSON.parse(JSON.stringify(this.ruleForm));
  587. const {
  588. yz_cat_id,
  589. item_auto_listing_time,
  590. auto_listing_time,
  591. origin,
  592. } = this.ruleForm;
  593. // console.log(yz_cat_id);
  594. model.platform_youzan_id = this.sitem.platform_youzan_id;
  595. model.yz_cat_id = "";
  596. model.good_ladder_id = "";
  597. model.final_price = "";
  598. model.start_sale_num = "";
  599. const { exam_status } = this.ruleForm;
  600. const isok = String(exam_status) === "1";
  601. if (isok) {
  602. const { id } = this.currentRow;
  603. if (!id) {
  604. this.$message.warning("请选择一个系统阶梯!");
  605. this.loading = false;
  606. return;
  607. }
  608. let is_ok = true;
  609. this.nakelist.forEach((e) => {
  610. if (e.sale_good_price + "" === "0" && e.sale_cost_fee + "" === "0") {
  611. is_ok = false;
  612. }
  613. });
  614. if (!is_ok) {
  615. this.$message.warning("暂无系统售价,请设置毛利率!");
  616. this.loading = false;
  617. return;
  618. }
  619. let index = this.nakelist.findIndex((si) => si.id === id);
  620. const {
  621. min_num,
  622. start_sale_num,
  623. sale_good_price,
  624. sale_cost_fee,
  625. final_price,
  626. } = this.nakelist[index];
  627. if (parseInt(start_sale_num) < parseInt(min_num)) {
  628. this.$message.warning("销售起订量不小于采购起订量!");
  629. this.loading = false;
  630. return;
  631. }
  632. if (!final_price) {
  633. this.$message.warning("最终售价不能为空!");
  634. this.loading = false;
  635. return;
  636. }
  637. if (sale_good_price * 100 > final_price * 100) {
  638. this.$message.warning("销售起订量不小于采购起订量!");
  639. this.loading = false;
  640. return;
  641. }
  642. let am = 0;
  643. const m = auto_listing_time ?? "",
  644. nm = new Date().valueOf(),
  645. fp = final_price * 100,
  646. op = origin * 100;
  647. if (m !== "0") {
  648. am = new Date(auto_listing_time).valueOf();
  649. }
  650. if (am !== 0 && nm >= am) {
  651. this.$message.warning("开始出售时间不能小于当前时间!");
  652. this.loading = false;
  653. return;
  654. }
  655. if (op < fp) {
  656. this.$message.warning("划线价不能小于最终售价!");
  657. this.loading = false;
  658. return;
  659. }
  660. model.platform_youzan_id = this.sitem.platform_youzan_id;
  661. model.yz_cat_id = yz_cat_id[yz_cat_id.length - 1];
  662. model.good_ladder_id = id;
  663. model.final_price = final_price;
  664. model.start_sale_num = start_sale_num;
  665. model.auto_listing_time =
  666. model.time !== "0" ? new Date(model.time).valueOf() : "0";
  667. delete model["time"];
  668. delete model["item_auto_listing_time"];
  669. }
  670. const { code, message } = await asyncRequest.goodupexam(model);
  671. if (code === 0) {
  672. this.$notify.success({
  673. title: "提交成功!",
  674. message: "",
  675. });
  676. this.$emit("searchChange");
  677. } else if (code >= 100 && code <= 104) {
  678. await this.logout();
  679. } else {
  680. this.$message.warning(message);
  681. }
  682. })
  683. .catch(() => {
  684. console.log("取消");
  685. });
  686. } else {
  687. console.log("error submit!!");
  688. return false;
  689. }
  690. });
  691. },
  692. async setstatus(model) {},
  693. },
  694. };
  695. </script>
  696. <style>
  697. .item_auto_listing_time .fl:last-child {
  698. width: calc(100% - 115px);
  699. }
  700. </style>