dislogOrganSet.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. <template>
  2. <div>
  3. <BaseDialog
  4. width="1800px"
  5. :isShow.sync="isShow"
  6. :title="title"
  7. @close="close"
  8. @submit="submitForm"
  9. >
  10. <div class="bop-tip">
  11. <div><i class="el-icon-warning-outline"></i>说明</div>
  12. <div>
  13. 如果提成方式是按阶梯价计算,则需设置阶梯价格区间(最高价无穷大,则填写
  14. “ * ” )。如果无需按阶梯价计算提成,留空即可。
  15. </div>
  16. </div>
  17. <el-form
  18. inline
  19. hide-required-asterisk
  20. :model="form"
  21. :rules="rules"
  22. ref="form"
  23. >
  24. <div>
  25. <el-form-item prop="tpName" label="模板名称:" label-width="100px">
  26. <el-input
  27. placeholder="请输入模板名称"
  28. v-model="form.tpName"
  29. ></el-input>
  30. </el-form-item>
  31. <el-form-item prop="tenantId" label="">
  32. <el-select
  33. filterable
  34. v-model="form.tenantId"
  35. placeholder="请选择关联机构"
  36. >
  37. <el-option
  38. v-for="item in tenantList"
  39. :key="item.tenantId"
  40. :label="item.tenantName"
  41. :value="item.tenantId"
  42. ></el-option>
  43. </el-select>
  44. </el-form-item>
  45. <el-form-item label="">
  46. <el-checkbox
  47. :true-label="1"
  48. :false-label="0"
  49. v-model="form.defaultStatus"
  50. >默认</el-checkbox
  51. >
  52. </el-form-item>
  53. </div>
  54. <div v-for="(item, index) in form.itemList" :key="index">
  55. <el-form-item
  56. :prop="'itemList.' + index + '.itemName'"
  57. :label="index == 0 ? '成本设置:' : ' '"
  58. :rules="rules['itemName']"
  59. label-width="100px"
  60. >
  61. <el-input
  62. placeholder="请输入成本项名称"
  63. v-model="item.itemName"
  64. ></el-input>
  65. </el-form-item>
  66. <el-form-item
  67. label=""
  68. :prop="'itemList.' + index + '.itemCategory'"
  69. :rules="rules['itemCategory']"
  70. >
  71. <el-select v-model="item.itemCategory" placeholder="请选择成本类型">
  72. <el-option label="分成成本" :value="1"></el-option>
  73. <el-option label="其他成本" :value="2"></el-option>
  74. </el-select>
  75. </el-form-item>
  76. <el-form-item
  77. label=""
  78. :prop="'itemList.' + index + '.educationTypeId'"
  79. :rules="rules['educationTypeId']"
  80. >
  81. <el-select
  82. @change="changeEdu(item)"
  83. v-model="item.educationTypeId"
  84. placeholder="请选择教育类型"
  85. >
  86. <el-option
  87. v-for="item in eduList"
  88. :key="item.id"
  89. :label="
  90. item.schemeName +
  91. (item.schemeName ? '-' : '') +
  92. item.educationName
  93. "
  94. :value="item.id"
  95. >
  96. </el-option>
  97. </el-select>
  98. </el-form-item>
  99. <el-form-item
  100. v-if="item.educationTypeId != -1"
  101. label=""
  102. :prop="'itemList.' + index + '.businessId'"
  103. :rules="rules['businessId']"
  104. >
  105. <el-select
  106. filterable
  107. v-model="item.businessId"
  108. placeholder="请选择业务层次"
  109. >
  110. <el-option
  111. v-for="level in backbusinessList(item.educationTypeId)"
  112. :key="level.businessId"
  113. :label="level.aliasName"
  114. :value="level.businessId"
  115. @click.native="changeBus(item, level.projectId)"
  116. >
  117. </el-option>
  118. </el-select>
  119. </el-form-item>
  120. <el-form-item
  121. label=""
  122. :prop="'itemList.' + index + '.itemType'"
  123. :rules="rules['itemType']"
  124. >
  125. <el-select v-model="item.itemType" placeholder="请选择成本类型">
  126. <el-option label="百分比成本" :value="1"></el-option>
  127. <el-option label="固定成本" :value="2"></el-option>
  128. </el-select>
  129. </el-form-item>
  130. <el-form-item
  131. label=""
  132. :prop="'itemList.' + index + '.minValue'"
  133. :rules="rules['minValue']"
  134. class="range"
  135. >
  136. <el-col :span="11">
  137. <el-input
  138. v-int
  139. placeholder="最低价"
  140. v-model.number="item.minValue"
  141. ></el-input>
  142. </el-col>
  143. <el-col class="line" :span="2" style="magrin: 10px">-</el-col>
  144. <el-col :span="11">
  145. <el-input
  146. @keyup.native="regValue(item)"
  147. placeholder="最高价"
  148. @change="changeMaxValue('itemList.' + index + '.minValue')"
  149. v-model.number="item.maxValue"
  150. ></el-input>
  151. </el-col>
  152. </el-form-item>
  153. <el-form-item
  154. v-if="item.itemType"
  155. class="ddd"
  156. label-width="0"
  157. :prop="'itemList.' + index + '.typeValue'"
  158. label=" "
  159. :rules="rules['typeValue']"
  160. >
  161. <el-input
  162. v-if="item.itemType == 1"
  163. placeholder="输入百分比"
  164. v-model="item.typeValue"
  165. key="2"
  166. v-int="{ max: 100 }"
  167. >
  168. <template slot="append"> % </template>
  169. </el-input>
  170. <el-input
  171. key="1"
  172. v-else
  173. placeholder="固定金额"
  174. v-model="item.typeValue"
  175. v-int
  176. >
  177. <template slot="append"> 元 </template>
  178. </el-input>
  179. </el-form-item>
  180. <template v-if="item.itemCategory == 1">
  181. <el-form-item label="">
  182. <el-checkbox
  183. :true-label="1"
  184. :false-label="0"
  185. v-model="item.dockStatus"
  186. >成本扣除</el-checkbox
  187. >
  188. </el-form-item>
  189. <template v-if="item.dockStatus == 1">
  190. <el-form-item
  191. label=""
  192. :prop="'itemList.' + index + '.dockType'"
  193. :rules="rules['dockType']"
  194. >
  195. <el-select v-model="item.dockType" placeholder="请选择扣除类型">
  196. <el-option label="百分比扣除" :value="1"></el-option>
  197. <el-option label="固定扣除" :value="2"></el-option>
  198. </el-select>
  199. </el-form-item>
  200. <el-form-item
  201. v-if="item.dockType"
  202. class="ddd"
  203. label-width="0"
  204. :prop="'itemList.' + index + '.dockValue'"
  205. label=" "
  206. :rules="rules['dockValue']"
  207. >
  208. <el-input
  209. v-if="item.dockType == 1"
  210. placeholder="输入百分比"
  211. v-model="item.dockValue"
  212. key="2"
  213. v-int="{ max: 100 }"
  214. >
  215. <template slot="append"> % </template>
  216. </el-input>
  217. <el-input
  218. key="1"
  219. v-else
  220. placeholder="固定金额"
  221. v-model="item.dockValue"
  222. v-int
  223. >
  224. <template slot="append"> 元 </template>
  225. </el-input>
  226. </el-form-item>
  227. </template>
  228. </template>
  229. <el-form-item label-width="0" label=" ">
  230. <div class="btns">
  231. <i @click="add(index, item)" class="el-icon-connection"></i>
  232. <i @click="add(index)" class="el-icon-circle-plus-outline"></i>
  233. <i
  234. v-if="index != 0"
  235. @click="del(index)"
  236. class="el-icon-remove-outline"
  237. ></i>
  238. </div>
  239. </el-form-item>
  240. </div>
  241. </el-form>
  242. </BaseDialog>
  243. </div>
  244. </template>
  245. <script>
  246. import { eduList, addCost, costDetail, editCost } from "@/api/financed/index";
  247. export default {
  248. name: "DislogSet",
  249. props: {
  250. dialogVisible: {
  251. type: Boolean,
  252. default: false,
  253. },
  254. // 0 新增 1修改 2复制 3订单成本设置 4批量设置
  255. type: {
  256. type: [String, Number],
  257. default: 0,
  258. },
  259. tpId: {
  260. type: [String, Number],
  261. default: "",
  262. },
  263. },
  264. data() {
  265. var checkMinValue = (rule, value, callback) => {
  266. const list = this.itemList[rule.field.split(".")[1]];
  267. const { maxValue, businessId, itemCategory } = list;
  268. if (maxValue || value || value === 0) {
  269. if (!value && value !== 0) {
  270. callback(new Error("请输入最低价"));
  271. } else if (!maxValue) {
  272. callback(new Error("请输入最高价"));
  273. } else if (maxValue <= value) {
  274. callback(new Error("最低价不能小于最高价"));
  275. }
  276. }
  277. if (businessId && itemCategory) {
  278. const levelList = this.itemList.filter(
  279. (e) =>
  280. e.businessId == list.businessId && e.itemCategory == itemCategory
  281. );
  282. if (levelList.length > 1) {
  283. const text = this.isHaveIntersect(levelList);
  284. text && callback(new Error(text));
  285. }
  286. }
  287. callback();
  288. };
  289. var checkEduId = (rule, value, callback) => {
  290. const { itemCategory } = this.itemList[rule.field.split(".")[1]];
  291. if (this.itemList.length > 1) {
  292. const levelList = this.itemList.filter(
  293. (e) => e.itemCategory && e.itemCategory == itemCategory
  294. );
  295. const len = levelList.length;
  296. if (len > 1) {
  297. const len1 = levelList.filter((e) => e.educationTypeId == -1).length;
  298. if (len1 > 0 && len1 != len) {
  299. callback(new Error("需统一不限!"));
  300. }
  301. }
  302. }
  303. callback();
  304. };
  305. var checkBusId = (rule, value, callback) => {
  306. const { educationTypeId, itemCategory } =
  307. this.itemList[rule.field.split(".")[1]];
  308. if (this.itemList.length > 1) {
  309. const levelList = this.itemList.filter(
  310. (e) =>
  311. itemCategory &&
  312. educationTypeId &&
  313. e.educationTypeId == educationTypeId &&
  314. e.itemCategory == itemCategory
  315. );
  316. console.log(levelList, 666);
  317. const len = levelList.length;
  318. if (len > 1) {
  319. const len1 = levelList.filter((e) => e.businessId == -1).length;
  320. if (len1 > 0 && len1 != len) {
  321. callback(new Error("需统一不限!"));
  322. }
  323. }
  324. }
  325. callback();
  326. };
  327. return {
  328. form: {},
  329. rules: {
  330. tpName: [
  331. { required: true, message: "请输入模板名称", trigger: "blur" },
  332. ],
  333. tenantId: [
  334. { required: true, message: "请选择关联机构", trigger: "change" },
  335. ],
  336. itemName: [
  337. { required: true, message: "请输入成本项名称", trigger: "blur" },
  338. ],
  339. businessId: [
  340. { required: true, message: "请选择业务层次", trigger: "blur" },
  341. { validator: checkBusId, trigger: "change" },
  342. ],
  343. educationTypeId: [
  344. { required: true, message: "请选择教育类型", trigger: "change" },
  345. { validator: checkEduId, trigger: "change" },
  346. ],
  347. itemCategory: [
  348. { required: true, message: "请选择业务类型", trigger: "change" },
  349. ],
  350. itemType: [
  351. { required: true, message: "请选择成本类型", trigger: "change" },
  352. ],
  353. typeValue: [
  354. { required: true, message: "请输入成本值", trigger: "blur" },
  355. ],
  356. dockType: [
  357. { required: true, message: "请选择扣除类型", trigger: "change" },
  358. ],
  359. dockValue: [
  360. { required: true, message: "请输入扣除值", trigger: "blur" },
  361. ],
  362. minValue: [{ validator: checkMinValue, trigger: "blur" }],
  363. },
  364. tenantList: [],
  365. eduList: [],
  366. };
  367. },
  368. methods: {
  369. init() {
  370. this.resetForm();
  371. if (this.type === 3) {
  372. this.getOrderCostDetail();
  373. } else if (this.type === 4) {
  374. } else {
  375. this.tpId && this.getCostDetail();
  376. }
  377. this.getTenantList();
  378. this.getEduList();
  379. },
  380. getOrderCostDetail() {
  381. this.$api.systemtopordercost(this.tpId).then((res) => {
  382. Object.keys(this.form).map((key) => {
  383. this.form[key] = res.data[key];
  384. });
  385. this.form.itemList.forEach((ele) => {
  386. if (ele.maxValue == -1) {
  387. ele.maxValue = "*";
  388. }
  389. });
  390. });
  391. },
  392. getCostDetail() {
  393. costDetail(this.tpId).then((res) => {
  394. if (this.type == 2) delete this.form["tpId"];
  395. Object.keys(this.form).map((key) => {
  396. this.form[key] = res.data[key];
  397. });
  398. this.form.itemList.forEach((ele) => {
  399. if (ele.maxValue == -1) {
  400. ele.maxValue = "*";
  401. }
  402. });
  403. });
  404. },
  405. getEduList() {
  406. if (this.eduList.length) return;
  407. eduList({}).then((res) => {
  408. this.eduList = [
  409. { schemeName: "", educationName: "不限", id: -1 },
  410. ...res.rows,
  411. ];
  412. });
  413. },
  414. backbusinessList(eduId) {
  415. if (!eduId || !this.eduList.length) return [];
  416. let data = this.eduList.find((e) => e.id == eduId);
  417. return data.businessList
  418. ? [
  419. { aliasName: "不限", businessId: -1, projectId: -1 },
  420. ...data.businessList,
  421. ]
  422. : [];
  423. },
  424. getTenantList() {
  425. if (this.tenantList.length) return;
  426. this.$api.systemtenantlist().then((res) => {
  427. this.tenantList = res.rows;
  428. });
  429. },
  430. changeEdu(data) {
  431. let value = data.educationTypeId == -1 ? -1 : undefined;
  432. data.businessId = value;
  433. data.projectId = value;
  434. },
  435. changeBus(data, projectId) {
  436. data.projectId = projectId;
  437. },
  438. add(index, data) {
  439. data = data ? JSON.parse(JSON.stringify(data)) : this.backItem();
  440. this.itemList.splice(index + 1, 0, data);
  441. },
  442. del(index) {
  443. this.itemList.splice(index, 1);
  444. },
  445. close() {
  446. this.$nextTick(() => {
  447. this.$refs["form"].resetFields();
  448. });
  449. },
  450. backItem() {
  451. return {
  452. projectId: undefined,
  453. itemName: undefined,
  454. itemCategory: undefined,
  455. businessId: undefined,
  456. educationTypeId: undefined,
  457. itemType: undefined,
  458. typeValue: undefined,
  459. minValue: undefined,
  460. maxValue: undefined,
  461. dockStatus: undefined,
  462. dockType: undefined,
  463. dockValue: undefined,
  464. };
  465. },
  466. resetForm() {
  467. this.form = {
  468. itemList: [this.backItem()],
  469. tpId: undefined,
  470. tpName: undefined,
  471. defaultStatus: 0,
  472. tenantId: undefined,
  473. };
  474. },
  475. cb() {
  476. this.$message.success(this.title + "成功");
  477. this.isShow = false;
  478. this.$emit("search");
  479. },
  480. submitForm() {
  481. this.$refs["form"].validate((valid) => {
  482. if (valid) {
  483. let form = JSON.parse(JSON.stringify(this.form));
  484. form.itemList.forEach((ele) => {
  485. if (ele.maxValue === "*") {
  486. ele.maxValue = -1;
  487. }
  488. });
  489. if (this.type === 3 || this.type === 4) {
  490. this.$api
  491. .systemtoporderupdatecost({
  492. costTpVo: form,
  493. orderSnList:
  494. this.type === 3 ? [this.tpId] : this.tpId?.split(","),
  495. })
  496. .then(this.cb);
  497. } else if (this.type !== 1) {
  498. addCost(form).then(this.cb);
  499. } else {
  500. editCost(form).then(this.cb);
  501. }
  502. } else {
  503. return false;
  504. }
  505. });
  506. },
  507. changeMaxValue(prop) {
  508. this.$refs.form.validateField(prop);
  509. },
  510. // 阶梯校验
  511. isHaveIntersect(list) {
  512. const isEmpty = list.some((e) => !e.minValue && !e.maxValue);
  513. if (isEmpty) {
  514. return "非阶梯计价只能存在一个";
  515. }
  516. let maxList = list.filter((e) => e.maxValue === "*");
  517. if (maxList.length > 1) {
  518. return "阶梯计价存在范围冲突";
  519. }
  520. list.sort((a, b) => {
  521. if (a.maxValue == "*") {
  522. return Number.MAX_VALUE;
  523. }
  524. if (b.maxValue == "*") {
  525. return -Number.MAX_VALUE;
  526. }
  527. return a.minValue - b.minValue;
  528. });
  529. for (let i = 0, len = list.length - 1; i < len; i++) {
  530. if (list[i].maxValue >= list[i + 1].minValue) {
  531. return "阶梯计价存在范围冲突";
  532. }
  533. }
  534. return;
  535. },
  536. regValue(data) {
  537. let { maxValue } = data;
  538. let val;
  539. if (maxValue.includes("*")) {
  540. val = "*";
  541. } else {
  542. val = maxValue.replace(/[^0-9]/g, "");
  543. }
  544. data.maxValue = val;
  545. },
  546. },
  547. computed: {
  548. isShow: {
  549. get() {
  550. if (this.dialogVisible) {
  551. this.init();
  552. }
  553. return this.dialogVisible;
  554. },
  555. set(val) {
  556. this.$emit("update:dialogVisible", false);
  557. },
  558. },
  559. title() {
  560. return ["新增", "修改", "复制", "订单成本设置", "批量成本设置"][
  561. this.type
  562. ];
  563. },
  564. itemList() {
  565. return this.form.itemList;
  566. },
  567. },
  568. };
  569. </script>
  570. <style lang="scss" scoped>
  571. /deep/.el-input--medium .el-input__inner {
  572. width: 144px;
  573. }
  574. /deep/ .range {
  575. .el-form-item__content {
  576. width: 170px;
  577. }
  578. .el-input--medium .el-input__inner {
  579. width: 76px;
  580. }
  581. }
  582. /deep/ .ddd {
  583. margin-left: -10px;
  584. .el-input--medium .el-input__inner {
  585. width: 105px;
  586. }
  587. }
  588. .line {
  589. text-align: center;
  590. }
  591. .btns {
  592. height: 36px;
  593. display: flex;
  594. align-items: center;
  595. i {
  596. font-size: 24px;
  597. cursor: pointer;
  598. margin-left: 5px;
  599. }
  600. }
  601. .bop-tip {
  602. background: #fff6f7;
  603. margin: 0 0 20px 10px;
  604. padding: 8px 10px;
  605. i {
  606. font-size: 16px;
  607. color: #e6a23c;
  608. }
  609. }
  610. </style>