This commit is contained in:
Shaun Chyxion 2017-07-13 00:20:14 +08:00
parent a80f427d05
commit edae9383d3
8 changed files with 283 additions and 58 deletions

View File

@ -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;
}
}

View 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);
}
}
});

View File

@ -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: '刷新',

View File

@ -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) {

View File

@ -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() {

View 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>

View File

@ -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>

View 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');
});