lj-button-menu.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. <!--
  2. @name 按钮菜单组件
  3. @desc 基于Muse UI
  4. 【必填参数】:
  5. @param [Array] [buttons] - 选填必要参数之一 或 使用方法 addMain({Object}) | addMore({Object}) 来初始化按钮
  6. @example1: buttons[
  7. {
  8. type:"main", // 按钮分类
  9. icon:"icon-ic_add", // 按钮图标
  10. color:"primary", // 按钮颜色
  11. span:3, // 按钮栅格占据的格数
  12. label:"明细", // 按钮文本
  13. isIconLeft:true, // 按钮图标是否靠左
  14. methodName:"add" // 按钮执行方法名
  15. },
  16. {
  17. type: "more",
  18. icon:"icon-settings",
  19. color:"grey",
  20. label:"布局",
  21. methodName:"setting"
  22. }
  23. ]
  24. @example2:
  25. this.$refs.xxxx
  26. .addMainMenu({icon:"icon-ic_add",color:"primary",span:3,label:"明细",iconLeft:true,methodName:"add"})
  27. .addMoreMenu({icon:"icon-settings",color:"grey",label:"布局",methodName:"setting"})
  28. .addMoreMenu({icon:"icon-ic_refresh",color:"grey",label:"清空",methodName:"clean"})
  29. 【选填参数】
  30. @param String [justifyContent] - 主轴的 flex 元素对齐方式
  31. @default: start
  32. @param String [alignItems] - 定义了侧轴方向上将当前行上的 flex 元素对齐方式
  33. @default: end
  34. 【插槽】
  35. @slot [default] - 主按钮与更多按钮之间自定义内容
  36. 【回调出参】
  37. @function {out} callFunction(methodName) - 按钮事件;
  38. 【参数】String methodName - 按钮事件方法名
  39. 【父组件调用方法】
  40. @function {in} handleLayoutSetting({param}) - 设置布局;
  41. @function {in} MergeCustomSetting({param}) - 获取布局;
  42. 【参数】param:{
  43. dwname:xxxx,
  44. apiName:xxxx,
  45. gridColumns:xxxx
  46. }
  47. 【实例】
  48. e.g. <button-menu-tools align-items = "start" :buttons = "buttonList" />
  49. -->
  50. <template>
  51. <div class="LjButtonMenu">
  52. <mu-row :justify-content="justifyContent" :align-items="alignItems">
  53. <mu-col :span="moreVisiable ? '10' : '12'">
  54. <mu-row class="button-menu-row">
  55. <template v-if="mainMenu.length > 0">
  56. <template v-for="(item,index) in mainMenu">
  57. <mu-col :key="index" :order="item.order" :span="item.span" v-if="item.visiable" :offset="item.offset">
  58. <template v-if="item.type == 'search'">
  59. <div class="search-box">
  60. <div class="prepend">
  61. <mu-select v-model="selectValue" class="prepend-select" @change="handleSelmuSelect">
  62. <i class="iconfont icon-search" slot="prepend" />
  63. <mu-option v-for="(option, idx) in selectList" :key="idx" :label="option" :value="option"></mu-option>
  64. </mu-select>
  65. </div>
  66. <div class="content">
  67. <mu-auto-complete class="search-auto-complete" :data="autoCompleteFruits" :max-search-results="5" v-model="searchAutoComplete" @select="handleSelectAutoComplete" @keyup.enter.native="handleEnterAutoComplete" open-on-focus>
  68. </mu-auto-complete>
  69. </div>
  70. <div class="append">
  71. <mu-button small round class="append-btn" color="primary" @click="handleEnterAutoComplete">
  72. 搜索
  73. </mu-button>
  74. </div>
  75. </div>
  76. </template>
  77. <template v-else-if="item.type == 'chip'">
  78. <mu-chip class="btnmenu-chip" :color="item.color" @click.stop="callFunction(item.methodName)" @delete="handleDelChip" delete>
  79. <template v-if="item.icon">
  80. <i :class="['iconfont',item.icon]" v-if="item.isIconLeft" />
  81. <span class="text-ellipsis-one">
  82. {{item.label}}
  83. </span>
  84. <i :class="['iconfont',item.icon]" v-if="!item.isIconLeft" />
  85. </template>
  86. <template v-else>
  87. <span class="text-ellipsis-one">
  88. {{item.label}}
  89. </span>
  90. </template>
  91. </mu-chip>
  92. </template>
  93. <template v-else-if="item.type == 'select'">
  94. <van-popover v-model:show="popoverOpen" :actions="popoverList" @select="handleClickPopoverItem">
  95. <template #reference>
  96. <van-button :type="item.color" plain size="small" class="vanbuttonTomu" @click="callFunction(item.methodName)">
  97. {{item.label}}{{item.value}}
  98. </van-button>
  99. </template>
  100. </van-popover>
  101. </template>
  102. <template v-else>
  103. <mu-button :color="item.color" flat @click="callFunction(item.methodName)">
  104. <template v-if="item.icon">
  105. <i :class="['iconfont',item.icon]" v-if="item.isIconLeft" />
  106. {{item.label}}
  107. <i :class="['iconfont',item.icon]" v-if="!item.isIconLeft" />
  108. </template>
  109. <template v-else>{{item.label}}</template>
  110. </mu-button>
  111. </template>
  112. </mu-col>
  113. </template>
  114. </template>
  115. <slot></slot>
  116. </mu-row>
  117. </mu-col>
  118. <mu-col v-if="moreVisiable && moreButtons.length > 0" span="2">
  119. <mu-menu placement="bottom-end" :open.sync="openMenu">
  120. <mu-button class="more-btn" flat>
  121. <i class="iconfont icon-more" />
  122. <mu-badge class="more-badge" v-if="morebadge" color="#FF3B30" :content="morebadge"></mu-badge>
  123. </mu-button>
  124. <mu-list slot="content">
  125. <template v-for="(item,index) in moreButtons">
  126. <mu-list-item button :key="index" @click="callFunction(item.methodName)" v-if="item.visiable">
  127. <mu-list-item-action><i :class="['iconfont',item.icon]" /></mu-list-item-action>
  128. <mu-list-item-title>{{item.label}}</mu-list-item-title>
  129. <mu-list-item-action v-if="item.badge">
  130. <mu-badge class="more-badge" :color="item.badgeColor" :content="item.badge"></mu-badge>
  131. </mu-list-item-action>
  132. </mu-list-item>
  133. </template>
  134. </mu-list>
  135. </mu-menu>
  136. </mu-col>
  137. </mu-row>
  138. </div>
  139. </template>
  140. <script>
  141. export default {
  142. components: {},
  143. props: {
  144. justifyContent: {
  145. type: String,
  146. default: "between"
  147. },
  148. alignItems: {
  149. type: String,
  150. default: "end"
  151. },
  152. mainButtons: {
  153. type: Array,
  154. default: () => {return []}
  155. },
  156. moreButtons: {
  157. type: Array,
  158. default: () => {return []}
  159. },
  160. moreVisiable: {
  161. type: Boolean,
  162. default: true
  163. },
  164. morebadge: { // 更多icon的微标
  165. type: String,
  166. default:''
  167. },
  168. autoCompleteFruits: { // 搜索推荐列表
  169. type: Array,
  170. default: () => {return []}
  171. },
  172. selectList: { // 搜索推荐列表
  173. type: Array,
  174. default: () => {return []}
  175. }
  176. },
  177. watch:{
  178. mainButtons: function(){
  179. this.mainMenu = this.mainButtons
  180. },
  181. // moreMenu: function(){
  182. // this.moreMenu = this.moreButtons
  183. // }
  184. // moreMenu: {
  185. // handler(val, oldVal) {
  186. // this.moreMenu = this.moreButtons
  187. // },
  188. // deep: true
  189. // }
  190. },
  191. data() {
  192. return {
  193. mainMenu: this.mainButtons,
  194. openMenu: false,
  195. // moreMenu: this.moreButtons
  196. selectValue: '',
  197. searchAutoComplete: "",
  198. popoverOpen: false,
  199. trigger: null,
  200. activeButton: null,
  201. popoverList: []
  202. }
  203. },
  204. methods: {
  205. /**清空搜索结果 */
  206. handleDelChip() {
  207. this.$emit('clearSearch');
  208. },
  209. /**搜索栏:mu-select下拉选择时 */
  210. handleSelmuSelect(val) {
  211. this.$emit('selMuSelect', val);
  212. },
  213. /**设置下拉初始值 */
  214. fnSetSelectVal(val) {
  215. this.selectValue = val;
  216. this.searchAutoComplete = '';
  217. },
  218. /**搜索栏:点击下拉推荐搜索 */
  219. handleSelectAutoComplete(val, item) {
  220. this.$emit('confirmAutoComplete', this.selectValue, {val, item});
  221. },
  222. /**搜索栏:回车或点击搜索 */
  223. handleEnterAutoComplete() {
  224. this.$emit('confirmAutoComplete', this.selectValue, {val:this.searchAutoComplete});
  225. },
  226. handleOpenPopover() {
  227. this.popoverOpen = true;
  228. },
  229. handleClosePopover() {
  230. this.popoverOpen = false;
  231. },
  232. handleSetPopoverList(list) {
  233. this.popoverList = list
  234. },
  235. handleClickPopoverItem(item) {
  236. this.$emit("callPopoverFunction",item.text)
  237. },
  238. callFunction(methodName) {
  239. this.openMenu = false;
  240. this.$emit("callFunction", methodName);
  241. },
  242. addMainMenu(button) {
  243. this.mainMenu.push(button)
  244. return this;
  245. },
  246. addMoreMenu(button) {
  247. this.moreMenu.push(button)
  248. return this;
  249. },
  250. /** 设置布局 */
  251. handleLayoutSetting(param) {
  252. let self = this;
  253. $lj.removeEventListener("grid_style_updated");
  254. $lj.addEventListener("grid_style_updated", function (ret) {
  255. if (ret.value) {
  256. if (ret.value.dwname === param.dwname && ret.value.itemname === param.apiName) {
  257. self.MergeCustomSetting(param);
  258. }
  259. }
  260. });
  261. $lj.openWin('grid-drag-setting', {
  262. columns: param.gridColumns,
  263. apiName: param.apiName
  264. });
  265. },
  266. MergeCustomSetting(param, callback) {
  267. let userInfo = $lj.getStorage('userInfo');
  268. let empid = userInfo.empid;
  269. let requestBody = {
  270. token: $lj.getStorage("token"),
  271. empid: empid,
  272. dwname: param.dwname,
  273. itemname: param.apiName,
  274. ifcompress: 1
  275. };
  276. $lj.postLJRequest("GetSysUserFileString", requestBody, function (ret) {
  277. if (ret && ret.itemvalue) {
  278. let customSetting = JSON.parse(ret.itemvalue);
  279. // 构建field-style键值对
  280. let customSettingDictionary = new Map();
  281. for (let item of customSetting) {
  282. customSettingDictionary.set(item.property, item);
  283. }
  284. // 合并过滤字段,以这个字典为准,用户历史设置多删少补
  285. for (let item of param.gridColumns) {
  286. let curField = item.property;
  287. let userStyle = customSettingDictionary.get(curField);
  288. if (userStyle) {
  289. for (let prop in userStyle) {
  290. item[prop] = userStyle[prop];
  291. }
  292. // item.order = userStyle.order;
  293. // item.invisible = userStyle.invisible;
  294. } else {
  295. // 新增字段,暂不显示
  296. // item.invisible = true;
  297. }
  298. }
  299. } else {
  300. for (let i in param.gridColumns) {
  301. param.gridColumns[i].order = i;
  302. }
  303. }
  304. param.gridColumns.sort(function (object1, object2) {
  305. return object1.order - object2.order;
  306. });
  307. for (let i in param.gridColumns) {
  308. let item = param.gridColumns[i];
  309. item.order = i;
  310. if (item.optionid) {
  311. let optionName = $lj.getOptionValue(item.optionid);
  312. item.label = optionName ? optionName : item.label;
  313. }
  314. // if (item.fixed) {
  315. // param.gridColumns.push(item);
  316. // }
  317. }
  318. callback && callback()
  319. });
  320. }
  321. },
  322. created() {
  323. },
  324. mounted() {
  325. }
  326. }
  327. </script>
  328. <style lang='less'>
  329. .vanbuttonTomu {
  330. border: none;
  331. line-height: 36px;
  332. font-size: 14px;
  333. background: transparent;
  334. min-width: 88px;
  335. border-radius: 2px;
  336. height: 36px;
  337. }
  338. .mu-flat-button .mu-button-wrapper{
  339. padding: 0px;
  340. }
  341. .button-menu-row {
  342. .iconfont {
  343. margin-right: 2px;
  344. }
  345. }
  346. .more-badge {
  347. margin-left: 4px;
  348. border-radius: 9px;
  349. }
  350. .search-auto-complete {
  351. width: 100%;
  352. }
  353. .search-box {
  354. display: flex;
  355. width: 100%;
  356. .prepend, .append {
  357. flex-shrink: 0;
  358. display: flex;
  359. align-items: center;
  360. }
  361. .content {
  362. flex: 1;
  363. }
  364. .prepend {
  365. margin-left: 8px;
  366. width: 100px;
  367. display: flex;
  368. }
  369. .prepend-select {
  370. width: 100%!important;
  371. margin-bottom: 0;
  372. margin-left: 8px;
  373. padding: 0;
  374. padding-left: 8px;
  375. padding-bottom: 4px;
  376. line-height: 32px!important;
  377. font-size: 14px;
  378. .mu-select-action {
  379. padding: 0;
  380. .mu-select-icom {
  381. width: 14px;
  382. height: 14px;
  383. }
  384. }
  385. }
  386. .append-btn {
  387. width: 60px;
  388. min-width: 60px;
  389. }
  390. .mu-input {
  391. min-height: 32px;
  392. margin: 0;
  393. padding: 2px 0;
  394. font-size: 14px;
  395. }
  396. }
  397. .btnmenu-chip {
  398. vertical-align: middle;
  399. .mu-chip-delete-icon {
  400. flex-shrink: 0;
  401. }
  402. }
  403. </style>
  404. <style lang='less' scoped>
  405. .LjButtonMenu{
  406. width: 100%;
  407. }
  408. .iconfont{
  409. font-size: 14px;
  410. }
  411. .mu-item-action {
  412. min-width: 30px;
  413. }
  414. .mu-flat-button {
  415. min-width: auto;
  416. width:100%;
  417. }
  418. .mu-menu{
  419. width: 100%;
  420. }
  421. </style>