0e0a4f7a53d06a726790d89b0f02987287c58c7d.svn-base 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. <template>
  2. <div id="singleDataTableManager">
  3. <div id="searchPanel" style="background-color:rgba(6, 186, 240, 0.08);border:1px dashed blue;border:0px 0px 0px 1px;padding-top:10px;padding-bottom:10px;">
  4. <el-row :gutter="20" style='padding-left:10px;padding-right:10px;'>
  5. <el-col :span="20" style="padding-top:1px;">
  6. <el-row :gutter="20" style='padding-left:10px;padding-right:10px;'>
  7. <el-col style='padding-bottom:10px;' :span="4" v-for="searchItem in mainSearchConfigure" :key="searchItem.label">
  8. <span style="font-size: small;font-weight: lighter;">{{searchItem.label}}</span>
  9. <div style="flex-basis:50%;display:flex;flex-direction:row;justify-content:flex-end;">
  10. <el-input :placeHolder="searchItem.label" v-if="searchItem.type=='text'" v-model="searchDataObject[searchItem.prop]"></el-input>
  11. <el-input :placeHolder="searchItem.label" v-if="searchItem.type=='tree'" @focus="showTrees" v-model="areaTxt"></el-input>
  12. <el-date-picker :placeHolder="searchItem.label" style="width:100%;" v-if="searchItem.type=='date'" v-model="searchDataObject[searchItem.prop]"></el-date-picker>
  13. <el-select-dict :placeHolder="searchItem.label" v-if="searchItem.type=='select'" :dictId="searchItem['refObjValue']" :initialValue="searchDataObject[searchItem.prop]" v-model="searchDataObject[searchItem.prop]"></el-select-dict>
  14. </div>
  15. </el-col>
  16. </el-row>
  17. </el-col>
  18. <el-col style='padding-bottom:10px;' :span="4" >
  19. <el-button style="float:right;" type="info" plain
  20. size="mini"
  21. @click="showExpandSearchPanel = !showExpandSearchPanel"
  22. v-show="expandSearchConfigue.length > 0"
  23. >
  24. 更多
  25. <i class="el-icon-arrow-down el-icon--right" v-show="!showExpandSearchPanel"/>
  26. <i class="el-icon-arrow-up el-icon--right" v-show="showExpandSearchPanel"/>
  27. </el-button>
  28. </el-col>
  29. </el-row>
  30. <el-row :gutter="24" style='padding-left:10px;padding-right:10px;' v-show="showExpandSearchPanel">
  31. <el-col style='padding-bottom:10px;' :span="4" v-for="searchItem in expandSearchConfigue" v-if="!searchItem.isMain" :key="searchItem.label">
  32. <span style="font-size: small;font-weight: lighter;">{{searchItem.label}}</span>
  33. <div style="flex-basis:50%;display:flex;flex-direction:row;justify-content:flex-end;">
  34. <el-input :placeHolder="searchItem.label" v-if="searchItem.type=='text'" v-model="searchDataObject[searchItem.prop]"></el-input>
  35. <el-input :placeHolder="searchItem.label" v-if="searchItem.type=='tree'" @focus="showTrees" v-model="areaTxt"></el-input>
  36. <el-date-picker :placeHolder="searchItem.label" style="width:100%;" v-if="searchItem.type=='date'" v-model="searchDataObject[searchItem.prop]"></el-date-picker>
  37. <el-select-dict :placeHolder="searchItem.label" v-if="searchItem.type=='select'" :dictId="searchItem['refObjValue']" :initialValue="searchDataObject[searchItem.prop]" v-model="searchDataObject[searchItem.prop]"></el-select-dict>
  38. </div>
  39. </el-col>
  40. </el-row>
  41. <el-row>
  42. <el-col :span="24">
  43. <el-button v-for="action in outerActions" :key="action.name" type="primary" style="float:right;margin-right:5px;"
  44. size="small"
  45. @click="handleouterActions(action)">{{action.label}}
  46. </el-button>
  47. </el-col>
  48. </el-row>
  49. </div>
  50. <el-container style="margin-top:10px;">
  51. <el-main style="padding:5px;">
  52. <el-table
  53. :data="tableData"
  54. stripe
  55. :height="mainHeight"
  56. border
  57. style="width: 100%"
  58. >
  59. <!--数据列配置-->
  60. <el-table-column v-for="colmun in tableViewConfigure" :key="colmun.prop" v-if="colmun.isHidden!='1'"
  61. :prop="colmun.prop"
  62. show-overflow-tooltip
  63. header-align="center"
  64. align="center"
  65. :label="colmun.label"
  66. :min-width="colmun.width">
  67. <template slot-scope="scope">
  68. {{tableColumnsFormatter(scope.row,scope,scope.$index,colmun)}}
  69. </template>
  70. </el-table-column>
  71. <!--操作列配置-->
  72. <el-table-column v-if="innerActions.length > 0"
  73. label="操作"
  74. header-align="center"
  75. align="center"
  76. min-width="180">
  77. <template slot-scope="scope">
  78. <el-button v-for="action in innerActions" :key="action.name"
  79. size="mini"
  80. @click="handleinnerActions(scope.$index, scope.row,action)">{{action.label}}</el-button>
  81. </template>
  82. </el-table-column>
  83. </el-table>
  84. </el-main>
  85. <el-footer>
  86. <div class="pagination">
  87. <el-pagination @current-change="handleCurrentChange" layout="total, prev, pager, next" :total="total">
  88. </el-pagination>
  89. </div>
  90. </el-footer>
  91. </el-container>
  92. </div>
  93. </template>
  94. <script>
  95. /*
  96. 组件名称:simpleDataTable
  97. 组件用途:结合基础组件、查询条件的可配置表格,基于singleDataManager拆分而来。独立用于展示,并且可通过与simpleDataForm组合构成原有的singleDataManager
  98. 依赖组件:
  99. axios - ajax请求
  100. @tinymce/tinymce-vue - 富文本编辑
  101. 包含API文件:
  102. (dictionaryApi - 字典相关的API)
  103. props:tableViewId:string - 指定管理视图代码 (通过此代码查询接口获得组成页面的所有信息)
  104. otherParamsObject:object - 额外查询参数(为有额外联查条件要求准备,所有属性均会附加在所有请求中)
  105. 版本记录:
  106. 0.0.1 (初版) @author:wxcwater @date:2019.06.24
  107. */
  108. import axios from 'axios';
  109. import request from '../utils/gw_ajax_request.js'
  110. import {dateFormat} from '../utils/gw_date.js'
  111. import {getdictItemBydictIdSync} from '../utils/gw_dictionary.js'
  112. import elSelectDict from './elSelectWithDict.vue'
  113. import elMultipleSelect from './selectMultiple.vue'
  114. export default {
  115. props:['tableViewConfig','tableViewId','dataTitle','otherParamsObject','data'],
  116. name: 'singleDataTableManager',
  117. components: {
  118. 'el-select-dict':elSelectDict,
  119. 'el-multiple-select': elMultipleSelect,
  120. },
  121. computed:{
  122. },
  123. watch:{
  124. searchDataObject(val){
  125. console.log(val)
  126. },
  127. otherParamsObject:{
  128. handler(){
  129. console.log('otherParamsObject');
  130. this.loadData();
  131. },
  132. deep:true,
  133. }
  134. },
  135. data () {
  136. return {
  137. heightForDialog:window.innerHeight*0.45,
  138. heightForTable:window.innerHeight-91,
  139. mainHeight:window.innerHeight-265,
  140. manageViewConfigure:{},//从后台获得的view整体的配置信息对象
  141. tableViewConfigure:[],//table表格的数据列配置
  142. outerActions:[],//脱离于table与form的操作 如刷新、查询等
  143. innerActions:[],//table表格每行的操作 如 查询 修改 删除
  144. mainSearchConfigure:[],
  145. expandSearchConfigue:[],
  146. tableData:[],//单表(视图)实体数据
  147. showDetailForm:false,//展示详细弹窗 以用于查看、新增、修改
  148. searchDataObject:{},
  149. formDataObject:{},//表单数据对象(实际持有表单数据的对象)
  150. idx: -1,
  151. page:{
  152. pageNum: 1,
  153. pageSize: 10
  154. },
  155. total:0,
  156. baseUrl:'',
  157. showExpandSearchPanel:false,
  158. }
  159. },
  160. mounted:function(){
  161. let me = this;
  162. me.getManageViewConfigureInformation();
  163. console.log(this.otherParamsObject);
  164. },
  165. methods:{
  166. getManageViewConfigureInformation:function(){ //获取table的配置信息以初始化组件配置
  167. let _self = this;
  168. let getConfigType = typeof this.tableViewConfig;
  169. if(getConfigType == 'object'){//如果props里的tableViewConfig是object认为给的就是配置对象了,还考虑function与promise的类型 后续添加
  170. _self.manageViewConfigure =this.tableViewConfig;
  171. this.analyseManageViewConfigure();//开始分析解析配置文件
  172. }
  173. },
  174. analyseManageViewConfigure:function(){//分析配置文件,生成一些基本对象
  175. let _self = this;
  176. this.tableViewConfigure = this.manageViewConfigure['fields']
  177. let fields = [];//fields为组件的数据配置,产生影响的包括table的列与一些查询、排序等的内容
  178. let actions = [];//actions为组件的操作配置,产生影响的包括一些button等的方法。
  179. let searchs = [];//searchs 为组件的查询项目配置
  180. if(this.manageViewConfigure && this.manageViewConfigure.hasOwnProperty('fields')){
  181. fields = this.manageViewConfigure['fields'];
  182. this.tableViewConfigure = fields;;//存到tableViewConfigure里方便模板使用
  183. }
  184. if(this.manageViewConfigure && this.manageViewConfigure.hasOwnProperty('actions')){
  185. actions = this.manageViewConfigure['actions'];
  186. }
  187. if(this.manageViewConfigure && this.manageViewConfigure.hasOwnProperty('searchs')){
  188. searchs = this.manageViewConfigure['searchs'];
  189. }
  190. actions.forEach(item => {//对actions进行细分,根据每个action的position属性确定action代表的button是在组件的位置(outer:table外,在查询部分,inner:在table的每行中)
  191. if(item.position=='inner'){
  192. this.innerActions.push(item);
  193. }else if(item.position=='outer'){
  194. this.outerActions.push(item);
  195. }
  196. });
  197. searchs.forEach(item => {
  198. if(item.hasOwnProperty('isMain') && (item.isMain || item.isMain == '1')){
  199. this.mainSearchConfigure.push(searchItem);
  200. }else{
  201. this.expandSearchConfigue.push(searchItem);
  202. }
  203. });
  204. let mainSearchLength = this.mainSearchConfigure.length;
  205. fields.forEach(item => {
  206. if(item.hasOwnProperty('isSearchable') && (item.isSearchable || item.isSearchable == '1')){
  207. let searchItem = Object.assign({},item);
  208. searchItem.isMain = false;
  209. if(mainSearchLength==0&&this.mainSearchConfigure.length<4){
  210. this.mainSearchConfigure.push(searchItem);
  211. }else{
  212. this.expandSearchConfigue.push(searchItem);
  213. }
  214. }
  215. });
  216. console.log('拆分结果');
  217. console.log(this.outerActions);
  218. console.log(this.innerActions);
  219. //以上配置的赋值会影响页面绘制,故绘制完再进行实体数据的获取
  220. this.$nextTick(function(){
  221. _self.loadData();//分析完毕后开始获取数据
  222. });
  223. },
  224. loadData:function(){//获取table数据,可由内外部调用,没有什么影响。
  225. let _self = this;
  226. let getTableType = typeof _self.data;
  227. if(getTableType == 'array'){//如果是数组表示是外部直接赋值的数据
  228. _self.tableData = _self.data;
  229. _self.total = _self.data.length;
  230. }else if(getTableType == 'string'){//如果是字符串考虑是远端的url
  231. let dataUrl = _self.data;
  232. let queryParams = Object.assign(_self.searchDataObject,_self.page);//组合查询参数与分页信息
  233. if(_self.otherParamsObject) {//考虑组件外业务逻辑会带进来额外的查询参数,将额外查询参数组合进来
  234. queryParams = Object.assign(queryParams, this.otherParamsObject);
  235. }
  236. request({
  237. url: dataUrl,
  238. method:'POST',//默认为POST
  239. params: queryParams
  240. }).then((response) => {
  241. console.log(response);//打印获取结果
  242. _self.tableData = response.data.list ? response.data.list : response.data;
  243. _self.total = response.data.total;
  244. }).catch(function (err) {
  245. console.log(err);
  246. });
  247. }
  248. },
  249. handleinnerActions:function(index,row,innerAction){//处理表格中的点击操作
  250. this.$emit('innerActionClick',{'row':row,'action':innerAction});
  251. let action = innerAction.action;//获取action的动作类型
  252. let _self = this;
  253. // 判断是否为组件内部方法,如果是可以直接调用。考虑通过|操作符对多个动作进行连接。
  254. if(this.hasOwnProperty(action) && (typeof this[action]) == "function"){
  255. //如果有同名内部方法就直接调用,为了是查询等操作可以直接使用loadData等
  256. console.log('innerAction调用内部方法');
  257. this[action]();
  258. }else if(action == 'request'){
  259. // 如果是request类型的 默认为发送请求类的动作。目前主要是 删除 等。删除完需要同步刷新数据
  260. let realUrl = this.analyseUrlTempLateToRealUrl(innerAction.url,row);//如果是restful的会按照模板进行处理,没有就不处理了
  261. let queryParams = this.formDataObject;
  262. if(this.otherParamsObject) {
  263. queryParams= this.otherParamsObject;
  264. }
  265. let requestType = innerAction.hasOwnProperty('requestType')&&innerAction['requestType'] != ''?innerAction['requestType']:'GET';
  266. //获取请求类型,默认是GET
  267. request({
  268. url: realUrl,
  269. method: requestType,
  270. params: queryParams,//考虑接口差异,data、params都传递
  271. data: queryParams//考虑接口差异,data、params都传递
  272. }).then((response) => {
  273. _self.loadData();//默认在请求后查询一遍数据。基本行内请求都对数据有操作。
  274. })
  275. }
  276. },
  277. handleouterActions:function(outerAction){//处理table外action的操作
  278. this.$emit("outerButtonClick",outerAction);
  279. let action = outerAction.action;//获取action的动作类型
  280. // 判断是否为组件内部方法,如果是可以直接调用。
  281. if(this.hasOwnProperty(action) && (typeof this[action]) == "function"){
  282. //如果有同名内部方法就直接调用,为了是查询等操作可以直接使用loadData等
  283. console.log('outerAction调用内部方法');
  284. this[action]();
  285. }else if(action == 'request'){
  286. // 如果是request类型的 默认为发送请求类的动作。目前主要可能是导出。
  287. }
  288. },
  289. analyseUrlTempLateToRealUrl:function(urlTemplate,paramsObject){
  290. let urlTemp = urlTemplate.split('/');
  291. urlTemp.forEach((element,index) => {
  292. if(element.startsWith('{')&&element.endsWith('}')){
  293. console.log('换'+paramsObject[element.substring(1,element.length-1)]);
  294. urlTemp[index] = paramsObject[element.substring(1,element.length-1)]
  295. }
  296. });
  297. console.log(urlTemp);
  298. return this.baseUrl + urlTemp.join('/');
  299. },
  300. tableColumnsFormatter:function(row, scope, index,colmunObj){//table列表中针对某一列的formatter
  301. let columnContentType = colmunObj["type"]; //获得type来确定是否需要对值进行处理
  302. let prop = scope.column.property;//获取配置的prop 用以返回属性
  303. if(columnContentType == 'select'){
  304. let formatterResult = row[prop];
  305. let dictOptions = getdictItemBydictIdSync(colmunObj["refObjValue"]);
  306. if(dictOptions){
  307. let hasDict = false;
  308. dictOptions.forEach(element => {
  309. if(element['key'] == row[prop]){
  310. hasDict = true;
  311. formatterResult = element['value'];
  312. }
  313. });
  314. }
  315. return formatterResult;
  316. }else if(columnContentType == 'selectMultiple'){
  317. let formatterResult = row[prop];
  318. let dictOptions = getdictItemBydictIdSync(colmunObj["refObjValue"]);
  319. if(dictOptions){
  320. let hasDict = false;
  321. dictOptions.forEach(element => {
  322. if(element['key'] == row[prop]){
  323. hasDict = true;
  324. formatterResult = element['value'];
  325. }
  326. });
  327. }
  328. return formatterResult;
  329. }else if(columnContentType == 'text'){
  330. let formatterResult = row[prop];
  331. let dictOptions = getdictItemBydictIdSync(colmunObj["refObjValue"]);
  332. if(dictOptions){
  333. let hasDict = false;
  334. dictOptions.forEach(element => {
  335. if(row[prop]){
  336. if(element['value'] == row[prop].toString()){
  337. hasDict = true;
  338. formatterResult = element['descr'];
  339. }
  340. }
  341. });
  342. }
  343. return formatterResult;
  344. // return row[prop];
  345. }else if(columnContentType == 'date'){
  346. let beFormatter = row[prop];
  347. if(typeof beFormatter == 'date'){
  348. return dateFormat(beFormatter,'yyyy-MM-dd');
  349. }else{
  350. return dateFormat(new Date(beFormatter),'yyyy-MM-dd');
  351. }
  352. }else{
  353. return row[prop];
  354. }
  355. return row[prop];
  356. },
  357. handleCurrentChange:function(val) {
  358. this.page.pageNum = val;
  359. this.loadData();
  360. },
  361. //3个
  362. handleClose(done){
  363. this.parentName = ''
  364. done()
  365. },
  366. },
  367. }
  368. </script>
  369. <style>
  370. #singleDataTableManager{
  371. /*height:100%;*/
  372. width:100%;
  373. /* margin:-15px; */
  374. }
  375. #singleDataTableManager th,#singleDataTableManager .el-table thead tr {
  376. font-size: 14px;
  377. background-color: #eef1f6;
  378. color: #1f2d3d;
  379. }
  380. .searchPanel{
  381. width:100%;
  382. /* border-bottom: 1px dotted #6161d7; */
  383. /* padding-bottom:10px; */
  384. padding-left: 10px;
  385. margin-top: 10px;
  386. box-sizing: border-box;
  387. /* overflow: hidden; */
  388. }
  389. .actionPanel{
  390. width:100%;
  391. }
  392. #singleDataTableManager .pagination{
  393. text-align: center;
  394. }
  395. #singleDataTableManager .el-select{
  396. width: 100%;
  397. }
  398. .menu_tree .el-tree-node__content .el-tree-node__expand-icon+span::before {
  399. content: url(../assets/images/place.png);
  400. margin-right: 6px;
  401. }
  402. .menu_tree .el-tree-node__children .el-tree-node__expand-icon+span::before {
  403. content: url(../assets/images/place.png);
  404. }
  405. </style>