index.vue 6.7 KB

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