index.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. <template>
  2. <div id="commodityManageMent">
  3. <search-box-new
  4. ref="searchBox"
  5. :formData="formData"
  6. :formList="formList"
  7. @search="search"
  8. @init="init"
  9. :topType="topType"
  10. />
  11. <table-list
  12. ref="tableList"
  13. :tableSets="tableSet"
  14. :tableData="tableData"
  15. :navText="navText"
  16. @addClick="addClick"
  17. :loading="loading"
  18. @editInfo="editInfo"
  19. @openClassNum="openClassNum"
  20. rowKey="goodsId"
  21. >
  22. <template slot="customize">
  23. <el-button
  24. size="medium"
  25. v-if="isShowCopy"
  26. @click="handelCopy"
  27. type="success"
  28. >商品复制</el-button
  29. >
  30. <el-button size="medium" @click="handelBatch(1)" type="success"
  31. >批量上架</el-button
  32. >
  33. <el-button size="medium" @click="handelBatch(0)" type="success"
  34. >批量下架</el-button
  35. >
  36. <el-button size="medium" @click="handelBatch(2)" type="warning"
  37. >批量删除</el-button
  38. >
  39. </template>
  40. <template slot="btn" slot-scope="props">
  41. <el-button
  42. v-if="
  43. props.scope.row.goodsType == 1 &&
  44. props.scope.row.courseNum &&
  45. props.scope.row.courseNum > 0 &&
  46. props.scope.row.goodsLearningOrder == 0
  47. "
  48. type="text"
  49. @click="setTeacher(props.scope.row)"
  50. >双师制设置</el-button
  51. ><el-button
  52. v-if="props.scope.row.examRecord"
  53. type="text"
  54. @click="$refs.dayPracticeSet.open(props.scope.row.goodsId)"
  55. >每日一练设置</el-button
  56. >
  57. <el-button type="text" @click="addClick(props.scope.row, 0)"
  58. >修改</el-button
  59. >
  60. <el-button type="text" @click="changeStatus(props.scope.row)">{{
  61. props.scope.row.goodsStatus === 1 ? "下架" : "上架"
  62. }}</el-button>
  63. <el-button
  64. type="text"
  65. v-if="props.scope.row.specTemplateId"
  66. @click="cancelBind(props.scope.row.goodsId, 0)"
  67. >取消绑定</el-button
  68. >
  69. <el-button type="text" @click="del(props.scope.row)">删除</el-button>
  70. </template>
  71. </table-list>
  72. <pagination
  73. :total="total"
  74. :pageSize="formData.pageSize"
  75. :currentPage="formData.pageNum"
  76. @handleSizeChange="handleSizeChange"
  77. @handleCurrentChange="handleCurrentChange"
  78. />
  79. <el-dialog
  80. :visible.sync="dialogVisible"
  81. width="1000px"
  82. :show-close="false"
  83. :close-on-click-modal="false"
  84. >
  85. <div slot="title" class="hearders">
  86. <div class="leftTitle">关联商品规格</div>
  87. <div class="rightBoxs">
  88. <img
  89. src="@/assets/images/Close@2x.png"
  90. alt=""
  91. @click="dialogVisible = false"
  92. />
  93. </div>
  94. </div>
  95. <div style="margin-bottom: 10px">
  96. <!-- 搜索框 -->
  97. <el-input
  98. style="width: 230px; margin: 0px 10px"
  99. size="small"
  100. v-model="specFormData.templateName"
  101. placeholder="商品规格模板名称"
  102. ></el-input>
  103. <el-button
  104. size="small"
  105. type="primary"
  106. @click="searchGoodsSpecList(specFormData.goodsId)"
  107. >查询</el-button
  108. >
  109. </div>
  110. <table-list
  111. :tableSets="dialogTableSet"
  112. :tableData="dialogTableData"
  113. :navText="dialogNavText"
  114. :radio.sync="tableRadio"
  115. >
  116. </table-list>
  117. <span slot="footer" class="dialog-footer">
  118. <el-button @click="dialogVisible = false">取 消</el-button>
  119. <el-button type="primary" @click="submit">确 定</el-button>
  120. </span>
  121. </el-dialog>
  122. <Day-practice-set-dialog ref="dayPracticeSet"></Day-practice-set-dialog>
  123. <Base-dialog
  124. title="商品复制机构选择"
  125. :isShow.sync="dialogCopyVisible"
  126. @submit="goodsCopy"
  127. :disabledBtn="copyLoading"
  128. >
  129. <el-radio-group v-model="tenantId">
  130. <el-radio
  131. style="display: block; margin-bottom: 10px"
  132. :label="item.tenantId"
  133. v-for="item in tenantList"
  134. :key="item.tenantId"
  135. >{{ item.tenantName }}</el-radio
  136. >
  137. </el-radio-group>
  138. </Base-dialog>
  139. </div>
  140. </template>
  141. <script>
  142. import searchBoxNew from "@/components/searchBoxNew";
  143. import tableList from "@/components/tableList";
  144. import pagination from "@/components/pagination";
  145. import DayPracticeSetDialog from "./DayPracticeSetDialog.vue";
  146. import {
  147. getGoodsSpecList,
  148. goodsUpdateSpec,
  149. goodsUpdateStatus,
  150. goodsDel,
  151. goodCancelBind,
  152. getTenantList,
  153. goodsCopy,
  154. } from "@/api/resource/good";
  155. export default {
  156. name: "CommodityManageMent",
  157. components: { searchBoxNew, tableList, pagination, DayPracticeSetDialog },
  158. data() {
  159. return {
  160. loading: false, //当前表单加载是否加载动画
  161. copyLoading: false,
  162. navText: {
  163. title: "商品列表",
  164. index: 0,
  165. ch: "条",
  166. num: false,
  167. border: true,
  168. choice: true,
  169. addHide: false,
  170. changeWidth: "180px",
  171. openCheckMore: true,
  172. backFatherBtn: {
  173. status: false,
  174. title: "未定义",
  175. },
  176. },
  177. topType: true,
  178. //搜索
  179. formList: [
  180. {
  181. prop: "educationTypeId",
  182. placeholder: "教育类型",
  183. scope: "educationType",
  184. },
  185. {
  186. prop: "businessId",
  187. placeholder: "业务层次",
  188. scope: "businessLevel",
  189. edu: "educationTypeId",
  190. },
  191. {
  192. prop: "schoolId",
  193. placeholder: "院校",
  194. scope: "schoolList",
  195. edu: "educationTypeId",
  196. },
  197. {
  198. prop: "majorId",
  199. placeholder: "专业",
  200. scope: "Professional",
  201. edu: "educationTypeId",
  202. },
  203. {
  204. prop: "subjectId",
  205. placeholder: "科目",
  206. scope: "sujectType",
  207. edu: "educationTypeId",
  208. },
  209. {
  210. prop: "status",
  211. placeholder: "商品状态",
  212. scope: "select",
  213. noClear: false,
  214. options: [
  215. {
  216. label: "全部状态",
  217. value: "0,1",
  218. },
  219. {
  220. label: "有效",
  221. value: 1,
  222. },
  223. {
  224. label: "无效",
  225. value: 0,
  226. },
  227. ],
  228. },
  229. {
  230. prop: "goodsStatus",
  231. placeholder: "前台可售状态",
  232. scope: "select",
  233. options: [
  234. {
  235. label: "已上架",
  236. value: 1,
  237. },
  238. {
  239. label: "未上架",
  240. value: 0,
  241. },
  242. ],
  243. },
  244. {
  245. prop1: "validityStartTime",
  246. prop2: "validityEndTime",
  247. placeholder1: "商品有效期开始时间",
  248. placeholder2: "商品有效期结束时间",
  249. scope: "moreDataPicker",
  250. },
  251. // {
  252. // prop: "orderGoodsStatus",
  253. // placeholder: "退款状态",
  254. // scope: "select",
  255. // options: [
  256. // {
  257. // label: "已退款",
  258. // value: 1,
  259. // },
  260. // {
  261. // label: "退款中",
  262. // value: 2,
  263. // },
  264. // {
  265. // label: "拒绝退款",
  266. // value: 3,
  267. // },
  268. // ],
  269. // },
  270. {
  271. prop: "goodsName",
  272. placeholder: "请输入商品名称",
  273. },
  274. ],
  275. formData: {
  276. goodsType: "",
  277. status: "0,1",
  278. pageSize: 10,
  279. pageNum: 1,
  280. },
  281. // 表单
  282. tableSet: [
  283. {
  284. label: "商品名称",
  285. prop: "goodsName",
  286. scope: "editInfo",
  287. hidden: true,
  288. },
  289. {
  290. label: "商品编码",
  291. prop: "code",
  292. hidden: false,
  293. },
  294. {
  295. label: "专业",
  296. prop: "categoryName",
  297. hidden: true,
  298. },
  299. {
  300. label: "院校",
  301. prop: "schoolName",
  302. hidden: false,
  303. },
  304. {
  305. label: "科目",
  306. prop: "subjectNames",
  307. hidden: true,
  308. },
  309. {
  310. label: "关联商品规格",
  311. prop: "specTemplateId",
  312. hidden: true,
  313. scope: "aboutSpec",
  314. },
  315. {
  316. label: "业务层次",
  317. prop1: "projectName",
  318. prop2: "businessName",
  319. hidden: false,
  320. scope: "InfoMore",
  321. },
  322. {
  323. label: "教育类型",
  324. prop: "educationName",
  325. hidden: false,
  326. },
  327. {
  328. label: "学时",
  329. prop: "classHours",
  330. hidden: true,
  331. },
  332. {
  333. label: "商品内容视图",
  334. hidden: true,
  335. scope: "treeWatch",
  336. },
  337. {
  338. label: "商品价格",
  339. prop: "standPrice",
  340. hidden: true,
  341. scope: "leftCh",
  342. ch: "¥",
  343. },
  344. {
  345. label: "商品划线价",
  346. prop: "linePrice",
  347. hidden: true,
  348. scope: "leftCh",
  349. ch: "¥",
  350. },
  351. {
  352. label: "商品状态",
  353. prop: "status",
  354. hidden: false,
  355. scope: "hasTime",
  356. },
  357. {
  358. label: "商品有效期",
  359. prop1: "validityStartTime",
  360. prop2: "validityEndTime",
  361. scope: "TimeLists",
  362. Diszing: false,
  363. hidden: true,
  364. },
  365. {
  366. label: "学习服务期",
  367. prop1: "serviceTimeType",
  368. prop2: "serviceTimeNum",
  369. prop3: "studyStartTime",
  370. prop4: "studyEndTime",
  371. scope: "studentServicePeriod",
  372. hidden: true,
  373. },
  374. {
  375. label: "供应方(服务)",
  376. prop: "supplyName",
  377. hidden: false,
  378. },
  379. {
  380. label: "最后编辑时间",
  381. prop: "updateTime",
  382. hidden: true,
  383. scope: "aTimeList",
  384. },
  385. {
  386. label: "创建时间",
  387. prop: "createTime",
  388. hidden: true,
  389. scope: "aTimeList",
  390. },
  391. {
  392. label: "可售状态",
  393. prop: "goodsStatus",
  394. hidden: true,
  395. scope: "status",
  396. },
  397. {
  398. label: "同步时间",
  399. prop: "copyTime",
  400. hidden: true,
  401. scope: "copyTime",
  402. },
  403. ],
  404. tableData: [], //表单数据
  405. total: 0, //一共多少条
  406. dialogVisible: false,
  407. dialogCopyVisible: false,
  408. dialogTableSet: [
  409. {
  410. label: "教育类型",
  411. prop: "educationName",
  412. hidden: true,
  413. },
  414. {
  415. label: "业务层次",
  416. prop: "businessName",
  417. hidden: true,
  418. },
  419. {
  420. label: "商品规格模板名称",
  421. prop: "name",
  422. hidden: true,
  423. },
  424. {
  425. label: "商品规格数量",
  426. prop: "specNumber",
  427. hidden: true,
  428. },
  429. ],
  430. dialogTableData: [],
  431. dialogNavText: {
  432. index: 0,
  433. num: false,
  434. border: true,
  435. choice: false,
  436. choiceRadio: true,
  437. radioKey: "specTemplateId",
  438. radioFixed: false,
  439. addHide: !false,
  440. tableHide: true,
  441. dontNum: true,
  442. headShow: false,
  443. backFatherBtn: {
  444. status: false,
  445. title: "未定义",
  446. },
  447. },
  448. tableRadio: "",
  449. specFormData: {
  450. templateName: "",
  451. goodsId: "",
  452. },
  453. tenantList: [],
  454. tenantId: "",
  455. };
  456. },
  457. mounted() {
  458. this.search();
  459. },
  460. activated() {
  461. this.search();
  462. },
  463. methods: {
  464. // 取消规格绑定
  465. cancelBind(goodsId) {
  466. this.$confirm(`此操作将该商品取消关联规格模板, 是否继续?`, "提示", {
  467. confirmButtonText: "确定",
  468. cancelButtonText: "取消",
  469. type: "warning",
  470. })
  471. .then(() => {
  472. goodCancelBind({
  473. goodsId,
  474. }).then((res) => {
  475. this.$message.success("取消关联成功");
  476. this.search(1);
  477. });
  478. })
  479. .catch(() => {});
  480. },
  481. handelCopy() {
  482. this.dialogCopyVisible = true;
  483. getTenantList().then((res) => {
  484. this.tenantList = res.data;
  485. });
  486. },
  487. goodsCopy() {
  488. if (!this.tenantId) {
  489. return this.$message.warning("请选择机构");
  490. }
  491. let data = this.$refs.tableList.allCheckData;
  492. if (!data.length) {
  493. return this.$message.warning("请先勾选商品");
  494. }
  495. this.copyLoading = true;
  496. const goodsIds = data.map((item) => item.goodsId);
  497. goodsCopy({ goodsIds, tenantId: this.tenantId })
  498. .then((res) => {
  499. this.dialogCopyVisible = false;
  500. this.$refs.tableList.clearMoreActive();
  501. this.$message.success("商品复制成功");
  502. })
  503. .finally((e) => {
  504. this.copyLoading = false;
  505. });
  506. },
  507. // 批量上下架
  508. handelBatch(type) {
  509. let len = this.$refs.tableList.allCheckData.length;
  510. if (!len) {
  511. return this.$message.warning("请先勾选商品");
  512. }
  513. let name = ["下架", "上架", "删除"][type];
  514. this.$confirm(`此操作将所勾选的${len}条商品${name}, 是否继续?`, "提示", {
  515. confirmButtonText: "确定",
  516. cancelButtonText: "取消",
  517. type: "warning",
  518. })
  519. .then(() => {
  520. const goodsIds = this.$refs.tableList.allCheckData.map(
  521. (item) => item.goodsId
  522. );
  523. if (type == 2) {
  524. goodsDel({
  525. status: -1,
  526. ids: goodsIds,
  527. }).then((res) => {
  528. this.$message.success("批量删除成功");
  529. this.$refs.tableList.clearMoreActive();
  530. this.search(1);
  531. });
  532. } else {
  533. goodsUpdateStatus({
  534. goodsStatus: type,
  535. goodsIds,
  536. }).then((res) => {
  537. this.$message.success(`批量${name}成功`);
  538. this.$refs.tableList.clearMoreActive();
  539. this.search(1);
  540. });
  541. }
  542. })
  543. .catch(() => {});
  544. },
  545. openClassNum(id) {
  546. this.specFormData.goodsId = id;
  547. this.tableRadio = "";
  548. let { specTemplateId } = this.tableData.find((e) => e.goodsId == id);
  549. this.tableRadio = specTemplateId || "";
  550. this.searchGoodsSpecList(id);
  551. this.dialogVisible = true;
  552. },
  553. searchGoodsSpecList(id) {
  554. // this.specFormData
  555. getGoodsSpecList(id).then((res) => {
  556. this.dialogTableData = res.data;
  557. });
  558. },
  559. editInfo(v) {
  560. this.addClick(v, 0);
  561. },
  562. search(int) {
  563. this.loading = true;
  564. if (int === 1) {
  565. this.formData.pageNum = 1;
  566. }
  567. if (int === 2) {
  568. this.formData = {
  569. goodsType: "",
  570. status: "0,1",
  571. pageSize: 10,
  572. pageNum: 1,
  573. };
  574. }
  575. if (int === 3) {
  576. this.formData.pageNum = 1;
  577. }
  578. var data = JSON.parse(JSON.stringify(this.formData));
  579. if (this.formData.validityStartTime) {
  580. data.validityStartTime = data.validityStartTime / 1000;
  581. }
  582. if (this.formData.validityEndTime) {
  583. data.validityEndTime = data.validityEndTime / 1000;
  584. }
  585. this.$api
  586. .inquireGoods(data)
  587. .then((res) => {
  588. this.tableData = res.rows;
  589. this.total = res.total;
  590. this.navText.index = res.total;
  591. })
  592. .finally(() => {
  593. this.loading = false;
  594. });
  595. },
  596. init() {
  597. this.search(2);
  598. },
  599. del(v) {
  600. this.$api.gradecheckGoodsChange({ goodsId: v.goodsId }).then((res) => {
  601. if (res.data > 0) {
  602. this.$message.error("已有学员正在学习该商品,无法删除");
  603. return;
  604. } else {
  605. this.$alert(
  606. "确定删除此内容?<br />内容删除后将无法恢复,请慎重考虑",
  607. "提示",
  608. {
  609. dangerouslyUseHTMLString: true,
  610. }
  611. )
  612. .then(() => {
  613. var data = {
  614. goodsId: v.goodsId,
  615. status: -1,
  616. };
  617. this.$api.editGoods(data).then((res) => {
  618. this.$message.success("删除成功");
  619. this.search();
  620. });
  621. })
  622. .catch(() => {
  623. this.$message({
  624. type: "info",
  625. message: "已取消删除",
  626. });
  627. });
  628. }
  629. });
  630. },
  631. //双师制设置
  632. setTeacher(data) {
  633. const jump = () => {
  634. this.$router.push({
  635. path: "commoditySetTeacher",
  636. query: {
  637. id: data.goodsId,
  638. },
  639. });
  640. };
  641. const statusPage = this.$store.state.tagsView.visitedViews.some(
  642. (item) => {
  643. return item.name == "CommoditySetTeacher";
  644. }
  645. );
  646. if (statusPage) {
  647. this.$store
  648. .dispatch("tagsView/delCachedView", {
  649. name: "CommoditySetTeacher",
  650. })
  651. .then((res) => {
  652. jump();
  653. });
  654. } else {
  655. jump();
  656. }
  657. },
  658. addClick(v, int) {
  659. if (v === undefined) {
  660. this.$router.push({
  661. path: "commodityManageMentAdd",
  662. });
  663. } else {
  664. const jump = () => {
  665. this.$router.push({
  666. path: "commodityManageMentEdit",
  667. query: {
  668. id: v.goodsId,
  669. },
  670. });
  671. };
  672. const statusPage = this.$store.state.tagsView.visitedViews.some(
  673. (item) => {
  674. return item.name == "CommodityManageMentEdit";
  675. }
  676. );
  677. if (statusPage) {
  678. this.$store
  679. .dispatch("tagsView/delCachedView", {
  680. name: "CommodityManageMentEdit",
  681. })
  682. .then((res) => {
  683. jump();
  684. });
  685. } else {
  686. jump();
  687. }
  688. }
  689. },
  690. handleSizeChange(v) {
  691. this.formData.pageSize = v;
  692. this.formData.pageNum = 1;
  693. this.search();
  694. },
  695. handleCurrentChange(v) {
  696. this.formData.pageNum = v;
  697. this.search();
  698. },
  699. changeStatus(item) {
  700. var items = JSON.parse(JSON.stringify(item));
  701. items.goodsStatus = items.goodsStatus === 1 ? 0 : 1;
  702. this.$api.editGoods(items).then((res) => {
  703. if (item.goodsStatus === 1) {
  704. this.$message.success("下架成功");
  705. } else {
  706. this.$message.success("上架成功");
  707. }
  708. this.search();
  709. });
  710. },
  711. submit() {
  712. if (!this.tableRadio) {
  713. return this.$message({
  714. message: "请选择关联商品规格",
  715. type: "warning",
  716. });
  717. }
  718. goodsUpdateSpec({
  719. goodsId: this.specFormData.goodsId,
  720. specTemplateId: this.tableRadio,
  721. }).then((res) => {
  722. this.dialogVisible = false;
  723. this.search();
  724. });
  725. },
  726. },
  727. computed: {
  728. isShowCopy() {
  729. return sessionStorage.TenantId == "867735392558919680";
  730. },
  731. },
  732. };
  733. </script>
  734. <style lang="less" scoped>
  735. /deep/.el-button {
  736. border-radius: 8px;
  737. }
  738. /deep/.el-dialog {
  739. border-radius: 8px;
  740. .el-dialog__header {
  741. padding: 0;
  742. .hearders {
  743. height: 40px;
  744. display: flex;
  745. align-items: center;
  746. justify-content: space-between;
  747. padding: 0px 18px 0px 20px;
  748. border-bottom: 1px solid #e2e2e2;
  749. .leftTitle {
  750. font-size: 14px;
  751. font-weight: bold;
  752. color: #2f4378;
  753. }
  754. .rightBoxs {
  755. display: flex;
  756. align-items: center;
  757. img {
  758. width: 14px;
  759. height: 14px;
  760. margin-left: 13px;
  761. cursor: pointer;
  762. }
  763. }
  764. }
  765. }
  766. .el-dialog__footer {
  767. padding: 0;
  768. .dialog-footer {
  769. padding: 0px 40px;
  770. height: 70px;
  771. border-top: 1px solid #e2e2e2;
  772. display: flex;
  773. align-items: center;
  774. justify-content: flex-end;
  775. }
  776. }
  777. }
  778. .imgBox {
  779. width: 100%;
  780. // height: 210px;
  781. border: 1px solid #e2e2e2;
  782. border-radius: 8px;
  783. padding: 8px 8px 3px;
  784. display: flex;
  785. flex-direction: column;
  786. align-items: center;
  787. .imgLabel {
  788. flex: 1;
  789. width: 100%;
  790. border: 1px dotted #e2e2e2;
  791. color: #999;
  792. font-size: 14px;
  793. cursor: pointer;
  794. border-radius: 8px;
  795. .msPhoto {
  796. display: flex;
  797. justify-content: center;
  798. align-items: center;
  799. max-width: 100%;
  800. max-height: 270px;
  801. img {
  802. max-width: 100%;
  803. max-height: 270px;
  804. }
  805. }
  806. .imgbbx {
  807. display: flex;
  808. flex-direction: column;
  809. align-items: center;
  810. justify-content: center;
  811. width: 100%;
  812. height: 100%;
  813. i {
  814. font-weight: bold;
  815. margin: 14px 0;
  816. font-size: 24px;
  817. }
  818. }
  819. }
  820. p {
  821. margin: 5px 0px;
  822. }
  823. }
  824. </style>