add-or-update.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. <template>
  2. <div class="page-container">
  3. <navFunction
  4. ref="navFunctionRef"
  5. module-title="云店"
  6. function-title="叫水码"
  7. :title="postForm.id ? '编辑' : '新增'"
  8. @change="$router.back()"
  9. ></navFunction>
  10. <el-row>
  11. <el-col :span="12" style="width:500px">
  12. <el-form
  13. ref="postForm"
  14. :model="postForm"
  15. :rules="postFormRule"
  16. label-width="80px"
  17. @keyup.enter.native="postFormSubmit()"
  18. >
  19. <template v-if="pageStatus === 'create'">
  20. <el-form-item label="运营中心" :prop="postForm.operationsCenterId" v-if="userInfo.userTypeModel == 'admin'">
  21. <el-select
  22. v-model="postForm.operationsCenterId"
  23. clearable
  24. filterable
  25. placeholder="请选择运营中心"
  26. @change="onOperationsCenterChange"
  27. >
  28. <el-option
  29. v-for="item in operationsCenterList"
  30. :key="item.value"
  31. :label="item.label"
  32. :value="item.value"
  33. />
  34. </el-select>
  35. </el-form-item>
  36. <el-form-item
  37. label="项目名称"
  38. :prop="postForm.orgId"
  39. v-if="userInfo.userTypeModel == 'admin' || userInfo.userTypeModel == 'operationsCenter'"
  40. >
  41. <el-select
  42. v-model="postForm.orgId"
  43. :disabled="!postForm.operationsCenterId"
  44. filterable
  45. clearable
  46. placeholder="请选择项目"
  47. @change="onProjectChange"
  48. >
  49. <el-option v-for="item in projectList" :key="item.value" :label="item.label" :value="item.value" />
  50. </el-select>
  51. </el-form-item>
  52. </template>
  53. <el-form-item label="房间号" prop="roomMarkId">
  54. <el-select
  55. v-model="postForm.roomMarkId"
  56. :disabled="!postForm.orgId || pageStatus === 'update'"
  57. filterable
  58. clearable
  59. placeholder="输入搜索选择房间号"
  60. @change="onSelectChange"
  61. >
  62. <el-option
  63. v-for="item in roomList"
  64. :key="item.roomMarkId"
  65. :label="item.roomName"
  66. :value="item.roomMarkId"
  67. />
  68. </el-select>
  69. </el-form-item>
  70. <el-form-item label="企业名称" prop="virtId">
  71. <el-select
  72. v-model="postForm.virtId"
  73. :disabled="!postForm.orgId"
  74. filterable
  75. clearable
  76. placeholder="输入搜索选择企业"
  77. @change="onSelect2Change"
  78. >
  79. <el-option v-for="item in virtList" :key="item.value" :label="item.label" :value="item.value" />
  80. </el-select>
  81. </el-form-item>
  82. <el-form-item label="常驻人数" prop="residentNum">
  83. <number-input
  84. v-model="postForm.residentNum"
  85. maxlength="10"
  86. :value="postForm.residentNum"
  87. placeholder="请输入常驻人数"
  88. />
  89. </el-form-item>
  90. <el-form-item label="饮水数据" prop="historyInfo">
  91. <el-input
  92. maxlength="500"
  93. type="textarea"
  94. placeholder="请输入饮水数据"
  95. :rows="4"
  96. v-model="postForm.historyInfo"
  97. ></el-input>
  98. <div class="tips">
  99. 原叫水品牌类型规格价格数量,逗号分隔,例如景田纯净水18.9L*16元*10,景田纯净水500ml24支装*30元*5
  100. </div>
  101. </el-form-item>
  102. <el-form-item label="叫水商品" prop="listMgtGoods">
  103. <el-table border :data="postForm.listMgtGoods">
  104. <el-table-column prop="productName" label="商品" width="200">
  105. <template slot-scope="{ row, $index }">
  106. <template v-if="row.productName">
  107. <div class="product">
  108. <el-image
  109. class="product-img"
  110. v-if="row.listFile && row.listFile.length"
  111. :src="row.listFile[0].fileUrl"
  112. />
  113. <div class="product-inner">
  114. <div class="product-title">{{ row.productName }}</div>
  115. <div class="product-desc">{{ row.descr }}</div>
  116. <div class="product-price">{{ row.price }}元</div>
  117. </div>
  118. </div>
  119. </template>
  120. <template v-else>
  121. <el-select
  122. :value="row.productName"
  123. filterable
  124. remote
  125. placeholder="输入商品名称搜索选择"
  126. :remote-method="searchProduct"
  127. :loading="searchProductLoading"
  128. @change="onProductChange($event, $index)"
  129. >
  130. <el-option v-for="item in productList" :key="item.id" :label="item.productName" :value="item.id">
  131. </el-option>
  132. </el-select>
  133. </template>
  134. </template>
  135. </el-table-column>
  136. <el-table-column prop="stock" label="数量">
  137. <template slot-scope="scope">
  138. <number-input v-model="scope.row.quantity" :value="scope.row.quantity" :decimal="0" placeholder="请输入数量" />
  139. </template>
  140. </el-table-column>
  141. <el-table-column label="操作" width="77">
  142. <template slot-scope="scope">
  143. <el-button size="mini" type="danger" @click="onMgtGoodDel(scope.$index)">删除</el-button>
  144. </template>
  145. </el-table-column>
  146. </el-table>
  147. <div class="product-bottom" @click="onProductAdd" v-if="postForm.listMgtGoods.length < 10">
  148. 继续添加+
  149. </div>
  150. </el-form-item>
  151. <el-form-item label="客户经理" prop="customerManagerId">
  152. <el-select
  153. v-model="postForm.customerManagerId"
  154. filterable
  155. clearable
  156. placeholder="输入用户名或姓名搜索选择"
  157. @change="onSelect3Change"
  158. >
  159. <el-option
  160. v-for="item in searchAccountManagerList"
  161. :key="item.id"
  162. :label="item.realName"
  163. :value="item.id"
  164. >
  165. </el-option>
  166. </el-select>
  167. </el-form-item>
  168. <el-form-item label="消费分润" prop="description">
  169. <number-input
  170. min="0"
  171. max="100"
  172. v-model="postForm.bonusProportion"
  173. :value="postForm.bonusProportion"
  174. placeholder="请输入消费分润"
  175. />
  176. </el-form-item>
  177. </el-form>
  178. <div class="dialog-footer tc db w-100">
  179. <el-button @click="$router.back()">取消</el-button>
  180. <el-button type="primary" :loading="postFormLoading" @click="postFormSubmit()">确定</el-button>
  181. </div>
  182. </el-col>
  183. </el-row>
  184. </div>
  185. </template>
  186. <script>
  187. import API_FLASHDELIVER_JIAOSHUIMA from "@/api/flashdeliver/jiaoshuima";
  188. import NumberInput from "@/components/NumberInput";
  189. import {
  190. companyGetselectlist,
  191. organizationGetselectlist,
  192. organisationVirtualarchitectureList,
  193. getRoomInfo
  194. } from "@/api/flashdeliver/jiaoshuima";
  195. export default {
  196. components: { NumberInput },
  197. data() {
  198. return {
  199. postFormLoading: false,
  200. uploadUrl: this.axiosURL + `${process.env.BASE_API}/common/file/upload`, // 上传图片的地址
  201. postForm: {
  202. id: "",
  203. operationsCenterId: "",
  204. orgId: "",
  205. orgName: "",
  206. roomMarkId: "",
  207. roomInfo: "",
  208. virtId: "",
  209. virtName: "",
  210. merchantId: "",
  211. merchantName: "",
  212. residentNum: "",
  213. historyInfo: "",
  214. listMgtGoods: [],
  215. bonusProportion: "",
  216. customerManagerId: "",
  217. customerManagerName: ""
  218. },
  219. postFormRule: {
  220. roomMarkId: [{ required: true, message: "房间号不能为空", trigger: "change" }],
  221. virtId: [{ required: true, message: "企业不能为空", trigger: "change" }],
  222. listMgtGoods: [
  223. {
  224. required: true,
  225. type: "array",
  226. validator: (rule, value, callback) => {
  227. const listMgtGoods = value.filter(v => Boolean(v.productName));
  228. if (!listMgtGoods.length) {
  229. return callback(new Error("叫水商品不能为空"));
  230. }
  231. callback();
  232. },
  233. trigger: "change"
  234. }
  235. ]
  236. },
  237. operationsCenterList: [], // 运营中心列表
  238. projectList: [], // 项目列表
  239. virtList: [], // 企业列表
  240. roomList: [],
  241. productList: [],
  242. searchProductLoading: false,
  243. searchAccountManagerList: []
  244. };
  245. },
  246. computed: {
  247. userInfo() {
  248. return this.$store.getters.userInfo
  249. },
  250. pageStatus() {
  251. return this.$route.query.id ? "update" : "create";
  252. }
  253. },
  254. async created() {
  255. const { id } = this.$route.query;
  256. if (id) {
  257. this.postForm.id = id;
  258. this.queryDetail();
  259. } else {
  260. if (this.userInfo.userTypeModel == "project") {
  261. this.postForm.operationsCenterId = this.userInfo.companyId;
  262. this.postForm.orgId = this.userInfo.orgId;
  263. } else if (this.userInfo.userTypeModel == "operationsCenter") {
  264. this.postForm.operationsCenterId = this.userInfo.companyId;
  265. await this.getProjectList();
  266. } else {
  267. await this.getOperationsCenterList();
  268. }
  269. this.onProjectChange();
  270. this.onProductAdd();
  271. this.onProductAdd();
  272. }
  273. },
  274. methods: {
  275. queryDetail() {
  276. API_FLASHDELIVER_JIAOSHUIMA.query({
  277. roomMarkId: this.$route.query.roomMarkId
  278. }).then(res => {
  279. this.postForm = res.data;
  280. this.postForm.virtId = String(res.data.virtId);
  281. this.onProjectChange();
  282. });
  283. },
  284. getSelectField(value, listKey, valueKey = "value", labelKey = "label") {
  285. const ov = this[listKey].find(v => v[valueKey] === value);
  286. return ov ? ov[labelKey] : "";
  287. },
  288. postFormSubmit() {
  289. this.$refs["postForm"].validate(valid => {
  290. if (valid) {
  291. const params = {
  292. orgId: this.postForm.orgId,
  293. orgName: this.postForm.orgName,
  294. virtId: this.postForm.virtId,
  295. virtName: this.postForm.virtName,
  296. roomMarkId: this.postForm.roomMarkId,
  297. roomInfo: this.postForm.roomInfo,
  298. merchantId: this.postForm.merchantId,
  299. merchantName: this.postForm.merchantName,
  300. historyInfo: this.postForm.historyInfo,
  301. residentNum: Number(this.postForm.residentNum),
  302. listMgtGoods: this.postForm.listMgtGoods.filter(v => Boolean(v.productName)),
  303. customerManagerId: this.postForm.customerManagerId,
  304. customerManagerName: this.postForm.customerManagerName,
  305. bonusProportion: Number(this.postForm.bonusProportion)
  306. };
  307. this.pageStatus === "update" && (params.id = this.postForm.id);
  308. this.postFormLoading = true;
  309. // console.log("API_FLASHDELIVER_JIAOSHUIMA", this.pageStatus, params);
  310. // this.postFormLoading = false;
  311. API_FLASHDELIVER_JIAOSHUIMA[this.pageStatus](params)
  312. .then(res => {
  313. this.$message({
  314. message: "操作成功",
  315. type: "success",
  316. duration: 1500,
  317. onClose: () => {
  318. this.$router.back();
  319. }
  320. });
  321. })
  322. .finally(() => {
  323. this.postFormLoading = false;
  324. });
  325. }
  326. });
  327. },
  328. onProductChange(value, index) {
  329. const ov = this.productList.find(v => v.id === value);
  330. const listMgtGoods = this.postForm.listMgtGoods.filter(v => Boolean(v.productName));
  331. if (listMgtGoods.length && this.postForm.merchantId && ov.saleId !== this.postForm.merchantId) {
  332. this.$message.error("抱歉,不支持添加跨商户商品!");
  333. return;
  334. }
  335. this.postForm.merchantId = ov.saleId;
  336. this.postForm.merchantName = ov.saleName;
  337. this.postForm.listMgtGoods.splice(index, 1, {
  338. productId: ov.id,
  339. productName: ov.productName,
  340. listFile: ov.listFile,
  341. price: ov.price,
  342. descr: ov.descr,
  343. quantity: 1
  344. });
  345. },
  346. onMgtGoodDel(index) {
  347. if (this.postForm.listMgtGoods.length === 1) {
  348. this.postForm.merchantId = "";
  349. this.postForm.merchantName = "";
  350. }
  351. this.postForm.listMgtGoods.splice(index, 1);
  352. },
  353. onProductAdd() {
  354. this.postForm.listMgtGoods.push({
  355. productName: ""
  356. });
  357. },
  358. searchProduct(query) {
  359. if (query !== "") {
  360. this.searchProductLoading = true;
  361. API_FLASHDELIVER_JIAOSHUIMA.productList({
  362. pageNo: 1,
  363. pageSize: 999,
  364. operationsCenterId: this.postForm.operationsCenterId,
  365. projectId: this.postForm.orgId,
  366. productName: query,
  367. isProductSpec: 0,
  368. status: 2 // 已上架
  369. })
  370. .then(res => {
  371. this.productList = res.data;
  372. })
  373. .finally(() => {
  374. this.searchProductLoading = false;
  375. });
  376. } else {
  377. this.productList = [];
  378. }
  379. },
  380. // searchAccountManagerFun(query) {
  381. // if (query !== "") {
  382. // this.searchAccountManagerLoading = true;
  383. // const params = {
  384. // pageNo: 1,
  385. // pageSize: 999,
  386. // conditions: { keyword: query }
  387. // };
  388. // this.postForm.orgId && (params["conditions[orgId]"] = this.postForm.orgId);
  389. // API_FLASHDELIVER_JIAOSHUIMA.queryAdminUser(params)
  390. // .then(res => {
  391. // this.searchAccountManagerList = res.data;
  392. // })
  393. // .finally(() => {
  394. // this.searchAccountManagerLoading = false;
  395. // });
  396. // } else {
  397. // this.searchAccountManagerList = [];
  398. // }
  399. // },
  400. onSelectChange() {
  401. this.postForm["roomInfo"] = this.getSelectField(this.postForm.roomMarkId, "roomList", "roomMarkId", "roomName");
  402. },
  403. onSelect2Change() {
  404. this.postForm["virtName"] = this.getSelectField(this.postForm.virtId, "virtList");
  405. },
  406. onSelect3Change() {
  407. this.postForm["customerManagerName"] = this.getSelectField(
  408. this.postForm.customerManagerId,
  409. "searchAccountManagerList",
  410. "id",
  411. "realName"
  412. );
  413. },
  414. onOperationsCenterChange() {
  415. this.getProjectList();
  416. },
  417. onProjectChange() {
  418. this.postForm["orgName"] = this.getSelectField(this.postForm.orgId, "projectList");
  419. this.getVirtList();
  420. this.getRoomList();
  421. if (this.postForm.orgId) {
  422. this.getAccountMangerList();
  423. }
  424. },
  425. getAccountMangerList() {
  426. const params = {
  427. pageNo: 1,
  428. pageSize: 999,
  429. conditions: {
  430. orgId: this.postForm.orgId
  431. // keyword: query
  432. }
  433. };
  434. API_FLASHDELIVER_JIAOSHUIMA.queryAdminUser(params).then(res => {
  435. this.searchAccountManagerList = res.data;
  436. });
  437. },
  438. getRoomList() {
  439. const params = {
  440. pageNo: 1,
  441. pageSize: 999,
  442. conditions: {
  443. orgId: this.postForm.orgId
  444. // queryRoomName: query || '',
  445. }
  446. };
  447. getRoomInfo(params).then(res => {
  448. this.roomList = res.data.data;
  449. });
  450. },
  451. async getVirtList() {
  452. const params = {
  453. pageNo: 1,
  454. pageSize: 999,
  455. conditions: {
  456. orgId: this.postForm.orgId
  457. }
  458. };
  459. organisationVirtualarchitectureList(params).then(res => {
  460. this.virtList = res.data;
  461. });
  462. },
  463. async getProjectList() {
  464. const params = {
  465. pageNo: 1,
  466. pageSize: 999
  467. };
  468. this.postForm.operationsCenterId && (params["conditions[companyId]"] = this.postForm.operationsCenterId);
  469. const res = await organizationGetselectlist(params);
  470. this.projectList = res.data;
  471. if (res.data && res.data.length === 1) {
  472. this.postForm.orgId = res.data[0].value;
  473. }
  474. },
  475. async getOperationsCenterList() {
  476. const res = await companyGetselectlist();
  477. this.operationsCenterList = res.data;
  478. if (res.data && res.data.length) {
  479. const operationsCenterId = res.data[0].value;
  480. this.postForm.operationsCenterId = operationsCenterId;
  481. this.getProjectList();
  482. }
  483. }
  484. }
  485. };
  486. </script>
  487. <style lang="scss" scoped>
  488. .upload-image {
  489. box-sizing: border-box;
  490. width: 60px;
  491. height: 60px;
  492. }
  493. .upload-tip {
  494. font-size: 12px;
  495. color: #606266;
  496. margin-top: 7px;
  497. }
  498. .image-preview {
  499. position: relative;
  500. width: 60px;
  501. height: 60px;
  502. img {
  503. width: 100%;
  504. height: 100%;
  505. }
  506. }
  507. .image-preview-action {
  508. position: absolute;
  509. width: 100%;
  510. height: 100%;
  511. left: 0;
  512. top: 0;
  513. cursor: default;
  514. text-align: center;
  515. color: #fff;
  516. opacity: 0;
  517. font-size: 20px;
  518. background-color: rgba(0, 0, 0, 0.5);
  519. transition: opacity 0.3s;
  520. cursor: pointer;
  521. text-align: center;
  522. line-height: 200px;
  523. .el-icon-delete {
  524. font-size: 36px;
  525. }
  526. }
  527. .product-bottom {
  528. padding: 10px 0;
  529. text-align: center;
  530. font: 18px;
  531. font-weight: bold;
  532. color: #409eff;
  533. border-radius: 4px;
  534. cursor: pointer;
  535. }
  536. .product {
  537. display: flex;
  538. &-img {
  539. width: 60px;
  540. height: 60px;
  541. margin-right: 10px;
  542. border-radius: 4px;
  543. }
  544. &-inner {
  545. flex: 1;
  546. min-width: 0;
  547. }
  548. &-title {
  549. font-size: 14px;
  550. line-height: 20px;
  551. color: #333;
  552. overflow: hidden;
  553. text-overflow: ellipsis;
  554. overflow: hidden;
  555. white-space: nowrap;
  556. word-break: break-all;
  557. margin-bottom: 2px;
  558. }
  559. &-desc {
  560. color: #999;
  561. font-size: 12px;
  562. line-height: 18px;
  563. overflow: hidden;
  564. text-overflow: ellipsis;
  565. display: -webkit-box;
  566. -webkit-line-clamp: 2;
  567. -webkit-box-orient: vertical;
  568. margin-bottom: 2px;
  569. }
  570. &-price {
  571. color: #f56c6c;
  572. }
  573. }
  574. .tips {
  575. padding: 2px 0;
  576. font-size: 14px;
  577. line-height: 1.4;
  578. color: #999999;
  579. letter-spacing: 0;
  580. text-align: left;
  581. }
  582. .page-container .el-select {
  583. display: block;
  584. }
  585. </style>