123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534 |
- <?php
- namespace Dcat\Admin\Widgets\Metrics;
- use Dcat\Admin\Admin;
- use Dcat\Admin\Support\Helper;
- use Dcat\Admin\Traits\InteractsWithApi;
- use Dcat\Admin\Widgets\ApexCharts\Chart;
- use Dcat\Admin\Widgets\Widget;
- use Illuminate\Support\Arr;
- use Illuminate\Support\Str;
- class Card extends Widget
- {
- use InteractsWithApi;
- /**
- * @var string
- */
- protected $view = 'admin::widgets.metrics.card';
- /**
- * @var array
- */
- protected $options = [
- 'icon' => null,
- 'title' => null,
- 'subTitle' => null,
- 'header' => null,
- 'content' => null,
- 'dropdown' => [],
- ];
- /**
- * 图标主题色.
- *
- * @var string
- */
- protected $style = 'primary';
- /**
- * 卡片高度.
- *
- * @var int|string
- */
- protected $height = null;
- /**
- * 图表高度.
- *
- * @var int
- */
- protected $chartHeight = 70;
- /**
- * 图表上间距.
- *
- * @var int
- */
- protected $chartMarginTop;
- /**
- * 图表下间距.
- *
- * @var int
- */
- protected $chartMarginBottom;
- /**
- * 图表配置.
- *
- * @var array
- */
- protected $chartOptions = [];
- /**
- * @var Chart
- */
- protected $chart;
- /**
- * @var \Closure
- */
- protected $chartCallback;
- public function __construct($title = null, $icon = null)
- {
- $this->title($title);
- $this->icon($icon);
- if ($options = $this->defaultChartOptions()) {
- $this->chartOptions = $options;
- }
- $this->init();
- }
- /**
- * 初始化.
- */
- protected function init()
- {
- $this->id('metric-card-'.Str::random(8));
- $this->class('card');
- }
- /**
- * 图表默认配置.
- *
- * @return array
- */
- protected function defaultChartOptions()
- {
- return [];
- }
- /**
- * 启用图表.
- *
- * @return Chart
- */
- public function useChart()
- {
- return $this->chart ?: ($this->chart = Chart::make());
- }
- /**
- * 设置图标.
- *
- * @param string $icon
- *
- * @return $this
- */
- public function icon(?string $icon)
- {
- $this->options['icon'] = $icon;
- return $this;
- }
- /**
- * 设置卡片标题.
- *
- * @param string $title
- *
- * @return $this
- */
- public function title(?string $title)
- {
- $this->options['title'] = $title;
- return $this;
- }
- /**
- * 设置卡片子标题.
- *
- * @param string $title
- *
- * @return $this
- */
- public function subTitle(?string $title)
- {
- $this->options['subTitle'] = $title;
- return $this;
- }
- /**
- * 设置卡片头内容.
- *
- * @param string $contents
- *
- * @return $this
- */
- public function header($contents)
- {
- $this->options['header'] = $contents;
- return $this;
- }
- /**
- * 设置卡片内容.
- *
- * @param string $contents
- *
- * @return $this
- */
- public function content($contents)
- {
- $this->options['content'] = $contents;
- return $this;
- }
- /**
- * 设置主题色.
- *
- * @param string $style
- *
- * @return $this
- */
- public function style(string $style)
- {
- $this->style = $style;
- return $this;
- }
- /**
- * 设置卡片的下拉菜单选项.
- *
- * @param array $items
- *
- * @return $this
- */
- public function dropdown(array $items)
- {
- $this->options['dropdown'] = $items;
- return $this;
- }
- /**
- * 设置最小高度.
- *
- * @param string|int $value
- *
- * @return $this
- */
- public function height($value)
- {
- $this->height = $value;
- return $this;
- }
- /**
- * 设置图表配置.
- *
- * @param string $key
- * @param mixed $value
- *
- * @return $this
- */
- public function chartOption($key, $value)
- {
- Arr::set($this->chartOptions, $key, $value);
- $this->useChart();
- return $this;
- }
- /**
- * 设置图表高度.
- *
- * @param int $number
- *
- * @return $this
- */
- public function chartHeight(int $number)
- {
- $this->chartHeight = $number;
- $this->useChart();
- return $this;
- }
- /**
- * 设置图表上间距.
- *
- * @param int $number
- *
- * @return $this
- */
- public function chartMarginTop(int $number)
- {
- $this->chartMarginBottom = $number;
- $this->useChart();
- return $this;
- }
- /**
- * 设置图表下间距.
- *
- * @param int $number
- *
- * @return $this
- */
- public function chartMarginBottom(int $number)
- {
- $this->chartMarginBottom = $number;
- $this->useChart();
- return $this;
- }
- /**
- * 设置图表label.
- *
- * @param string|array $label
- *
- * @return $this
- */
- public function chartLabels($label)
- {
- $this->chartOptions['labels'] = (array) $label;
- $this->useChart();
- return $this;
- }
- /**
- * 设置图表颜色.
- *
- * @param string|array $colors
- *
- * @return $this
- */
- public function chartColors($colors)
- {
- $this->chartOptions['colors'] = (array) $colors;
- $this->useChart();
- return $this;
- }
- /**
- * 设置图表.
- *
- * @param array|\Closure $options
- *
- * @return $this
- */
- public function chart($options = [])
- {
- if ($options instanceof \Closure) {
- $this->chartCallback = $options;
- } else {
- $this->chartOptions = array_merge(
- $this->chartOptions,
- Helper::array($options)
- );
- }
- $this->useChart();
- return $this;
- }
- /**
- * 设置图表.
- */
- protected function setUpChart()
- {
- if (! $chart = $this->chart) {
- return;
- }
- $this->setUpChartMargin();
- // 设置图表高度
- $this->chartOptions['chart']['height'] = $this->chartHeight;
- // 颜色
- if (empty($this->chartOptions['colors'])) {
- $this->chartOptions['colors'] = (array) Admin::color()->get($this->style);
- }
- // 图表配置选项
- $chart->options($this->chartOptions);
- if ($callback = $this->chartCallback) {
- $callback($chart);
- }
- }
- /**
- * 设置图表间距.
- *
- * @return void
- */
- protected function setUpChartMargin()
- {
- if ($this->chartMarginTop !== null) {
- $this->chart->style("margin-top: {$this->chartMarginTop}px;");
- }
- if ($this->chartMarginBottom !== null) {
- $this->chart->style("margin-bottom: {$this->chartMarginBottom}px;");
- }
- }
- /**
- * @return mixed
- */
- public function script()
- {
- if (! $this->allowBuildRequest()) {
- return;
- }
- $id = $this->id();
- // 开启loading效果
- $this->fetching(
- <<<JS
- var \$card = $('#{$id}');
- \$card.loading();
- JS
- );
- $this->fetched(
- <<<'JS'
- $card.loading(false);
- $card.find('.metric-header').html(response.header);
- $card.find('.metric-content').html(response.content);
- JS
- );
- $clickable = "#{$id} .dropdown .select-option";
- $cardRequestScript = '';
- if ($this->chart) {
- // 有图表的情况下,直接使用图表的js代码.
- $this->chart->merge($this)->click($clickable);
- } else {
- // 没有图表,需要构建卡片数据请求js代码.
- $cardRequestScript = $this->click($clickable)->buildRequestScript();
- }
- // 按钮显示选中文本
- return <<<JS
- $('{$clickable}').click(function () {
- $(this).parents('.dropdown').find('.btn').html($(this).text());
- });
- {$cardRequestScript}
- JS;
- }
- /**
- * 渲染卡片头部内容.
- *
- * @return string
- */
- public function renderHeader()
- {
- return Helper::render($this->options['header']);
- }
- /**
- * 渲染卡片主体内容.
- *
- * @return string
- */
- public function renderContent()
- {
- return Helper::render($this->options['content']);
- }
- /**
- * 渲染图表.
- *
- * @return string
- */
- public function renderChart()
- {
- return $this->chart ? $this->chart->render() : '';
- }
- /**
- * 设置卡片高度.
- */
- protected function setUpCardHeight()
- {
- if (! $height = $this->height) {
- return;
- }
- if (is_numeric($height)) {
- $height .= 'px';
- }
- $this->appendHtmlAttribute('style', "min-height:{$height};");
- }
- /**
- * @return string
- */
- public function render()
- {
- $this->setUpChart();
- $this->setUpCardHeight();
- $this->script = $this->script();
- $this->variables['style'] = $this->style;
- $this->variables['header'] = $this->renderHeader();
- $this->variables['content'] = $this->renderContent();
- return parent::render();
- }
- /**
- * 返回API请求结果.
- *
- * @return array
- */
- public function valueResult()
- {
- $this->setUpChart();
- return array_merge(
- [
- 'status' => 1,
- 'header' => $this->renderHeader(),
- 'content' => $this->renderContent(),
- ],
- (array) optional($this->chart)->valueResult()
- );
- }
- }
|