multiple_liu1tian.vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. <script>
  2. import { REFER } from "../popover-select/api/index";
  3. import deepCopy from "@gby/deep-copy";
  4. export default {
  5. name: "PopoverSelectV2",
  6. props: {
  7. // v-model
  8. value: {
  9. type: [Array, String, Number],
  10. require: true,
  11. },
  12. // 参照类型 ,对应后端
  13. referName: {
  14. type: String,
  15. require: true,
  16. },
  17. // 作为 value 唯一标识的键名,绑定值
  18. valueKey: {
  19. type: [String, null, undefined],
  20. },
  21. // 默认查询参数
  22. queryParams: {
  23. type: Function,
  24. default: () => {},
  25. },
  26. // 需映射源数据
  27. source: {
  28. type: Object,
  29. default: () => ({}),
  30. },
  31. // 参照内外映射
  32. dataMapping: {
  33. type: Object,
  34. default: () => ({}),
  35. },
  36. // 回显
  37. dataListArray: {
  38. type: Array
  39. },
  40. },
  41. components: {
  42. ElSuperTable: () => import("@/components/super-table/index.vue"),
  43. },
  44. data() {
  45. return {
  46. size: "mini",
  47. width: "50%",
  48. page: { pageNum: 1, pageSize: 10, total: 0 },
  49. visible: false,
  50. loading: false,
  51. scroll: false,
  52. model: {
  53. search: "",
  54. isPage: true,
  55. },
  56. data: [],
  57. selectData: [],
  58. lastSelectData: [],
  59. };
  60. },
  61. computed: {
  62. innerValue: {
  63. get() {
  64. return this.value;
  65. },
  66. set(value) {
  67. this.$emit("input", value);
  68. },
  69. },
  70. TableColumns: {
  71. get() {
  72. const { referName } = this.$props;
  73. return require(`../popover-select/components/${referName}`).default;
  74. },
  75. },
  76. },
  77. watch: {
  78. innerValue: {
  79. handler: function (newValue) {
  80. if (!newValue) this.lastSelectData = [];
  81. },
  82. },
  83. dataListArray: {
  84. handler: function (newValue) {
  85. console.log("A:::" + JSON.stringify(newValue))
  86. if (newValue.length>0){
  87. newValue.forEach(element => {
  88. this.lastSelectData.push(element)
  89. });
  90. }
  91. },
  92. immediate: true
  93. }
  94. },
  95. methods: {
  96. // open dialog
  97. async open() {
  98. let { disabled } = this.$attrs;
  99. if (!disabled) {
  100. this.visible = true;
  101. await this.useReset();
  102. }
  103. },
  104. // hide dialog
  105. async hide() {
  106. this.visible = false;
  107. },
  108. // fetch list
  109. async fetchList(prop, page) {
  110. try {
  111. // try
  112. this.loading = true;
  113. const { pageNum, pageSize } = page;
  114. const { referName: type, source, queryParams } = this.$props;
  115. const { code, rows, total } = await REFER(
  116. {
  117. ...prop,
  118. ...queryParams(source),
  119. type: type,
  120. },
  121. {
  122. pageNum,
  123. pageSize,
  124. }
  125. );
  126. if (code === 200) {
  127. this.data = rows;
  128. this.page.total = total;
  129. }
  130. } catch (err) {
  131. // catch
  132. console.error(err);
  133. } finally {
  134. // finally
  135. this.loading = false;
  136. }
  137. },
  138. // reset
  139. async useReset() {
  140. this.data = [];
  141. this.model.search = null;
  142. await this.fetchList(this.model, this.page);
  143. },
  144. // query
  145. async useQuery() {
  146. await this.fetchList(this.model, this.page);
  147. },
  148. // select
  149. useSelect(prop) {
  150. this.selectData = prop;
  151. },
  152. // delete
  153. useDelete(prop) {
  154. this.selectData.splice(prop, 1);
  155. this.useConfirm(this.selectData);
  156. },
  157. // confirm
  158. useConfirm(prop) {
  159. const {
  160. $props: { valueKey },
  161. } = this;
  162. // string
  163. if (typeof valueKey === "string") {
  164. this.innerValue = prop.map((item) => item[valueKey]);
  165. }
  166. // null
  167. else {
  168. this.innerValue = prop;
  169. }
  170. //
  171. this.hide();
  172. this.lastSelectData = deepCopy(prop);
  173. // console.log("A:::" + JSON.stringify(this.lastSelectData))
  174. this.$emit("change", prop, this.$props);
  175. },
  176. // cancel
  177. useCancel() {
  178. this.hide();
  179. },
  180. },
  181. created() {},
  182. mounted() {},
  183. destroyed() {},
  184. };
  185. </script>
  186. <template>
  187. <div class="popover-select-v2 popover-select-v2--multiple">
  188. <el-input v-bind="$attrs" @focus="open">
  189. <i class="el-icon-search" slot="suffix" @click="open"> </i>
  190. </el-input>
  191. <el-dialog
  192. :width="width"
  193. :visible.sync="visible"
  194. :show-close="false"
  195. :close-on-click-modal="false"
  196. :close-on-press-escape="false"
  197. append-to-body
  198. >
  199. <div slot="title" style="display: flex; justify-content: space-between">
  200. <el-form
  201. :size="size"
  202. :inline="true"
  203. :model="model"
  204. @submit.native.prevent
  205. style="display: flex; flex-direction: column"
  206. >
  207. <div>
  208. <el-form-item prop="search">
  209. <el-input
  210. v-model="model.search"
  211. @change="useQuery"
  212. @keydown.enter="useQuery"
  213. >
  214. </el-input>
  215. </el-form-item>
  216. <el-form-item>
  217. <el-button icon="el-icon-refresh" @click="useReset"></el-button>
  218. </el-form-item>
  219. </div>
  220. </el-form>
  221. <div>
  222. <el-button
  223. type="primary"
  224. :size="$attrs.size"
  225. :loading="loading"
  226. @click="useConfirm(selectData)"
  227. >
  228. 确认
  229. </el-button>
  230. <el-button :size="$attrs.size" :loading="loading" @click="hide">
  231. 取消
  232. </el-button>
  233. </div>
  234. </div>
  235. <div
  236. v-loading="loading"
  237. style="height: 40vh; display: flex; margin-top: -30px"
  238. >
  239. <el-super-table
  240. v-model="data"
  241. :size="size"
  242. :page="page"
  243. :columns="TableColumns"
  244. checkbox
  245. pagination
  246. highlight-current-row
  247. @pagination="useQuery"
  248. @row-select="useSelect"
  249. @row-dblclick="useConfirm([$event])"
  250. >
  251. </el-super-table>
  252. </div>
  253. </el-dialog>
  254. <el-scrollbar
  255. v-if="lastSelectData.length"
  256. :viewStyle="{
  257. display: 'flex',
  258. alignItems: 'center',
  259. padding: '5px 0 0 5px',
  260. }"
  261. class="popover-select-v2_tags"
  262. >
  263. <el-tag
  264. v-for="(tag, index) in lastSelectData"
  265. hit
  266. closable
  267. :size="size"
  268. @close="useDelete(index)"
  269. style="margin-right: 5px"
  270. >
  271. {{ tag.name || tag[valueKey] }}
  272. </el-tag>
  273. </el-scrollbar>
  274. </div>
  275. </template>
  276. <style scoped>
  277. .popover-select-v2 .el-input {
  278. width: inherit;
  279. height: 100%;
  280. }
  281. .popover-select-v2 .el-input .el-icon-search {
  282. cursor: pointer;
  283. }
  284. .popover-select-v2 .popover-select-v2_tags {
  285. position: absolute;
  286. left: 0;
  287. top: 50%;
  288. transform: translateY(-50%);
  289. width: calc(100% - 40px);
  290. height: 100%;
  291. }
  292. ::v-deep .el-table--mini .el-table__cell {
  293. height: 50px;
  294. }
  295. </style>