diff --git a/app/Domains/Virtual/Exports/PropertyExport.php b/app/Domains/Virtual/Exports/PropertyExport.php index 5f087995..552b01df 100644 --- a/app/Domains/Virtual/Exports/PropertyExport.php +++ b/app/Domains/Virtual/Exports/PropertyExport.php @@ -41,12 +41,12 @@ class PropertyExport extends AbstractExport implements FromCollection, WithHeadi '销售数', '活跃数', '*公司类型', + '平台/API', + '*客户类型', '*产品类型', '套餐类型', - '平台/API', '*车辆类型', - '商用车分类', - '*客户类型', + '车型分组', ]; foreach ($provinces as $province) { @@ -77,12 +77,12 @@ class PropertyExport extends AbstractExport implements FromCollection, WithHeadi strval($value['counts']), strval($value['actives']), $value['company'], + $value['platform'], + $value['customer'], $value['product'], $value['package'], - $value['platform'], + $value['vehicle_type'], $value['vehicle'], - $value['commercial_vehicle'], - $value['customer'], ]; foreach ($provinces as $province) { diff --git a/app/Domains/Virtual/Http/Controllers/PropertyController.php b/app/Domains/Virtual/Http/Controllers/PropertyController.php index 7764c988..5e2f710b 100644 --- a/app/Domains/Virtual/Http/Controllers/PropertyController.php +++ b/app/Domains/Virtual/Http/Controllers/PropertyController.php @@ -117,7 +117,7 @@ class PropertyController extends Controller 'company_id', 'package_id', 'product', - 'vehicle', + 'vehicle_type', 'company', 'customer', ]; @@ -138,12 +138,11 @@ class PropertyController extends Controller $value = [ 'company_id' => $item['企业id'], 'package_id' => $item['套餐id'], - 'product' => $item['产品类型'], - 'vehicle' => $item['车辆类型'], - 'commercial_vehicle' => $item['商用车分类'], 'company' => $item['公司类型'], 'platform' => $item['平台/api'], 'customer' => $item['客户类型'], + 'product' => $item['产品类型'], + 'vehicle_type' => $item['车辆类型'], ]; foreach ($provinces as $province) { diff --git a/app/Domains/Virtual/Services/PropertyService.php b/app/Domains/Virtual/Services/PropertyService.php index 22c900df..b76dd774 100644 --- a/app/Domains/Virtual/Services/PropertyService.php +++ b/app/Domains/Virtual/Services/PropertyService.php @@ -21,26 +21,27 @@ class PropertyService extends Service protected $propertySettingRepository; public static $property_types = [ - 'product' => '产品类型', + 'vehicle_group' => '车型分组', + 'vehicle_type' => '车型选项', 'vehicle' => '车辆类型', - 'commercial_vehicle' => '商用车分类', 'company' => '公司类型', 'platform' => '平台/API类型', 'customer' => '客户类型', 'package' => '套餐分类', - 'province' => '省份设置', + 'product' => '产品类型', 'package_type' => '套餐类型', + 'province' => '省份设置', 'agent' => '代理商设置', ]; public static $default = [ - 'product' => '', 'vehicle' => '', 'commercial_vehicle' => '', 'company' => '', 'platform' => '', 'customer' => '', 'package' => '', + 'product' => '', 'province' => null, 'province_status' => 0, 'agent' => null, @@ -89,6 +90,22 @@ class PropertyService extends Service } } + $vehicleTypes = $settings['vehicle_type']; + + foreach ($settings as $key => $setting) { + if ($setting['name'] === 'vehicle') { + $values = $setting['value']; + foreach ($values as $k => $value) { + foreach ($value as $i => $v) { + if (!in_array($v, $vehicleTypes)) { + unset($settings[$key]['value'][$k][$i]); + $settings[$key]['value'][$k] = array_values($settings[$key]['value'][$k]); + } + } + } + } + } + if ($conditions['names']) { $conditions['names'] = array_wrap($conditions['names']); @@ -115,7 +132,7 @@ class PropertyService extends Service throw new NotExistException("分类{$key}不存在"); } - if ($key !== 'province' && $key !== 'package') { + if ($key !== 'province' && $key !== 'package' && $key !== 'vehicle') { $value = array_values(array_unique(array_merge($value))); $value = array_map(function ($item) { return is_string($item) ? trim($item) : $item; @@ -147,6 +164,28 @@ class PropertyService extends Service } } + if (isset($values['vehicle'])) { + $vehicles = $values['vehicle']; + $vehicleTypes = $values['vehicle_type']; + foreach ($vehicles as $k => $v) { + if (!is_array($v)) { + throw new InvalidArgumentException('传入的车型配置错误'); + } + + foreach ($v as $m) { + if (!in_array($m, $vehicleTypes)) { + throw new NotExistException("车型({$m})未配置或已删除"); + } + + foreach ($vehicles as $i => $j) { + if ($i !== $k && in_array($m, $j)) { + throw new NotAllowedException('一个车型仅能归属一个分组'); + } + } + } + } + } + $data = []; foreach ($values as $key => $value) { @@ -227,8 +266,8 @@ class PropertyService extends Service $values = [$values]; } - $only = ['company_id', 'package_id', 'product', 'vehicle', 'commercial_vehicle', 'company', 'platform', 'customer', 'province', 'agent']; - $checks = ['product', 'vehicle', 'company', 'customer']; + $only = ['company_id', 'package_id', 'product', 'vehicle_type', 'company', 'platform', 'customer', 'province', 'agent']; + $checks = ['product', 'vehicle_type', 'company', 'customer']; $settings = $this->propertySettingRepository->getAll(); $agents = app(AgentService::class)->listGroupByCompanyId(); @@ -241,7 +280,6 @@ class PropertyService extends Service } $value['platform'] = $value['platform'] ?: ''; - $value['commercial_vehicle'] = $value['commercial_vehicle'] ?: ''; $value = array_only($value, $only); foreach ($value as $k => $v) { @@ -253,7 +291,7 @@ class PropertyService extends Service throw new InvalidArgumentException(self::$property_types[$k] . '值不正确'); } - if (in_array($k, ['commercial_vehicle', 'platform']) && !in_array($v, $settings[$k]) && ($v !== '')) { + if (in_array($k, ['platform']) && !in_array($v, $settings[$k]) && ($v !== '')) { throw new InvalidArgumentException(self::$property_types[$k] . '值不正确'); } } @@ -301,7 +339,12 @@ class PropertyService extends Service throw new NotExistException('产品套餐关系未配置'); } + if (!$vehicle = $this->getVehicle($value['vehicle_type'])) { + throw new NotExistException('车型分组关系未配置'); + } + $value['package'] = $package; + $value['vehicle'] = $vehicle; $value['created_at'] = date('Y-m-d H:i:s'); $value['updated_at'] = date('Y-m-d H:i:s'); @@ -339,6 +382,23 @@ class PropertyService extends Service return null; } + protected function getVehicle($vehicleType) + { + if (!$vehicle = $this->vehicle) { + $settings = $this->propertySettingRepository->getAll(); + $vehicles = $settings['vehicle']; + $this->vehicle = $vehicle; + } + + foreach ($vehicles as $key => $vehicleTypes) { + if (in_array($vehicleType, $vehicleTypes)) { + return $key; + } + } + + return null; + } + public static function load($company_id, $package_id) { if (!self::$properties) { diff --git a/database/migrations/2020_01_08_110723_add_virtual_device_province.php b/database/migrations/2020_01_08_110723_add_virtual_device_province.php index 4dfa70c0..68ee29ea 100644 --- a/database/migrations/2020_01_08_110723_add_virtual_device_province.php +++ b/database/migrations/2020_01_08_110723_add_virtual_device_province.php @@ -15,6 +15,11 @@ class AddVirtualDeviceProvince extends Migration { Schema::table('virtual_devices', function (Blueprint $table) { $table->string('province', 15)->default("")->comment('所属省份'); + $table->integer('agent_id')->unsigned()->default(0)->comment('代理商ID'); + + $table->index(['sim']); + $table->index(['unique_key']); + $table->index(['imsi']); }); } @@ -27,6 +32,10 @@ class AddVirtualDeviceProvince extends Migration { Schema::table('virtual_devices', function (Blueprint $table) { $table->dropColumn('province'); + $table->dropColumn('agent_id'); + $table->dropIndex("virtual_devices_sim_index"); + $table->dropIndex("virtual_devices_unique_key_index"); + $table->dropIndex("virtual_devices_imsi_index"); }); } } diff --git a/database/migrations/2020_01_09_143834_add_virtual_order_cards_partition_id_idx.php b/database/migrations/2020_01_09_143834_add_virtual_order_cards_partition_id_idx.php new file mode 100644 index 00000000..c725064a --- /dev/null +++ b/database/migrations/2020_01_09_143834_add_virtual_order_cards_partition_id_idx.php @@ -0,0 +1,64 @@ +index(['id']); + }); + + Schema::table('virtual_order_renewal_cards', function (Blueprint $table) { + $table->index(['id']); + }); + + Schema::table('virtual_order_renewal_package_cards', function (Blueprint $table) { + $table->index(['id']); + }); + + Schema::table('virtual_order_flows_package_cards', function (Blueprint $table) { + $table->index(['id']); + }); + + Schema::table('virtual_order_upgrade_cards', function (Blueprint $table) { + $table->index(['id']); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('virtual_order_cards', function (Blueprint $table) { + $table->dropIndex("virtual_order_cards_id_index"); + }); + + Schema::table('virtual_order_renewal_cards', function (Blueprint $table) { + $table->dropIndex("virtual_order_renewal_cards_id_index"); + }); + + Schema::table('virtual_order_renewal_package_cards', function (Blueprint $table) { + $table->dropIndex("virtual_order_renewal_package_cards_id_index"); + }); + + Schema::table('virtual_order_flows_package_cards', function (Blueprint $table) { + $table->dropIndex("virtual_order_flows_package_cards_id_index"); + }); + + Schema::table('virtual_order_upgrade_cards', function (Blueprint $table) { + $table->dropIndex("virtual_order_upgrade_cards_id_index"); + }); + } +} diff --git a/database/migrations/2020_01_10_092917_rename_virtual_properties_vehicle_type.php b/database/migrations/2020_01_10_092917_rename_virtual_properties_vehicle_type.php new file mode 100644 index 00000000..f6bb9763 --- /dev/null +++ b/database/migrations/2020_01_10_092917_rename_virtual_properties_vehicle_type.php @@ -0,0 +1,32 @@ +renameColumn('commercial_vehicle', 'vehicle_type'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('virtual_properties', function (Blueprint $table) { + $table->renameColumn('vehicle_type', 'commercial_vehicle'); + }); + } +} diff --git a/database/migrations/create_virtual_order_cards_func.pgsql b/database/migrations/create_virtual_order_cards_func.pgsql index 18dad7fe..75833495 100644 --- a/database/migrations/create_virtual_order_cards_func.pgsql +++ b/database/migrations/create_virtual_order_cards_func.pgsql @@ -12,6 +12,22 @@ CREATE OR REPLACE VIEW real_virtual_relations AS WHERE r.virtual_order_id <> 0 GROUP BY r.type,r.company_id,r.package_id,v.company_id,v.package_id; +CREATE OR REPLACE FUNCTION GET_TIMELINES_JSON(INT8) + RETURNS JSONB +AS $$ +DECLARE + return_row JSONB; +BEGIN + SELECT TO_JSONB(ARRAY_AGG(t)) INTO return_row + FROM (SELECT type, service_start_at, service_end_at + FROM virtual_order_cards_partition + WHERE service_start_at IS NOT NULL + AND sim = $1 + AND deleted_at IS NULL) t; + RETURN return_row; +END; +$$ LANGUAGE plpgsql; + CREATE OR REPLACE FUNCTION GET_TIMELINES(INT8[]) RETURNS TABLE ( diff --git a/database/seeds/PropertySettingSeeder.php b/database/seeds/PropertySettingSeeder.php index f53c8803..f575b843 100644 --- a/database/seeds/PropertySettingSeeder.php +++ b/database/seeds/PropertySettingSeeder.php @@ -7,15 +7,16 @@ use function GuzzleHttp\json_encode; class PropertySettingSeeder extends Seeder { const PROPERTY_SETTING = [ - 'commercial_vehicle' => ['货车','两客一危','其他','其他商用车'], 'company' => ['北斗/GPS运营公司','物联网运营公司','汽车电子后市场','公交集团','企业客户','北斗/GPS/物联网运营公司','北斗/GPS工厂','车厂','汽车电子方案公司'], 'customer' => ['行业客户','车后市场客户'], - 'package' => ['A类套餐'=>['行车记录仪','电子狗'],'B类套餐'=>['智能后视镜'],'C类套餐'=>['物联网终端','北斗/GPS定位器','北斗超长待机终端','车载WIFI'],'D类套餐'=>['北斗/4G部标机']], 'package_type' => ['A类套餐','B类套餐','C类套餐','D类套餐'], - 'platform' => ['TSP平台','API接口','主动安全防控平台', '塔杆北斗应急监控平台', '网约车/出租车监控平台', '金融租赁风控平台', '公务车监管平台', '政府监管平台', '电动摩托车监控平台'], 'product' => ['物联网终端','北斗/GPS定位器','电子狗','行车记录仪','后视镜','大屏机','北斗/4G部标机','智能后视镜','北斗超长待机终端','车载WIFI'], + 'package' => ['A类套餐'=>['行车记录仪','电子狗'],'B类套餐'=>['智能后视镜'],'C类套餐'=>['物联网终端','北斗/GPS定位器','北斗超长待机终端','车载WIFI'],'D类套餐'=>['北斗/4G部标机']], + 'platform' => ['TSP平台','API接口','主动安全防控平台', '塔杆北斗应急监控平台', '网约车/出租车监控平台', '金融租赁风控平台', '公务车监管平台', '政府监管平台', '电动摩托车监控平台'], 'province' => ['福建省','广东省','山东省','江西省','安徽省','湖北省','江苏省','浙江省','上海市','四川省','河北省','湖南省','广西壮族自治区','山西省','辽宁省','河南省','贵州省','云南省','北京市','青海省','新疆维吾尔自治区','重庆市','天津市','吉林省','黑龙江省','海南省','陕西省','甘肃省','内蒙古自治区','西藏自治区','宁夏回族自治区','台湾省','香港特别行政区','澳门特别行政区'], - 'vehicle' => ['乘用车','商用车','其他'], + 'vehicle_group' => ['乘用车','商用车', '其他'], + 'vehicle_type' => ['私家车', '金融车', '出租车', '公交车', '旅行客车', '省际客车', '市际客车', '县际客车', '县内客车', '普通货车', '大型普通货车', '中型普通货车', '小型普通货车', '罐车', '牵引车', '挂车', '危险运输车', '其他'], + 'vehicle' => ['乘用车' => ['私家车', '金融车'], '商用车' => ['出租车', '公交车', '旅行客车', '省际客车', '市际客车', '县际客车', '县内客车', '普通货车', '大型普通货车', '中型普通货车', '小型普通货车', '罐车', '牵引车', '挂车', '危险运输车'], '其他' => ['其他']] ]; /** diff --git a/frontend/public/config.js b/frontend/public/config.js index 030346b9..2a80e3c6 100644 --- a/frontend/public/config.js +++ b/frontend/public/config.js @@ -3,7 +3,7 @@ var CONFIG = { login_background: '/assets/login_background.jpg', logo_big: '/assets/logo_big.png', logo_small: '/assets/logo_small.png', - url: (window.location.hostname === 'localhost') ? 'http://vd.dipp.ink/' : '/' + url: (window.location.hostname === 'localhost') ? 'http://127.0.0.1:8000/' : '/' }; window.CONFIG = CONFIG; diff --git a/frontend/src/views/virtual/properties/js/index.js b/frontend/src/views/virtual/properties/js/index.js index aa029a24..d9e720ef 100644 --- a/frontend/src/views/virtual/properties/js/index.js +++ b/frontend/src/views/virtual/properties/js/index.js @@ -15,7 +15,7 @@ export default { company_id: '', package_id: '' }, - only: ['company_id', 'package_id', 'product', 'vehicle', 'commercial_vehicle', 'company', 'platform', 'customer', 'province', 'agent'], + only: ['company_id', 'package_id', 'product', 'vehicle_type', 'company', 'platform', 'customer', 'province', 'agent'], updates: new Map(), settingsShow: false, settingsData: {}, @@ -88,6 +88,22 @@ export default { return this.editRender('company', h, context); } }, + { + title: '平台/API', + key: 'platform', + minWidth: 120, + render: (h, context) => { + return this.editRender('platform', h, context); + } + }, + { + title: '客户类型', + key: 'customer', + minWidth: 120, + render: (h, context) => { + return this.editRender('customer', h, context); + } + }, { title: '产品类型', key: 'product', @@ -104,36 +120,20 @@ export default { return h('span', this.productPackageTypes[context.row.product]); } }, - { - title: '平台/API', - key: 'platform', - minWidth: 120, - render: (h, context) => { - return this.editRender('platform', h, context); - } - }, { title: '车辆类型', - key: 'vehicle', + key: 'vehicle_type', minWidth: 120, render: (h, context) => { - return this.editRender('vehicle', h, context); + return this.editRender('vehicle_type', h, context); } }, { - title: '商用车分类', - key: 'commercial_vehicle', + title: '车型分类', + key: 'vehicle_group', minWidth: 120, render: (h, context) => { - return this.editRender('commercial_vehicle', h, context); - } - }, - { - title: '客户类型', - key: 'customer', - minWidth: 120, - render: (h, context) => { - return this.editRender('customer', h, context); + return h('span', this.vehicleTypeVehicleGroups[context.row.vehicle_type]); } }, { @@ -235,6 +235,22 @@ export default { } } + return obj; + }, + vehicleTypeVehicleGroups() { + let obj = {}; + + let vehicles = this.settingsData.vehicle ? this.settingsData.vehicle : {}; + + for (const key in vehicles) { + const element = vehicles[key]; + + for (let index = 0; index < element.length; index++) { + const value = element[index]; + obj[value] = key; + } + } + return obj; } }, @@ -251,7 +267,14 @@ export default { let options = []; - let arr = (key === 'product') ? Object.values(this.settingsData['package']).join(",").split(",") : this.settingsData[key]; + let arr; + if (key === 'product') { + arr = Object.values(this.settingsData['package']).join(",").split(","); + } else if (key === 'vehicle_type') { + arr = Object.values(this.settingsData['vehicle']).join(",").split(","); + } else { + arr = this.settingsData[key]; + } for (let index = 0; index < arr.length; index++) { const element = arr[index]; @@ -426,7 +449,7 @@ export default { API.store({ data: updates }).then(res => { if (res.code === 0) { - this.updates = []; + this.updates = new Map(); this.editModel = false; } this.isShowLoading(false); diff --git a/frontend/src/views/virtual/properties/js/settings.js b/frontend/src/views/virtual/properties/js/settings.js index c8a4e5c3..eab937ac 100644 --- a/frontend/src/views/virtual/properties/js/settings.js +++ b/frontend/src/views/virtual/properties/js/settings.js @@ -20,7 +20,8 @@ export default { my_show: false, loading: false, settings: {}, - selectedTab: "", + selectedPackageTab: "", + selectedVehicleTab: "", completePackagesFilter: [], dragOptions: { animation: 0, @@ -62,6 +63,39 @@ export default { this.settings.product = values.concat(array); } + }, + vehicles: { + get() { + return this.settings.vehicle ? this.settings.vehicle : {}; + }, + set(value) { + console.log("vehicles", value); + } + }, + vehicleTypes: { + get() { + let vehicleTypes = this.settings.vehicle_type ? this.settings.vehicle_type : []; + let vehicles = this.settings.vehicle ? this.settings.vehicle : {}; + + let values = []; + + for (const key in vehicles) { + values = values.concat(vehicles[key]); + } + + return vehicleTypes.filter(v => { + return !values.includes(v); + }); + }, + set(array) { + let vehicleTypes = this.settings.vehicle_type ? this.settings.vehicle_type : []; + + let values = vehicleTypes.filter(v => { + return !array.includes(v); + }); + + this.settings.vehicle_type = values.concat(array); + } } }, watch: { @@ -72,7 +106,11 @@ export default { this.settings = JSON.parse(JSON.stringify(this.data)); if (this.settings.package_type && this.settings.package_type.length) { - this.selectedTab = this.settings.package_type[0]; + this.selectedPackageTab = this.settings.package_type[0]; + } + + if (this.settings.vehicle_group && this.settings.vehicle_group.length) { + this.selectedVehicleTab = this.settings.vehicle_group[0]; } } } @@ -115,19 +153,30 @@ export default { title: "提示", content: "已设置的属性值不会因删除改变,确认是否还要删除", onOk: () => { - let node = - key === "package" - ? this.settings[key][this.selectedTab] - : this.settings[key]; + let node; + if (key === "package") { + node = this.settings[key][this.selectedPackageTab]; + } else if (key === "vehicle") { + node = this.settings[key][this.selectedVehicleTab]; + } else { + node = this.settings[key]; + } + let index = node.indexOf(value); node.splice(index, 1); if (key === "package") { - this.settings[key][this.selectedTab] = node; + this.settings[key][this.selectedPackageTab] = node; this.settings.product.splice( this.settings.product.indexOf(value), 1 ); + } else if (key === "vehicle") { + this.settings[key][this.selectedVehicleTab] = node; + this.settings.vehicle_type.splice( + this.settings.vehicle_type.indexOf(value), + 1 + ); } else { this.settings[key] = node; } @@ -136,10 +185,15 @@ export default { }, handleAdd(key) { let value = ""; - let node = - key === "package" - ? this.settings[key][this.selectedTab] - : this.settings[key]; + let node; + + if (key === "package") { + node = this.settings[key][this.selectedPackageTab]; + } else if (key === "vehicle") { + node = this.settings[key][this.selectedVehicleTab]; + } else { + node = this.settings[key]; + } this.$Modal.confirm({ render: h => { @@ -164,8 +218,11 @@ export default { node.push(value); if (key === "package") { - this.settings[key][this.selectedTab] = node; + this.settings[key][this.selectedPackageTab] = node; this.settings.product.push(value); + } else if (key === "vehicle") { + this.settings[key][this.selectedVehicleTab] = node; + this.settings.vehicle_type.push(value); } else { this.settings[key] = node; } @@ -238,9 +295,78 @@ export default { } }); }, + handleRemoveVehicleGroup(key) { + let value = this.settings.vehicle_group[key]; + return new Promise(resolve => { + this.$Modal.confirm({ + title: "提示", + content: + "删除车辆类型分类将同时删除分类及分类下的车辆类型,但已设置的属性值不会因删除改变,请谨慎操作", + onOk: () => { + let carType = this.settings.vehicle[value]; + + if (carType) { + for (let i = 0; i < carType.length; i++) { + const element = carType[i]; + let index = this.settings.product.indexOf(element); + + if (index !== -1) { + this.settings.product.splice(index, 1); + } + } + } + + this.settings.vehicle_group.splice(key, 1); + delete this.settings.vehicle[value]; + + resolve(true); + }, + onCannel: () => { + resolve(false); + } + }); + }); + }, + handleAddVehicleGroup() { + let value = ""; + + this.$Modal.confirm({ + render: h => { + return h("Input", { + props: { + value: value, + autofocus: true, + placeholder: "请输入车辆分类名称" + }, + on: { + input: val => { + value = val; + } + } + }); + }, + onOk: () => { + if (value === "") { + return this.$Message.error("名称不能为空"); + } + + let vehicle_group = this.settings.vehicle_group + ? this.settings.vehicle_group + : []; + + vehicle_group.push(value); + + this.settings.vehicle_group = vehicle_group; + this.settings.vehicle[value] = []; + } + }); + }, onChange(event) { - let packages = this.packages[this.selectedTab]; - this.settings.package[this.selectedTab] = packages; + let packages = this.packages[this.selectedPackageTab]; + this.settings.package[this.selectedPackageTab] = packages; + + let vehicles = this.vehicles[this.selectedPackageTab]; + this.settings.vehicle[this.selectedPackageTab] = vehicles; } } }; diff --git a/frontend/src/views/virtual/properties/settings.vue b/frontend/src/views/virtual/properties/settings.vue index 1b6a64a1..b1855690 100644 --- a/frontend/src/views/virtual/properties/settings.vue +++ b/frontend/src/views/virtual/properties/settings.vue @@ -11,39 +11,6 @@