dislogSet.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. <template>
  2. <div>
  3. <BaseDialog
  4. width="1400px"
  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. <template v-if="item.itemCategory == 1">
  77. <el-form-item
  78. label=""
  79. :prop="'itemList.' + index + '.educationTypeId'"
  80. :rules="rules['educationTypeId']"
  81. >
  82. <el-select
  83. @change="changeEdu(item)"
  84. v-model="item.educationTypeId"
  85. placeholder="请选择教育类型"
  86. >
  87. <el-option
  88. v-for="item in eduList"
  89. :key="item.id"
  90. :label="
  91. item.schemeName +
  92. (item.schemeName ? '-' : '') +
  93. item.educationName
  94. "
  95. :value="item.id"
  96. >
  97. </el-option>
  98. </el-select>
  99. </el-form-item>
  100. <el-form-item
  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. </template>
  121. <el-form-item
  122. label=""
  123. :prop="'itemList.' + index + '.itemType'"
  124. :rules="rules['itemType']"
  125. >
  126. <el-select v-model="item.itemType" placeholder="请选择成本类型">
  127. <el-option label="百分比成本" :value="1"></el-option>
  128. <el-option label="固定成本" :value="2"></el-option>
  129. </el-select>
  130. </el-form-item>
  131. <el-form-item
  132. label=""
  133. :prop="'itemList.' + index + '.minValue'"
  134. :rules="rules['minValue']"
  135. class="range"
  136. >
  137. <el-col :span="11">
  138. <el-input
  139. v-int="{ set: 0 }"
  140. placeholder="最低价"
  141. v-model.number="item.minValue"
  142. ></el-input>
  143. </el-col>
  144. <el-col class="line" :span="2" style="magrin: 10px">-</el-col>
  145. <el-col :span="11">
  146. <el-input
  147. @keyup.native="regValue(item)"
  148. placeholder="最高价"
  149. @change="changeMaxValue('itemList.' + index + '.minValue')"
  150. v-model="item.maxValue"
  151. ></el-input>
  152. </el-col>
  153. </el-form-item>
  154. <el-form-item
  155. v-if="item.itemType"
  156. class="ddd"
  157. label-width="0"
  158. :prop="'itemList.' + index + '.typeValue'"
  159. label=" "
  160. :rules="rules['typeValue']"
  161. >
  162. <el-input
  163. v-if="item.itemType == 1"
  164. placeholder="百分比成本"
  165. v-model="item.typeValue"
  166. key="2"
  167. v-int="{ max: 100 }"
  168. >
  169. <template slot="append"> % </template>
  170. </el-input>
  171. <el-input
  172. key="1"
  173. v-else
  174. placeholder="固定成本"
  175. v-model="item.typeValue"
  176. v-int
  177. >
  178. <template slot="append"> 元 </template>
  179. </el-input>
  180. </el-form-item>
  181. <el-form-item label-width="0" label=" ">
  182. <div class="btns">
  183. <i @click="add(index, item)" class="el-icon-connection"></i>
  184. <i @click="add(index)" class="el-icon-circle-plus-outline"></i>
  185. <i
  186. v-if="index != 0"
  187. @click="del(index)"
  188. class="el-icon-remove-outline"
  189. ></i>
  190. </div>
  191. </el-form-item>
  192. </div>
  193. </el-form>
  194. </BaseDialog>
  195. </div>
  196. </template>
  197. <script>
  198. import { eduList, addCost, costDetail, editCost } from "@/api/financed/index";
  199. export default {
  200. name: "DislogSet",
  201. props: {
  202. dialogVisible: {
  203. type: Boolean,
  204. default: false,
  205. },
  206. // 0 新增 1修改 2复制
  207. type: {
  208. type: [String, Number],
  209. default: 0,
  210. },
  211. tpId: {
  212. type: [String, Number],
  213. default: "",
  214. },
  215. },
  216. data() {
  217. var checkMinValue = (rule, value, callback) => {
  218. const list = this.itemList[rule.field.split(".")[1]];
  219. const { maxValue, businessId } = list;
  220. if (maxValue || value) {
  221. if (!value) {
  222. callback(new Error("请输入最低价"));
  223. } else if (!maxValue) {
  224. callback(new Error("请输入最高价"));
  225. } else if (maxValue <= value) {
  226. callback(new Error("最低价不能小于最高价"));
  227. }
  228. }
  229. if (businessId) {
  230. const levelList = this.itemList.filter(
  231. (e) => e.businessId == list.businessId
  232. );
  233. if (levelList.length > 1) {
  234. const text = this.isHaveIntersect(levelList);
  235. text && callback(new Error(text));
  236. }
  237. }
  238. callback();
  239. };
  240. return {
  241. form: {},
  242. rules: {
  243. tpName: [
  244. { required: true, message: "请输入模板名称", trigger: "blur" },
  245. ],
  246. tenantId: [
  247. { required: true, message: "请选择关联机构", trigger: "change" },
  248. ],
  249. itemName: [
  250. { required: true, message: "请输入成本项名称", trigger: "blur" },
  251. ],
  252. businessId: [
  253. { required: true, message: "请选择业务层次", trigger: "blur" },
  254. ],
  255. educationTypeId: [
  256. { required: true, message: "请选择教育类型", trigger: "change" },
  257. ],
  258. itemCategory: [
  259. { required: true, message: "请选择业务类型", trigger: "change" },
  260. ],
  261. itemType: [
  262. { required: true, message: "请选择成本类型", trigger: "change" },
  263. ],
  264. typeValue: [
  265. { required: true, message: "请输入百分比成本", trigger: "blur" },
  266. ],
  267. minValue: [{ validator: checkMinValue, trigger: "blur" }],
  268. },
  269. tenantList: [],
  270. eduList: [],
  271. };
  272. },
  273. methods: {
  274. init() {
  275. this.resetForm();
  276. this.tpId && this.getCostDetail();
  277. this.getTenantList();
  278. this.getEduList();
  279. },
  280. getCostDetail() {
  281. costDetail(this.tpId).then((res) => {
  282. if (this.type == 2) delete this.form["tpId"];
  283. Object.keys(this.form).map((key) => {
  284. this.form[key] = res.data[key];
  285. });
  286. this.form.itemList.forEach((ele) => {
  287. if (ele.maxValue == -1) {
  288. ele.maxValue = "*";
  289. }
  290. });
  291. });
  292. },
  293. getEduList() {
  294. if (this.eduList.length) return;
  295. eduList({}).then((res) => {
  296. this.eduList = res.rows;
  297. });
  298. },
  299. backbusinessList(eduId) {
  300. if (!eduId || !this.eduList.length) return [];
  301. let data = this.eduList.find((e) => e.id == eduId);
  302. return data.businessList || [];
  303. },
  304. getTenantList() {
  305. if (this.tenantList.length) return;
  306. this.$api.systemtenantlist().then((res) => {
  307. this.tenantList = res.rows;
  308. });
  309. },
  310. changeEdu(data) {
  311. data.businessId = undefined;
  312. data.projectId = undefined;
  313. },
  314. changeBus(data, projectId) {
  315. data.projectId = projectId;
  316. },
  317. add(index, data) {
  318. data = data
  319. ? JSON.parse(JSON.stringify(data))
  320. : {
  321. projectId: undefined,
  322. itemName: undefined,
  323. itemCategory: undefined,
  324. businessId: undefined,
  325. educationTypeId: undefined,
  326. itemType: undefined,
  327. typeValue: undefined,
  328. minValue: undefined,
  329. maxValue: undefined,
  330. };
  331. this.itemList.splice(index + 1, 0, data);
  332. },
  333. del(index) {
  334. this.itemList.splice(index, 1);
  335. },
  336. close() {
  337. this.$refs["form"].resetFields();
  338. },
  339. resetForm() {
  340. this.form = {
  341. itemList: [
  342. {
  343. projectId: undefined,
  344. itemName: undefined,
  345. itemCategory: undefined,
  346. businessId: undefined,
  347. educationTypeId: undefined,
  348. itemType: undefined,
  349. typeValue: undefined,
  350. minValue: undefined,
  351. maxValue: undefined,
  352. },
  353. ],
  354. tpId: undefined,
  355. tpName: undefined,
  356. defaultStatus: 0,
  357. tenantId: undefined,
  358. };
  359. },
  360. cb() {
  361. this.$message.success(this.title + "成功");
  362. this.isShow = false;
  363. this.$emit("search");
  364. },
  365. submitForm() {
  366. this.$refs["form"].validate((valid) => {
  367. if (valid) {
  368. let form = JSON.parse(JSON.stringify(this.form));
  369. form.itemList.forEach((ele) => {
  370. if (ele.maxValue === "*") {
  371. ele.maxValue = -1;
  372. }
  373. });
  374. if (this.type !== 1) {
  375. addCost(form).then(this.cb);
  376. } else {
  377. editCost(form).then(this.cb);
  378. }
  379. } else {
  380. return false;
  381. }
  382. });
  383. },
  384. changeMaxValue(prop) {
  385. this.$refs.form.validateField(prop);
  386. },
  387. // 阶梯校验
  388. isHaveIntersect(list) {
  389. const isEmpty = list.some((e) => !e.minValue && !e.maxValue);
  390. if (isEmpty) {
  391. return "非阶梯计价只能存在一个";
  392. }
  393. let maxList = list.filter((e) => e.maxValue === "*");
  394. if (maxList.length > 1) {
  395. return "阶梯计价存在范围冲突";
  396. }
  397. list.sort((a, b) => {
  398. if (a.maxValue == "*") {
  399. return Number.MAX_VALUE;
  400. }
  401. if (b.maxValue == "*") {
  402. return -Number.MAX_VALUE;
  403. }
  404. return a.minValue - b.minValue;
  405. });
  406. for (let i = 0, len = list.length - 1; i < len; i++) {
  407. if (list[i].maxValue >= list[i + 1].minValue) {
  408. return "阶梯计价存在范围冲突";
  409. }
  410. }
  411. return;
  412. },
  413. regValue(data) {
  414. let { maxValue } = data;
  415. let val;
  416. if (maxValue.includes("*")) {
  417. val = "*";
  418. } else {
  419. val = maxValue.replace(/[^0-9]/g, "");
  420. }
  421. data.maxValue = val;
  422. },
  423. },
  424. computed: {
  425. isShow: {
  426. get() {
  427. if (this.dialogVisible) {
  428. this.init();
  429. }
  430. return this.dialogVisible;
  431. },
  432. set(val) {
  433. this.$emit("update:dialogVisible", false);
  434. },
  435. },
  436. title() {
  437. return ["新增", "修改", "复制"][this.type];
  438. },
  439. itemList() {
  440. return this.form.itemList;
  441. },
  442. },
  443. };
  444. </script>
  445. <style lang="scss" scoped>
  446. /deep/.el-input--medium .el-input__inner {
  447. width: 144px;
  448. }
  449. /deep/ .range {
  450. .el-form-item__content {
  451. width: 170px;
  452. }
  453. .el-input--medium .el-input__inner {
  454. width: 76px;
  455. }
  456. }
  457. /deep/ .ddd {
  458. margin-left: -10px;
  459. .el-input--medium .el-input__inner {
  460. width: 105px;
  461. }
  462. }
  463. .line {
  464. text-align: center;
  465. }
  466. .btns {
  467. height: 36px;
  468. display: flex;
  469. align-items: center;
  470. i {
  471. font-size: 24px;
  472. cursor: pointer;
  473. margin-left: 5px;
  474. }
  475. }
  476. .bop-tip {
  477. background: #fff6f7;
  478. margin: 0 0 20px 10px;
  479. padding: 8px 10px;
  480. i {
  481. font-size: 16px;
  482. color: #e6a23c;
  483. }
  484. }
  485. </style>