complete
This commit is contained in:
parent
a80f427d05
commit
edae9383d3
@ -1,8 +1,11 @@
|
||||
package com.pudonghot.ambition.crm.controller;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import javax.validation.Valid;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chyxion.tigon.mybatis.Search;
|
||||
import me.chyxion.tigon.model.ViewModel;
|
||||
import javax.validation.constraints.Max;
|
||||
@ -10,14 +13,18 @@ import javax.validation.constraints.Min;
|
||||
import me.chyxion.tigon.model.ListResult;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import com.pudonghot.ambition.crm.model.User;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import com.pudonghot.ambition.crm.model.Customer;
|
||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.pudonghot.ambition.crm.model.CustomerProperty;
|
||||
import com.pudonghot.ambition.crm.service.CustomerService;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import com.pudonghot.ambition.crm.service.CustomerPropertyService;
|
||||
import com.pudonghot.ambition.crm.form.create.CustomerFormForCreate;
|
||||
import com.pudonghot.ambition.crm.form.update.CustomerFormForUpdate;
|
||||
|
||||
@ -26,6 +33,7 @@ import com.pudonghot.ambition.crm.form.update.CustomerFormForUpdate;
|
||||
* donghuang@wacai.com <br>
|
||||
* Jun 23, 2017 21:43:31
|
||||
*/
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RequestMapping("/customer")
|
||||
public class CustomerController
|
||||
@ -59,6 +67,19 @@ public class CustomerController
|
||||
SORT_COLS.put("ytdSale", "ytd_sale." + Customer.YTD_SALE);
|
||||
}
|
||||
|
||||
private static final Map<String, String> CRITERION_COLS;
|
||||
static {
|
||||
CRITERION_COLS = new HashMap<>(SORT_COLS);
|
||||
CRITERION_COLS.put(Customer.NAME, Customer.NAME);
|
||||
CRITERION_COLS.put(Customer.STATE, Customer.STATE);
|
||||
CRITERION_COLS.put(Customer.CITY, Customer.CITY);
|
||||
|
||||
CRITERION_COLS.put("status", "prop.id");
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private CustomerPropertyService customerPropertyService;
|
||||
|
||||
@RequestMapping("/list")
|
||||
public ListResult<ViewModel<Customer>> list(
|
||||
@Min(0)
|
||||
@ -70,14 +91,27 @@ public class CustomerController
|
||||
final int limit,
|
||||
@RequestParam(value = "search", required = false)
|
||||
final String strSearch,
|
||||
@RequestParam(value = "criteria", required = false)
|
||||
final String criteria,
|
||||
@RequestParam(value = "sorters", required = false)
|
||||
final String sorters) {
|
||||
|
||||
final Search search = new Search();
|
||||
User user = getUser().getData();
|
||||
if (!user.isAdmin()) {
|
||||
search.setAttr(User.ACCOUNT, user.getAccount());
|
||||
}
|
||||
return listViewModels(search(search, start, limit, strSearch, sorters));
|
||||
final ListResult<ViewModel<Customer>> result =
|
||||
listViewModels(search(criteria(search, criteria), start, limit, strSearch, sorters));
|
||||
|
||||
// status for advance search
|
||||
result.setAttr("statusList",
|
||||
customerPropertyService.list(
|
||||
new Search(CustomerProperty.TYPE,
|
||||
CustomerProperty.TYPE_STATUS)
|
||||
.eq(CustomerProperty.ENABLED, true)
|
||||
.asc(CustomerProperty.SORT)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@RequiresRoles(User.ROLE_ADMIN)
|
||||
@ -118,4 +152,71 @@ public class CustomerController
|
||||
protected Map<String, String> sorterCols() {
|
||||
return SORT_COLS;
|
||||
}
|
||||
|
||||
private String criterionCol(String col) {
|
||||
return CRITERION_COLS.get(col);
|
||||
}
|
||||
|
||||
private Search criteria(final Search search, final String strCriteria) {
|
||||
|
||||
if (StringUtils.isBlank(strCriteria)) {
|
||||
log.debug("No Criteria Given.");
|
||||
return search;
|
||||
}
|
||||
|
||||
final List<String[]> criteria;
|
||||
try {
|
||||
criteria = JSON.parseArray(decodeParam(strCriteria), String[].class);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException(
|
||||
"Invalid Criteria [" + strCriteria + "]", e);
|
||||
}
|
||||
|
||||
for (String[] criterion : criteria) {
|
||||
if (criterion.length == 3) {
|
||||
final String col = criterion[0];
|
||||
if (StringUtils.isNotBlank(col)) {
|
||||
final String criterionCol = criterionCol(col);
|
||||
if (StringUtils.isNotBlank(criterionCol)) {
|
||||
final String op = criterion[1];
|
||||
final String val = criterion[2];
|
||||
if (StringUtils.isNotBlank(op) && StringUtils.isNotBlank(val)) {
|
||||
if ("eq".equals(op)) {
|
||||
search.eq(criterionCol, val);
|
||||
}
|
||||
else if ("gt".equals(op)) {
|
||||
search.gt(criterionCol, val);
|
||||
}
|
||||
else if ("gte".equals(op)) {
|
||||
search.gte(criterionCol, val);
|
||||
}
|
||||
else if ("lt".equals(op)) {
|
||||
search.lt(criterionCol, val);
|
||||
}
|
||||
else if ("lte".equals(op)) {
|
||||
search.lt(criterionCol, val);
|
||||
}
|
||||
else if ("ne".equals(op)) {
|
||||
search.ne(criterionCol, val);
|
||||
}
|
||||
else if ("like".equals(op)) {
|
||||
search.like(criterionCol, val, true);
|
||||
}
|
||||
else {
|
||||
log.warn("Unknown Criterion Op [{}], Ignore.", op);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.warn("Criterion Col Is Blank, Ignore.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.warn("Invalid Criterion [{}], Ignore.", criterion);
|
||||
}
|
||||
}
|
||||
return search;
|
||||
}
|
||||
}
|
||||
|
28
web/app/components/query-criterion.js
Normal file
28
web/app/components/query-criterion.js
Normal file
@ -0,0 +1,28 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNames: ['form-group'],
|
||||
actions: {
|
||||
remove() {
|
||||
let me = this;
|
||||
let criterion = me.get('criterion');
|
||||
Ember.Logger.info('Remove Criterion: ', criterion);
|
||||
let removeAction = me.get('removeCriterion');
|
||||
removeAction && removeAction(criterion);
|
||||
},
|
||||
onColChanged(col) {
|
||||
let me = this;
|
||||
// remove option val
|
||||
if ('status' === me.get('criterion.col')) {
|
||||
me.set('criterion.val', '');
|
||||
}
|
||||
me.set('criterion.col', col);
|
||||
},
|
||||
onOpChanged(op) {
|
||||
this.set('criterion.op', op);
|
||||
},
|
||||
onValChanged(val) {
|
||||
this.set('criterion.val', val);
|
||||
}
|
||||
}
|
||||
});
|
@ -2,6 +2,7 @@ import Ember from 'ember';
|
||||
import BaseComponent from './base-component';
|
||||
|
||||
export default BaseComponent.extend({
|
||||
trimIndex: true,
|
||||
tagName: 'a',
|
||||
attributeBindings: ['href', 'title'],
|
||||
title: '刷新',
|
||||
|
@ -43,6 +43,11 @@ cols.forEach((col) => {
|
||||
const TableOptions = Ember.Object.extend(config);
|
||||
|
||||
export default BaseListRoute.extend({
|
||||
queryParams: {
|
||||
criteria: {
|
||||
refreshModel: true
|
||||
}
|
||||
},
|
||||
breadcrumbs: [{text: '客户列表'}],
|
||||
actions: {
|
||||
sort(col) {
|
||||
|
@ -3,18 +3,73 @@ import Ember from 'ember';
|
||||
export default Ember.Route.extend({
|
||||
model() {
|
||||
let me = this;
|
||||
let parentController = me.controllerFor(me.getParentRouteName());
|
||||
let strCriteria = parentController.get('criteria');
|
||||
let criteria;
|
||||
if (strCriteria) {
|
||||
criteria = JSON.parse(strCriteria).map(c => {
|
||||
return {
|
||||
col: c[0],
|
||||
op: c[1],
|
||||
val: c[2]
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!criteria || !criteria.length) {
|
||||
criteria = [{
|
||||
col: 'year',
|
||||
op: 'eq'
|
||||
}];
|
||||
}
|
||||
|
||||
return {
|
||||
tableOptions: me.controllerFor(me.getParentRouteName()).get('tableOptions'),
|
||||
criteria: [{col: 'id', op: 'eq', val: ''}]
|
||||
tableOptions: parentController.get('tableOptions'),
|
||||
statusList: parentController.get('model.statusList'),
|
||||
criteria: criteria,
|
||||
cols: [{col: 'name', name: '名称'},
|
||||
{col: 'year', name: '年份'},
|
||||
{col: 'ytdSale', name: '年销售额'},
|
||||
{col: 'countryCode', name: '国家'},
|
||||
{col: 'state', name: '省份'},
|
||||
{col: 'city', name: '城市'},
|
||||
{col: 'ms', name: 'MS'},
|
||||
{col: 'region', name: '区域'},
|
||||
{col: 'salesperson', name: '销售'},
|
||||
{col: 'status', name: '状态'},
|
||||
],
|
||||
ops: [{op: 'eq', name: '等于'},
|
||||
{op: 'gt', name: '大于'},
|
||||
{op: 'lt', name: '小于'},
|
||||
{op: 'gte', name: '大于等于'},
|
||||
{op: 'lte', name: '小于等于'},
|
||||
{op: 'ne', name: '不等于'},
|
||||
{op: 'like', name: '匹配'}
|
||||
]
|
||||
};
|
||||
},
|
||||
actions: {
|
||||
addCriterion() {
|
||||
|
||||
Ember.Logger.info('Add Criterion.');
|
||||
this.get('controller.model.criteria').pushObject({
|
||||
col: 'name',
|
||||
op: 'eq'
|
||||
});
|
||||
},
|
||||
submit() {
|
||||
removeCriterion(criterion) {
|
||||
Ember.Logger.info('Route Remove Criterion: ', criterion);
|
||||
this.get('controller.model.criteria').removeObject(criterion);
|
||||
},
|
||||
query() {
|
||||
let me = this;
|
||||
console.log('parent route:', me.getParentRouteName());
|
||||
let parentRouteName = me.getParentRouteName();
|
||||
console.log('parent route:', parentRouteName);
|
||||
const parentController = me.controllerFor(parentRouteName);
|
||||
let criteria = me.get('controller.model.criteria');
|
||||
parentController.set('criteria',
|
||||
JSON.stringify(criteria.filter(c => c.val)
|
||||
.map(c => [c.col, c.op, c.val])));
|
||||
me.transitionTo(parentRouteName);
|
||||
}
|
||||
},
|
||||
getParentRouteName() {
|
||||
|
38
web/app/templates/components/query-criterion.hbs
Normal file
38
web/app/templates/components/query-criterion.hbs
Normal file
@ -0,0 +1,38 @@
|
||||
<div class="col-sm-12">
|
||||
<div class="col-sm-4 no-padding-left">
|
||||
{{#x-select class='form-control' action=(action 'onColChanged') value=criterion.col as |xs|}}
|
||||
{{#each cols as |col|}}
|
||||
{{#xs.option value=col.col}}{{col.name}}{{/xs.option}}
|
||||
{{/each}}
|
||||
{{/x-select}}
|
||||
</div>
|
||||
|
||||
{{#unless valOptions}}
|
||||
<div class="col-sm-3 no-padding-left">
|
||||
{{#x-select class='form-control' action=(action 'onOpChanged') value=criterion.op as |xs|}}
|
||||
{{#each ops as |op|}}
|
||||
{{#xs.option value=op.op}}{{op.name}}{{/xs.option}}
|
||||
{{/each}}
|
||||
{{/x-select}}
|
||||
</div>
|
||||
{{/unless}}
|
||||
|
||||
<div class="col-sm-5 no-padding">
|
||||
<div class="col-sm-10 no-padding">
|
||||
{{#if valOptions}}
|
||||
{{#x-select class='form-control' action=(action 'onValChanged') value=criterion.val as |xs|}}
|
||||
{{#each valOptions as |val|}}
|
||||
{{#xs.option value=val.id}}{{val.name}}{{/xs.option}}
|
||||
{{/each}}
|
||||
{{/x-select}}
|
||||
{{else}}
|
||||
{{input type='text' class='input-medium' value=(mut (get criterion 'val'))}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="col-sm-2 no-padding">
|
||||
<button class="form-control red close" {{action 'remove'}}>
|
||||
<i class="ace-icon fa fa-times smaller-80"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -12,24 +12,22 @@
|
||||
<div class="row">
|
||||
<div class="col-xs-5 col-sm-5">
|
||||
<div class="control-group">
|
||||
<!-- <label class="control-label bolder blue">结果列</label> -->
|
||||
{{ace-checkbox label='编号' value=model.showId}}
|
||||
{{ace-checkbox label='名称' value=model.showName}}
|
||||
{{ace-checkbox label='年份' value=model.showYear}}
|
||||
{{ace-checkbox label='年销售额' value=model.showYtdSale}}
|
||||
{{ace-checkbox label='国家' value=model.showCountryCode}}
|
||||
{{ace-checkbox label='省份' value=model.showState}}
|
||||
{{ace-checkbox label='编号' value=model.tableOptions.showId}}
|
||||
{{ace-checkbox label='名称' value=model.tableOptions.showName}}
|
||||
{{ace-checkbox label='年份' value=model.tableOptions.showYear}}
|
||||
{{ace-checkbox label='年销售额' value=model.tableOptions.showYtdSale}}
|
||||
{{ace-checkbox label='国家' value=model.tableOptions.showCountryCode}}
|
||||
{{ace-checkbox label='省份' value=model.tableOptions.showState}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-5 col-sm-5">
|
||||
<div class="control-group">
|
||||
<!-- <label class="control-label bolder white">_</label> -->
|
||||
{{ace-checkbox label='城市' value=model.showCity}}
|
||||
{{ace-checkbox label='MS' value=model.showMs}}
|
||||
{{ace-checkbox label='区域' value=model.showRegion}}
|
||||
{{ace-checkbox label='销售' value=model.showSalesperson}}
|
||||
{{ace-checkbox label='状态' value=model.showStatus}}
|
||||
{{ace-checkbox label='全部选择' value=model.showAll}}
|
||||
{{ace-checkbox label='城市' value=model.tableOptions.showCity}}
|
||||
{{ace-checkbox label='MS' value=model.tableOptions.showMs}}
|
||||
{{ace-checkbox label='区域' value=model.tableOptions.showRegion}}
|
||||
{{ace-checkbox label='销售' value=model.tableOptions.showSalesperson}}
|
||||
{{ace-checkbox label='状态' value=model.tableOptions.showStatus}}
|
||||
{{ace-checkbox label='全部选择' value=model.tableOptions.showAll}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -40,13 +38,11 @@
|
||||
|
||||
<div class="col-xs-12 col-sm-7">
|
||||
<div class="control-group">
|
||||
{{!--<label class="control-label bolder blue">金额条件</label>--}}
|
||||
<div class="widget-box">
|
||||
<div class="widget-header">
|
||||
<h4 class="widget-title">查询条件</h4>
|
||||
|
||||
<h5 class="widget-title">查询条件</h5>
|
||||
<span class="widget-toolbar">
|
||||
<a href="#" data-action="add_row">
|
||||
<a href="#" {{action (route-action 'addCriterion')}}>
|
||||
<i class="green ace-icon fa fa-plus"></i>
|
||||
</a>
|
||||
</span>
|
||||
@ -55,52 +51,29 @@
|
||||
<div class="widget-body">
|
||||
<div class="widget-main">
|
||||
<form class="form-horizontal" role="form">
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<div class="col-sm-4 no-padding-left">
|
||||
{{#x-select class='form-control' name=name value=(mut (get model name)) as |xs|}}
|
||||
{{#xs.option value='M'}}男{{/xs.option}}
|
||||
{{#xs.option value='F'}}女{{/xs.option}}
|
||||
{{/x-select}}
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3 no-padding-left">
|
||||
{{#x-select class='form-control' name=name value=(mut (get model name)) as |xs|}}
|
||||
{{#xs.option value='eq'}}等于{{/xs.option}}
|
||||
{{#xs.option value='gt'}}大于{{/xs.option}}
|
||||
{{/x-select}}
|
||||
</div>
|
||||
|
||||
<div class="col-sm-5 no-padding">
|
||||
<div class="col-sm-10 no-padding">
|
||||
{{input type='text' class='input-medium'}}
|
||||
</div>
|
||||
<div class="col-sm-2 no-padding">
|
||||
<button class="form-control red close">
|
||||
<i class="ace-icon fa fa-times smaller-80"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{#each model.criteria as |criterion|}}
|
||||
{{query-criterion
|
||||
cols=model.cols
|
||||
ops=model.ops
|
||||
valOptions=(if (eq 'status' criterion.col) model.statusList)
|
||||
criterion=criterion
|
||||
removeCriterion=(route-action 'removeCriterion')}}
|
||||
{{/each}}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer no-margin-top">
|
||||
{{!--<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">
|
||||
<i class="ace-icon fa fa-times"></i>
|
||||
取消
|
||||
</button>--}}
|
||||
<button type="button" class="btn btn-sm btn-primary" data-dismiss="modal" {{!action (if submit submit (route-action 'submit'))}}>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-primary" {{action (route-action 'query')}}>
|
||||
<i class="ace-icon fa fa-check"></i>
|
||||
确定
|
||||
</button>
|
||||
|
24
web/tests/integration/components/query-criterion-test.js
Normal file
24
web/tests/integration/components/query-criterion-test.js
Normal file
@ -0,0 +1,24 @@
|
||||
import { moduleForComponent, test } from 'ember-qunit';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
|
||||
moduleForComponent('query-criterion', 'Integration | Component | query criterion', {
|
||||
integration: true
|
||||
});
|
||||
|
||||
test('it renders', function(assert) {
|
||||
// Set any properties with this.set('myProperty', 'value');
|
||||
// Handle any actions with this.on('myAction', function(val) { ... });
|
||||
|
||||
this.render(hbs`{{query-criterion}}`);
|
||||
|
||||
assert.equal(this.$().text().trim(), '');
|
||||
|
||||
// Template block usage:
|
||||
this.render(hbs`
|
||||
{{#query-criterion}}
|
||||
template block text
|
||||
{{/query-criterion}}
|
||||
`);
|
||||
|
||||
assert.equal(this.$().text().trim(), 'template block text');
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user