You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4044 lines
135 KiB

  1. /*
  2. Copyright (c) 2018 jones
  3. http://www.apache.org/licenses/LICENSE-2.0
  4. 开源项目 https://github.com/jones2000/HQChart
  5. jones_2000@163.com
  6. 封装股票列表控件 (小程序版本)
  7. 不提供内置测试数据
  8. */
  9. //日志
  10. import { JSConsole } from "./umychart.console.wechat.js"
  11. //画布DOM
  12. import { JSCanvasElement } from "./umychart.element.wechart.js";
  13. import{
  14. g_JSChartResource,
  15. JSCHART_LANGUAGE_ID,
  16. g_JSChartLocalization,
  17. } from './umychart.resource.wechat.js'
  18. import
  19. {
  20. IFrameSplitOperator,
  21. } from './umychart.framesplit.wechat.js'
  22. import
  23. {
  24. GetfloatPrecision,
  25. } from "./umychart.coordinatedata.wechat.js";
  26. //图形库
  27. import {
  28. ChartSplashPaint,
  29. GetFontHeight,
  30. } from "./umychart.chartpaint.wechat.js";
  31. //行情数据结构体 及涉及到的行情算法(复权,周期等)
  32. import {
  33. JSCHART_EVENT_ID,
  34. PhoneDBClick,
  35. } from "./umychart.data.wechat.js";
  36. //边框信息
  37. function ChartBorder()
  38. {
  39. this.UIElement;
  40. //四周间距
  41. this.Left = 50;
  42. this.Right = 80;
  43. this.Top = 50;
  44. this.Bottom = 50;
  45. this.GetChartWidth = function ()
  46. {
  47. return this.UIElement.Width;
  48. }
  49. this.GetChartHeight = function ()
  50. {
  51. return this.UIElement.Height;
  52. }
  53. this.GetLeft = function ()
  54. {
  55. return this.Left;
  56. }
  57. this.GetRight = function ()
  58. {
  59. return this.UIElement.Width - this.Right;
  60. }
  61. this.GetTop = function ()
  62. {
  63. return this.Top;
  64. }
  65. this.GetBottom = function ()
  66. {
  67. return this.UIElement.Height - this.Bottom;
  68. }
  69. this.GetWidth = function ()
  70. {
  71. return this.UIElement.Width - this.Left - this.Right;
  72. }
  73. this.GetHeight = function ()
  74. {
  75. return this.UIElement.Height - this.Top - this.Bottom;
  76. }
  77. }
  78. function JSReportChart(element)
  79. {
  80. this.CanvasElement=element;
  81. this.JSChartContainer; //表格控件
  82. this.OnSize=function(option)
  83. {
  84. if (option)
  85. {
  86. if (IFrameSplitOperator.IsNumber(option.Width)) this.CanvasElement.Width=option.Width;
  87. if (IFrameSplitOperator.IsNumber(option.Height)) this.CanvasElement.Height=option.Height;
  88. }
  89. if (option && option.Redraw==false) return;
  90. if (this.JSChartContainer && this.JSChartContainer.OnSize)
  91. {
  92. this.JSChartContainer.OnSize();
  93. }
  94. }
  95. this.SetOption=function(option)
  96. {
  97. var chart=this.CreateJSReportChartContainer(option);
  98. if (!chart) return false;
  99. if (option.OnCreatedCallback) option.OnCreatedCallback(chart);
  100. this.JSChartContainer=chart;
  101. if (option.Symbol) chart.Symbol=option.Symbol;
  102. if (option.Name) chart.Name=option.Name;
  103. var requestOption={ Callback:null };
  104. if (chart.Symbol) requestOption.Callback=function() { chart.RequestMemberListData(); };
  105. chart.RequestStockListData(requestOption); //下载码表
  106. }
  107. this.CreateJSReportChartContainer=function(option)
  108. {
  109. var chart=new JSReportChartContainer(this.CanvasElement);
  110. chart.Create(option);
  111. if (option.NetworkFilter) chart.NetworkFilter=option.NetworkFilter;
  112. if (IFrameSplitOperator.IsNonEmptyArray(option.Column)) chart.SetColumn(option.Column);
  113. if (IFrameSplitOperator.IsNonEmptyArray(option.Tab)) chart.SetTab(option.Tab);
  114. if (IFrameSplitOperator.IsNumber(option.TabSelected)) chart.SetSelectedTab(option.TabSelected);
  115. if (option.SortInfo)
  116. {
  117. var item=option.SortInfo;
  118. if (IFrameSplitOperator.IsNumber(item.Field)) chart.SortInfo.Field=item.Field;
  119. if (IFrameSplitOperator.IsNumber(item.Sort)) chart.SortInfo.Sort=item.Sort;
  120. }
  121. this.SetChartBorder(chart, option);
  122. //是否自动更新
  123. if (option.IsAutoUpdate!=null) chart.IsAutoUpdate=option.IsAutoUpdate;
  124. if (option.AutoUpdateFrequency>0) chart.AutoUpdateFrequency=option.AutoUpdateFrequency;
  125. if (IFrameSplitOperator.IsBool(option.EnableFilter)) chart.EnableFilter=option.EnableFilter;
  126. //注册事件
  127. if (option.EventCallback)
  128. {
  129. for(var i=0;i<option.EventCallback.length;++i)
  130. {
  131. var item=option.EventCallback[i];
  132. chart.AddEventCallback(item);
  133. }
  134. }
  135. return chart;
  136. }
  137. this.SetChartBorder=function(chart, option)
  138. {
  139. if (!option.Border) return;
  140. var item=option.Border;
  141. if (IFrameSplitOperator.IsNumber(option.Border.Left)) chart.Frame.ChartBorder.Left=option.Border.Left;
  142. if (IFrameSplitOperator.IsNumber(option.Border.Right)) chart.Frame.ChartBorder.Right=option.Border.Right;
  143. if (IFrameSplitOperator.IsNumber(option.Border.Top)) chart.Frame.ChartBorder.Top=option.Border.Top;
  144. if (IFrameSplitOperator.IsNumber(option.Border.Bottom)) chart.Frame.ChartBorder.Bottom=option.Border.Bottom;
  145. }
  146. /////////////////////////////////////////////////////////////////////////////
  147. //对外接口
  148. //切换股票代码接口
  149. this.ChangeSymbol=function(symbol, option)
  150. {
  151. if (this.JSChartContainer) this.JSChartContainer.ChangeSymbol(symbol,option);
  152. }
  153. this.SetColumn=function(aryColumn, option)
  154. {
  155. if (this.JSChartContainer) this.JSChartContainer.SetColumn(aryColumn,option);
  156. }
  157. //事件回调
  158. this.AddEventCallback=function(obj)
  159. {
  160. if(this.JSChartContainer && typeof(this.JSChartContainer.AddEventCallback)=='function')
  161. {
  162. JSConsole.Chart.Log('[JSReportChart:AddEventCallback] obj=', obj);
  163. this.JSChartContainer.AddEventCallback(obj);
  164. }
  165. }
  166. //重新加载配置
  167. this.ReloadResource=function(option)
  168. {
  169. if(this.JSChartContainer && typeof(this.JSChartContainer.ReloadResource)=='function')
  170. {
  171. JSConsole.Chart.Log('[JSReportChart:ReloadResource] ');
  172. this.JSChartContainer.ReloadResource(option);
  173. }
  174. }
  175. this.ChartDestory=function()
  176. {
  177. if (this.JSChartContainer && typeof (this.JSChartContainer.ChartDestory) == 'function')
  178. {
  179. JSConsole.Chart.Log("[JSReportChart::ChartDestory]");
  180. this.JSChartContainer.ChartDestory();
  181. }
  182. }
  183. this.OnTouchStart = function (e)
  184. {
  185. if (this.JSChartContainer) this.JSChartContainer.OnTouchStart(e);
  186. }
  187. this.OnTouchMove = function (e)
  188. {
  189. if (this.JSChartContainer) this.JSChartContainer.OnTouchMove(e);
  190. }
  191. this.OnTouchEnd = function (e)
  192. {
  193. if (this.JSChartContainer) this.JSChartContainer.OnTouchEnd(e);
  194. }
  195. }
  196. JSReportChart.Init=function(uielement)
  197. {
  198. var jsChartControl=new JSReportChart(uielement);
  199. jsChartControl.OnSize();
  200. return jsChartControl;
  201. }
  202. //自定义风格
  203. JSReportChart.SetStyle = function (style)
  204. {
  205. if (style) g_JSChartResource.SetStyle(style);
  206. }
  207. //获取颜色配置 (设置配必须啊在JSChart.Init()之前)
  208. JSReportChart.GetResource = function ()
  209. {
  210. return g_JSChartResource;
  211. }
  212. //修正线段有毛刺
  213. function ToFixedPoint(value)
  214. {
  215. //return value;
  216. return parseInt(value) + 0.5;
  217. }
  218. function ToFixedRect(value)
  219. {
  220. var rounded;
  221. return rounded = (0.5 + value) << 0;
  222. }
  223. function HQReportItem()
  224. {
  225. this.OriginalSymbol; //原始代码
  226. this.Symbol;
  227. this.Name;
  228. this.YClose;
  229. this.Open;
  230. this.Price;
  231. this.High;
  232. this.Low;
  233. this.Amount;
  234. this.Vol;
  235. this.Increase; //涨幅
  236. this.UpDown; //涨跌
  237. this.Exchange; //换手
  238. this.Amplitude; //振幅
  239. this.BuyPrice; //买价/量
  240. this.BuyVol;
  241. this.SellPrice; //卖价/量
  242. this.SellVol;
  243. this.AvPrice; //均价
  244. this.LimitHigh; //涨停价
  245. this.LimitLow; //跌停价
  246. this.VolIn; //内盘
  247. this.VolOut; //外盘
  248. this.DealNum; //现量
  249. this.OutShares; //流通股本
  250. this.TotalShares; //总股本
  251. this.MarketValue; //总市值
  252. this.CircMarketValue;//流通市值
  253. this.CloseLine; //{Data:[], Max:, Min:, Count: }
  254. this.ExtendData; //扩展数据
  255. }
  256. function JSReportChartContainer(uielement)
  257. {
  258. this.ClassName='JSReportChartContainer';
  259. this.Frame; //框架画法
  260. this.ChartPaint=[]; //图形画法
  261. this.ChartSplashPaint=null; //等待提示
  262. this.LoadDataSplashTitle="数据加载中"; //下载数据提示信息
  263. this.SplashTitle={ StockList:"下载码表中.....", MemberList:"下载成分中....." } ;
  264. this.Canvas=uielement.GetContext("2d"); //画布
  265. this.ShowCanvas=null;
  266. this.Symbol; //板块代码
  267. this.Name; //板块名称
  268. this.NetworkFilter; //数据回调接口
  269. this.Data={ XOffset:0, YOffset:0, Data:[] }; //股票列表
  270. this.SourceData={ Data:[] } ; //原始股票顺序(排序还原用)
  271. this.BlockData=new Map(); //当前板块数据
  272. this.MapStockData=new Map(); //原始股票数据
  273. this.FixedRowData={ Data:[], Type:0, Symbol:[] }; //顶部固定行Data:[{ Value:, Text:, Color:, TextAgiln: }], Type:0=自定义数据, 1 =(股票数据) Symbol:[],
  274. //this.FixedRowData.Data=[ [null, {Value:11, Text:"11" }], [null, null, null, {Value:12, Text:"ddddd", Color:"rgb(45,200,4)"}]];
  275. this.SortInfo={ Field:-1, Sort:0 }; //排序信息 {Field:排序字段id, Sort:0 不排序 1升序 2降序 }
  276. //事件回调
  277. this.mapEvent=new Map(); //通知外部调用 key:JSCHART_EVENT_ID value:{Callback:回调,}
  278. this.AutoUpdateTimer=null;
  279. this.AutoUpdateFrequency=15000; //15秒更新一次数据
  280. this.DelayUpdateTimer=null; //延迟更新
  281. this.DelayUpdateFrequency=500; //延迟更新时间
  282. this.UIElement=uielement;
  283. this.LastPoint=null; //鼠标位置
  284. this.IsOnTouch=false;
  285. this.TouchDrag;
  286. this.TouchMoveMinAngle=70; //左右移动最小角度
  287. this.YStepPixel=5;
  288. this.XStepPixel=10;
  289. this.PageUpDownCycle=true; //翻页循环
  290. this.DragPageCycle=true; //手机翻页循环
  291. //拖拽滚动条
  292. this.DragXScroll=null; //{Start:{x,y}, End:{x, y}}
  293. this.IsDestroy=false; //是否已经销毁了
  294. this.ChartDestory=function() //销毁
  295. {
  296. this.IsDestroy=true;
  297. this.StopAutoUpdate();
  298. }
  299. //清空固定行数据
  300. this.ClearFixedRowData=function()
  301. {
  302. this.FixedRowData.Data=[];
  303. this.FixedRowData.Symbol=[];
  304. }
  305. //设置固定行
  306. this.SetFixedRowCount=function(value)
  307. {
  308. var chart=this.GetReportChart();
  309. if (!chart) return;
  310. chart.FixedRowCount=value;
  311. }
  312. //创建
  313. this.Create=function(option)
  314. {
  315. this.UIElement.JSChartContainer=this;
  316. //创建等待提示
  317. this.ChartSplashPaint = new ChartSplashPaint();
  318. this.ChartSplashPaint.Canvas = this.Canvas;
  319. this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle);
  320. this.ChartSplashPaint.IsEnableSplash=true;
  321. //创建框架
  322. this.Frame=new JSReportFrame();
  323. this.Frame.ChartBorder=new ChartBorder();
  324. this.Frame.ChartBorder.UIElement=this.UIElement;
  325. this.Frame.ChartBorder.Top=30;
  326. this.Frame.ChartBorder.Left=5;
  327. this.Frame.ChartBorder.Bottom=20;
  328. this.Frame.Canvas=this.Canvas;
  329. this.ChartSplashPaint.Frame = this.Frame;
  330. //创建表格
  331. var chart=new ChartReport();
  332. chart.Frame=this.Frame;
  333. chart.ChartBorder=this.Frame.ChartBorder;
  334. chart.Canvas=this.Canvas;
  335. chart.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  336. chart.GetStockDataCallback=(symbol)=>{ return this.GetStockData(symbol);}
  337. chart.GetBlockDataCallback=(symbol)=>{ return this.GetBlockData(symbol);}
  338. chart.Data=this.Data;
  339. chart.FixedRowData=this.FixedRowData;
  340. chart.SortInfo=this.SortInfo;
  341. this.ChartPaint[0]=chart;
  342. //页脚
  343. if (option && option.PageInfo===true)
  344. {
  345. var pageInfoChart=new ChartReportPageInfo();
  346. pageInfoChart.Frame=this.Frame;
  347. pageInfoChart.ChartBorder=this.Frame.ChartBorder;
  348. pageInfoChart.Canvas=this.Canvas;
  349. pageInfoChart.Report=chart;
  350. this.ChartPaint[1]=pageInfoChart;
  351. }
  352. if (option)
  353. {
  354. if (IFrameSplitOperator.IsBool(option.IsShowHeader)) chart.IsShowHeader=option.IsShowHeader; //是否显示表头
  355. if (IFrameSplitOperator.IsNumber(option.FixedColumn)) chart.FixedColumn=option.FixedColumn; //固定列
  356. if (IFrameSplitOperator.IsNumber(option.BorderLine)) this.Frame.BorderLine=option.BorderLine; //边框
  357. if (IFrameSplitOperator.IsNumber(option.FixedRowCount)) chart.FixedRowCount=option.FixedRowCount; //固定行
  358. if (IFrameSplitOperator.IsBool(option.ItemBorder)) chart.IsDrawBorder=option.ItemBorder; //单元格边框
  359. if (IFrameSplitOperator.IsNonEmptyArray(option.FixedSymbol))
  360. {
  361. chart.FixedRowCount=0;
  362. this.FixedRowData.Type=1;
  363. this.FixedRowData.Symbol=[];
  364. var aryData=option.FixedSymbol;
  365. for(var i=0; i<aryData.length; ++i)
  366. {
  367. var item=aryData[i];
  368. this.FixedRowData.Symbol.push(item.Symbol);
  369. ++chart.FixedRowCount;
  370. }
  371. }
  372. }
  373. }
  374. this.Draw=function()
  375. {
  376. if (this.UIElement.Width<=0 || this.UIElement.Height<=0) return;
  377. this.Canvas.clearRect(0,0,this.UIElement.Width,this.UIElement.Height);
  378. if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash)
  379. {
  380. this.Frame.Draw( { IsEnableSplash:this.ChartSplashPaint.IsEnableSplash} );
  381. this.ChartSplashPaint.Draw();
  382. return;
  383. }
  384. this.Frame.Draw();
  385. this.Frame.DrawLogo();
  386. //框架内图形
  387. for(var i=0;i<this.ChartPaint.length;++i)
  388. {
  389. var item=this.ChartPaint[i];
  390. if (item.IsDrawFirst)
  391. item.Draw();
  392. }
  393. for(var i=0; i<this.ChartPaint.length; ++i)
  394. {
  395. var item=this.ChartPaint[i];
  396. if (!item.IsDrawFirst)
  397. item.Draw();
  398. }
  399. this.Canvas.draw(false);
  400. }
  401. this.ResetReportStatus=function()
  402. {
  403. this.Data.XOffset=0;
  404. this.Data.YOffset=0;
  405. }
  406. this.ResetReportSelectStatus=function()
  407. {
  408. var chart=this.GetReportChart();
  409. if (chart)
  410. {
  411. chart.SelectedRow=-1;
  412. chart.SelectedFixedRow=-1;
  413. }
  414. }
  415. this.ClearData=function()
  416. {
  417. this.SourceData.Data=[];
  418. this.Data.Data=[];
  419. }
  420. this.ResetSortStatus=function()
  421. {
  422. this.SortInfo.Field=-1;
  423. this.SortInfo.Sort=0;
  424. }
  425. //设置股票列表
  426. this.SetSymbolList=function(arySymbol, option)
  427. {
  428. this.ClearData();
  429. this.ResetReportStatus();
  430. this.ResetSortStatus();
  431. if (IFrameSplitOperator.IsNonEmptyArray(arySymbol))
  432. {
  433. for(var i=0;i<arySymbol.length;++i)
  434. {
  435. this.Data.Data.push(arySymbol[i]);
  436. }
  437. }
  438. var chart=this.ChartPaint[0];
  439. if (chart) chart.Data=this.Data;
  440. this.Draw();
  441. }
  442. this.ChangeSymbol=function(symbol, option)
  443. {
  444. this.Symbol=symbol;
  445. this.ClearData();
  446. this.ResetReportStatus();
  447. this.ResetSortStatus();
  448. this.ResetReportSelectStatus();
  449. if (option)
  450. {
  451. if (IFrameSplitOperator.IsNumber(option.TabSelected))
  452. {
  453. var chartTab=this.GetTabChart();
  454. if (chartTab) chartTab.SelectedTabIndex=option.TabSelected;
  455. }
  456. if (Array.isArray(option.FixedSymbol))
  457. {
  458. var chart=this.GetReportChart();
  459. if (chart)
  460. {
  461. chart.FixedRowCount=0;
  462. this.FixedRowData.Type=1;
  463. this.FixedRowData.Symbol=[];
  464. var aryData=option.FixedSymbol;
  465. for(var i=0; i<aryData.length; ++i)
  466. {
  467. var item=aryData[i];
  468. this.FixedRowData.Symbol.push(item.Symbol);
  469. ++chart.FixedRowCount;
  470. }
  471. this.SetSizeChange(true);
  472. }
  473. }
  474. if (option.SortInfo)
  475. {
  476. var item=option.SortInfo;
  477. if (IFrameSplitOperator.IsNumber(item.Field)) this.SortInfo.Field=item.Field;
  478. if (IFrameSplitOperator.IsNumber(item.Sort)) this.SortInfo.Sort=item.Sort;
  479. }
  480. }
  481. this.RequestMemberListData();
  482. }
  483. this.RequestMemberListData=function()
  484. {
  485. //this.ChartSplashPaint.SetTitle(this.SplashTitle.MemberList);
  486. //this.ChartSplashPaint.EnableSplash(true);
  487. //this.Draw();
  488. var self=this;
  489. if (this.NetworkFilter)
  490. {
  491. var obj=
  492. {
  493. Name:'JSReportChartContainer::RequestMemberListData', //类名::
  494. Explain:'板块成分数据',
  495. Request:{ Data: { symbol: this.Symbol } },
  496. Self:this,
  497. PreventDefault:false
  498. };
  499. if (this.SortInfo.Field>=0 && this.SortInfo.Sort>0)
  500. {
  501. var reportChart=this.GetReportChart();
  502. if (reportChart)
  503. {
  504. var column=reportChart.Column[this.SortInfo.Field];
  505. obj.Sort={ Column:column, Field:this.SortInfo.Field, Sort:this.SortInfo.Sort} ;
  506. }
  507. }
  508. this.NetworkFilter(obj, function(data)
  509. {
  510. self.ChartSplashPaint.EnableSplash(false);
  511. self.RecvMemberListData(data);
  512. });
  513. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  514. }
  515. throw { Name:'JSReportChartContainer::RequestMemberListData', Error:'(板块成分数据)不提供内置测试数据' };
  516. }
  517. this.RecvMemberListData=function(recvData)
  518. {
  519. this.ClearData();
  520. if (IFrameSplitOperator.IsNonEmptyArray(recvData.data))
  521. {
  522. for(var i=0;i<recvData.data.length;++i)
  523. {
  524. this.Data.Data.push(recvData.data[i]);
  525. this.SourceData.Data.push(recvData.data[i]);
  526. }
  527. }
  528. this.Draw();
  529. this.UpdateStockData();
  530. }
  531. this.AutoUpdateEvent=function(bStart, explain) //自定更新事件, 是给websocket使用
  532. {
  533. var eventID=bStart ? JSCHART_EVENT_ID.RECV_START_AUTOUPDATE:JSCHART_EVENT_ID.RECV_STOP_AUTOUPDATE;
  534. if (!this.mapEvent.has(eventID)) return;
  535. var self=this;
  536. var event=this.mapEvent.get(eventID);
  537. var data={ Stock:{ Symbol:this.Symbol, Name:this.Name, DayCount:this.DayCount }, Explain: explain };
  538. if (bStart)
  539. {
  540. data.Callback=function(data) //数据到达更新回调
  541. {
  542. self.RecvDealUpdateData(data);
  543. }
  544. }
  545. event.Callback(event,data,this);
  546. }
  547. //下载码表
  548. this.RequestStockListData=function(option)
  549. {
  550. this.ChartSplashPaint.SetTitle(this.SplashTitle.StockList);
  551. this.ChartSplashPaint.EnableSplash(true);
  552. this.Draw();
  553. var self=this;
  554. if (this.NetworkFilter)
  555. {
  556. var obj=
  557. {
  558. Name:'JSReportChartContainer::RequestStockListData', //类名::
  559. Explain:'码表数据',
  560. Self:this,
  561. PreventDefault:false
  562. };
  563. this.NetworkFilter(obj, function(data)
  564. {
  565. self.ChartSplashPaint.EnableSplash(false);
  566. self.RecvStockListData(data,option);
  567. });
  568. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  569. }
  570. throw { Name:'JSReportChartContainer::RequestStockListData', Error:'(码表数据)不提供内置测试数据' };
  571. }
  572. this.RecvStockListData=function(data, option)
  573. {
  574. if (IFrameSplitOperator.IsNonEmptyArray(data.data))
  575. {
  576. //0=证券代码 1=股票名称
  577. for(var i=0;i<data.data.length;++i)
  578. {
  579. var item=data.data[i];
  580. var symbol=item[0];
  581. var stock=null;
  582. if (this.MapStockData.has(symbol))
  583. {
  584. stock=this.MapStockData.get(symbol);
  585. }
  586. else
  587. {
  588. stock=new HQReportItem();
  589. stock.OriginalSymbol=symbol;
  590. this.MapStockData.set(symbol, stock);
  591. }
  592. stock.Symbol=this.GetSymbolNoSuffix(symbol);
  593. stock.Name=item[1];
  594. this.ReadStockJsonData(stock, item);
  595. }
  596. }
  597. if (option && option.Callback)
  598. {
  599. option.Callback();
  600. return;
  601. }
  602. this.Draw();
  603. this.UpdateStockData();
  604. }
  605. //更新股票数据
  606. this.UpdateMapStockData=function(data)
  607. {
  608. if (!data || !IFrameSplitOperator.IsNonEmptyArray(data.data)) return;
  609. //0=证券代码 1=股票名称
  610. for(var i=0;i<data.data.length;++i)
  611. {
  612. var item=data.data[i];
  613. var symbol=item[0];
  614. var stock=null;
  615. if (this.MapStockData.has(symbol))
  616. {
  617. stock=this.MapStockData.get(symbol);
  618. }
  619. else
  620. {
  621. stock=new HQReportItem();
  622. this.MapStockData.set(symbol, stock);
  623. }
  624. stock.Symbol=this.GetSymbolNoSuffix(symbol);
  625. stock.Name=item[1];
  626. this.ReadStockJsonData(stock, item);
  627. }
  628. }
  629. //获取个股数据
  630. this.GetStockData=function(symbol)
  631. {
  632. if (!this.MapStockData) return null;
  633. if (!this.MapStockData.has(symbol)) return null;
  634. return this.MapStockData.get(symbol);
  635. }
  636. this.GetBlockData=function(symbol)
  637. {
  638. if (!this.BlockData) return null;
  639. if (!this.BlockData.has(symbol)) return null;
  640. return this.BlockData.get(symbol);
  641. }
  642. //delay=是否延迟
  643. this.DelayUpdateStockData=function()
  644. {
  645. if (this.DelayUpdateTimer!=null)
  646. {
  647. clearTimeout(this.DelayUpdateTimer);
  648. this.DelayUpdateTimer = null;
  649. }
  650. var frequency=this.DelayUpdateFrequency;
  651. this.DelayUpdateTimer=setTimeout(()=>
  652. {
  653. this.UpdateStockData();
  654. },frequency);
  655. }
  656. this.UpdateStockData=function()
  657. {
  658. if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return;
  659. var chart=this.ChartPaint[0];
  660. if (!chart) return;
  661. if (this.SortInfo && this.SortInfo.Field>=0 && this.SortInfo.Sort>0)
  662. {
  663. var column=chart.Column[this.SortInfo.Field];
  664. if (column.Sort==2)
  665. {
  666. this.RequestStockSortData(column, this.SortInfo.Field, this.SortInfo.Sort); //远程排序
  667. return;
  668. }
  669. }
  670. var arySymbol=chart.ShowSymbol;
  671. if (!IFrameSplitOperator.IsNonEmptyArray(arySymbol)) return;
  672. this.RequestStockData(arySymbol);
  673. }
  674. //下载股票数据
  675. this.RequestStockData=function(arySymbol)
  676. {
  677. var self=this;
  678. if (this.NetworkFilter)
  679. {
  680. var obj=
  681. {
  682. Name:'JSDealChartContainer::RequestStockData', //类名::函数名
  683. Explain:'报价列表股票数据',
  684. Request:{ Data: { stocks: arySymbol } },
  685. Self:this,
  686. PreventDefault:false
  687. };
  688. this.NetworkFilter(obj, function(data)
  689. {
  690. self.RecvStockData(data);
  691. self.AutoUpdate();
  692. });
  693. if (obj.PreventDefault==true) return;
  694. }
  695. throw { Name:'JSReportChartContainer::RequestStockData', Error:'(报价列表股票数据)不提供内置测试数据' };
  696. }
  697. this.RecvStockData=function(data)
  698. {
  699. var setUpdateSymbol=new Set(); //更新的股票列表
  700. if (IFrameSplitOperator.IsNonEmptyArray(data.data))
  701. {
  702. //0=证券代码 1=股票名称 2=昨收 3=开 4=高 5=低 6=收 7=成交量 8=成交金额, 9=买价 10=买量 11=卖价 12=卖量 13=均价 14=流通股 15=总股本
  703. for(var i=0;i<data.data.length;++i)
  704. {
  705. var item=data.data[i];
  706. var symbol=item[0];
  707. if (!symbol) continue;
  708. var stock=null;
  709. if (this.MapStockData.has(symbol))
  710. {
  711. stock=this.MapStockData.get(symbol);
  712. }
  713. else
  714. {
  715. stock=new HQReportItem();
  716. stock.OriginalSymbol=symbol;
  717. stock.Symbol=this.GetSymbolNoSuffix(symbol);
  718. this.MapStockData.set(symbol, stock);
  719. }
  720. this.ReadStockJsonData(stock, item);
  721. if (!setUpdateSymbol.has(symbol)) setUpdateSymbol.add(symbol);
  722. }
  723. }
  724. var chart=this.ChartPaint[0];
  725. if (!chart) return;
  726. //更新的股票在当前页面,需要重绘
  727. var bUpdate=false;
  728. var aryStock=chart.ShowSymbol;
  729. for(var i=0;i<aryStock.length;++i)
  730. {
  731. if (setUpdateSymbol.has(aryStock[i].Symbol))
  732. {
  733. bUpdate=true;
  734. break;
  735. }
  736. }
  737. if (bUpdate) this.Draw();
  738. }
  739. //读取单条股票json数据
  740. this.ReadStockJsonData=function(stock, item)
  741. {
  742. //0=证券代码 1=股票名称 2=昨收 3=开 4=高 5=低 6=收 7=成交量 8=成交金额, 9=买价 10=买量 11=卖价 12=卖量 13=均价 14=流通股 15=总股本 16=涨停价 17=跌停价
  743. //18=内盘 19=外盘 20=现量 21=涨幅% 22=涨跌 23=换手率% 24=振幅% 25=流通市值 26=总市值
  744. //30=全局扩展数据 31=当前板块扩展数据
  745. if (IFrameSplitOperator.IsString(item[1])) stock.Name=item[1];
  746. if (IFrameSplitOperator.IsNumber(item[2])) stock.YClose=item[2];
  747. if (IFrameSplitOperator.IsNumber(item[3])) stock.Open=item[3];
  748. if (IFrameSplitOperator.IsNumber(item[4])) stock.High=item[4];
  749. if (IFrameSplitOperator.IsNumber(item[5])) stock.Low=item[5];
  750. if (IFrameSplitOperator.IsNumber(item[6])) stock.Price=item[6];
  751. if (IFrameSplitOperator.IsNumber(item[7])) stock.Vol=item[7];
  752. if (IFrameSplitOperator.IsNumber(item[8])) stock.Amount=item[8];
  753. if (IFrameSplitOperator.IsNumber(item[9])) stock.BuyPrice=item[9];
  754. if (IFrameSplitOperator.IsNumber(item[10])) stock.BuyVol=item[10];
  755. if (IFrameSplitOperator.IsNumber(item[11])) stock.SellPrice=item[11];
  756. if (IFrameSplitOperator.IsNumber(item[12])) stock.SellVol=item[12];
  757. if (IFrameSplitOperator.IsNumber(item[13])) stock.AvPrice=item[13]; //均价
  758. if (IFrameSplitOperator.IsNumber(item[14])) stock.OutShares=item[14]; //流通股
  759. if (IFrameSplitOperator.IsNumber(item[15])) stock.TotalShares=item[15]; //总股本
  760. if (IFrameSplitOperator.IsNumber(item[16])) stock.LimitHigh=item[16]; //涨停价
  761. if (IFrameSplitOperator.IsNumber(item[17])) stock.LimitLow=item[17]; //跌停价
  762. if (IFrameSplitOperator.IsNumber(item[18])) stock.VolIn=item[18]; //内盘
  763. if (IFrameSplitOperator.IsNumber(item[19])) stock.VolOut=item[19]; //外盘
  764. if (IFrameSplitOperator.IsNumber(item[20])) stock.DealNum=item[20]; //现量
  765. if (IFrameSplitOperator.IsNumber(item[21])) stock.Increase=item[21]; //涨幅%
  766. if (IFrameSplitOperator.IsNumber(item[22])) stock.UpDown=item[22]; //涨跌
  767. if (IFrameSplitOperator.IsNumber(item[23])) stock.Exchange=item[23]; //换手率%
  768. if (IFrameSplitOperator.IsNumber(item[24])) stock.Amplitude=item[24]; //振幅%
  769. if (IFrameSplitOperator.IsNumber(item[25])) stock.CircMarketValue=item[25]; //流通市值
  770. if (IFrameSplitOperator.IsNumber(item[26])) stock.MarketValue=item[26]; //总市值
  771. //衍生数据计算
  772. if (!IFrameSplitOperator.IsNumber(item[21])) //涨幅%
  773. {
  774. if (IFrameSplitOperator.IsNumber(stock.Price) && IFrameSplitOperator.IsNumber(stock.YClose) && stock.YClose!=0)
  775. stock.Increase=(stock.Price-stock.YClose)/stock.YClose*100;
  776. }
  777. if (!IFrameSplitOperator.IsNumber(item[22])) //涨跌
  778. {
  779. if (IFrameSplitOperator.IsNumber(stock.Price) && IFrameSplitOperator.IsNumber(stock.YClose))
  780. stock.UpDown=stock.Price-stock.YClose;
  781. }
  782. if (!IFrameSplitOperator.IsNumber(item[23])) //换手率%
  783. {
  784. if (IFrameSplitOperator.IsNumber(stock.Vol) && IFrameSplitOperator.IsNumber(stock.OutShares) && stock.OutShares>0)
  785. stock.Exchange=stock.Vol/stock.OutShares*100;
  786. }
  787. if (!IFrameSplitOperator.IsNumber(item[24])) //振幅%
  788. {
  789. if (IFrameSplitOperator.IsNumber(stock.High) && IFrameSplitOperator.IsNumber(stock.Low) && IFrameSplitOperator.IsNumber(stock.YClose) && stock.YClose!=0)
  790. stock.Amplitude=(stock.High-stock.Low)/stock.YClose*100;
  791. }
  792. if (!IFrameSplitOperator.IsNumber(item[25])) //流通市值
  793. {
  794. if (IFrameSplitOperator.IsNumber(stock.OutShares) && IFrameSplitOperator.IsNumber(stock.Price))
  795. stock.CircMarketValue=stock.OutShares*stock.Price;
  796. }
  797. if (!IFrameSplitOperator.IsNumber(item[26])) //总市值
  798. {
  799. if (IFrameSplitOperator.IsNumber(stock.TotalShares) && IFrameSplitOperator.IsNumber(stock.Price))
  800. stock.MarketValue=stock.TotalShares*stock.Price;
  801. }
  802. if (item[30]) stock.ExtendData=item[30]; //30扩展数据
  803. if (item[31]) this.BlockData.set(stock.OriginalSymbol,item[31]); //31=当前板块数据
  804. if (item[32]) stock.CloseLine=item[32]; //32=收盘价线
  805. }
  806. this.GetSymbolNoSuffix=function(symbol)
  807. {
  808. var index=symbol.lastIndexOf(".");
  809. if (index>0)
  810. return symbol.substring(0,index);
  811. else
  812. return symbol;
  813. }
  814. this.CancelAutoUpdate=function() //关闭停止更新
  815. {
  816. if (this.AutoUpdateTimer)
  817. {
  818. clearTimeout(this.AutoUpdateTimer);
  819. this.AutoUpdateTimer = null;
  820. }
  821. }
  822. this.AutoUpdate=function(waitTime) //waitTime 更新时间
  823. {
  824. this.CancelAutoUpdate();
  825. if (!this.IsAutoUpdate) return;
  826. var self = this;
  827. var marketStatus=2;
  828. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_REPORT_MARKET_STATUS);
  829. if (event && event.Callback)
  830. {
  831. var sendData={ MarketStatus:2 };
  832. event.Callback(event, sendData, this);
  833. if (IFrameSplitOperator.IsNumber(sendData.MarketStatus)) marketStatus=sendData.MarketStatus;
  834. }
  835. if (marketStatus==0 || marketStatus==3) return; //闭市,盘后
  836. var frequency=this.AutoUpdateFrequency;
  837. if (marketStatus==1) //盘前
  838. {
  839. this.AutoUpdateTimer=setTimeout(function()
  840. {
  841. self.AutoUpdate();
  842. },frequency);
  843. }
  844. else if (marketStatus==2) //盘中
  845. {
  846. this.AutoUpdateTimer=setTimeout(function()
  847. {
  848. self.UpdateStockData();
  849. },frequency);
  850. }
  851. }
  852. this.StopAutoUpdate=function()
  853. {
  854. this.CancelAutoUpdate();
  855. this.AutoUpdateEvent(false,'JSDealChartContainer::StopAutoUpdate');
  856. if (!this.IsAutoUpdate) return;
  857. this.IsAutoUpdate=false;
  858. }
  859. //设置事件回调
  860. //{event:事件id, callback:回调函数}
  861. this.AddEventCallback=function(object)
  862. {
  863. if (!object || !object.event || !object.callback) return;
  864. var data={Callback:object.callback, Source:object};
  865. this.mapEvent.set(object.event,data);
  866. }
  867. this.RemoveEventCallback=function(eventid)
  868. {
  869. if (!this.mapEvent.has(eventid)) return;
  870. this.mapEvent.delete(eventid);
  871. }
  872. this.GetEventCallback=function(id) //获取事件回调
  873. {
  874. if (!this.mapEvent.has(id)) return null;
  875. var item=this.mapEvent.get(id);
  876. return item;
  877. }
  878. this.OnSize=function()
  879. {
  880. if (!this.Frame) return;
  881. this.SetSizeChange(true);
  882. this.Draw();
  883. this.DelayUpdateStockData();
  884. }
  885. this.SetSizeChange=function(bChanged)
  886. {
  887. for(var i=0;i<this.ChartPaint.length;++i)
  888. {
  889. var chart=this.ChartPaint[i];
  890. if (chart) chart.SizeChange=bChanged;
  891. }
  892. }
  893. //判断是单个手指
  894. this.IsPhoneDragging=function(e)
  895. {
  896. // JSConsole.Chart.Log(e);
  897. var changed=e.changedTouches.length;
  898. var touching=e.touches.length;
  899. return changed==1 && touching==1;
  900. }
  901. this.GetToucheData=function(e)
  902. {
  903. var touches=[];
  904. for(var i=0; i<e.touches.length; ++i)
  905. {
  906. var item=e.touches[i];
  907. touches.push( {clientX: item.x, clientY: item.y, pageX: item.x, pageY: item.y });
  908. }
  909. return touches;
  910. }
  911. this.GetMoveAngle=function(pt,pt2) //计算角度
  912. {
  913. var xMove=Math.abs(pt.X-pt2.X);
  914. var yMove=Math.abs(pt.Y-pt2.Y);
  915. var angle=Math.atan(xMove/yMove)*180/Math.PI;
  916. return angle;
  917. }
  918. this.PreventTouchEvent=function(e)
  919. {
  920. }
  921. //手势事件
  922. this.OnTouchStart=function(e)
  923. {
  924. if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
  925. this.IsOnTouch=true;
  926. var reportChart=this.GetReportChart();
  927. if (!reportChart) return;
  928. if (this.IsPhoneDragging(e))
  929. {
  930. var drag= { "Click":{}, "LastMove":{} }; //LastMove 最后移动的位置
  931. var touches=this.GetToucheData(e);
  932. drag.Click.X=touches[0].clientX;
  933. drag.Click.Y=touches[0].clientY;
  934. drag.LastMove.X=touches[0].clientX;
  935. drag.LastMove.Y=touches[0].clientY;
  936. drag.IsXMove=false;
  937. drag.IsYMove=false;
  938. if (reportChart.IsPtInBody(drag.Click.X,drag.Click.Y))
  939. {
  940. this.TouchDrag=drag;
  941. }
  942. this.TouchInfo={ Click:{X:touches[0].clientX, Y:touches[0].clientY } };
  943. this.PreventTouchEvent(e);
  944. }
  945. }
  946. this.OnDragYOffset=function(drag, touches, moveUpDown, e)
  947. {
  948. if (moveUpDown<5) return false
  949. var isUp=true;
  950. if (drag.LastMove.Y<touches[0].clientY) isUp=false; //Down
  951. var oneStep=this.YStepPixel;
  952. if (oneStep<=0) oneStep=5;
  953. var step=parseInt(moveUpDown/oneStep);
  954. if (step<=0) return false
  955. if (isUp==false) step*=-1;
  956. if (this.MoveYOffset(step, this.DragPageCycle))
  957. {
  958. drag.IsYMove=true;
  959. this.Draw();
  960. this.DelayUpdateStockData();
  961. }
  962. return true;
  963. }
  964. this.OnDragXOffset=function(drag, touches, moveLeftRight, e)
  965. {
  966. if (moveLeftRight<5) return false;
  967. var isLeft=true;
  968. if (drag.LastMove.X<touches[0].clientX) isLeft=false;//右移数据
  969. var oneStep=this.XStepPixel;
  970. if (oneStep<=0) oneStep=5;
  971. var step=parseInt(moveLeftRight/oneStep); //除以4个像素
  972. if (step<=0) return false;
  973. if (!isLeft) step*=-1;
  974. if (this.MoveXOffset(step))
  975. {
  976. drag.IsXMove=true;
  977. this.Draw();
  978. }
  979. return true;
  980. }
  981. this.OnTouchMove=function(e)
  982. {
  983. if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
  984. var reportChart=this.GetReportChart();
  985. if (!reportChart) return;
  986. var touches=this.GetToucheData(e);
  987. if (this.IsPhoneDragging(e))
  988. {
  989. var drag=this.TouchDrag;
  990. this.TouchInfo.Move={ X:touches[0].clientX, Y:touches[0].clientY };
  991. if (drag)
  992. {
  993. this.PreventTouchEvent(e);
  994. var moveAngle=this.GetMoveAngle(drag.LastMove,{X:touches[0].clientX, Y:touches[0].clientY});
  995. var moveLeftRight=Math.abs(drag.LastMove.X-touches[0].clientX);
  996. var moveUpDown=Math.abs(drag.LastMove.Y-touches[0].clientY);
  997. if (drag.IsYMove==true)
  998. {
  999. this.ShowPageInfo(true);
  1000. if (!this.OnDragYOffset(drag, touches,moveUpDown, e)) return;
  1001. }
  1002. else if (drag.IsXMove==true)
  1003. {
  1004. if (!this.OnDragXOffset(drag, touches,moveLeftRight, e)) return;
  1005. }
  1006. else if (moveUpDown>0 && moveAngle<this.TouchMoveMinAngle)
  1007. {
  1008. this.ShowPageInfo(true);
  1009. if (!this.OnDragYOffset(drag, touches,moveUpDown, e)) return;
  1010. }
  1011. else if (moveLeftRight>0 && moveAngle>=this.TouchMoveMinAngle)
  1012. {
  1013. if (!this.OnDragXOffset(drag, touches,moveLeftRight, e)) return;
  1014. }
  1015. else
  1016. {
  1017. return;
  1018. }
  1019. drag.LastMove.X=touches[0].clientX;
  1020. drag.LastMove.Y=touches[0].clientY;
  1021. }
  1022. }
  1023. }
  1024. this.OnTouchEnd=function(e)
  1025. {
  1026. JSConsole.Chart.Log('[JSReportChartContainer:OnTouchEnd]',e);
  1027. if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
  1028. this.ShowPageInfo(false);
  1029. this.OnTouchClick(this.TouchInfo, e);
  1030. this.IsOnTouch=false;
  1031. this.TouchDrag=null;
  1032. this.TouchInfo=null;
  1033. }
  1034. this.OnTouchClick=function(touchInfo, e)
  1035. {
  1036. if (!touchInfo || !touchInfo.Click) return false;
  1037. if (touchInfo.Move) return false;
  1038. var clickPoint=touchInfo.Click;
  1039. var reportChart=this.GetReportChart();
  1040. if (!reportChart) return false;
  1041. var clickData=reportChart.OnMouseDown(clickPoint.X,clickPoint.Y,e);
  1042. if (!clickData) return false;
  1043. if (clickData.Type==2 || clickData.Type==4) //点击行
  1044. {
  1045. if (clickData.Redraw==true)
  1046. this.Draw();
  1047. }
  1048. else if (clickData.Type==3) //表头
  1049. {
  1050. this.OnClickHeader(clickData, e);
  1051. }
  1052. JSConsole.Chart.Log('[JSReportChartContainer:OnTouchClick] clickData', clickData);
  1053. }
  1054. this.GetTabChart=function()
  1055. {
  1056. var chart=this.ChartPaint[0];
  1057. if (!chart) return null;
  1058. return chart.Tab;
  1059. }
  1060. this.GetReportChart=function()
  1061. {
  1062. var chart=this.ChartPaint[0];
  1063. return chart;
  1064. }
  1065. this.GotoNextPage=function(bCycle) //bCycle 是否循环
  1066. {
  1067. if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false;
  1068. var chart=this.ChartPaint[0];
  1069. if (!chart) return false;
  1070. var pageSize=chart.GetPageSize();
  1071. if (pageSize>this.Data.Data.length) return false;
  1072. if (this.Data.YOffset+pageSize>=this.Data.Data.length)
  1073. {
  1074. if (bCycle===true)
  1075. {
  1076. this.Data.YOffset=0; //循环到第1页
  1077. return true;
  1078. }
  1079. else
  1080. {
  1081. return false;
  1082. }
  1083. }
  1084. this.Data.YOffset+=pageSize;
  1085. var showDataCount=this.Data.Data.length-this.Data.YOffset;
  1086. if (chart.SelectedModel==0)
  1087. {
  1088. if (chart.SelectedRow>showDataCount-1) chart.SelectedRow=showDataCount-1;
  1089. }
  1090. return true;
  1091. }
  1092. this.GotoPreviousPage=function(bCycle) //bCycle 是否循环
  1093. {
  1094. if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false;
  1095. var chart=this.ChartPaint[0];
  1096. if (!chart) return false;
  1097. var pageSize=chart.GetPageSize();
  1098. if (pageSize>this.Data.Data.length) return false;
  1099. if (this.Data.YOffset<=0)
  1100. {
  1101. if (bCycle===true)
  1102. {
  1103. this.Data.YOffset=this.Data.Data.length-pageSize; //循环到最后一页
  1104. return true;
  1105. }
  1106. else
  1107. {
  1108. return false;
  1109. }
  1110. }
  1111. var offset=this.Data.YOffset;
  1112. offset-=pageSize;
  1113. if (offset<0) offset=0;
  1114. this.Data.YOffset=offset;
  1115. return true;
  1116. }
  1117. this.MoveYOffset=function(setp, bCycle) //bCycle 是否循环
  1118. {
  1119. if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false;
  1120. var chart=this.ChartPaint[0];
  1121. if (!chart) return false;
  1122. var pageStatus=chart.GetCurrentPageStatus();
  1123. if (pageStatus.IsSinglePage) return false;
  1124. if (setp>0) //向上
  1125. {
  1126. var count=this.Data.Data.length;
  1127. var pageSize=pageStatus.PageSize;
  1128. var offset=this.Data.YOffset;
  1129. if (bCycle)
  1130. {
  1131. for(var i=0;i<setp;++i)
  1132. {
  1133. ++offset;
  1134. if (offset+pageSize>count) offset=0;
  1135. }
  1136. }
  1137. else
  1138. {
  1139. if (offset+pageSize>=count) return false;
  1140. for(var i=0;i<setp;++i)
  1141. {
  1142. if (offset+pageSize+1>count) break;
  1143. ++offset;
  1144. }
  1145. }
  1146. this.Data.YOffset=offset;
  1147. return true;
  1148. }
  1149. else if (setp<0) //向下
  1150. {
  1151. setp=Math.abs(setp);
  1152. var offset=this.Data.YOffset;
  1153. if (bCycle)
  1154. {
  1155. var pageSize=pageStatus.PageSize;
  1156. for(var i=0;i<setp;++i)
  1157. {
  1158. --offset;
  1159. if (offset<0) offset=this.Data.Data.length-pageSize;
  1160. }
  1161. }
  1162. else
  1163. {
  1164. if (this.Data.YOffset<=0) return false;
  1165. for(var i=0;i<setp;++i)
  1166. {
  1167. if (offset-1<0) break;
  1168. --offset;
  1169. }
  1170. }
  1171. this.Data.YOffset=offset;
  1172. return true;
  1173. }
  1174. return false;
  1175. }
  1176. this.MoveSelectedRow=function(step)
  1177. {
  1178. var chart=this.ChartPaint[0];
  1179. if (!chart) return null;
  1180. if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return null;
  1181. var result={ Redraw:false, Update:false }; //Redraw=重绘, Update=更新数据
  1182. if (chart.SelectedModel==0) //不可翻页模式, 只能在当前页移动
  1183. {
  1184. var pageStatus=chart.GetCurrentPageStatus();
  1185. var pageSize=pageStatus.End-pageStatus.Start+1;
  1186. var selected=pageStatus.SelectedRow;
  1187. if (step>0)
  1188. {
  1189. selected+=step;
  1190. selected=selected%pageSize;
  1191. chart.SelectedRow=selected;
  1192. chart.SelectedFixedRow=-1;
  1193. result.Redraw=true;
  1194. return result;
  1195. }
  1196. else if (step<0)
  1197. {
  1198. selected+=step;
  1199. if (selected<0)
  1200. {
  1201. selected=selected%pageSize;
  1202. selected=pageSize+selected;
  1203. }
  1204. chart.SelectedRow=selected;
  1205. chart.SelectedFixedRow=-1;
  1206. result.Redraw=true;
  1207. return result;
  1208. }
  1209. }
  1210. else if (chart.SelectedModel==1) //可翻页模式
  1211. {
  1212. var pageStatus=chart.GetCurrentPageStatus();
  1213. var pageSize=pageStatus.PageSize;
  1214. var selected=pageStatus.SelectedRow;
  1215. if (step>0)
  1216. {
  1217. if (selected<0 || selected<pageStatus.Start || selected>pageStatus.End)
  1218. {
  1219. chart.SelectedRow=pageStatus.Start;
  1220. result.Redraw=true;
  1221. return result;
  1222. }
  1223. var offset=this.Data.YOffset;
  1224. for(var i=0;i<step;++i)
  1225. {
  1226. ++selected;
  1227. if (selected>pageStatus.End) ++offset;
  1228. if (selected>=this.Data.Data.length)
  1229. {
  1230. selected=0;
  1231. offset=0;
  1232. }
  1233. }
  1234. result.Redraw=true;
  1235. result.Update=(offset!=this.Data.YOffset);
  1236. chart.SelectedRow=selected;
  1237. this.Data.YOffset=offset;
  1238. return result;
  1239. }
  1240. else if (step<0)
  1241. {
  1242. if (selected<0 || selected<pageStatus.Start || selected>pageStatus.End)
  1243. {
  1244. chart.SelectedRow=pageStatus.End;
  1245. result.Redraw=true;
  1246. return result;
  1247. }
  1248. step=Math.abs(step);
  1249. var offset=this.Data.YOffset;
  1250. for(var i=0;i<step;++i)
  1251. {
  1252. --selected;
  1253. if (selected<pageStatus.Start) --offset;
  1254. if (selected<0)
  1255. {
  1256. selected=this.Data.Data.length-1;
  1257. offset=this.Data.Data.length-pageSize;
  1258. if (offset<0) offset=0;
  1259. }
  1260. }
  1261. result.Redraw=true;
  1262. result.Update=(offset!=this.Data.YOffset);
  1263. chart.SelectedRow=selected;
  1264. this.Data.YOffset=offset;
  1265. return result;
  1266. }
  1267. }
  1268. return null;
  1269. }
  1270. //左右移动
  1271. this.MoveXOffset=function(step)
  1272. {
  1273. var chart=this.ChartPaint[0];
  1274. if (!chart) return false;
  1275. var maxOffset=chart.GetXScrollRange();
  1276. if (maxOffset<=0) return false;
  1277. if (step>0)
  1278. {
  1279. if (this.Data.XOffset>=maxOffset) return false;
  1280. for(var i=0;i<step;++i)
  1281. {
  1282. if (this.Data.XOffset>=maxOffset) break;
  1283. ++this.Data.XOffset;
  1284. }
  1285. return true;
  1286. }
  1287. else if (step<0)
  1288. {
  1289. if (this.Data.XOffset<=0) return false;
  1290. step=Math.abs(step);
  1291. for(var i=0;i<step;++i)
  1292. {
  1293. if (this.Data.XOffset-1<0) break;
  1294. --this.Data.XOffset;
  1295. }
  1296. return true;
  1297. }
  1298. return false;
  1299. }
  1300. this.SetXOffset=function(pos)
  1301. {
  1302. if (!IFrameSplitOperator.IsNumber(pos)) return false;
  1303. var chart=this.ChartPaint[0];
  1304. if (!chart) return false;
  1305. var maxOffset=chart.GetXScrollRange();
  1306. if (pos<0) pos=0;
  1307. if (pos>maxOffset) pos=maxOffset;
  1308. this.Data.XOffset=pos;
  1309. return true;
  1310. }
  1311. this.GotoLastPage=function()
  1312. {
  1313. var chart=this.ChartPaint[0];
  1314. if (!chart) return;
  1315. //显示最后一屏
  1316. var pageSize=chart.GetPageSize(true);
  1317. var offset=this.Data.Data.length-pageSize;
  1318. if (offset<0) offset=0;
  1319. this.Data.DataOffset=offset;
  1320. }
  1321. this.SetColumn=function(aryColunm, option)
  1322. {
  1323. var chart=this.ChartPaint[0];
  1324. if (!chart) return;
  1325. chart.SetColumn(aryColunm);
  1326. chart.SizeChange=true;
  1327. if (option && option.Redraw) this.Draw();
  1328. }
  1329. this.SetTab=function(aryTab, option)
  1330. {
  1331. var chart=this.ChartPaint[0];;
  1332. if (!chart) return;
  1333. var chartTab=chart.Tab;
  1334. if (!chartTab) return;
  1335. chartTab.SetTabList(aryTab);
  1336. if (option && option.Redraw) this.Draw();
  1337. }
  1338. this.SetSelectedTab=function(index, opiton)
  1339. {
  1340. var chart=this.ChartPaint[0];;
  1341. if (!chart) return;
  1342. var chartTab=chart.Tab;
  1343. if (!chartTab) return;
  1344. chartTab.SelectedTabIndex=index;
  1345. }
  1346. this.ReloadResource=function(option)
  1347. {
  1348. this.Frame.ReloadResource(option);
  1349. for(var i=0;i<this.ChartPaint.length;++i)
  1350. {
  1351. var item=this.ChartPaint[i];
  1352. if (item.ReloadResource) item.ReloadResource(option);
  1353. }
  1354. if (option && option.Redraw)
  1355. {
  1356. this.SetSizeChange(true);
  1357. this.Draw();
  1358. }
  1359. }
  1360. //点表头
  1361. this.OnClickHeader=function(clickData, e)
  1362. {
  1363. var header=clickData.Header;
  1364. if (header.Column && (header.Column.Sort==1 || header.Column.Sort==2))
  1365. {
  1366. var index=header.Index;
  1367. var sortInfo={Field:this.SortInfo.Field, Sort:this.SortInfo.Sort };
  1368. var arySortType=header.Column.SortType;
  1369. if (sortInfo.Field!=index)
  1370. {
  1371. sortInfo.Field=index;
  1372. sortInfo.Sort=arySortType[0]
  1373. }
  1374. else
  1375. {
  1376. if (arySortType.length==1)
  1377. {
  1378. sortInfo.Sort=arySortType[0];
  1379. }
  1380. else
  1381. {
  1382. for(var i=0;i<arySortType.length;++i)
  1383. {
  1384. if (sortInfo.Sort==arySortType[i])
  1385. {
  1386. sortInfo.Sort=arySortType[(i+1)%arySortType.length];
  1387. break;
  1388. }
  1389. }
  1390. }
  1391. }
  1392. if (header.Column.Sort==1 || header.Column.Sort==2)
  1393. {
  1394. if (sortInfo.Sort==0)
  1395. {
  1396. this.Data.Data=[];
  1397. for(var i=0;i<this.SourceData.Data.length;++i)
  1398. {
  1399. this.Data.Data.push(this.SourceData.Data[i]);
  1400. }
  1401. }
  1402. else
  1403. {
  1404. if (header.Column.Sort==1) //本地排序
  1405. {
  1406. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_REPORT_LOCAL_SORT);
  1407. if (event && event.Callback)
  1408. {
  1409. var sendData={ Column:header.Column, SortInfo:sortInfo, SymbolList:this.Data.Data, Result:null };
  1410. event.Callback (event, sendData, this);
  1411. if (Array.isArray(sendData.Result)) this.Data.Data=sendData.Result;
  1412. }
  1413. else
  1414. {
  1415. this.Data.Data.sort((left, right)=> { return this.LocalSort(left, right, header.Column, sortInfo.Sort); });
  1416. }
  1417. }
  1418. else if (header.Column.Sort==2) //远程排序
  1419. {
  1420. if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return;
  1421. this.SortInfo.Field=sortInfo.Field;
  1422. this.SortInfo.Sort=sortInfo.Sort;
  1423. this.Data.YOffset=0;
  1424. this.ResetReportSelectStatus();
  1425. this.RequestStockSortData(header.Column, sortInfo.Field, sortInfo.Sort); //远程排序
  1426. return;
  1427. }
  1428. }
  1429. this.Data.YOffset=0;
  1430. this.ResetReportSelectStatus();
  1431. this.SortInfo.Field=sortInfo.Field;
  1432. this.SortInfo.Sort=sortInfo.Sort;
  1433. this.Draw();
  1434. this.DelayUpdateStockData();
  1435. }
  1436. }
  1437. }
  1438. //点击标签
  1439. this.OnClickTab=function(tabData, e)
  1440. {
  1441. if (!tabData.Tab) return;
  1442. var redraw=false;
  1443. var pixelTatio = GetDevicePixelRatio();
  1444. var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio;
  1445. var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio;
  1446. if (tabData.Tab.IsMenu)
  1447. {
  1448. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_REPORT_TABMENU);
  1449. if (event && event.Callback)
  1450. {
  1451. redraw=true;
  1452. var rtItem=tabData.Rect;
  1453. var rtDOM={ Left: rtItem.Left/pixelTatio, Right:rtItem.Right/pixelTatio, Top:rtItem.Top/pixelTatio, Bottom:rtItem.Bottom/pixelTatio };
  1454. var sendData={ Data:tabData, IsSide:{X:x, Y:x}, Rect:rtDOM, e:e , Redraw:redraw };
  1455. event.Callback(event, sendData, this);
  1456. if (IFrameSplitOperator.IsBool(sendData.Redraw)) redraw=sendData.Redraw;
  1457. }
  1458. this.SetSelectedTab(tabData.Index); //选中tab
  1459. }
  1460. else
  1461. {
  1462. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_REPORT_TAB);
  1463. if (event && event.Callback)
  1464. {
  1465. var sendData={ Data:tabData, IsSide:{X:x, Y:x}, e:e , Redraw:redraw };
  1466. event.Callback(event, sendData, this);
  1467. if (IFrameSplitOperator.IsBool(sendData.Redraw)) redraw=sendData.Redraw;
  1468. }
  1469. this.SetSelectedTab(tabData.Index);
  1470. }
  1471. if (redraw) this.Draw();
  1472. }
  1473. //本地排序
  1474. this.LocalSort=function(left, right, column, sortType)
  1475. {
  1476. switch(column.Type)
  1477. {
  1478. case REPORT_COLUMN_ID.SYMBOL_ID:
  1479. case REPORT_COLUMN_ID.NAME_ID:
  1480. return this.LocalStringSort(left, right, column, sortType);
  1481. case REPORT_COLUMN_ID.PRICE_ID:
  1482. case REPORT_COLUMN_ID.VOL_ID:
  1483. case REPORT_COLUMN_ID.INCREASE_ID:
  1484. case REPORT_COLUMN_ID.UPDOWN_ID:
  1485. case REPORT_COLUMN_ID.BUY_PRICE_ID:
  1486. case REPORT_COLUMN_ID.SELL_PRICE_ID:
  1487. case REPORT_COLUMN_ID.AMOUNT_ID:
  1488. case REPORT_COLUMN_ID.BUY_VOL_ID:
  1489. case REPORT_COLUMN_ID.SELL_VOL_ID:
  1490. case REPORT_COLUMN_ID.YCLOSE_ID:
  1491. case REPORT_COLUMN_ID.OPEN_ID:
  1492. case REPORT_COLUMN_ID.HIGH_ID:
  1493. case REPORT_COLUMN_ID.LOW_ID:
  1494. case REPORT_COLUMN_ID.AVERAGE_PRICE_ID:
  1495. case REPORT_COLUMN_ID.OUTSTANDING_SHARES_ID:
  1496. case REPORT_COLUMN_ID.TOTAL_SHARES_ID:
  1497. case REPORT_COLUMN_ID.CIRC_MARKET_VALUE_ID:
  1498. case REPORT_COLUMN_ID.MARKET_VALUE_ID:
  1499. case REPORT_COLUMN_ID.EXCHANGE_RATE_ID:
  1500. case REPORT_COLUMN_ID.AMPLITUDE_ID:
  1501. case REPORT_COLUMN_ID.LIMIT_HIGH_ID:
  1502. case REPORT_COLUMN_ID.LIMIT_LOW_ID:
  1503. case REPORT_COLUMN_ID.VOL_IN_ID:
  1504. case REPORT_COLUMN_ID.VOL_OUT_ID:
  1505. return this.LocalNumberSort(left, right, column, sortType);
  1506. case REPORT_COLUMN_ID.CUSTOM_NUMBER_TEXT_ID: //自定义数值字段
  1507. return this.LoacCustomNumberSort(left, right, column, sortType);
  1508. case REPORT_COLUMN_ID.CUSTOM_STRING_TEXT_ID: //自定义字符串字段
  1509. return this.LoacCustomStringSort(left, right, column, sortType);
  1510. case REPORT_COLUMN_ID.CUSTOM_DATETIME_TEXT_ID:
  1511. return this.LoacCustomDateTimeSort(left, right, column, sortType);
  1512. default:
  1513. return 0;
  1514. }
  1515. }
  1516. this.GetStockExtendData=function(symbol,column)
  1517. {
  1518. if (IFrameSplitOperator.IsNumber(column.DataIndex))
  1519. {
  1520. if (column.DataIndex<0) return null;
  1521. var stock=this.GetStockData(symbol);
  1522. if (!stock || !stock.ExtendData) return null;
  1523. return stock.ExtendData[column.DataIndex];
  1524. }
  1525. if (IFrameSplitOperator.IsNumber(column.BlockIndex))
  1526. {
  1527. if (column.BlockIndex<0) return null;
  1528. var stock=this.GetBlockData(symbol);
  1529. if (!stock) return null;
  1530. return stock[column.BlockIndex];
  1531. }
  1532. return null;
  1533. }
  1534. this.LocalStringSort=function(left, right, column, sortType)
  1535. {
  1536. var leftStock=this.GetStockData(left);
  1537. var rightStock=this.GetStockData(right);
  1538. var leftValue="", rightValue="";
  1539. if (sortType==2)
  1540. {
  1541. leftValue="啊啊啊啊啊";
  1542. rightValue="啊啊啊啊啊";
  1543. }
  1544. var filedName=MAP_COLUMN_FIELD.get(column.Type);
  1545. if (leftStock && leftStock[filedName]) leftValue=leftStock[filedName];
  1546. if (rightStock && rightStock[filedName]) rightValue=rightStock[filedName];
  1547. if (sortType==1)
  1548. {
  1549. if (rightValue<leftValue) return -1;
  1550. else if (rightValue<leftValue) return 1;
  1551. else return 0;
  1552. }
  1553. else
  1554. {
  1555. if (leftValue<rightValue) return -1;
  1556. else if (leftValue>rightValue) return 1;
  1557. else return 0;
  1558. }
  1559. }
  1560. this.LocalNumberSort=function(left, right, column, sortType)
  1561. {
  1562. var leftStock=this.GetStockData(left);
  1563. var rightStock=this.GetStockData(right);
  1564. var leftValue=-99999999999999, rightValue=-99999999999999;
  1565. if (sortType==2) leftValue=rightValue=99999999999999;
  1566. var filedName=MAP_COLUMN_FIELD.get(column.Type);
  1567. if (leftStock && IFrameSplitOperator.IsNumber(leftStock[filedName])) leftValue=leftStock[filedName];
  1568. if (rightStock && IFrameSplitOperator.IsNumber(rightStock[filedName])) rightValue=rightStock[filedName];
  1569. if (sortType==1)
  1570. {
  1571. if (rightValue<leftValue) return -1;
  1572. else if (rightValue<leftValue) return 1;
  1573. else return 0;
  1574. }
  1575. else
  1576. {
  1577. if (leftValue<rightValue) return -1;
  1578. else if (leftValue>rightValue) return 1;
  1579. else return 0;
  1580. }
  1581. }
  1582. this.LoacCustomNumberSort=function(left, right, column, sortType)
  1583. {
  1584. var leftValue=-99999999999999, rightValue=-99999999999999;
  1585. if (sortType==2) leftValue=rightValue=99999999999999;
  1586. var value=this.GetStockExtendData(left, column);
  1587. if (IFrameSplitOperator.IsNumber(value)) leftValue=value;
  1588. var value=this.GetStockExtendData(right, column);
  1589. if (IFrameSplitOperator.IsNumber(value)) rightValue=value;
  1590. if (sortType==1)
  1591. {
  1592. if (rightValue<leftValue) return -1;
  1593. else if (rightValue<leftValue) return 1;
  1594. else return 0;
  1595. }
  1596. else
  1597. {
  1598. if (leftValue<rightValue) return -1;
  1599. else if (leftValue>rightValue) return 1;
  1600. else return 0;
  1601. }
  1602. }
  1603. this.LoacCustomDateTimeSort=function(left, right, column, sortType)
  1604. {
  1605. var leftValue=-99999999999999, rightValue=-99999999999999;
  1606. if (sortType==2) leftValue=rightValue=99999999999999;
  1607. var value=this.GetStockExtendData(left, column);
  1608. if (IFrameSplitOperator.IsNumber(value)) leftValue=value;
  1609. var value=this.GetStockExtendData(right, column);
  1610. if (IFrameSplitOperator.IsNumber(value)) rightValue=value;
  1611. if (sortType==1)
  1612. {
  1613. if (rightValue<leftValue) return -1;
  1614. else if (rightValue<leftValue) return 1;
  1615. else return 0;
  1616. }
  1617. else
  1618. {
  1619. if (leftValue<rightValue) return -1;
  1620. else if (leftValue>rightValue) return 1;
  1621. else return 0;
  1622. }
  1623. }
  1624. this.RequestStockSortData=function(column, filedid, sortType)
  1625. {
  1626. var chart=this.ChartPaint[0];
  1627. if (!chart) return;
  1628. var self=this;
  1629. var startIndex=this.Data.YOffset;
  1630. var pageSize=chart.GetPageSize();
  1631. var endIndex=startIndex+pageSize;
  1632. if (endIndex>=this.Data.Data.length) endIndex=this.Data.Data.length-1;
  1633. if (this.NetworkFilter)
  1634. {
  1635. var obj=
  1636. {
  1637. Name:'JSDealChartContainer::RequestStockSortData', //类名::函数名
  1638. Explain:'报价列表股票排序数据',
  1639. Request:
  1640. {
  1641. Data:
  1642. {
  1643. range:{ start:startIndex, end:endIndex, count:this.Data.Data.length },
  1644. column:{ name: column.Title, type: column.Type, index:filedid , ID:column.ID},
  1645. sort:sortType, symbol:this.Symbol, name:this.Name,
  1646. pageSize:pageSize
  1647. }
  1648. },
  1649. Self:this,
  1650. PreventDefault:false
  1651. };
  1652. if (chart.FixedRowCount>0 && chart.FixedRowData.Type==1)
  1653. {
  1654. var arySymbol=[];
  1655. for(var i=0;i<chart.FixedRowData.Symbol.length;++i)
  1656. {
  1657. var item=chart.FixedRowData.Symbol[i];
  1658. if (item) arySymbol.push(item);
  1659. }
  1660. obj.Request.FixedSymbol=arySymbol;
  1661. }
  1662. this.NetworkFilter(obj, function(data)
  1663. {
  1664. self.RecvStockSortData(data);
  1665. self.AutoUpdate();
  1666. });
  1667. if (obj.PreventDefault==true) return;
  1668. }
  1669. throw { Name:'JSReportChartContainer::RequestStockSortData', Error:'(报价列表股票排序数据)不提供内置测试数据' };
  1670. }
  1671. this.RecvStockSortData=function(data)
  1672. {
  1673. //更新股票数据
  1674. var arySymbol=[];
  1675. if (IFrameSplitOperator.IsNonEmptyArray(data.data))
  1676. {
  1677. for(var i=0;i<data.data.length;++i)
  1678. {
  1679. var item=data.data[i]; //数据
  1680. var symbol=item[0];
  1681. if (!symbol) continue;
  1682. var stock=null;
  1683. if (this.MapStockData.has(symbol))
  1684. {
  1685. stock=this.MapStockData.get(symbol);
  1686. }
  1687. else
  1688. {
  1689. stock=new HQReportItem();
  1690. stock.OriginalSymbol=symbol;
  1691. stock.Symbol=this.GetSymbolNoSuffix(symbol);
  1692. this.MapStockData.set(symbol, stock);
  1693. }
  1694. this.ReadStockJsonData(stock, item);
  1695. arySymbol.push(symbol);
  1696. }
  1697. }
  1698. //更新股票顺序
  1699. if (IFrameSplitOperator.IsNonEmptyArray(data.index))
  1700. {
  1701. for(var i=0;i<data.index.length;++i)
  1702. {
  1703. var index=data.index[i];
  1704. var newSymbol=arySymbol[i];
  1705. var oldSymbol=this.Data.Data[index];
  1706. if (newSymbol==oldSymbol) continue;
  1707. this.Data.Data[index]=newSymbol;
  1708. }
  1709. }
  1710. var chart=this.ChartPaint[0];
  1711. if (!chart) return;
  1712. //更新的股票在当前页面,需要重绘
  1713. var bUpdate=true;
  1714. if (bUpdate) this.Draw();
  1715. }
  1716. //底部标签
  1717. this.ShowPageInfo=function(bShow)
  1718. {
  1719. var chart=this.ChartPaint[1];
  1720. if (!chart) return false;
  1721. chart.IsShow=bShow;
  1722. return true;
  1723. }
  1724. }
  1725. function JSReportFrame()
  1726. {
  1727. this.ChartBorder;
  1728. this.Canvas; //画布
  1729. this.BorderLine=null; //1=上 2=下 4=左 8=右
  1730. this.BorderColor=g_JSChartResource.Report.BorderColor; //边框线
  1731. this.LogoTextColor=g_JSChartResource.FrameLogo.TextColor;
  1732. this.LogoTextFont=g_JSChartResource.FrameLogo.Font;
  1733. this.ReloadResource=function(resource)
  1734. {
  1735. this.BorderColor=g_JSChartResource.Report.BorderColor; //边框线
  1736. this.LogoTextColor=g_JSChartResource.FrameLogo.TextColor;
  1737. this.LogoTextFont=g_JSChartResource.FrameLogo.Font;
  1738. }
  1739. this.Draw=function()
  1740. {
  1741. var left=ToFixedPoint(this.ChartBorder.GetLeft());
  1742. var top=ToFixedPoint(this.ChartBorder.GetTop());
  1743. var right=ToFixedPoint(this.ChartBorder.GetRight());
  1744. var bottom=ToFixedPoint(this.ChartBorder.GetBottom());
  1745. var width=right-left;
  1746. var height=bottom-top;
  1747. if (!IFrameSplitOperator.IsNumber(this.BorderLine))
  1748. {
  1749. this.Canvas.strokeStyle=this.BorderColor;
  1750. this.Canvas.strokeRect(left,top,width,height);
  1751. }
  1752. else
  1753. {
  1754. this.Canvas.strokeStyle=this.BorderColor;
  1755. this.Canvas.beginPath();
  1756. if ((this.BorderLine&1)>0) //上
  1757. {
  1758. this.Canvas.moveTo(left,top);
  1759. this.Canvas.lineTo(right,top);
  1760. }
  1761. if ((this.BorderLine&2)>0) //下
  1762. {
  1763. this.Canvas.moveTo(left,bottom);
  1764. this.Canvas.lineTo(right,bottom);
  1765. }
  1766. if ((this.BorderLine&4)>0) //左
  1767. {
  1768. this.Canvas.moveTo(left,top);
  1769. this.Canvas.lineTo(left,bottom);
  1770. }
  1771. if ((this.BorderLine&8)>0) //右
  1772. {
  1773. this.Canvas.moveTo(right,top);
  1774. this.Canvas.lineTo(right,bottom);
  1775. }
  1776. this.Canvas.stroke();
  1777. }
  1778. }
  1779. this.DrawLogo=function()
  1780. {
  1781. var text=g_JSChartResource.FrameLogo.Text;
  1782. if (!IFrameSplitOperator.IsString(text)) return;
  1783. this.Canvas.fillStyle=this.LogoTextColor;
  1784. this.Canvas.font=this.LogoTextFont;
  1785. this.Canvas.textAlign = 'right';
  1786. this.Canvas.textBaseline = 'bottom';
  1787. var x=this.ChartBorder.GetRight()-10;
  1788. var y=this.ChartBorder.GetBottom()-5;
  1789. this.Canvas.fillText(text,x,y);
  1790. }
  1791. }
  1792. var REPORT_COLUMN_ID=
  1793. {
  1794. SYMBOL_ID:0,
  1795. NAME_ID:1,
  1796. PRICE_ID:2, //成交价格
  1797. VOL_ID:3, //成交量
  1798. INCREASE_ID:4, //涨幅
  1799. UPDOWN_ID:5, //涨跌
  1800. BUY_PRICE_ID:6, //买价
  1801. SELL_PRICE_ID:7, //卖价
  1802. AMOUNT_ID:8, //总金额
  1803. BUY_VOL_ID:9, //买量
  1804. SELL_VOL_ID:10, //卖量
  1805. YCLOSE_ID:11, //昨收
  1806. OPEN_ID:12,
  1807. HIGH_ID:13,
  1808. LOW_ID:14,
  1809. AVERAGE_PRICE_ID:15,//均价
  1810. INDEX_ID:16, //序号 从1开始
  1811. OUTSTANDING_SHARES_ID:17, //流通股本
  1812. TOTAL_SHARES_ID:18, //总股本
  1813. CIRC_MARKET_VALUE_ID:19, //流通市值
  1814. MARKET_VALUE_ID:20, //总市值
  1815. EXCHANGE_RATE_ID:21, //换手率 成交量/流通股本
  1816. AMPLITUDE_ID:22, //振幅
  1817. LIMIT_HIGH_ID:23, //涨停价
  1818. LIMIT_LOW_ID:24, //跌停价
  1819. VOL_IN_ID:25,
  1820. VOL_OUT_ID:26,
  1821. CLOSE_LINE_ID:28, //收盘价线
  1822. SYMBOL_NAME_ID:99,
  1823. CUSTOM_STRING_TEXT_ID:100, //自定义字符串文本
  1824. CUSTOM_NUMBER_TEXT_ID:101, //自定义数值型
  1825. CUSTOM_DATETIME_TEXT_ID:102 //自定义日期类型
  1826. };
  1827. var MAP_COLUMN_FIELD=new Map([
  1828. [REPORT_COLUMN_ID.SYMBOL_ID, "Symbol"],
  1829. [REPORT_COLUMN_ID.NAME_ID, "Name"],
  1830. [REPORT_COLUMN_ID.PRICE_ID, "Price"],
  1831. [REPORT_COLUMN_ID.INCREASE_ID, "Increase"],
  1832. [REPORT_COLUMN_ID.UPDOWN_ID, "UpDown"],
  1833. [REPORT_COLUMN_ID.VOL_ID, "Vol"],
  1834. [REPORT_COLUMN_ID.BUY_PRICE_ID, "BuyPrice"],
  1835. [REPORT_COLUMN_ID.SELL_PRICE_ID, "SellPrice"],
  1836. [REPORT_COLUMN_ID.AMOUNT_ID, "Amount"],
  1837. [REPORT_COLUMN_ID.BUY_VOL_ID, "BuyVol"],
  1838. [REPORT_COLUMN_ID.SELL_VOL_ID, "SellVol"],
  1839. [REPORT_COLUMN_ID.YCLOSE_ID, "YClose"],
  1840. [REPORT_COLUMN_ID.OPEN_ID, "Open"],
  1841. [REPORT_COLUMN_ID.HIGH_ID, "High"],
  1842. [REPORT_COLUMN_ID.LOW_ID, "Low"],
  1843. [REPORT_COLUMN_ID.AVERAGE_PRICE_ID,"AvPrice"],
  1844. [REPORT_COLUMN_ID.OUTSTANDING_SHARES_ID,"OutShares"],
  1845. [REPORT_COLUMN_ID.TOTAL_SHARES_ID,"TotalShares"],
  1846. [REPORT_COLUMN_ID.CIRC_MARKET_VALUE_ID,"CircMarketValue"],
  1847. [REPORT_COLUMN_ID.MARKET_VALUE_ID,"MarketValue"],
  1848. [REPORT_COLUMN_ID.EXCHANGE_RATE_ID, "Exchange"],
  1849. [REPORT_COLUMN_ID.AMPLITUDE_ID, "Amplitude"],
  1850. [REPORT_COLUMN_ID.LIMIT_HIGH_ID, "LimitHigh"],
  1851. [REPORT_COLUMN_ID.LIMIT_LOW_ID,"LimitLow"],
  1852. [REPORT_COLUMN_ID.VOL_IN_ID, "VolIn"],
  1853. [REPORT_COLUMN_ID.VOL_OUT_ID,"VolOut"],
  1854. ]);
  1855. function ChartReport()
  1856. {
  1857. this.Canvas; //画布
  1858. this.ChartBorder; //边框信息
  1859. this.ChartFrame; //框架画法
  1860. this.Name; //名称
  1861. this.ClassName='ChartReport'; //类名
  1862. this.IsDrawFirst=false;
  1863. this.GetEventCallback; //获取事件
  1864. this.GetStockDataCallback; //获取股票数据
  1865. this.GetBlockDataCallback; //获取当前板块的数据
  1866. this.Data; //数据 { XOffset:0, YOffset:0, Data:['600000.sh', '000001.sz'] }
  1867. this.FixedRowData; //固定行
  1868. this.SortInfo; //排序信息 {Field:排序字段id, Sort:0 不排序 1升序 2降序 }
  1869. this.FixedColumn=2; //固定列
  1870. this.FixedRowCount=0; //固定行
  1871. this.IsShowHeader=true; //是否显示表头
  1872. this.SizeChange=true;
  1873. this.SelectedModel=0; //选中模式 0=SelectedRow表示当前屏索引
  1874. this.SelectedRow=-1; //选中行ID
  1875. this.SelectedFixedRow=-1; //选中固定行ID
  1876. this.IsDrawBorder=1; //是否绘制单元格边框
  1877. this.ShowSymbol=[]; //显示的股票列表 { Index:序号(排序用), Symbol:股票代码 }
  1878. //涨跌颜色
  1879. this.UpColor=g_JSChartResource.Report.UpTextColor;
  1880. this.DownColor=g_JSChartResource.Report.DownTextColor;
  1881. this.UnchagneColor=g_JSChartResource.Report.UnchagneTextColor;
  1882. this.BorderColor=g_JSChartResource.Report.BorderColor; //边框线
  1883. this.SelectedColor=g_JSChartResource.Report.SelectedColor; //选中行
  1884. //表头配置
  1885. this.HeaderFontConfig={ Size:g_JSChartResource.Report.Header.Font.Size, Name:g_JSChartResource.Report.Header.Font.Name };
  1886. this.HeaderColor=g_JSChartResource.Report.Header.Color;
  1887. this.SortColor=g_JSChartResource.Report.Header.SortColor; //排序箭头颜色
  1888. this.HeaderMergin=
  1889. {
  1890. Left:g_JSChartResource.Report.Header.Mergin.Left,
  1891. Right:g_JSChartResource.Report.Header.Mergin.Right,
  1892. Top:g_JSChartResource.Report.Header.Mergin.Top,
  1893. Bottom:g_JSChartResource.Report.Header.Mergin.Bottom
  1894. };
  1895. //表格内容配置
  1896. this.ItemFontConfig={ Size:g_JSChartResource.Report.Item.Font.Size, Name:g_JSChartResource.Report.Item.Font.Name };
  1897. this.ItemFixedFontConfg={ Size:g_JSChartResource.Report.FixedItem.Font.Size, Name:g_JSChartResource.Report.FixedItem.Font.Name }; //固定行
  1898. this.ItemMergin=
  1899. {
  1900. Left:g_JSChartResource.Report.Item.Mergin.Left,
  1901. Right:g_JSChartResource.Report.Item.Mergin.Right,
  1902. Top:g_JSChartResource.Report.Item.Mergin.Top,
  1903. Bottom:g_JSChartResource.Report.Item.Mergin.Bottom
  1904. };
  1905. this.BarMergin=
  1906. {
  1907. Top:g_JSChartResource.Report.Item.BarMergin.Top,
  1908. Left:g_JSChartResource.Report.Item.BarMergin.Left,
  1909. Right:g_JSChartResource.Report.Item.BarMergin.Right,
  1910. Bottom:g_JSChartResource.Report.Item.BarMergin.Bottom
  1911. };
  1912. this.LimitBorderColor=g_JSChartResource.Report.LimitBorder.Color;
  1913. this.LimitMergin=
  1914. {
  1915. Top:g_JSChartResource.Report.LimitBorder.Mergin.Top,
  1916. Left:g_JSChartResource.Report.LimitBorder.Mergin.Left,
  1917. Right:g_JSChartResource.Report.LimitBorder.Mergin.Right,
  1918. Bottom:g_JSChartResource.Report.LimitBorder.Mergin.Bottom
  1919. }
  1920. //走势图
  1921. this.CloseLineConfig=
  1922. {
  1923. CloseColor:g_JSChartResource.Report.CloseLine.CloseColor,
  1924. YCloseColor:g_JSChartResource.Report.CloseLine.YCloseColor,
  1925. AreaColor:g_JSChartResource.Report.CloseLine.AreaColor
  1926. }
  1927. //股票代码+股票名称
  1928. this.ItemSymbolFontConfig={Size:g_JSChartResource.Report.Item.SymbolFont.Size, Name:g_JSChartResource.Report.Item.SymbolFont.Name};
  1929. this.ItemNameFontConfg={Size:g_JSChartResource.Report.Item.NameFont.Size, Name:g_JSChartResource.Report.Item.NameFont.Name};
  1930. //缓存
  1931. this.HeaderFont="12px 微软雅黑";
  1932. this.ItemFont="15px 微软雅黑";
  1933. this.ItemFixedFont="15px 微软雅黑";
  1934. this.ItemSymbolFont="12px 微软雅黑";
  1935. this.ItemNameFont="15px 微软雅黑";
  1936. this.ItemNameHeight=0;
  1937. this.RowCount=0; //一屏显示行数
  1938. this.HeaderHeight=0; //表头高度
  1939. this.FixedRowHeight=0; //固定行高度
  1940. this.RowHeight=0; //行高度
  1941. this.BottomToolbarHeight=0; //底部工具条高度
  1942. this.IsShowAllColumn=false; //是否已显示所有列
  1943. this.Column= //{ Type:列id, Title:标题, TextAlign:文字对齐方式, MaxText:文字最大宽度 , TextColor:文字颜色, Sort:0=不支持排序 1=本地排序 0=远程排序 }
  1944. [
  1945. { Type:REPORT_COLUMN_ID.INDEX_ID, Title:"序号", TextAlign:"center", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Index, MaxText:"8888"},
  1946. { Type:REPORT_COLUMN_ID.SYMBOL_ID, Title:"代码", TextAlign:"left", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Symbol, MaxText:"888888"},
  1947. { Type:REPORT_COLUMN_ID.NAME_ID, Title:"名称", TextAlign:"left", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Name, MaxText:"擎擎擎擎" },
  1948. { Type:REPORT_COLUMN_ID.INCREASE_ID, Title:"涨幅%", TextAlign:"right", Width:null, MaxText:"-888.88" },
  1949. ];
  1950. this.RectClient={};
  1951. this.ReloadResource=function(resource)
  1952. {
  1953. this.UpColor=g_JSChartResource.Report.UpTextColor;
  1954. this.DownColor=g_JSChartResource.Report.DownTextColor;
  1955. this.UnchagneColor=g_JSChartResource.Report.UnchagneTextColor;
  1956. this.BorderColor=g_JSChartResource.Report.BorderColor; //边框线
  1957. this.SelectedColor=g_JSChartResource.Report.SelectedColor; //选中行
  1958. //表头配置
  1959. this.HeaderFontConfig={ Size:g_JSChartResource.Report.Header.Font.Size, Name:g_JSChartResource.Report.Header.Font.Name };
  1960. this.HeaderColor=g_JSChartResource.Report.Header.Color;
  1961. this.SortColor=g_JSChartResource.Report.Header.SortColor; //排序箭头颜色
  1962. this.HeaderMergin=
  1963. {
  1964. Left:g_JSChartResource.Report.Header.Mergin.Left,
  1965. Right:g_JSChartResource.Report.Header.Mergin.Right,
  1966. Top:g_JSChartResource.Report.Header.Mergin.Top,
  1967. Bottom:g_JSChartResource.Report.Header.Mergin.Bottom
  1968. };
  1969. //表格内容配置
  1970. this.ItemFontConfig={ Size:g_JSChartResource.Report.Item.Font.Size, Name:g_JSChartResource.Report.Item.Font.Name };
  1971. this.ItemMergin=
  1972. {
  1973. Left:g_JSChartResource.Report.Item.Mergin.Left,
  1974. Right:g_JSChartResource.Report.Item.Mergin.Right,
  1975. Top:g_JSChartResource.Report.Item.Mergin.Top,
  1976. Bottom:g_JSChartResource.Report.Item.Mergin.Bottom
  1977. };
  1978. this.BarMergin=
  1979. {
  1980. Top:g_JSChartResource.Report.Item.BarMergin.Top,
  1981. Left:g_JSChartResource.Report.Item.BarMergin.Left,
  1982. Right:g_JSChartResource.Report.Item.BarMergin.Right,
  1983. Bottom:g_JSChartResource.Report.Item.BarMergin.Bottom
  1984. };
  1985. this.LimitBorderColor=g_JSChartResource.Report.LimitBorder.Color;
  1986. this.LimitMergin=
  1987. {
  1988. Top:g_JSChartResource.Report.LimitBorder.Mergin.Top,
  1989. Left:g_JSChartResource.Report.LimitBorder.Mergin.Left,
  1990. Right:g_JSChartResource.Report.LimitBorder.Mergin.Right,
  1991. Bottom:g_JSChartResource.Report.LimitBorder.Mergin.Bottom
  1992. }
  1993. for(var i=0;i<this.Column.length;++i)
  1994. {
  1995. var item=this.Column[i];
  1996. if (item.Type==REPORT_COLUMN_ID.INDEX_ID)
  1997. item.TextColor=g_JSChartResource.Report.FieldColor.Index;
  1998. else if (item.Type==REPORT_COLUMN_ID.SYMBOL_ID)
  1999. item.TextColor=g_JSChartResource.Report.FieldColor.Symbol;
  2000. else if (item.Type==REPORT_COLUMN_ID.NAME_ID)
  2001. item.TextColor=g_JSChartResource.Report.FieldColor.Name;
  2002. else if (item.Type==REPORT_COLUMN_ID.VOL_ID)
  2003. item.TextColor=g_JSChartResource.Report.FieldColor.Vol;
  2004. else if (item.Type==REPORT_COLUMN_ID.BUY_VOL_ID)
  2005. item.TextColor=g_JSChartResource.Report.FieldColor.Vol;
  2006. else if (item.Type==REPORT_COLUMN_ID.SELL_VOL_ID)
  2007. item.TextColor=g_JSChartResource.Report.FieldColor.Vol;
  2008. else if (item.Type==REPORT_COLUMN_ID.AMOUNT_ID)
  2009. item.TextColor=g_JSChartResource.Report.FieldColor.Amount;
  2010. else if (item.Type==REPORT_COLUMN_ID.VOL_IN_ID)
  2011. item.TextColor=g_JSChartResource.Report.DownTextColor;
  2012. else if (item.Type==REPORT_COLUMN_ID.VOL_OUT_ID)
  2013. item.TextColor=g_JSChartResource.Report.UpTextColor;
  2014. else
  2015. item.TextColor=g_JSChartResource.Report.FieldColor.Text;
  2016. }
  2017. if (this.Tab) this.Tab.ReloadResource(resource);
  2018. }
  2019. this.SetColumn=function(aryColumn)
  2020. {
  2021. if (!IFrameSplitOperator.IsNonEmptyArray(aryColumn)) return;
  2022. this.Column=[];
  2023. for(var i=0;i<aryColumn.length;++i)
  2024. {
  2025. var item=aryColumn[i];
  2026. var colItem=this.GetDefaultColunm(item.Type);
  2027. if (!colItem) continue;
  2028. if (item.Title) colItem.Title=item.Title;
  2029. if (item.TextAlign) colItem.TextAlign=item.TextAlign;
  2030. if (item.TextColor) colItem.TextColor=item.TextColor;
  2031. if (item.MaxText) colItem.MaxText=item.MaxText;
  2032. if (item.ID) colItem.ID=item.ID;
  2033. if (IFrameSplitOperator.IsNumber(item.Sort)) colItem.Sort=item.Sort;
  2034. if (item.Sort==1 || item.Sort==2) //1本地排序 2=远程排序
  2035. {
  2036. colItem.SortType=[1,2]; //默认 降序 ,升序
  2037. if (IFrameSplitOperator.IsNonEmptyArray(item.SortType)) colItem.SortType=item.SortType.slice();
  2038. }
  2039. if (item.Type==REPORT_COLUMN_ID.CUSTOM_STRING_TEXT_ID)
  2040. {
  2041. if (!IFrameSplitOperator.IsNumber(item.DataIndex) && !IFrameSplitOperator.IsNumber(item.BlockIndex)) continue;
  2042. if (IFrameSplitOperator.IsNumber(item.DataIndex)) colItem.DataIndex=item.DataIndex; //数据在扩展数据索引列
  2043. if (IFrameSplitOperator.IsNumber(item.BlockIndex)) colItem.BlockIndex=item.BlockIndex;
  2044. colItem.IsDrawCallback=false; //是否回调
  2045. if (IFrameSplitOperator.IsBool(item.IsDrawCallback)) colItem.IsDrawCallback=item.IsDrawCallback;
  2046. }
  2047. else if (item.Type==REPORT_COLUMN_ID.CUSTOM_NUMBER_TEXT_ID)
  2048. {
  2049. if (!IFrameSplitOperator.IsNumber(item.DataIndex) && !IFrameSplitOperator.IsNumber(item.BlockIndex)) continue;
  2050. if (IFrameSplitOperator.IsNumber(item.DataIndex)) colItem.DataIndex=item.DataIndex; //数据在扩展数据索引列
  2051. if (IFrameSplitOperator.IsNumber(item.BlockIndex)) colItem.BlockIndex=item.BlockIndex;
  2052. colItem.Decimal=2;
  2053. colItem.FormatType=0; //0=默认格式化 1=原始输出 2=科学计数 3=成交量格式化
  2054. colItem.ColorType=0; //0=默认使用TextColor, 1=(>0涨,<0跌)2=(>昨收涨,<昨收跌)
  2055. colItem.IsDrawCallback=false; //是否回调
  2056. if (IFrameSplitOperator.IsNumber(item.Decimal)) colItem.Decimal=item.Decimal; //小数位数
  2057. if (IFrameSplitOperator.IsNumber(item.FormatType)) colItem.FormatType=item.FormatType; //输出样式
  2058. if (IFrameSplitOperator.IsNumber(item.ColorType)) colItem.ColorType=item.ColorType; //颜色属性
  2059. if (IFrameSplitOperator.IsBool(item.IsDrawCallback)) colItem.IsDrawCallback=item.IsDrawCallback;
  2060. }
  2061. else if (item.Type==REPORT_COLUMN_ID.CUSTOM_DATETIME_TEXT_ID)
  2062. {
  2063. if (!IFrameSplitOperator.IsNumber(item.DataIndex) && !IFrameSplitOperator.IsNumber(item.BlockIndex)) continue;
  2064. if (IFrameSplitOperator.IsNumber(item.DataIndex)) colItem.DataIndex=item.DataIndex; //数据在扩展数据索引列
  2065. if (IFrameSplitOperator.IsNumber(item.BlockIndex)) colItem.BlockIndex=item.BlockIndex;
  2066. colItem.FormatType=0; //0=yyyy-mm-dd 1=YYYY/MM/DD
  2067. colItem.ValueType=0; //0=yyyymmdd 1=hhmmss
  2068. colItem.IsDrawCallback=false; //是否回调
  2069. if (IFrameSplitOperator.IsNumber(item.FormatType)) colItem.FormatType=item.FormatType; //输出样式
  2070. if (IFrameSplitOperator.IsNumber(item.ValueType)) colItem.FormatType=item.ValueType; //输出样式
  2071. if (IFrameSplitOperator.IsBool(item.IsDrawCallback)) colItem.IsDrawCallback=item.IsDrawCallback;
  2072. }
  2073. else if (item.Type==REPORT_COLUMN_ID.CLOSE_LINE_ID)
  2074. {
  2075. if (IFrameSplitOperator.IsBool(item.IsDrawArea)) colItem.IsDrawArea=item.IsDrawArea;
  2076. }
  2077. this.Column.push(colItem);
  2078. }
  2079. }
  2080. this.GetDefaultColunm=function(id)
  2081. {
  2082. var DEFAULT_COLUMN=
  2083. [
  2084. { Type:REPORT_COLUMN_ID.INDEX_ID, Title:"序号", TextAlign:"center", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Index, MaxText:"8888"},
  2085. { Type:REPORT_COLUMN_ID.SYMBOL_ID, Title:"代码", TextAlign:"left", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Symbol, MaxText:"888888"},
  2086. { Type:REPORT_COLUMN_ID.NAME_ID, Title:"名称", TextAlign:"left", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Name, MaxText:"擎擎擎擎" },
  2087. { Type:REPORT_COLUMN_ID.SYMBOL_NAME_ID, Title:"股票名称", TextAlign:"left", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Name, MaxText:"擎擎擎擎"},
  2088. { Type:REPORT_COLUMN_ID.INCREASE_ID, Title:"涨幅%", TextAlign:"right", Width:null, MaxText:"-888.88" },
  2089. { Type:REPORT_COLUMN_ID.PRICE_ID, Title:"现价", TextAlign:"right", Width:null, MaxText:"88888.88" },
  2090. { Type:REPORT_COLUMN_ID.UPDOWN_ID, Title:"涨跌", TextAlign:"right", Width:null, MaxText:"-888.88" },
  2091. { Type:REPORT_COLUMN_ID.AMPLITUDE_ID, Title:"振幅%", TextAlign:"right", Width:null, MaxText:"888.88" },
  2092. { Type:REPORT_COLUMN_ID.BUY_PRICE_ID, Title:"买价", TextAlign:"right", Width:null, MaxText:"88888.88" },
  2093. { Type:REPORT_COLUMN_ID.SELL_PRICE_ID, Title:"卖价", TextAlign:"right", Width:null, MaxText:"88888.88" },
  2094. { Type:REPORT_COLUMN_ID.AVERAGE_PRICE_ID, Title:"均价", TextAlign:"right", Width:null, MaxText:"88888.88" },
  2095. { Type:REPORT_COLUMN_ID.OPEN_ID, Title:"今开", TextAlign:"right", Width:null, MaxText:"88888.88" },
  2096. { Type:REPORT_COLUMN_ID.HIGH_ID, Title:"最高", TextAlign:"right", Width:null, MaxText:"88888.88" },
  2097. { Type:REPORT_COLUMN_ID.LOW_ID, Title:"最低", TextAlign:"right", Width:null, MaxText:"88888.88" },
  2098. { Type:REPORT_COLUMN_ID.YCLOSE_ID, Title:"昨收", TextAlign:"right", Width:null, MaxText:"88888.88" },
  2099. { Type:REPORT_COLUMN_ID.VOL_ID, Title:"总量", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Vol, Width:null, MaxText:"8888.8擎" },
  2100. { Type:REPORT_COLUMN_ID.AMOUNT_ID, Title:"总金额", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Amount, Width:null, MaxText:"8888.8擎" },
  2101. { Type:REPORT_COLUMN_ID.EXCHANGE_RATE_ID, Title:"换手%", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, Width:null, MaxText:"88.88" },
  2102. { Type:REPORT_COLUMN_ID.OUTSTANDING_SHARES_ID, Title:"流通股本", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, Width:null, MaxText:"8888.8擎" },
  2103. { Type:REPORT_COLUMN_ID.TOTAL_SHARES_ID, Title:"总股本", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, Width:null, MaxText:"8888.8擎" },
  2104. { Type:REPORT_COLUMN_ID.CIRC_MARKET_VALUE_ID, Title:"流通市值", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, Width:null, MaxText:"8888.8擎" },
  2105. { Type:REPORT_COLUMN_ID.MARKET_VALUE_ID, Title:"总市值", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, Width:null, MaxText:"8888.8擎" },
  2106. { Type:REPORT_COLUMN_ID.VOL_IN_ID, Title:"内盘", TextAlign:"right", TextColor:g_JSChartResource.Report.DownTextColor, Width:null, MaxText:"8888.8擎" },
  2107. { Type:REPORT_COLUMN_ID.VOL_OUT_ID, Title:"外盘", TextAlign:"right", TextColor:g_JSChartResource.Report.UpTextColor, Width:null, MaxText:"8888.8擎" },
  2108. { Type:REPORT_COLUMN_ID.CLOSE_LINE_ID, Title:"走势", TextAlign:"center", TextColor:g_JSChartResource.Report.CloseLineColor, Width:null, MaxText:"88888.88" },
  2109. { Type:REPORT_COLUMN_ID.BUY_VOL_ID, Title:"买量", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Vol, Width:null, MaxText:"8888.8擎" },
  2110. { Type:REPORT_COLUMN_ID.SELL_VOL_ID, Title:"卖量", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Vol, Width:null, MaxText:"8888.8擎" },
  2111. //{ Type:REPORT_COLUMN_ID.MULTI_BAR_ID, Title:"柱子", TextAlign:"center", Width:null, TextColor:g_JSChartResource.DealList.FieldColor.BarTitle, MaxText:"888888" },
  2112. //{ Type:REPORT_COLUMN_ID.CENTER_BAR_ID, Title:"柱子2", TextAlign:"center", Width:null, TextColor:g_JSChartResource.DealList.FieldColor.BarTitle, MaxText:"888888" },
  2113. { Type:REPORT_COLUMN_ID.CUSTOM_STRING_TEXT_ID, Title:"自定义", TextAlign:"center", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"擎擎擎擎擎" },
  2114. { Type:REPORT_COLUMN_ID.CUSTOM_NUMBER_TEXT_ID, Title:"自定义", TextAlign:"center", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"擎擎擎擎擎" },
  2115. { Type:REPORT_COLUMN_ID.CUSTOM_DATETIME_TEXT_ID, Title:"自定义", TextAlign:"center", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"9999-99-99" },
  2116. ];
  2117. for(var i=0;i<DEFAULT_COLUMN.length;++i)
  2118. {
  2119. var item=DEFAULT_COLUMN[i];
  2120. if (item.Type==id) return item;
  2121. }
  2122. return null;
  2123. }
  2124. this.Draw=function()
  2125. {
  2126. this.ShowSymbol=[];
  2127. if (this.SizeChange) this.CalculateSize();
  2128. else this.UpdateCacheData();
  2129. this.Canvas.save();
  2130. this.Canvas.beginPath();
  2131. this.Canvas.rect(this.RectClient.Left,this.RectClient.Top,(this.RectClient.Right-this.RectClient.Left),(this.RectClient.Bottom-this.RectClient.Top));
  2132. //this.Canvas.stroke(); //调试用
  2133. this.Canvas.clip();
  2134. this.DrawHeader();
  2135. this.DrawBody();
  2136. this.Canvas.restore();
  2137. if (this.Tab && this.BottomToolbarHeight>0)
  2138. {
  2139. var bottom=this.ChartBorder.GetBottom();
  2140. this.Tab.DrawTab(this.RectClient.Left,bottom-this.BottomToolbarHeight, this.RectClient.Right, bottom)
  2141. this.Tab.DrawScrollbar(this.RectClient.Left,bottom-this.BottomToolbarHeight, this.RectClient.Right, bottom);
  2142. }
  2143. this.DrawBorder();
  2144. this.SizeChange=false;
  2145. }
  2146. //更新缓存变量
  2147. this.UpdateCacheData=function()
  2148. {
  2149. this.RectClient.Left=this.ChartBorder.GetLeft();
  2150. this.RectClient.Right=this.ChartBorder.GetRight();
  2151. this.RectClient.Top=this.ChartBorder.GetTop();
  2152. this.RectClient.Bottom=this.ChartBorder.GetBottom()-this.BottomToolbarHeight;
  2153. }
  2154. this.GetPageSize=function(recalculate) //recalculate 是否重新计算
  2155. {
  2156. if (recalculate) this.CalculateSize();
  2157. var size=this.RowCount;
  2158. return size;
  2159. }
  2160. this.GetCurrentPageStatus=function() //{ Start:起始索引, End:结束索引(数据), PageSize:页面可以显示几条记录, IsEnd:是否是最后一页, IsSinglePage:是否只有一页数据}
  2161. {
  2162. var result={ Start:this.Data.YOffset, PageSize:this.RowCount, IsEnd:false, SelectedRow:this.SelectedRow, IsSinglePage:false, DataCount:0 };
  2163. if (IFrameSplitOperator.IsNonEmptyArray(this.Data.Data))
  2164. {
  2165. result.End=this.Data.YOffset+this.RowCount-1;
  2166. result.IsSinglePage=this.Data.Data.length<=this.RowCount;
  2167. result.DataCount=this.Data.Data.length;
  2168. if (result.End>=this.Data.Data.length-1) result.IsEnd=true;
  2169. if (result.End>=this.Data.Data.length) result.End=this.Data.Data.length-1;
  2170. }
  2171. else
  2172. {
  2173. result.Star=0;
  2174. result.End=0;
  2175. result.IsEnd=true;
  2176. result.IsSinglePage=true;
  2177. }
  2178. return result;
  2179. }
  2180. this.CalculateSize=function() //计算大小
  2181. {
  2182. this.BottomToolbarHeight=0;
  2183. this.UpdateCacheData();
  2184. this.HeaderFont=`${this.HeaderFontConfig.Size}px ${ this.HeaderFontConfig.Name}`;
  2185. this.ItemFont=`${this.ItemFontConfig.Size}px ${ this.ItemFontConfig.Name}`;
  2186. this.ItemFixedFont=`${this.ItemFixedFontConfg.Size}px ${ this.ItemFixedFontConfg.Name}`;
  2187. this.ItemSymbolFont=`${this.ItemSymbolFontConfig.Size}px ${ this.ItemSymbolFontConfig.Name}`;
  2188. this.ItemNameFont=`${this.ItemNameFontConfg.Size}px ${ this.ItemNameFontConfg.Name}`;
  2189. this.RowHeight=this.GetFontHeight(this.ItemFont,"擎")+ this.ItemMergin.Top+ this.ItemMergin.Bottom;
  2190. this.FixedRowHeight=this.GetFontHeight(this.ItemFixedFont,"擎")+ this.ItemMergin.Top+ this.ItemMergin.Bottom;
  2191. this.Canvas.font=this.ItemFont;
  2192. var itemWidth=0;
  2193. for(var i=0;i<this.Column.length;++i)
  2194. {
  2195. var item=this.Column[i];
  2196. if (item.Type==REPORT_COLUMN_ID.SYMBOL_NAME_ID)
  2197. {
  2198. this.Canvas.font=this.ItemNameFont;
  2199. var nameWidth=this.Canvas.measureText(item.MaxText).width;
  2200. var nameHeight=this.GetFontHeight(this.ItemNameFont,"擎");
  2201. this.ItemNameHeight=nameHeight;
  2202. this.Canvas.font=this.ItemSymbolFont;
  2203. var symbolWidth=this.Canvas.measureText(item.MaxText).width;
  2204. var symboHeight=this.GetFontHeight(this.ItemSymbolFont,"擎");
  2205. this.Canvas.font=this.ItemFont;
  2206. itemWidth=Math.max(nameWidth, symbolWidth);
  2207. item.Width=itemWidth+4+this.ItemMergin.Left+this.ItemMergin.Right;
  2208. var rowHeight=nameHeight+symboHeight+this.ItemMergin.Top+ this.ItemMergin.Bottom;
  2209. if (rowHeight>this.RowHeight) this.RowHeight=rowHeight;
  2210. if (rowHeight>this.FixedRowHeight) this.FixedRowHeight=rowHeight;
  2211. }
  2212. else
  2213. {
  2214. itemWidth=this.Canvas.measureText(item.MaxText).width;
  2215. item.Width=itemWidth+4+this.ItemMergin.Left+this.ItemMergin.Right;
  2216. }
  2217. }
  2218. this.Canvas.font=this.HeaderFont;
  2219. for(var i=0;i<this.Column.length;++i)
  2220. {
  2221. var item=this.Column[i];
  2222. if (!item.Title || item.Title.length<=0) continue;
  2223. var text=item.Title;
  2224. if (item.Sort>0) text+="↓";
  2225. itemWidth=this.Canvas.measureText(text).width;
  2226. itemWidth+=(4+this.HeaderMergin.Left+this.HeaderMergin.Right);
  2227. if (item.Width<itemWidth) item.Width=itemWidth;
  2228. }
  2229. this.HeaderHeight=this.GetFontHeight(this.HeaderFont,"擎")+ this.HeaderMergin.Top+ this.HeaderMergin.Bottom;
  2230. if (!this.IsShowHeader) this.HeaderHeight=0;
  2231. if (this.FixedRowCount<=0) this.FixedRowHeight=0;
  2232. this.RowCount=parseInt((this.RectClient.Bottom-this.RectClient.Top-this.HeaderHeight-(this.FixedRowHeight*this.FixedRowCount))/this.RowHeight);
  2233. var subWidth=0;
  2234. var reportWidth=this.RectClient.Right-this.RectClient.Left;
  2235. for(var i=0;i<this.Column.length;++i)
  2236. {
  2237. var item=this.Column[i];
  2238. subWidth+=item.Width;
  2239. }
  2240. this.IsShowAllColumn=(subWidth<reportWidth);
  2241. }
  2242. this.DrawHeader=function()
  2243. {
  2244. if (!this.IsShowHeader) return;
  2245. var left=this.RectClient.Left;
  2246. var top=this.RectClient.Top;
  2247. var y=top+this.HeaderMergin.Top+(this.HeaderHeight-this.HeaderMergin.Top-this.HeaderMergin.Bottom)/2;
  2248. this.Canvas.font=this.HeaderFont;
  2249. this.Canvas.fillStyle=this.HeaderColor;
  2250. var textLeft=left;
  2251. //固定列
  2252. for(var i=0;i<this.FixedColumn && i<this.Column.length;++i)
  2253. {
  2254. var item=this.Column[i];
  2255. var itemWidth=item.Width;
  2256. var textWidth=itemWidth-this.HeaderMergin.Left-this.HeaderMergin.Right;
  2257. var x=textLeft+this.HeaderMergin.Left;
  2258. if (this.SortInfo && this.SortInfo.Field==i && this.SortInfo.Sort>0)
  2259. {
  2260. this.DrawSortHeader(item.Title,item.TextAlign,x,y,textWidth,this.SortInfo.Sort);
  2261. }
  2262. else
  2263. {
  2264. this.DrawText(item.Title,item.TextAlign,x,y,textWidth);
  2265. }
  2266. textLeft+=item.Width;
  2267. }
  2268. for(var i=this.FixedColumn+this.Data.XOffset;i<this.Column.length;++i)
  2269. {
  2270. var item=this.Column[i];
  2271. var itemWidth=item.Width;
  2272. var textWidth=itemWidth-this.HeaderMergin.Left-this.HeaderMergin.Right;
  2273. var x=textLeft+this.HeaderMergin.Left;
  2274. if (this.SortInfo && this.SortInfo.Field==i && this.SortInfo.Sort>0)
  2275. {
  2276. this.DrawSortHeader(item.Title,item.TextAlign,x,y,textWidth,this.SortInfo.Sort);
  2277. }
  2278. else
  2279. {
  2280. this.DrawText(item.Title,item.TextAlign,x,y,textWidth);
  2281. }
  2282. textLeft+=item.Width;
  2283. }
  2284. }
  2285. this.DrawText=function(text, textAlign, x, y, textWidth)
  2286. {
  2287. if (textAlign=='center')
  2288. {
  2289. x=x+textWidth/2;
  2290. this.Canvas.textAlign="center";
  2291. }
  2292. else if (textAlign=='right')
  2293. {
  2294. x=x+textWidth;
  2295. this.Canvas.textAlign="right";
  2296. }
  2297. else
  2298. {
  2299. this.Canvas.textAlign="left";
  2300. }
  2301. this.Canvas.textBaseline="middle";
  2302. this.Canvas.fillText(text,x,y);
  2303. }
  2304. this.DrawSortHeader=function(text, textAlign, x, y, width, sortType)
  2305. {
  2306. var sortText=sortType==1?"↓":"↑";
  2307. var sortTextWidth=this.Canvas.measureText(sortText).width;
  2308. var textWidth=this.Canvas.measureText(text).width+2;
  2309. this.Canvas.textBaseline="middle";
  2310. this.Canvas.textAlign="left";
  2311. if (textAlign=='center')
  2312. {
  2313. x=x+width/2-(sortTextWidth+textWidth)/2;
  2314. }
  2315. else if (textAlign=='right')
  2316. {
  2317. x=(x+width)-sortTextWidth-textWidth;
  2318. }
  2319. else
  2320. {
  2321. }
  2322. this.Canvas.fillText(text,x,y);
  2323. this.Canvas.fillStyle=this.SortColor;
  2324. this.Canvas.fillText(sortText,x+textWidth,y);
  2325. this.Canvas.fillStyle=this.HeaderColor;
  2326. }
  2327. this.DrawBorder=function()
  2328. {
  2329. if (!this.IsDrawBorder) return;
  2330. var left=this.RectClient.Left;
  2331. var right=this.RectClient.Right;
  2332. var top=this.RectClient.Top;
  2333. var bottom=this.RectClient.Bottom;
  2334. this.Canvas.strokeStyle=this.BorderColor;
  2335. this.Canvas.beginPath();
  2336. this.Canvas.moveTo(left,ToFixedPoint(top+this.HeaderHeight));
  2337. this.Canvas.lineTo(right,ToFixedPoint(top+this.HeaderHeight));
  2338. var rowTop=top+this.HeaderHeight+this.RowHeight;
  2339. var rotBottom=rowTop;
  2340. for(var i=0;i<this.FixedRowCount;++i)
  2341. {
  2342. var drawTop=ToFixedPoint(rowTop);
  2343. this.Canvas.moveTo(left,drawTop);
  2344. this.Canvas.lineTo(right,drawTop);
  2345. rotBottom=rowTop;
  2346. rowTop+=this.FixedRowHeight;
  2347. }
  2348. var rowTop=top+this.HeaderHeight+this.RowHeight+this.FixedRowHeight*this.FixedRowCount;
  2349. var rotBottom=rowTop;
  2350. //横线
  2351. for(var i=0;i<this.RowCount;++i)
  2352. {
  2353. var drawTop=ToFixedPoint(rowTop);
  2354. this.Canvas.moveTo(left,drawTop);
  2355. this.Canvas.lineTo(right,drawTop);
  2356. rotBottom=rowTop;
  2357. rowTop+=this.RowHeight;
  2358. }
  2359. //竖线
  2360. var columnLeft=left;
  2361. for(var i=0;i<this.FixedColumn && i<this.Column.length; ++i)
  2362. {
  2363. var item=this.Column[i];
  2364. var drawLeft=ToFixedPoint(columnLeft+item.Width);
  2365. this.Canvas.moveTo(drawLeft,top);
  2366. this.Canvas.lineTo(drawLeft,rotBottom);
  2367. columnLeft+=item.Width;
  2368. }
  2369. for(var i=this.FixedColumn+this.Data.XOffset;i<this.Column.length;++i)
  2370. {
  2371. var item=this.Column[i];
  2372. var drawLeft=ToFixedPoint(columnLeft+item.Width);
  2373. this.Canvas.moveTo(drawLeft,top);
  2374. this.Canvas.lineTo(drawLeft,rotBottom);
  2375. columnLeft+=item.Width;
  2376. }
  2377. this.Canvas.stroke();
  2378. }
  2379. this.DrawBody=function()
  2380. {
  2381. if (!this.Data) return;
  2382. if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return;
  2383. this.Canvas.font=this.ItemFont;
  2384. var top=this.RectClient.Top+this.HeaderHeight;
  2385. var left=this.RectClient.Left;
  2386. var rowWidth=this.RectClient.Right-this.RectClient.Left;
  2387. //固定行
  2388. var textTop=top;
  2389. this.Canvas.font=this.ItemFixedFont;
  2390. for(var i=0; i<this.FixedRowCount; ++i)
  2391. {
  2392. if (this.SelectedFixedRow==i)
  2393. {
  2394. this.Canvas.fillStyle=this.SelectedColor;;
  2395. this.Canvas.fillRect(left,textTop,rowWidth,this.FixedRowHeight);
  2396. }
  2397. if (this.FixedRowData.Type==1)
  2398. this.DrawFixedSymbolRow(textTop,i);
  2399. else
  2400. this.DrawFixedRow(textTop, i);
  2401. textTop+=this.FixedRowHeight;
  2402. }
  2403. textTop=top+this.FixedRowHeight*this.FixedRowCount;
  2404. this.Canvas.font=this.ItemFont;
  2405. for(var i=this.Data.YOffset, j=0; i<this.Data.Data.length && j<this.RowCount ;++i, ++j)
  2406. {
  2407. var symbol=this.Data.Data[i];
  2408. var bFillRow=false;
  2409. if (this.SelectedModel==0)
  2410. {
  2411. if (j==this.SelectedRow) bFillRow=true; //选中行
  2412. }
  2413. else
  2414. {
  2415. if (i==this.SelectedRow) bFillRow=true; //选中行
  2416. }
  2417. if (bFillRow)
  2418. {
  2419. this.Canvas.fillStyle=this.SelectedColor;
  2420. this.Canvas.fillRect(left,textTop,rowWidth,this.RowHeight);
  2421. }
  2422. this.DrawRow(symbol, textTop, i);
  2423. this.ShowSymbol.push( { Index:i, Symbol:symbol } );
  2424. textTop+=this.RowHeight;
  2425. }
  2426. }
  2427. this.DrawFixedSymbolRow=function(top, dataIndex)
  2428. {
  2429. var left=this.RectClient.Left;
  2430. var chartRight=this.RectClient.Right;
  2431. if (!this.FixedRowData || !IFrameSplitOperator.IsNonEmptyArray(this.FixedRowData.Symbol)) return;
  2432. var symbol=this.FixedRowData.Symbol[dataIndex];
  2433. if (!symbol) return;
  2434. this.DrawRow(symbol, top, dataIndex, 1);
  2435. this.ShowSymbol.push( { Index:dataIndex, Symbol:symbol, RowType:1 } );
  2436. }
  2437. this.DrawFixedRow=function(top, dataIndex)
  2438. {
  2439. var left=this.RectClient.Left;
  2440. var chartRight=this.RectClient.Right;
  2441. for(var i=0;i<this.FixedColumn && i<this.Column.length;++i)
  2442. {
  2443. var item=this.Column[i];
  2444. this.DrawFixedItem(dataIndex, i, item, left, top);
  2445. left+=item.Width;
  2446. if (left>=chartRight) break;
  2447. }
  2448. for(var i=this.FixedColumn+this.Data.XOffset;i<this.Column.length;++i)
  2449. {
  2450. var item=this.Column[i];
  2451. this.DrawFixedItem(dataIndex, i, item, left, top);
  2452. left+=item.Width;
  2453. if (left>=chartRight) break;
  2454. }
  2455. }
  2456. this.DrawFixedItem=function(dataIndex, colIndex, column, left, top)
  2457. {
  2458. var x=left+this.ItemMergin.Left;
  2459. var textWidth=column.Width-this.ItemMergin.Left-this.ItemMergin.Right;
  2460. var drawInfo={ Text:null, TextColor:column.TextColor , TextAlign:column.TextAlign };
  2461. if (this.GetFixedRowTextDrawInfo(dataIndex, colIndex, column, drawInfo))
  2462. {
  2463. this.DrawItemText(drawInfo.Text, drawInfo.TextColor, drawInfo.TextAlign, x, top, textWidth);
  2464. return;
  2465. }
  2466. if (!this.FixedRowData || !IFrameSplitOperator.IsNonEmptyArray(this.FixedRowData.Data)) return;
  2467. var data=this.FixedRowData.Data;
  2468. var rowData=data[dataIndex];
  2469. if (!IFrameSplitOperator.IsNonEmptyArray(rowData)) return;
  2470. var itemData=rowData[colIndex];
  2471. if (!itemData || !itemData.Text) return;
  2472. drawInfo.Text=itemData.Text;
  2473. if (itemData.Color) drawInfo.TextColor=itemData.Color;
  2474. if (itemData.TextAlign) drawInfo.TextAlign=itemData.TextAlign;
  2475. this.DrawItemText(drawInfo.Text, drawInfo.TextColor, drawInfo.TextAlign, x, top, textWidth);
  2476. }
  2477. this.DrawRow=function(symbol, top, dataIndex, rowType) //rowType 0=表格行 1=顶部固定行
  2478. {
  2479. var left=this.RectClient.Left;
  2480. var chartRight=this.RectClient.Right;
  2481. var data= { Symbol:symbol , Stock:null };
  2482. if (this.GetStockDataCallback) data.Stock=this.GetStockDataCallback(symbol);
  2483. if (this.GetBlockDataCallback) data.Block=this.GetBlockDataCallback(symbol);
  2484. data.Decimal=GetfloatPrecision(symbol); //小数位数
  2485. for(var i=0;i<this.FixedColumn && i<this.Column.length;++i)
  2486. {
  2487. var item=this.Column[i];
  2488. this.DrawItem(dataIndex, data, item, left, top, rowType);
  2489. left+=item.Width;
  2490. if (left>=chartRight) break;
  2491. }
  2492. for(var i=this.FixedColumn+this.Data.XOffset;i<this.Column.length;++i)
  2493. {
  2494. var item=this.Column[i];
  2495. this.DrawItem(dataIndex, data, item, left, top, rowType);
  2496. left+=item.Width;
  2497. if (left>=chartRight) break;
  2498. }
  2499. }
  2500. this.DrawItem=function(index, data, column, left, top, rowType)
  2501. {
  2502. var itemWidth=column.Width;
  2503. var x=left+this.ItemMergin.Left;
  2504. var textWidth=column.Width-this.ItemMergin.Left-this.ItemMergin.Right;
  2505. var stock=data.Stock;
  2506. var drawInfo={ Text:null, TextColor:column.TextColor , TextAlign:column.TextAlign };
  2507. if (column.Type==REPORT_COLUMN_ID.INDEX_ID)
  2508. {
  2509. if (rowType==1) return; //固定行序号空
  2510. drawInfo.Text=(index+1).toString();
  2511. }
  2512. else if (column.Type==REPORT_COLUMN_ID.SYMBOL_ID)
  2513. {
  2514. if (stock && stock.Symbol) drawInfo.Text=stock.Symbol;
  2515. else drawInfo.Text=data.Symbol;
  2516. }
  2517. else if (column.Type==REPORT_COLUMN_ID.SYMBOL_NAME_ID)
  2518. {
  2519. this.DrawSymbolName(data, column, left, top, rowType);
  2520. }
  2521. else if (column.Type==REPORT_COLUMN_ID.NAME_ID)
  2522. {
  2523. if (stock && stock.Name)
  2524. {
  2525. drawInfo.Text=this.TextEllipsis(stock.Name, textWidth, column.MaxText);
  2526. drawInfo.TextColor=this.GetNameColor(column,data.Symbol, rowType);
  2527. }
  2528. }
  2529. else if (column.Type==REPORT_COLUMN_ID.PRICE_ID)
  2530. {
  2531. if (stock) this.GetPriceDrawInfo(stock.Price, stock, data, drawInfo);
  2532. }
  2533. else if (column.Type==REPORT_COLUMN_ID.OPEN_ID)
  2534. {
  2535. //如果行情开盘价为涨停价或跌停价,则对内容加灰框
  2536. if (stock)
  2537. {
  2538. this.DrawLimitPriceBorder(stock.Open, stock, left, top, column.Width);
  2539. this.GetPriceDrawInfo(stock.Open, stock, data, drawInfo);
  2540. }
  2541. }
  2542. else if (column.Type==REPORT_COLUMN_ID.HIGH_ID)
  2543. {
  2544. //如果行情最高价为涨停价,则对内容加灰框
  2545. if (stock)
  2546. {
  2547. this.DrawLimitPriceBorder(stock.High, stock, left, top, column.Width);
  2548. this.GetPriceDrawInfo(stock.High, stock, data, drawInfo);
  2549. }
  2550. }
  2551. else if (column.Type==REPORT_COLUMN_ID.LOW_ID)
  2552. {
  2553. //如果行情最低价为跌停价,则对内容加灰框
  2554. if (stock)
  2555. {
  2556. this.DrawLimitPriceBorder(stock.Low, stock, left, top, column.Width);
  2557. this.GetPriceDrawInfo(stock.Low, stock, data, drawInfo);
  2558. }
  2559. }
  2560. else if (column.Type==REPORT_COLUMN_ID.YCLOSE_ID)
  2561. {
  2562. if (stock) this.GetPriceDrawInfo(stock.YClose, stock, data, drawInfo);
  2563. }
  2564. else if (column.Type==REPORT_COLUMN_ID.BUY_PRICE_ID)
  2565. {
  2566. if (stock) this.GetPriceDrawInfo(stock.BuyPrice, stock, data, drawInfo);
  2567. }
  2568. else if (column.Type==REPORT_COLUMN_ID.SELL_PRICE_ID)
  2569. {
  2570. if (stock) this.GetPriceDrawInfo(stock.SellPrice, stock, data, drawInfo);
  2571. }
  2572. else if (column.Type==REPORT_COLUMN_ID.AVERAGE_PRICE_ID)
  2573. {
  2574. if (stock) this.GetPriceDrawInfo(stock.AvPrice, stock, data, drawInfo);
  2575. }
  2576. else if (column.Type==REPORT_COLUMN_ID.EXCHANGE_RATE_ID)
  2577. {
  2578. if (stock && IFrameSplitOperator.IsNumber(stock.Exchange))
  2579. drawInfo.Text=stock.Exchange.toFixed(2);
  2580. }
  2581. else if (column.Type==REPORT_COLUMN_ID.BUY_VOL_ID)
  2582. {
  2583. if (stock && IFrameSplitOperator.IsNumber(stock.BuyVol)) drawInfo.Text=this.FormatVolString(stock.BuyVol);
  2584. }
  2585. else if (column.Type==REPORT_COLUMN_ID.SELL_VOL_ID)
  2586. {
  2587. if (stock && IFrameSplitOperator.IsNumber(stock.SellVol)) drawInfo.Text=this.FormatVolString(stock.SellVol);
  2588. }
  2589. else if (column.Type==REPORT_COLUMN_ID.VOL_ID)
  2590. {
  2591. if (stock && IFrameSplitOperator.IsNumber(stock.Vol)) drawInfo.Text=this.FormatVolString(stock.Vol);
  2592. }
  2593. else if (column.Type==REPORT_COLUMN_ID.VOL_IN_ID)
  2594. {
  2595. if (stock && IFrameSplitOperator.IsNumber(stock.VolIn)) drawInfo.Text=this.FormatVolString(stock.VolIn);
  2596. }
  2597. else if (column.Type==REPORT_COLUMN_ID.VOL_OUT_ID)
  2598. {
  2599. if (stock && IFrameSplitOperator.IsNumber(stock.VolOut)) drawInfo.Text=this.FormatVolString(stock.VolOut);
  2600. }
  2601. else if (column.Type==REPORT_COLUMN_ID.TOTAL_SHARES_ID)
  2602. {
  2603. if (stock && IFrameSplitOperator.IsNumber(stock.TotalShares)) drawInfo.Text=this.FormatVolString(stock.TotalShares);
  2604. }
  2605. else if (column.Type==REPORT_COLUMN_ID.OUTSTANDING_SHARES_ID)
  2606. {
  2607. if (stock && IFrameSplitOperator.IsNumber(stock.OutShares)) drawInfo.Text=this.FormatVolString(stock.OutShares);
  2608. }
  2609. else if (column.Type==REPORT_COLUMN_ID.CIRC_MARKET_VALUE_ID || column.Type==REPORT_COLUMN_ID.MARKET_VALUE_ID || column.Type==REPORT_COLUMN_ID.AMOUNT_ID)
  2610. {
  2611. var fieldName=MAP_COLUMN_FIELD.get(column.Type);
  2612. if (stock && IFrameSplitOperator.IsNumber(stock[fieldName]))
  2613. drawInfo.Text=this.FormatVolString(stock[fieldName]);
  2614. }
  2615. else if (column.Type==REPORT_COLUMN_ID.INCREASE_ID || column.Type==REPORT_COLUMN_ID.AMPLITUDE_ID || column.Type==REPORT_COLUMN_ID.UPDOWN_ID)
  2616. {
  2617. var fieldName=MAP_COLUMN_FIELD.get(column.Type);
  2618. if (stock && IFrameSplitOperator.IsNumber(stock[fieldName]))
  2619. {
  2620. var value=stock[fieldName];
  2621. drawInfo.Text=value.toFixed(2);
  2622. drawInfo.TextColor=this.GetUpDownColor(value,0);
  2623. }
  2624. }
  2625. else if (column.Type==REPORT_COLUMN_ID.CUSTOM_STRING_TEXT_ID)
  2626. {
  2627. this.GetCustomStringDrawInfo(data, column, drawInfo);
  2628. }
  2629. else if (column.Type==REPORT_COLUMN_ID.CUSTOM_NUMBER_TEXT_ID)
  2630. {
  2631. this.GetCustomNumberDrawInfo(data, column, drawInfo);
  2632. }
  2633. else if (column.Type==REPORT_COLUMN_ID.CUSTOM_DATETIME_TEXT_ID)
  2634. {
  2635. this.GetCustomDateTimeDrawInfo(data, column, drawInfo);
  2636. }
  2637. else if (column.Type==REPORT_COLUMN_ID.CLOSE_LINE_ID)
  2638. {
  2639. var rtItem={ Left:left, Top:top, Width:column.Width, Height:this.RowHeight };
  2640. rtItem.Right=rtItem.Left+rtItem.Width;
  2641. rtItem.Bottom=rtItem.Top+rtItem.Height;
  2642. if (stock) this.DrawLine(stock.CloseLine, column, rtItem);
  2643. }
  2644. this.DrawItemText(drawInfo.Text, drawInfo.TextColor, drawInfo.TextAlign, x, top, textWidth);
  2645. }
  2646. this.DrawSymbolName=function(data, column, left, top, rowType)
  2647. {
  2648. var stock=data.Stock;
  2649. var symbol=data.Symbol;
  2650. var name;
  2651. if (stock)
  2652. {
  2653. symbol=stock.Symbol;
  2654. name=stock.Name;
  2655. }
  2656. if (!symbol && !name) return;
  2657. var y=top+this.ItemMergin.Top+this.ItemNameHeight;
  2658. var textLeft=left+this.ItemMergin.Left;
  2659. var x=textLeft;
  2660. var width=column.Width-this.ItemMergin.Left-this.ItemMergin.Right;
  2661. var textAlign=column.TextAlign;
  2662. if (textAlign=='center')
  2663. {
  2664. x=textLeft+width/2;
  2665. this.Canvas.textAlign="center";
  2666. }
  2667. else if (textAlign=='right')
  2668. {
  2669. x=textLeft+width-2;
  2670. this.Canvas.textAlign="right";
  2671. }
  2672. else
  2673. {
  2674. x+=2;
  2675. this.Canvas.textAlign="left";
  2676. }
  2677. var textColor=this.GetNameColor(column,symbol,rowType);
  2678. var text=name;
  2679. if (text)
  2680. {
  2681. this.Canvas.textBaseline="ideographic";
  2682. this.Canvas.fillStyle=textColor;
  2683. this.Canvas.font=this.ItemNameFont;
  2684. text=this.TextEllipsis(text, width, column.MaxText);
  2685. if (text) this.Canvas.fillText(text,x,y);
  2686. }
  2687. text=symbol;
  2688. if (text)
  2689. {
  2690. this.Canvas.textBaseline="top";
  2691. this.Canvas.font=this.ItemSymbolFont;
  2692. this.Canvas.fillStyle=textColor;
  2693. this.Canvas.fillText(text,x,y);
  2694. }
  2695. this.Canvas.font=this.ItemFont; //还原字体
  2696. }
  2697. this.DrawLimitPriceBorder=function(value, stock, left, top, itemWidth)
  2698. {
  2699. if (!IFrameSplitOperator.IsNumber(value) || !stock) return;
  2700. var bDraw=false;
  2701. if (IFrameSplitOperator.IsNumber(stock.LimitHigh))
  2702. {
  2703. if (value>=stock.LimitHigh) bDraw=true;
  2704. }
  2705. if (IFrameSplitOperator.IsNumber(stock.LimitLow))
  2706. {
  2707. if (value<=stock.LimitLow) bDraw=true;
  2708. }
  2709. if (!bDraw) return;
  2710. var x=left+this.ItemMergin.Left+this.LimitMergin.Left;
  2711. var width=itemWidth-this.ItemMergin.Left-this.ItemMergin.Right-this.LimitMergin.Left-this.LimitMergin.Right;
  2712. var y=top+this.ItemMergin.Top+this.LimitMergin.Top;
  2713. var height=this.RowHeight-this.ItemMergin.Top-this.ItemMergin.Bottom-this.LimitMergin.Top-this.LimitMergin.Bottom;
  2714. this.Canvas.strokeStyle=this.LimitBorderColor;
  2715. this.Canvas.strokeRect(ToFixedPoint(x),ToFixedPoint(y),ToFixedRect(width),ToFixedRect(height));
  2716. }
  2717. this.GetExtendData=function(data, column)
  2718. {
  2719. if (IFrameSplitOperator.IsNumber(column.DataIndex))
  2720. {
  2721. if (!data.Stock || !data.Stock.ExtendData) return null;
  2722. if (column.DataIndex<0) return;
  2723. return data.Stock.ExtendData[column.DataIndex];
  2724. }
  2725. if (IFrameSplitOperator.IsNumber(column.BlockIndex))
  2726. {
  2727. if (!data.Block) return;
  2728. if (column.BlockIndex<0) return;
  2729. return data.Block[column.BlockIndex];
  2730. }
  2731. return null;
  2732. }
  2733. this.GetCustomStringDrawInfo=function(data, column, drawInfo)
  2734. {
  2735. var value=this.GetExtendData(data, column);
  2736. if (!IFrameSplitOperator.IsString(value)) return;
  2737. if (column.IsDrawCallback) //外部处理输出格式
  2738. {
  2739. this.GetCustomTextDrawInfo(column, data.Symbol, value, drawInfo, data);
  2740. return;
  2741. }
  2742. drawInfo.Text=value;
  2743. }
  2744. this.GetCustomNumberDrawInfo=function(data, column, drawInfo)
  2745. {
  2746. var value=this.GetExtendData(data, column);
  2747. if (!IFrameSplitOperator.IsNumber(value)) return;
  2748. if (column.IsDrawCallback) //外部处理输出格式
  2749. {
  2750. this.GetCustomTextDrawInfo(column, data.Symbol, value, drawInfo,data);
  2751. return;
  2752. }
  2753. //格式化输出
  2754. switch(column.FormatType)
  2755. {
  2756. case 1:
  2757. drawInfo.Text=value.toFixed(column.Decimal);
  2758. break;
  2759. case 2:
  2760. drawInfo.Text=IFrameSplitOperator.FormatValueThousandsString(value, column.Decimal);
  2761. break;
  2762. case 3:
  2763. drawInfo.Text=this.FormatVolString(value);
  2764. break;
  2765. default:
  2766. drawInfo.Text=IFrameSplitOperator.FormatValueString(value, column.Decimal);
  2767. break;
  2768. }
  2769. //颜色
  2770. switch(column.ColorType)
  2771. {
  2772. case 1:
  2773. drawInfo.TextColor=this.GetUpDownColor(value,0);
  2774. break;
  2775. case 2:
  2776. if (!IFrameSplitOperator.IsNumber(data.Stock.YClose))
  2777. drawInfo.TextColor=this.UnchagneColor;
  2778. else
  2779. drawInfo.TextColor=this.GetUpDownColor(value, data.Stock.YClose);
  2780. break;
  2781. default:
  2782. break;
  2783. }
  2784. }
  2785. this.GetCustomDateTimeDrawInfo=function(data, column, drawInfo)
  2786. {
  2787. var value=this.GetExtendData(data, column);
  2788. if (!IFrameSplitOperator.IsNumber(value)) return;
  2789. if (column.IsDrawCallback) //外部处理输出格式
  2790. {
  2791. this.GetCustomTextDrawInfo(column, data.Symbol, value, drawInfo, data);
  2792. return;
  2793. }
  2794. if (column.ValueType==0)
  2795. {
  2796. if (column.FormatType==1)
  2797. drawInfo.Text=IFrameSplitOperator.FormatDateString(value,"YYYY/MM/DD");
  2798. else
  2799. drawInfo.Text=IFrameSplitOperator.FormatDateString(value);
  2800. }
  2801. }
  2802. this.GetPriceDrawInfo=function(price, stock, data, drawInfo)
  2803. {
  2804. if (!IFrameSplitOperator.IsNumber(price)) return false;
  2805. drawInfo.Text=price.toFixed(data.Decimal);
  2806. if (!IFrameSplitOperator.IsNumber(stock.YClose))
  2807. drawInfo.TextColor=this.UnchagneColor;
  2808. else
  2809. drawInfo.TextColor=this.GetUpDownColor(price, stock.YClose);
  2810. }
  2811. this.GetUpDownColor=function(price, price2)
  2812. {
  2813. if (price>price2) return this.UpColor;
  2814. else if (price<price2) return this.DownColor;
  2815. else return this.UnchagneColor;
  2816. }
  2817. //单独处理成交量显示
  2818. this.FormatVolString=function(value,languageID)
  2819. {
  2820. var absValue = Math.abs(value);
  2821. if (absValue<100000)
  2822. return absValue.toFixed(0);
  2823. else if (absValue<10000000)
  2824. return (value/10000).toFixed(1)+"万";
  2825. else if (absValue<100000000)
  2826. return (value/10000).toFixed(0)+"万";
  2827. else if (absValue<1000000000)
  2828. return (value/100000000).toFixed(2)+"亿";
  2829. else if (absValue < 1000000000000)
  2830. return (value/100000000).toFixed(1)+"亿";
  2831. else
  2832. return (value/1000000000000).toFixed(1)+"万亿";
  2833. }
  2834. this.DrawItemText=function(text, textColor, textAlign, left, top, width)
  2835. {
  2836. if (!text) return;
  2837. var x=left;
  2838. if (textAlign=='center')
  2839. {
  2840. x=left+width/2;
  2841. this.Canvas.textAlign="center";
  2842. }
  2843. else if (textAlign=='right')
  2844. {
  2845. x=left+width-2;
  2846. this.Canvas.textAlign="right";
  2847. }
  2848. else
  2849. {
  2850. x+=2;
  2851. this.Canvas.textAlign="left";
  2852. }
  2853. this.Canvas.textBaseline="middle";
  2854. this.Canvas.fillStyle=textColor;
  2855. this.Canvas.fillText(text,x,top+this.ItemMergin.Top+this.RowHeight/2);
  2856. }
  2857. //字体由外面设置
  2858. this.TextEllipsis=function(text, maxWidth, maxText)
  2859. {
  2860. if (!text) return null;
  2861. if (text.length<=maxText.length) return text;
  2862. var start=maxText.length-3;
  2863. if (start<0) return null;
  2864. var newText=text.slice(0,start);
  2865. for(var i=start;i<text.length;++i)
  2866. {
  2867. var value=newText + text[i] + "...";
  2868. var width=this.Canvas.measureText(value).width;
  2869. if (width>maxWidth)
  2870. {
  2871. newText+="...";
  2872. break;
  2873. }
  2874. newText+=text[i];
  2875. }
  2876. return newText;
  2877. }
  2878. this.DrawMultiBar=function(colunmInfo, data, rtItem)
  2879. {
  2880. if (!data.Source || !IFrameSplitOperator.IsNonEmptyArray(data.Source)) return false;
  2881. var barData=data.Source[colunmInfo.DataIndex]; //{ Value:[0.4,0,2], Color:[0,1] };
  2882. if (!barData) return false;
  2883. if (!IFrameSplitOperator.IsNonEmptyArray(barData.Value)) return false;
  2884. var width=rtItem.Width-this.BarMergin.Left-this.BarMergin.Right;
  2885. var left=rtItem.Left+this.BarMergin.Left;
  2886. var top=rtItem.Top+this.RowMergin.Top+this.BarMergin.Top;
  2887. var height=rtItem.Height-this.RowMergin.Top-this.RowMergin.Bottom-this.BarMergin.Top-this.BarMergin.Bottom;
  2888. var right=left+width;
  2889. for(var i=0;i<barData.Value.length;++i)
  2890. {
  2891. var value=barData.Value[i];
  2892. if (value<=0) continue;
  2893. if (left>=right) break;
  2894. var barWidth=width*value;
  2895. if (barWidth<1) barWidth=1;
  2896. if (left+barWidth>right) barWidth=right-left;
  2897. var colorIndex=i;
  2898. if (IFrameSplitOperator.IsNonEmptyArray(barData.Color) && i<barData.Color.length) colorIndex= barData.Color[i];
  2899. this.Canvas.fillStyle=g_JSChartResource.DealList.FieldColor.Bar[colorIndex];
  2900. this.Canvas.fillRect(left,top,barWidth,height);
  2901. left+=barWidth;
  2902. }
  2903. return true;
  2904. }
  2905. this.DrawCenterBar=function(colunmInfo, data, rtItem)
  2906. {
  2907. if (!data.Source || !IFrameSplitOperator.IsNonEmptyArray(data.Source)) return false;
  2908. var barData=data.Source[colunmInfo.DataIndex]; //{ Value:[0.4,0,2], Color:[0,1] };
  2909. if (!barData) return false;
  2910. if (!IFrameSplitOperator.IsNonEmptyArray(barData.Value)) return false;
  2911. var width=(rtItem.Width-this.BarMergin.Left-this.BarMergin.Right)/2;
  2912. var left=rtItem.Left+this.BarMergin.Left;
  2913. var center=left+width;
  2914. var top=rtItem.Top+this.RowMergin.Top+this.BarMergin.Top;
  2915. var height=rtItem.Height-this.RowMergin.Top-this.RowMergin.Bottom-this.BarMergin.Top-this.BarMergin.Bottom;
  2916. var right=left+width;
  2917. for(var i=0;i<barData.Value.length && i<2;++i)
  2918. {
  2919. var value=barData.Value[i];
  2920. if (value<=0) continue;
  2921. if (value>1) value=1;
  2922. var barWidth=width*value;
  2923. if (barWidth<1) barWidth=1;
  2924. var colorIndex=i;
  2925. if (IFrameSplitOperator.IsNonEmptyArray(barData.Color) && i<barData.Color.length) colorIndex= barData.Color[i];
  2926. this.Canvas.fillStyle=g_JSChartResource.DealList.FieldColor.Bar[colorIndex];
  2927. if (i==0) //左边
  2928. {
  2929. this.Canvas.fillRect(center,top,-barWidth,height);
  2930. }
  2931. else //右边
  2932. {
  2933. this.Canvas.fillRect(center,top,barWidth,height);
  2934. }
  2935. }
  2936. }
  2937. //绘制线段
  2938. this.DrawLine=function(lineData, column, rtItem)
  2939. {
  2940. if (!lineData) return false;
  2941. if (!IFrameSplitOperator.IsNonEmptyArray(lineData.Data)) return false;
  2942. var width=rtItem.Width-this.ItemMergin.Left-this.ItemMergin.Right;
  2943. var left=rtItem.Left+this.ItemMergin.Left;
  2944. var top=rtItem.Top+this.ItemMergin.Top;
  2945. var height=rtItem.Height-this.ItemMergin.Top-this.ItemMergin.Bottom;
  2946. var right=left+width;
  2947. var bottom=top+height;
  2948. var Temp_GetXFromIndex=function(index)
  2949. {
  2950. var count=lineData.Count;
  2951. if (count==1)
  2952. {
  2953. if (index==0) return left;
  2954. else return right;
  2955. }
  2956. else if (count<=0)
  2957. {
  2958. return left;
  2959. }
  2960. else if (index>=count)
  2961. {
  2962. return right;
  2963. }
  2964. else
  2965. {
  2966. var offset=left+width*index/count;
  2967. return offset;
  2968. }
  2969. }
  2970. var Temp_GetYFromData=function(value)
  2971. {
  2972. if(value<=lineData.Min) return bottom;
  2973. if(value>=lineData.Max) return top;
  2974. var value=height*(value-lineData.Min)/(lineData.Max-lineData.Min);
  2975. return bottom-value;
  2976. }
  2977. this.Canvas.save();
  2978. var yCenter=null;
  2979. if (IFrameSplitOperator.IsNumber(lineData.YClose))
  2980. {
  2981. var y=Temp_GetYFromData(lineData.YClose);
  2982. y=ToFixedPoint(y);
  2983. yCenter=y;
  2984. this.Canvas.setLineDash([2,2]);
  2985. this.Canvas.strokeStyle=this.CloseLineConfig.YCloseColor;
  2986. this.Canvas.beginPath();
  2987. this.Canvas.moveTo(left,y);
  2988. this.Canvas.lineTo(right,y);
  2989. this.Canvas.stroke();
  2990. this.Canvas.setLineDash([]);
  2991. }
  2992. if (lineData.Color) this.Canvas.strokeStyle=lineData.Color;
  2993. else this.Canvas.strokeStyle=column.TextColor;
  2994. var bFirstPoint=true;
  2995. var ptFirst={}; //第1个点
  2996. var drawCount=0, x,y;
  2997. for(var i=0; i<lineData.Data.length; ++i)
  2998. {
  2999. var value=lineData.Data[i];
  3000. if (!IFrameSplitOperator.IsNumber(value)) continue;
  3001. x=Temp_GetXFromIndex(i);
  3002. y=Temp_GetYFromData(value);
  3003. if (bFirstPoint)
  3004. {
  3005. this.Canvas.beginPath();
  3006. this.Canvas.moveTo(x,y);
  3007. bFirstPoint=false;
  3008. ptFirst={ X:x, Y:y };
  3009. }
  3010. else
  3011. {
  3012. this.Canvas.lineTo(x,y);
  3013. }
  3014. ++drawCount;
  3015. }
  3016. if (drawCount>0)
  3017. {
  3018. this.Canvas.stroke();
  3019. if (column.IsDrawArea && IFrameSplitOperator.IsNumber(yCenter))
  3020. {
  3021. this.Canvas.lineTo(x,yCenter);
  3022. this.Canvas.lineTo(ptFirst.X,yCenter);
  3023. this.Canvas.closePath();
  3024. this.SetFillStyle(this.CloseLineConfig.AreaColor,left,top, left,bottom);
  3025. this.Canvas.fill();
  3026. }
  3027. }
  3028. this.Canvas.restore();
  3029. }
  3030. this.SetFillStyle=function(color, x0, y0, x1, y1)
  3031. {
  3032. if (Array.isArray(color))
  3033. {
  3034. let gradient = this.Canvas.createLinearGradient(x0, y0, x1, y1);
  3035. var offset=1/(color.length);
  3036. for(var i in color)
  3037. {
  3038. gradient.addColorStop(i*offset, color[i]);
  3039. }
  3040. this.Canvas.fillStyle=gradient;
  3041. }
  3042. else
  3043. {
  3044. this.Canvas.fillStyle=color;
  3045. }
  3046. }
  3047. //外部配置显示格式 颜色 对齐方式
  3048. this.GetCustomTextDrawInfo=function(columnInfo, symbol, value, drawInfo,data)
  3049. {
  3050. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DRAW_CUSTOM_TEXT);
  3051. if (!event || !event.Callback) return false;
  3052. var sendData=
  3053. {
  3054. Symbol:symbol, Column:columnInfo, Value:value, Data:data,
  3055. Out:{ Text:null, TextColor:null, TextAlign:null }
  3056. };
  3057. event.Callback(event,sendData,this);
  3058. if (sendData.Out.Text) drawInfo.Text=sendData.Out.Text;
  3059. if (sendData.Out.TextColor) drawInfo.TextColor=sendData.Out.TextColor;
  3060. if (sendData.Out.TextAlign) drawInfo.TextAlign=sendData.Out.TextAlign;
  3061. return true;
  3062. }
  3063. this.GetFixedRowTextDrawInfo=function(rowIndex, colIndex, columnInfo, drawInfo)
  3064. {
  3065. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DRAW_REPORT_FIXEDROW_TEXT);
  3066. if (!event || !event.Callback) return false;
  3067. var sendData=
  3068. {
  3069. RowIndex:rowIndex, ColIndex:colIndex, Column:columnInfo, Data:this.FixedRowData,
  3070. Out:{ Text:null, TextColor:null, TextAlign:null }
  3071. };
  3072. event.Callback(event,sendData,this);
  3073. if (sendData.Out.Text) drawInfo.Text=sendData.Out.Text;
  3074. if (sendData.Out.TextColor) drawInfo.TextColor=sendData.Out.TextColor;
  3075. if (sendData.Out.TextAlign) drawInfo.TextAlign=sendData.Out.TextAlign;
  3076. return true;
  3077. }
  3078. this.GetVolColor=function(colunmInfo, data)
  3079. {
  3080. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DRAW_DEAL_VOL_COLOR);
  3081. if (event && event.Callback)
  3082. {
  3083. var sendData={ Data:data, TextColor:null };
  3084. event.Callback(event,sendData,this);
  3085. if (sendData.TextColor) return sendData.TextColor;
  3086. }
  3087. return colunmInfo.TextColor;
  3088. }
  3089. //获取股票名称颜色
  3090. this.GetNameColor=function(colunmInfo, symbol, rowType)
  3091. {
  3092. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DRAW_REPORT_NAME_COLOR);
  3093. if (event && event.Callback)
  3094. {
  3095. var sendData={ Symbol:symbol, TextColor:null, RowType:rowType };
  3096. event.Callback(event,sendData,this);
  3097. if (sendData.TextColor) return sendData.TextColor;
  3098. }
  3099. return colunmInfo.TextColor;
  3100. }
  3101. this.GetFontHeight=function(font,word)
  3102. {
  3103. return GetFontHeight(this.Canvas, font, word);
  3104. }
  3105. this.OnMouseDown=function(x,y,e)
  3106. {
  3107. if (!this.Data) return null;
  3108. if (this.Tab)
  3109. {
  3110. var tab=this.Tab.OnMouseDown(x,y,e);
  3111. if (tab) return { Type:1, Tab: tab }; //顶部工具栏
  3112. }
  3113. var row=this.PtInFixedBody(x,y)
  3114. if (row)
  3115. {
  3116. var bRedraw=true;
  3117. var eventID=JSCHART_EVENT_ID.ON_CLICK_REPORT_FIXEDROW;
  3118. if (e.button==2) eventID=JSCHART_EVENT_ID.ON_RCLICK_REPORT_FIXEDROW;
  3119. this.SendClickEvent(eventID, { Data:row, X:x, Y:y, e:e });
  3120. this.SelectedFixedRow=row.Index;
  3121. this.SelectedRow=-1;
  3122. return { Type:4, Redraw:bRedraw, Row:row }; //行
  3123. }
  3124. var row=this.PtInBody(x,y);
  3125. if (row)
  3126. {
  3127. var bRedraw=true;
  3128. if (this.SelectedModel==0)
  3129. {
  3130. if (this.SelectedRow==row.Index) bRedraw=false;
  3131. this.SelectedRow=row.Index;
  3132. this.SelectedFixedRow=-1;
  3133. }
  3134. else
  3135. {
  3136. if (this.SelectedRow==row.DataIndex) bRedraw=false;
  3137. this.SelectedRow=row.DataIndex;
  3138. this.SelectedFixedRow=-1;
  3139. }
  3140. var eventID=JSCHART_EVENT_ID.ON_CLICK_REPORT_ROW;
  3141. if (e.button==2) eventID=JSCHART_EVENT_ID.ON_RCLICK_REPORT_ROW;
  3142. this.SendClickEvent(eventID, { Data:row, X:x, Y:y, e:e });
  3143. return { Type:2, Redraw:bRedraw, Row:row }; //行
  3144. }
  3145. var header=this.PtInHeader(x,y);
  3146. if (header)
  3147. {
  3148. var eventID=JSCHART_EVENT_ID.ON_CLICK_REPORT_HEADER;
  3149. if (e.button==2)
  3150. {
  3151. eventID=JSCHART_EVENT_ID.ON_RCLICK_REPORT_HEADER;
  3152. }
  3153. else if (e.button==0)
  3154. {
  3155. eventID=JSCHART_EVENT_ID.ON_CLICK_REPORT_HEADER;
  3156. }
  3157. this.SendClickEvent(eventID, { Data:row, X:x, Y:y , e:e });
  3158. return { Type:3, Redraw:bRedraw, Header:header }; //表头
  3159. }
  3160. return null;
  3161. }
  3162. this.OnDblClick=function(x,y,e)
  3163. {
  3164. if (!this.Data) return false;
  3165. var row=this.PtInBody(x,y);
  3166. if (row)
  3167. {
  3168. this.SendClickEvent(JSCHART_EVENT_ID.ON_DBCLICK_REPORT_ROW, { Data:row, X:x, Y:y });
  3169. return true;
  3170. }
  3171. return false;
  3172. }
  3173. this.PtInBody=function(x,y)
  3174. {
  3175. if (!this.Data) return null;
  3176. if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return null;
  3177. var top=this.RectClient.Top+this.HeaderHeight;
  3178. var left=this.RectClient.Left;
  3179. var right=this.RectClient.Right;
  3180. var rowWidth=this.RectClient.Right-this.RectClient.Left;
  3181. var textTop=top+this.FixedRowHeight*this.FixedRowCount;
  3182. for(var i=this.Data.YOffset, j=0; i<this.Data.Data.length && j<this.RowCount ;++i, ++j)
  3183. {
  3184. var symbol=this.Data.Data[i];
  3185. var rtRow={ Left:left, Top:textTop, Right:right, Bottom: textTop+this.RowHeight };
  3186. if (x>=rtRow.Left && x<=rtRow.Right && y>=rtRow.Top && y<=rtRow.Bottom)
  3187. {
  3188. var data={ Rect:rtRow, DataIndex:i, Index:j , Symbol:symbol };
  3189. data.Item=this.PtInItem(x,y, rtRow.Top, rtRow.Bottom);
  3190. return data;
  3191. }
  3192. textTop+=this.RowHeight;
  3193. }
  3194. return null;
  3195. }
  3196. this.PtInFixedBody=function(x,y)
  3197. {
  3198. if (this.FixedRowCount<=0) return null;
  3199. var top=this.RectClient.Top+this.HeaderHeight;
  3200. var left=this.RectClient.Left;
  3201. var right=this.RectClient.Right;
  3202. var rowWidth=this.RectClient.Right-this.RectClient.Left;
  3203. var textTop=top;
  3204. for(var i=0; i<this.FixedRowCount; ++i)
  3205. {
  3206. var rtRow={ Left:left, Top:textTop, Right:right, Bottom: textTop+this.FixedRowHeight };
  3207. if (x>=rtRow.Left && x<=rtRow.Right && y>=rtRow.Top && y<=rtRow.Bottom)
  3208. {
  3209. var data={ Rect:rtRow, Index:i};
  3210. data.Item=this.PtInItem(x,y, rtRow.Top, rtRow.Bottom);
  3211. return data;
  3212. }
  3213. textTop+=this.FixedRowHeight;
  3214. }
  3215. return null;
  3216. }
  3217. this.PtInItem=function(x,y, top, bottom)
  3218. {
  3219. var left=this.RectClient.Left;
  3220. var right=this.RectClient.Right;
  3221. var textLeft=left;
  3222. //固定列
  3223. for(var i=0;i<this.FixedColumn && i<this.Column.length;++i)
  3224. {
  3225. var item=this.Column[i];
  3226. var header={Left:textLeft, Right:textLeft+item.Width, Top:top, Bottom:bottom };
  3227. if (x>=header.Left && x<=header.Right && y>=header.Top && y<=header.Bottom)
  3228. {
  3229. return { Rect:header, Column:item, Index:i };
  3230. }
  3231. textLeft+=item.Width;
  3232. }
  3233. for(var i=this.FixedColumn+this.Data.XOffset;i<this.Column.length;++i)
  3234. {
  3235. var item=this.Column[i];
  3236. if (textLeft>=right) break;
  3237. var header={Left:textLeft, Right:textLeft+item.Width, Top:top, Bottom:bottom };
  3238. if (x>=header.Left && x<=header.Right && y>=header.Top && y<=header.Bottom)
  3239. {
  3240. return { Rect:header, Column:item, Index:i };
  3241. }
  3242. textLeft+=item.Width;
  3243. }
  3244. return null;
  3245. }
  3246. this.PtInHeader=function(x,y)
  3247. {
  3248. if (!this.IsShowHeader) return null;
  3249. var left=this.RectClient.Left;
  3250. var right=this.RectClient.Right;
  3251. var top=this.RectClient.Top;
  3252. var bottom=top+this.HeaderHeight;
  3253. if (!(x>=left && x<=right && y>=top && y<=bottom)) return null;
  3254. return this.PtInItem(x,y,top,bottom);
  3255. }
  3256. this.IsPtInBody=function(x,y)
  3257. {
  3258. var top=this.RectClient.Top+this.HeaderHeight;
  3259. var left=this.RectClient.Left;
  3260. var right=this.RectClient.Right;
  3261. var bottom=this.RectClient.Bottom;
  3262. if (x>=left && x<=right && y>=top && y<=bottom) return true;
  3263. return false;
  3264. }
  3265. this.IsPtInHeader=function(x,y)
  3266. {
  3267. if (!this.IsShowHeader) return false;
  3268. var left=this.RectClient.Left;
  3269. var right=this.RectClient.Right;
  3270. var top=this.RectClient.Top;
  3271. var bottom=top+this.HeaderHeight;
  3272. if (x>=left && x<=right && y>=top && y<=bottom) return true;
  3273. return false;
  3274. }
  3275. this.SendClickEvent=function(id, data)
  3276. {
  3277. var event=this.GetEventCallback(id);
  3278. if (event && event.Callback)
  3279. {
  3280. event.Callback(event,data,this);
  3281. }
  3282. }
  3283. this.GetXScrollPos=function()
  3284. {
  3285. return this.Data.XOffset;
  3286. }
  3287. this.GetXScrollRange=function()
  3288. {
  3289. var maxOffset=this.Column.length-this.FixedColumn-3;
  3290. if (maxOffset<0) return 0;
  3291. return maxOffset;
  3292. }
  3293. }
  3294. //页脚信息
  3295. function ChartReportPageInfo()
  3296. {
  3297. this.Canvas; //画布
  3298. this.ChartBorder; //边框信息
  3299. this.ChartFrame; //框架画法
  3300. this.Name; //名称
  3301. this.ClassName='ChartPageInfo'; //类名
  3302. this.IsDrawFirst=false;
  3303. this.IsShow=false; //是否显示
  3304. this.SizeChange=true;
  3305. this.Report;
  3306. this.FontConfig={ Size:g_JSChartResource.Report.PageInfo.Font.Size, Name:g_JSChartResource.Report.PageInfo.Font.Name };
  3307. this.TextColor=g_JSChartResource.Report.PageInfo.TextColor;
  3308. this.BGColor=g_JSChartResource.Report.PageInfo.BGColor;
  3309. this.Mergin=
  3310. {
  3311. Top:g_JSChartResource.Report.PageInfo.Mergin.Top,
  3312. Left:g_JSChartResource.Report.PageInfo.Mergin.Left,
  3313. Right:g_JSChartResource.Report.PageInfo.Mergin.Right,
  3314. Bottom:g_JSChartResource.Report.PageInfo.Mergin.Bottom
  3315. }
  3316. this.Font;
  3317. this.TextHeight=0;
  3318. this.ReloadResource=function(resource)
  3319. {
  3320. this.FontConfig={ Size:g_JSChartResource.Report.PageInfo.Font.Size, Name:g_JSChartResource.Report.PageInfo.Font.Name };
  3321. this.TextColor=g_JSChartResource.Report.PageInfo.TextColor;
  3322. this.BGColor=g_JSChartResource.Report.PageInfo.BGColor;
  3323. this.Mergin=
  3324. {
  3325. Top:g_JSChartResource.Report.PageInfo.Mergin.Top,
  3326. Left:g_JSChartResource.Report.PageInfo.Mergin.Left,
  3327. Right:g_JSChartResource.Report.PageInfo.Mergin.Right,
  3328. Bottom:g_JSChartResource.Report.PageInfo.Mergin.Bottom
  3329. }
  3330. }
  3331. this.Draw=function()
  3332. {
  3333. if (!this.IsShow) return;
  3334. if (!this.Report) return;
  3335. var pageStatus=this.Report.GetCurrentPageStatus();
  3336. if (pageStatus.IsSinglePage) return;
  3337. if (this.SizeChange)
  3338. {
  3339. this.Font=`${this.FontConfig.Size}px ${ this.FontConfig.Name}`;
  3340. this.TextHeight=GetFontHeight(this.Canvas, this.Font, "擎")+this.Mergin.Top+this.Mergin.Bottom;
  3341. }
  3342. var left=this.ChartBorder.GetLeft();
  3343. var right=this.ChartBorder.GetRight();
  3344. var bottom=this.ChartBorder.GetBottom()-2;
  3345. var center=left+(right-left)/2;
  3346. var text=`${pageStatus.DataCount}/${pageStatus.DataCount}`;
  3347. this.Canvas.font=this.Font;
  3348. var textWidth=this.Canvas.measureText(text).width+4;
  3349. var bgLeft=center-textWidth/2-this.Mergin.Left;
  3350. var bgTop=bottom-this.TextHeight;
  3351. this.Canvas.fillStyle=this.BGColor;;
  3352. this.Canvas.fillRect(bgLeft,bgTop,textWidth+(this.Mergin.Left+this.Mergin.Right),this.TextHeight);
  3353. text=`${pageStatus.Start+1}/${pageStatus.DataCount}`;
  3354. this.Canvas.textAlign="center";
  3355. this.Canvas.textBaseline="bottom";
  3356. this.Canvas.fillStyle=this.TextColor;
  3357. this.Canvas.fillText(text,center,bottom-this.Mergin.Bottom);
  3358. this.SizeChange=false;
  3359. }
  3360. }
  3361. //导出统一使用JSCommon命名空间名
  3362. var JSReport=
  3363. {
  3364. JSCanvasElement:JSCanvasElement,
  3365. JSReportChart: JSReportChart,
  3366. IFrameSplitOperator: IFrameSplitOperator,
  3367. JSCHART_EVENT_ID:JSCHART_EVENT_ID,
  3368. REPORT_COLUMN_ID:REPORT_COLUMN_ID,
  3369. };
  3370. export
  3371. {
  3372. JSReport,
  3373. JSCanvasElement,
  3374. JSReportChart,
  3375. IFrameSplitOperator,
  3376. JSCHART_EVENT_ID,
  3377. REPORT_COLUMN_ID,
  3378. }
  3379. /*
  3380. module.exports =
  3381. {
  3382. JSReport:
  3383. {
  3384. JSCanvasElement:JSCanvasElement,
  3385. JSReportChart: JSReportChart,
  3386. IFrameSplitOperator: IFrameSplitOperator,
  3387. JSCHART_EVENT_ID:JSCHART_EVENT_ID,
  3388. REPORT_COLUMN_ID:REPORT_COLUMN_ID,
  3389. },
  3390. };
  3391. */