diff --git a/base/web/html/html.go b/base/web/html/html.go index 9b4e8d85..0aa8df24 100644 --- a/base/web/html/html.go +++ b/base/web/html/html.go @@ -41,6 +41,7 @@ const ( TEXT_PLAIN = "text/plain" ) const ( + LABEL = "label" TABLE = "table" TR = "tr" TH = "th" diff --git a/core/chat/location/amap.go b/core/chat/location/amap.go index efe554cd..1f344563 100644 --- a/core/chat/location/amap.go +++ b/core/chat/location/amap.go @@ -17,7 +17,9 @@ const AMAP = "amap" func init() { web.Index.MergeCommands(ice.Commands{ "/_AMapService/": {Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(web.SPIDE, ice.DEV, web.SPIDE_RAW, m.R.Method, "https://restapi.amap.com/"+path.Join(arg...)+"?"+m.R.URL.RawQuery+"&jscode="+mdb.Conf(m, chat.Prefix(AMAP), kit.Keym(aaa.SECRET))).RenderResult() + m.Cmdy(web.SPIDE, ice.DEV, web.SPIDE_RAW, m.R.Method, kit.MergeURL("https://restapi.amap.com/"+path.Join(arg...)+"?"+m.R.URL.RawQuery, + "jscode", mdb.Conf(m, chat.Prefix(AMAP), kit.Keym(aaa.SECRET))), + ).RenderResult() }}, }) chat.Index.MergeCommands(ice.Commands{ diff --git a/core/chat/location/amap.js b/core/chat/location/amap.js index efd210af..af61d4f4 100644 --- a/core/chat/location/amap.js +++ b/core/chat/location/amap.js @@ -2,55 +2,75 @@ Volcanos(chat.ONIMPORT, { _init: function(can, msg, cb) { window._AMapSecurityConfig = {serviceHost: location.origin+"/_AMapService"}, can.require([can.Conf(nfs.SCRIPT)], function() { can.require(["location.js"], function() { can.onimport._layout_init(can, msg, function() { cb && cb(msg) can.page.style(can, can.ui.content, html.WIDTH, can.ConfWidth(can._fields.offsetWidth)-can.ui.project.offsetWidth) - can.onimport._content(can) }) - }) + can.onimport._content(can) + }) }) }) }, _content: function(can, item) { - var map = new AMap.Map(can.ui.content, {viewMode: '3D', lang: can.getHeaderLanguage().split("-")[0], zoom: can.Action("zoom"), pitch: can.Action("pitch"), rotation: can.Action("rotation")}); can.ui.map = map - can.onimport._style(can, can.getHeaderTheme()), can.onengine.listen(can, chat.ONTHEMECHANGE, function() { can.onimport._style(can, can.getHeaderTheme()) }) + var map = new AMap.Map(can.ui.content, {viewMode: '3D', lang: can.getHeaderLanguage().split("-")[0], zoom: can.Action("zoom"), pitch: can.Action("pitch"), rotation: can.Action("rotation")}) + can.ui.map = map, can.onimport._style(can, can.getHeaderTheme()), can.onengine.listen(can, chat.ONTHEMECHANGE, function() { can.onimport._style(can, can.getHeaderTheme()) }) map.on("moveend", function(event) { can.Action("pitch", map.getPitch().toFixed(2)), can.Action("rotation", map.getRotation()) }) map.on("zoomend", function(event) { can.Action("zoom", map.getZoom().toFixed(2)) }) map.on("click", function(event) { can.onexport.status(can, event.lnglat) }) - map.plugin(['AMap.Scale', 'AMap.ToolBar', 'AMap.MapType', 'AMap.Geolocation', 'AMap.Geocoder', 'AMap.Weather'], function() { + map.plugin([ + 'AMap.Scale', 'AMap.ToolBar', 'AMap.MapType', 'AMap.Geolocation', 'AMap.Geocoder', 'AMap.Weather', + 'AMap.Autocomplete', + 'AMap.DistrictLayer', + ], function() { map.addControl(new AMap.Scale()), map.addControl(new AMap.ToolBar()), map.addControl(new AMap.MapType()) map.addControl(can.ui.geolocation = new AMap.Geolocation({buttonPosition: 'RB', enableHighAccuracy: true})), can.ui.geocoder = new AMap.Geocoder({}) + AMap.event.addListener(can.ui.geolocation, 'error', function(res) { can.user.toastFailure(can, res.message) }) AMap.event.addListener(can.ui.geolocation, 'complete', function() { can.ui.map.setZoom(can.Action("zoom", 16)), can.ui.map.setPitch(can.Action("pitch", 0)), can.ui.map.setRotation(can.Action("rotation", 0)) can.user.toastSuccess(can), can.onmotion.delay(can, function() { can.onexport.status(can) var weather = new AMap.Weather(); weather.getLive(can.Status("city"), function(err, data) { can.Status(data) }) }, 500) }), can.onmotion.delay(can, function() { can.onaction.current({}, can) }) - AMap.event.addListener(can.ui.geolocation, 'error', function(res) { - can.user.toastFailure(can, res.message) - }) }) - map.add(can.ui.favor = new AMap.OverlayGroup()) + can.ui.layer = {} + map.add(can.ui.layer.favor = new AMap.OverlayGroup()) + map.add(can.ui.layer.search = new AMap.OverlayGroup()) map.add(can.ui.marker = new AMap.Marker({position: [116.39, 39.9]})) map.add(can.ui.circle = new AMap.CircleMarker({ center: new AMap.LngLat("116.403322", "39.920255"), radius: 100, strokeColor: "#F33", strokeWeight: 1, fillColor: "#ee2200", fillOpacity: 0.35, })) }, + _district: function(can, city) { can.ui._district = can.ui._district||{}; if (can.ui._district[city]) { return } + can.ui.map.add(can.ui._district[city] = new AMap.DistrictLayer.Province({ + zIndex: 12, depth: 2, adcode: [city], + styles:{'fill': "transparent", 'city-stroke': 'blue', 'province-stroke': 'red'} + })) + if (can.ui._district.length > 1) { return } + can.ui.map.add(new AMap.DistrictLayer.Country({ + zIndex: 10, depth: 2, SOC: 'CHN', + styles:{'fill': 'transparent', 'city-stroke': 'blue', 'province-stroke': 'red'} + })) + }, _style: function(can, style) { style = {"light": "normal", "dark": "grey", "black": "blue", "white": "macaron", "silver": "grey", "blue": "graffiti", "red": "graffiti"}[style]||style can.ui.map.setMapStyle("amap://styles/"+can.Action("style", style)) return style }, - _mark: function(can, item, target) { - var p = new AMap.Marker({position: [parseFloat(item.longitude), parseFloat(item.latitude)]}) - p.on("click", function() { target.click() }), can.ui.favor.addOverlay(p) + _mark: function(can, item, target, layer) { layer = layer||can.ui.layer.favor + var p = new AMap.Marker({position: [parseFloat(item.longitude), parseFloat(item.latitude)], label: item.label && {content: item.label, direction: "bottom"}, title: item.name}) + p.on("click", function() { target.click() }), layer.addOverlay(p) }, }) Volcanos(chat.ONACTION, { _trans: { - current: "定位", favor: "收藏", + favor: "收藏", + explore: "周边", + direction: "导航", + district: "行政", + current: "定位", input: { + district: "区域", street: "街道", zoom: "缩放", pitch: "倾斜", rotation: "旋转", weather: "天气", temperature: "温度", humidity: "湿度", windPower: "风速", }, - }, - current: function(event, can) { - can.user.toastProcess(can), can.ui.geolocation.getCurrentPosition() + icons: { + current: "bi bi-pin-map", + }, }, feature: function(event, can, button, value) { if (value == "road") { @@ -59,17 +79,35 @@ Volcanos(chat.ONACTION, { can.ui.map.setFeatures(["bg", "road", "building", "point"]) } }, + current: function(event, can) { + can.user.toastProcess(can), can.ui.geolocation.getCurrentPosition() + }, + search: function(event, can) { + can.user.input(event, can, ["keyword"], function(data) { + can.ui.autoComplete = new AMap.Autocomplete({city: can.ui.city.citycode}) + can.ui.autoComplete.search(data.keyword, function(status, result) { var _select + can.core.List(result.tips, function(value) { value = {name: value.name, label: value.name, longitude: value.location.lng, latitude: value.location.lat} + var item = can.onimport._item(can, value, can.ui.zone.search._target, can.ui.layer.search) + _select = _select||item._target + }), can.ui.zone.favor.toggle(false), can.ui.zone.search.toggle(true), _select.click() + // can.ui.map.setFitView([can.ui.layer.search], true, [10, 10, 10, 10], 15) + }) + }) + }, + direction: function(event, can, button, item) { + can.user.isMobile && window.open(`https://uri.amap.com/marker?position=${item.longitude},${item.latitude}&name=${item.name||item.text}&callnative=1`) + }, center: function(can, item) { can.ui.marker.setTitle(item.name) can.ui.map.setCenter(new AMap.LngLat(parseFloat(item.longitude), parseFloat(item.latitude))) can.onmotion.delay(can, function() { can.onexport.status(can) }, 500) }, - direction: function(event, can, button, item) { - can.user.isMobile && window.open(`https://uri.amap.com/marker?position=${item.longitude},${item.latitude}&name=${item.name||item.text}&callnative=1`) - } }) Volcanos(chat.ONEXPORT, { status: function(can, p) { p = p||can.ui.map.getCenter(), can.ui.marker.setPosition(p), can.ui.circle.setCenter(p) - can.Status({longitude: p.getLng().toFixed(6), latitude: p.getLat().toFixed(6)}), can.ui.map.getCity(function(result) { can.Status(result) }) + can.Status({longitude: p.getLng().toFixed(6), latitude: p.getLat().toFixed(6)}), can.ui.map.getCity(function(result) { + can.ui.city = result, can.Status(result) + can.onimport._district(can, can.ui.map.getAdcode()) + }) can.ui.geocoder.getAddress(p, function(status, result) { var info = result.regeocode.addressComponent, text = result.regeocode.formattedAddress text = can.base.trimPrefix(text, info.province, info.city, info.district, info.township) diff --git a/core/chat/location/location.css b/core/chat/location/location.css new file mode 100644 index 00000000..cc57036b --- /dev/null +++ b/core/chat/location/location.css @@ -0,0 +1,6 @@ +fieldset.web.chat.location div.output { +} +fieldset.web.chat.location div.action>div.item.text.zoom input { width:60px; } +fieldset.web.chat.location div.action>div.item.text.pitch input { width:60px; } +fieldset.web.chat.location div.action>div.item.text.rotation input { width:60px; } +div.amap-marker-label { background-color:var(--output-bg-color); } \ No newline at end of file diff --git a/core/chat/location/location.go b/core/chat/location/location.go index 4640c7dd..95258315 100644 --- a/core/chat/location/location.go +++ b/core/chat/location/location.go @@ -5,7 +5,6 @@ import ( "shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/web" - "shylinux.com/x/icebergs/base/web/html" "shylinux.com/x/icebergs/core/chat" kit "shylinux.com/x/toolkits" ) @@ -24,12 +23,7 @@ const LOCATION = "location" func init() { chat.Index.MergeCommands(ice.Commands{ - LOCATION: {Help: "地图", Icon: "Maps.png", Meta: kit.Dict( - ice.CTX_TRANS, kit.Dict(EXPLORE, "周边", DIRECTION, "导航", DISTRICT, "地区", html.INPUT, kit.Dict( - LONGITUDE, "经度", LATITUDE, "纬度", PROVINCE, "省份", CITY, "城市", DISTRICT, "区域", STREET, "街路", - )), - ), Actions: ice.MergeActions(ice.Actions{ - "current": {Icon: "bi bi-pin-map"}, + LOCATION: {Help: "地图", Icon: "Maps.png", Actions: ice.MergeActions(ice.Actions{ chat.FAVOR_INPUTS: {Hand: func(m *ice.Message, arg ...string) { kit.If(arg[0] == mdb.TYPE, func() { m.Push(arg[0], LOCATION) }) }}, diff --git a/core/chat/location/location.js b/core/chat/location/location.js index ea2587bc..50a19383 100644 --- a/core/chat/location/location.js +++ b/core/chat/location/location.js @@ -1,36 +1,35 @@ -Volcanos(chat.ONIMPORT, {_init: function(can, msg) {}, +Volcanos(chat.ONIMPORT, { + _init: function(can, msg) {}, _layout_init: function(can, msg, cb) { can.db.list = {}, can.ui = can.onappend.layout(can), can.onimport._project(can) - can.onmotion.hidden(can, can.ui.project) - can.onmotion.hidden(can, can._action) - // can.core.Item(can.ui.zone, function(key, item) { key == "favor" || item._legend.click() }) + can.onappend.style(can, "web.chat.location", can._fields) if (can.user.isMobile) { can.page.style(can, can.ui.project, "z-index", 2, "position", "absolute", html.MAX_HEIGHT, can.ConfHeight()-120) can.page.style(can, can.ui.content, html.HEIGHT, can.ConfHeight(), html.WIDTH, can.ConfWidth()) can.onmotion.hidden(can, can._action), can.onmotion.hidden(can, can._status) } else { + can.isCmdMode() || can.onmotion.hidden(can, can.ui.project), can.isCmdMode() || can.onmotion.hidden(can, can._action) can.ui.layout(can.ConfHeight(), can.ConfWidth()) } msg.Option(ice.MSG_ACTION, ""), cb && cb(msg) if (msg.IsDetail()) { can.onaction.center(can, can.onimport._item(can, msg.TableDetail())) } else { msg.Table(function(item) { can.onimport._item(can, item) }), can.ui.zone.favor._total(msg.Length()), can.ui.zone.favor.toggle(true) - var item = can.db.list[can.db.hash[0]]; item && item.click() + var item = can.db.list[can.db.hash[0]]; item && item.click() } }, _project: function(can) { can.onmotion.clear(can, can.ui.project), can.onimport.zone(can, [ - {name: "search"}, {name: "explore"}, {name: "direction"}, {name: "favor", _menu: shy({"play": function(event, can, button) { can.core.Next(can.page.Select(can, can.ui.zone.favor._target, html.DIV_ITEM), function(item, next) { item.click(), can.onmotion.delay(can, next, 3000) }, function() { can.user.toastSuccess(can) }) }})}, + {name: "search"}, {name: "explore"}, {name: "direction"}, {name: "district", _delay_init: function(target, zone) { can.onimport._province(can, target) }}, ], can.ui.project) }, - _item: function(can, item, target) { if (!item.latitude || !item.longitude) { return item } + _item: function(can, item, target, layer) { if (!item.latitude || !item.longitude) { return item } var _target = can.onimport.item(can, item, function(event) { can.onaction.center(can, item), can.ui.map.setZoom(can.Action("zoom", 16)), can.misc.SearchHash(can, item.hash) - can.onimport.plugin(can, item) && can.onmotion.delay(can, function() { - var ls = can.ui.map.getBounds().path + can.onimport.plugin(can, item) && can.onmotion.delay(can, function() { var ls = can.ui.map.getBounds().path ls && can.ui.map.setCenter([ls[1][0]-(ls[1][0]-ls[3][0])*3/8, ls[1][1]+(ls[3][1]-ls[1][1])*3/8]) }, 500) }, function(event) { @@ -44,7 +43,7 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg) {}, remove: function(event, button) { can.runAction(event, mdb.REMOVE, [mdb.HASH, item.hash], function() { can.page.Remove(can, _target) }) }, }) }, target||can.ui.zone.favor._target); can.db.list[item.hash] = _target, can.ui.zone.favor._total() - return can.onimport._mark(can, item, _target), item + return can.onimport._mark(can, item, item._target = _target, layer), item }, _mark: function(can, item) {}, _style: function(can, style) {}, plugin: function(can, item) { var extra = can.base.Obj(item.extra, {}) if (!extra.index) { return can.onmotion.toggle(can, can.ui.profile, false) } can.onmotion.toggle(can, can.ui.profile, true) @@ -59,15 +58,8 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg) {}, }, can.ui.profile) return true }, -}) +}, [""]) Volcanos(chat.ONACTION, { - _trans: { - current: "定位", favor: "收藏", - input: { - zoom: "缩放", pitch: "倾斜", rotation: "旋转", - weather: "天气", temperature: "温度", humidity: "湿度", windPower: "风速", - }, - }, list: [ ["style", "normal", "light", "whitesmoke", "fresh", "macaron", "graffiti", "darkblue", "blue", "grey", "dark"], ["feature", "point", "road"], @@ -75,11 +67,11 @@ Volcanos(chat.ONACTION, { {type: html.TEXT, name: "pitch", value: 30, range: [0, 80, 5]}, {type: html.TEXT, name: "rotation", value: 0, range: [0, 360, 10]}, "current:button", "search", "explore", "direction", mdb.CREATE, - ], _trans: {current: "定位", favor: "收藏"}, + ], style: function(event, can, button, value) { can.onimport._style(can, value) }, zoom: function(event, can) { can.ui.map.setZoom(can.Action("zoom")) }, pitch: function(event, can) { can.ui.map.setPitch(can.Action("pitch")) }, rotation: function(event, can) { can.ui.map.setRotation(can.Action("rotation")) }, center: function(can, item) {}, }) -Volcanos(chat.ONEXPORT, {list: ["province", "city", "district", "street", aaa.LONGITUDE, aaa.LATITUDE, "type", "name", "text", "space", "weather", "temperature", "humidity", "windPower"]}) +Volcanos(chat.ONEXPORT, {list: ["province", "city", "district", "street", aaa.LONGITUDE, aaa.LATITUDE, mdb.TYPE, mdb.NAME, mdb.TEXT, web.SPACE, "weather", "temperature", "humidity", "windPower"]}) diff --git a/misc.go b/misc.go index e454b029..3fb0a87e 100644 --- a/misc.go +++ b/misc.go @@ -77,7 +77,9 @@ func (m *Message) SetAppend(arg ...string) *Message { kit.If(len(arg) == 0, func() { m.OptionFields("") }) return m.Set(MSG_APPEND, arg...) } -func (m *Message) SetResult(arg ...string) *Message { return m.Set(MSG_RESULT, arg...) } +func (m *Message) SetResult(arg ...string) *Message { + return m.Set(MSG_RESULT, arg...) +} func (m *Message) PushRecord(value Any, arg ...string) *Message { if m.FieldsIsDetail() { return m.PushDetail(value, arg...)