Highcharts 插件的使用

项目中需要通过解析文本,读取文本的数据来生成曲线图,由于文本的数据都是对数,所以把XY轴都设成对数,

<script type="text/javascript" src="~/Content/Base/Highcharts/highcharts.js"></script>
    <script type="text/javascript" src="~/Content/Base/Highcharts/modules/exporting.js"></script>
    <script type="text/javascript" src="~/Content/Base/Highcharts/modules/oldie.js"></script>

引用js

html

<div style="width:100%; height: 600px; border:1px solid #cccccc; margin-top:5px;">
            <div id="container" style="max-width:100%;height:600px"></div>
        </div>
(function (H) {
            // Pass error messages
            H.Axis.prototype.allowNegativeLog = true;

            // Override conversions
            H.Axis.prototype.log2lin = function (num) {
                var isNegative = num < 0,
            adjustedNum = Math.abs(num),
            result;
                if (adjustedNum < 10) {
                    adjustedNum += (10 - adjustedNum) / 10;
                }
                result = Math.log(adjustedNum) / Math.LN10;
                return isNegative ? -result : result;
            };
            H.Axis.prototype.lin2log = function (num) {
                var isNegative = num < 0,
            absNum = Math.abs(num),
            result = Math.pow(10, absNum);
                if (result < 10) {
                    result = (10 * (result - 1)) / (10 - 1);
                }
                return isNegative ? -result : result;
            };
        } (Highcharts));

        function InitializeData(data, xUnit, yUnit) {
            Highcharts.setOptions({
                lang: {
                     printChart:"打印图表",
                      downloadJPEG: "下载JPEG 图片" , 
                      downloadPDF: "下载PDF文档"  ,
                      downloadPNG: "下载PNG 图片"  ,
                      downloadSVG: "下载SVG 矢量图" , 
                      exportButtonTitle: "导出图片" 
                }
            });
            $('#container').highcharts({
                title: {
                    text: ' '
                },
                credits: {
                    enabled: false // 禁用版权信息
                },
                legend: {
                    enabled: true 
                },
                xAxis: {
                    type: 'logarithmic',
                    title: {
                        text: 'Frequency(' + xUnit + ')'
                    }
                },
                yAxis: {
                    type: 'logarithmic',//Y轴属性
                    title: {
                        text: '' + yUnit + '(log)'
                    }//Y轴名字
                },
                /*数据点设置*/
                plotOptions: {
                    series: {
                        marker: {
                            enabled: false, /*数据点是否显示*/
                            radius: 1  /*数据点大小px*/
                        }
                    }
                },
                tooltip: {//此为当你指上点时显示的具体窗口
                    crosshairs: true ,
                    positioner: function() {
                        return {
                            x: 20,
                            y: 0
                        }//固定显示位置
                    },
                    headerFormat: 'Point ID:<b>{series.name}</b><br />',
                    pointFormat: 'x = {point.x}, y = {point.y}'
                },
                series: eval('(' + data + ')')// 把字符串解析为json             
            });
        };

        function confimXianshi() {
            var selectXian = getSelectValues();
            var fileName = $.trim($("#fileNameSelect").val());
            var tmpData = {};
            tmpData["FileName"] = fileName;
            for (var i = 0; i < selectXian.length; i++) {
                tmpData["SelectXian[" + i + "]"] = selectXian[i];
            }
            console.log(tmpData);
            $.ajax({
                url: "/Desdatlab/ProjectManager/confimSelectXian",
                data: tmpData,
                type: "post",
                dataType: "json",
                success: function (rntData) {
                    document.getElementById('testId').value = rntData[0].fileName;
                    document.getElementById('testDate').value = rntData[0].testTime;
                    console.log(rntData);
                    InitializeData(rntData[0].data, rntData[0].xUnit, rntData[0].yUnit);
                }
            });
        };

其主要是对于后台返回的数据格式有要求,需要在后台把数据处理好返回,

返回数据格式可参考官网给出的文档,或者在官网进行操作熟悉

for (var i = 0; i < tmpXYList.Count; i++)
                {
                    if (jiequQuJian == 0)
                    {
                        if (tmpXYList[i].ToString() == "    -1")
                        {
                            jiequQuJian = 1;
                            continue;
                        }
                    }
                    else if (jiequQuJian == 1)
                    {
                        if (tmpXYList[i].ToString() != "    -1")
                        {
                            if ((i % (jiequCount * 2 + 2)) == 1)
                            {
                                tmpXYData = "[" + tmpXYList[i].ToString() + "," + tmpXYList[++i].ToString() + "]";
                                isOneFor = 0;
                            }
                            else
                            {
                                tmpXYData = tmpXYData + ",[" + tmpXYList[i].ToString() + "," + tmpXYList[++i].ToString() + "]";
                            }
                        }
                        else
                        {
                            jiequQuJian = 0;
                            XYList.Add(tmpXYData);
                            tmpXYData = "";
                        }
                    }
                }

tmpXYList为我在文本中解析所得到的点,并且都是XY轴的数据

tmpXYData = “[” + tmpXYList[i].ToString() + “,” + tmpXYList[++i].ToString() + “]”;
tmpXYData = tmpXYData + “,[” + tmpXYList[i].ToString() + “,” + tmpXYList[++i].ToString() + “]”;
此形成的数据格式类似[X,Y],[X, Y]
此为形成前端所需要点的数据格式,

if (xuyaoCount.Length == 1 && i == 0) {
                        DataInfoXY = "[{name:'" + nameList[i] + "',data: [" + XYList[i].ToString() + "]}]";
                    }
                    else if ((i + 1) == xuyaoCount.Length)
                    {
                        dataPosition = xuyaoCount[i];
                        DataInfoXY = DataInfoXY + ",{name:'" + nameList[i] + "',data: [" + XYList[i].ToString() + "]}]";
                    }
                    else if (i == 0)
                    {
                        dataPosition = xuyaoCount[i];
                        DataInfoXY = "[{name:'" + nameList[dataPosition] + "',data: [" + XYList[dataPosition].ToString() + "]}";
                    }
                    else
                    {
                        dataPosition = xuyaoCount[i];
                        DataInfoXY = DataInfoXY + ",{name:'" + nameList[i] + "',data:[ " + XYList[i].ToString() + "]}";
                    }

此方法为返回前端所需要的json格式,需要注意的时当只有一条线时json的数据格式为
[{name: name, data: [刚才形成的点的地方]}]
多条线时
[{name: name, data: [刚才形成的点的地方]},{name: name, data: [刚才形成的点的地方]}]

贴上后台具体处理代码
前面部分都是项目需求自己所写的
主要是在前面有讲到的两部分
由于自己是第一次接触C#,部分代码写的会比较复杂比较低效,
不过以此记录自己做完的过程,方便自己记录

HttpPost]
        [HandlerAjaxOnly]
        public ActionResult confimSelectXian(string FileName, string[] SelectXian)
        {
            try
            {
                List<string> listLines = new List<string>();
                var filePath = "E:/Desdatlab/CoteWebView/Content/Base/" + FileName;
                using (StreamReader reader = new StreamReader(filePath))
                {
                    int i = 1;
                    string line = reader.ReadLine();
                    while (line != "" && line != null)
                    {
                        listLines.Add(line);
                        line = reader.ReadLine();
                    }
                }

                //读取时间
                string[] tmpTimeInfo = listLines[4].Split(new char[2] { '-', ' ' });
                string[] timeMonth = new string[12];
                string timeInfo = "";
                string monthInfo = "";
                string weekInfo = "";
                timeMonth[0] = "Jan"; timeMonth[1] = "Feb"; timeMonth[2] = "Mar"; timeMonth[3] = "Apr"; timeMonth[4] = "May"; timeMonth[5] = "Jun";
                timeMonth[6] = "Jul"; timeMonth[7] = "Aug"; timeMonth[8] = "Sep"; timeMonth[9] = "Oct"; timeMonth[10] = "Nov"; timeMonth[11] = "Dec";
                for (var i = 0; i < timeMonth.Length; i++)
                {
                    if (tmpTimeInfo[1].Equals(timeMonth[i]))
                    {
                        if ((i + 1) < 10)
                        {
                            monthInfo = "0" + (i + 1).ToString();
                        }
                        else
                        {
                            monthInfo = (i + 1).ToString();
                        }
                    }
                }
                tmpTimeInfo[0] = "20" + tmpTimeInfo[0];
                weekInfo = CaculateWeekDay(tmpTimeInfo[0].ToInt(), monthInfo.ToInt(), tmpTimeInfo[2].ToInt());
                timeInfo = tmpTimeInfo[0] + "-" + monthInfo + "-" + tmpTimeInfo[2] + " " + weekInfo;


                ArrayList dataList = new ArrayList();
                string[] tmpDataInfo;
                for (var i = 0; i < listLines.Count; i++)
                {
                    //listLines[i] = new System.Text.RegularExpressions.Regex("[\\s]+").Replace(listLines[i], " ");
                    tmpDataInfo = listLines[i].Split(' ');
                    for (var j = 0; j < tmpDataInfo.Length; j++)
                    {
                        if (tmpDataInfo[j] == "")
                        {
                            continue;
                        }
                        else
                        {
                            if (tmpDataInfo.Length == 5 && tmpDataInfo[j].ToString() == "-1")
                            {
                                dataList.Add("    " + tmpDataInfo[j]);
                            }
                            else
                            {
                                dataList.Add(tmpDataInfo[j]);
                            }

                        }
                    }
                }
                //获取XY轴单位
                string XUnit = "";
                string YUnit = "";
                string[] tmpXUnitNull = listLines[9].Split(' ');
                string[] tmpYUnitNull = listLines[10].Split(' ');
                string[] tmpXUnit = new string[6];
                string[] tmpYUnit = new string[6];
                int xUnitCount = 0;
                int yUnitCount = 0;
                for (var i = 0; i < tmpXUnitNull.Length; i++) {
                    if (tmpXUnitNull[i].ToString() != "") {
                        tmpXUnit[xUnitCount] = tmpXUnitNull[i];
                        xUnitCount++;
                    }
                }
                for (var i = 0; i < tmpYUnitNull.Length; i++)
                {
                    if (tmpYUnitNull[i].ToString() != "")
                    {
                        tmpYUnit[yUnitCount] = tmpYUnitNull[i];
                        yUnitCount++;
                    }
                }
                XUnit = tmpXUnit[tmpXUnit.Length - 1].ToString();
                YUnit = tmpYUnit[tmpYUnit.Length - 1].ToString();

                ArrayList tmpNameList = new ArrayList();
                ArrayList tmpXYList = new ArrayList();
                var jiequQuJian = 0;
                int jiequCount = 0;
                //获取线的名字
                for (var i = 0; i < dataList.Count; i++)
                {
                    if (jiequCount == 0)
                    {
                        if (dataList[i].ToString() == "    -1")
                        {
                            jiequCount = 1;
                            continue;
                        }
                    }
                    else if (jiequCount == 1)
                    {
                        if (dataList[i - 1].ToString() == "    -1")
                        {
                            tmpNameList.Add(dataList[i + 1]);
                        }
                        else
                        {
                            jiequCount = 0;
                            continue;
                        }
                    }
                }

                ArrayList nameList = new ArrayList();
                for (var i = 0; i < tmpNameList.Count; i++)
                {
                    if (i == 0)
                    {
                        string[] tmpNameShuzu = tmpNameList[i].ToString().Split(new char[2] { '(', ')' });
                        nameList.Add(tmpNameShuzu[1]);
                    }
                    else
                    {
                        if (i % 2 == 0)
                        {
                            string[] tmpNameShuzu = tmpNameList[i].ToString().Split(new char[2] { '(', ')' });
                            nameList.Add(tmpNameShuzu[1]);
                        }
                    }
                }


                //获取点数据
                for (var i = 0; i < dataList.Count; i++)
                {
                    string tmpData = dataList[i].ToString();
                    if (jiequQuJian == 0)
                    {
                        if (tmpData == "    -1")
                        {
                            tmpXYList.Add("    -1");
                            i = i + 40;
                            jiequQuJian = 1;
                        }
                        if (tmpData.Contains("E+") || tmpData.Contains("E-"))
                        {
                            tmpXYList.Add(tmpData);
                        }
                    }
                    else if (jiequQuJian == 1)
                    {
                        if (tmpData == "    -1")
                        {
                            tmpXYList.Add("    -1");
                            jiequQuJian = 0;
                        }
                        if (tmpData.Contains("E+") || tmpData.Contains("E-"))
                        {
                            tmpXYList.Add(tmpData);
                        }
                    }
                }
                int[] fuyiData = new int[tmpXYList.Count];
                var m = 0;
                for (var i = 0; i < tmpXYList.Count; i++)
                {
                    if (tmpXYList[i].ToString() == "    -1")
                    {
                        fuyiData[m] = i;
                        m++;
                    }
                }
                jiequCount = (fuyiData[1] - fuyiData[0] - 1) / 2;
                string[][] XYDataInfo = new string[jiequCount][];
                ArrayList XYList = new ArrayList();
                jiequQuJian = 0;
                int k = 0;
                string tmpXYData = "";
                int isOneFor = 1;
                for (var i = 0; i < tmpXYList.Count; i++)
                {
                    if (jiequQuJian == 0)
                    {
                        if (tmpXYList[i].ToString() == "    -1")
                        {
                            jiequQuJian = 1;
                            continue;
                        }
                    }
                    else if (jiequQuJian == 1)
                    {
                        if (tmpXYList[i].ToString() != "    -1")
                        {
                            if ((i % (jiequCount * 2 + 2)) == 1)
                            {
                                tmpXYData = "[" + tmpXYList[i].ToString() + "," + tmpXYList[++i].ToString() + "]";
                                isOneFor = 0;
                            }
                            else
                            {
                                tmpXYData = tmpXYData + ",[" + tmpXYList[i].ToString() + "," + tmpXYList[++i].ToString() + "]";
                            }
                        }
                        else
                        {
                            jiequQuJian = 0;
                            XYList.Add(tmpXYData);
                            tmpXYData = "";
                        }
                    }
                }
                string DataInfoXY = "";
                int[] xuyaoCount = new int[SelectXian.Length];
                for(var i = 0; i < SelectXian.Length; i++){
                    for(var j = 0; j < nameList.Count; j++){
                        if(SelectXian[i].ToString() == nameList[j].ToString()){
                            xuyaoCount[i] = j;
                            break;
                        }
                    }
                }

                //形成最后series所需的数据格式
                int dataPosition = 0;
                for (var i = 0; i < xuyaoCount.Length; i++)
                {
                    if (xuyaoCount.Length == 1 && i == 0) {
                        DataInfoXY = "[{name:'" + nameList[i] + "',data: [" + XYList[i].ToString() + "]}]";
                    }
                    else if ((i + 1) == xuyaoCount.Length)
                    {
                        dataPosition = xuyaoCount[i];
                        DataInfoXY = DataInfoXY + ",{name:'" + nameList[i] + "',data: [" + XYList[i].ToString() + "]}]";
                    }
                    else if (i == 0)
                    {
                        dataPosition = xuyaoCount[i];
                        DataInfoXY = "[{name:'" + nameList[dataPosition] + "',data: [" + XYList[dataPosition].ToString() + "]}";
                    }
                    else
                    {
                        dataPosition = xuyaoCount[i];
                        DataInfoXY = DataInfoXY + ",{name:'" + nameList[i] + "',data:[ " + XYList[i].ToString() + "]}";
                    }
                }





                List<object> lsNode = new List<object>();
                var zTreeData = new
                {
                    data = DataInfoXY,
                    xUnit = XUnit,
                    yUnit = YUnit,
                    fileName = FileName,
                    testTime = timeInfo
                };
                lsNode.Add(zTreeData);

                return Content(lsNode.ToJson());
            }
            catch (Exception e) {
                return null;
            }
        }

记录下自己处理另一文本的操作

[HttpPost]
        [HandlerAjaxOnly]
        public ActionResult jiexiWenBenXian(string FileName, string XianName, string[] SelectXianXYZ)
        {
            try
            {
                //string strFilePath = "E:/Desdatlab/CoteWebView/Content/Base/" + FileName;
                string strFilePath = "F:/bakBS/Desdatlab/CoteWebView/Content/Base/" + FileName;
                List<string> listLines = new List<string>();
                int jiequQuJian = 1;
                int dianJieQu = 1;
                int kaishiJieQu = 1;
                string sStuName = string.Empty;
                FileStream fs = new FileStream(strFilePath, FileMode.Open);
                StreamReader reader = new StreamReader(fs, UnicodeEncoding.GetEncoding("GB2312"));
                string[] tmpDataInfo;
                while ((sStuName = reader.ReadLine()) != null)
                {
                    if (sStuName.Contains("      FREQUENCY =  "))
                    {
                        jiequQuJian = 0;
                        listLines.Add(sStuName);
                    }
                    else if (sStuName.Contains("F O R C E S   I N   B A R"))
                    {
                        break;
                    }
                    if (jiequQuJian == 0)
                    {
                        if (kaishiJieQu == 0) {
                            if (dianJieQu == 0)
                            {
                                string tmpList = string.Empty;
                                tmpList = new System.Text.RegularExpressions.Regex("[\\s]+").Replace(sStuName, " ");
                                tmpDataInfo = tmpList.Split(' ');
                                if (tmpDataInfo[1].ToString() == XianName && tmpDataInfo[0].ToString() == "0")
                                {
                                    listLines.Add(sStuName);
                                    dianJieQu = 1;
                                    jiequQuJian = 1;
                                    kaishiJieQu = 1;
                                }
                                else
                                {
                                    continue;
                                }

                            }
                            if (sStuName.Contains("      POINT ID.   TYPE"))
                            {
                                dianJieQu = 0;
                            }
                        }
                        if (sStuName.Contains("A C C E L E R A T I O N"))
                        {
                            kaishiJieQu = 0;
                        }
                    }
                }

                //X轴的值
                string tmpXData = "";
                for (var i = 0; i < listLines.Count; i++) {
                    if (i == 0)
                    {
                        listLines[i] = new System.Text.RegularExpressions.Regex("[\\s]+").Replace(listLines[i], " ");
                        listLines[i + 1] = new System.Text.RegularExpressions.Regex("[\\s]+").Replace(listLines[i + 1], " ");
                        string[] tmpXXPoint = listLines[i].Split(' ');
                        string[] tmpXYPoint = listLines[i + 1].Split(' ');
                        tmpXData = "[" + tmpXXPoint[3].ToString() + "," + tmpXYPoint[3].ToString() + "]";
                        ++i;
                    }
                    else {
                        if (i == (listLines.Count-1))
                        {
                            continue;
                        }
                        else {
                            listLines[i] = new System.Text.RegularExpressions.Regex("[\\s]+").Replace(listLines[i], " ");
                            listLines[i + 1] = new System.Text.RegularExpressions.Regex("[\\s]+").Replace(listLines[i + 1], " ");
                            string[] tmpXXPoint = listLines[i].Split(' ');
                            string[] tmpXYPoint = listLines[i + 1].Split(' ');
                            tmpXData = tmpXData + ",[" + tmpXXPoint[3].ToString() + "," + tmpXYPoint[3].ToString() + "]";
                            ++i;
                        }
                    }
                }
                //Y轴的值
                string tmpYData = "";
                for (var i = 0; i < listLines.Count; i++)
                {
                    if (i == 0)
                    {
                        listLines[i] = new System.Text.RegularExpressions.Regex("[\\s]+").Replace(listLines[i], " ");
                        listLines[i + 1] = new System.Text.RegularExpressions.Regex("[\\s]+").Replace(listLines[i + 1], " ");
                        string[] tmpXXPoint = listLines[i].Split(' ');
                        string[] tmpXYPoint = listLines[i + 1].Split(' ');
                        tmpYData = "[" + tmpXXPoint[3].ToString() + "," + tmpXYPoint[4].ToString() + "]";
                        ++i;
                    }
                    else
                    {
                        if (i != (listLines.Count - 1))
                        {
                            listLines[i] = new System.Text.RegularExpressions.Regex("[\\s]+").Replace(listLines[i], " ");
                            listLines[i + 1] = new System.Text.RegularExpressions.Regex("[\\s]+").Replace(listLines[i + 1], " ");
                            string[] tmpXXPoint = listLines[i].Split(' ');
                            string[] tmpXYPoint = listLines[i + 1].Split(' ');
                            tmpYData = tmpYData + ",[" + tmpXXPoint[3].ToString() + "," + tmpXYPoint[3].ToString() + "]";
                            ++i;
                        }
                        else {
                            continue;
                        }
                    }
                }

                //Z轴的值
                string tmpZData = "";
                for (var i = 0; i < listLines.Count; i++)
                {
                    if (i == 0)
                    {
                        listLines[i] = new System.Text.RegularExpressions.Regex("[\\s]+").Replace(listLines[i], " ");
                        listLines[i + 1] = new System.Text.RegularExpressions.Regex("[\\s]+").Replace(listLines[i + 1], " ");
                        string[] tmpXXPoint = listLines[i].Split(' ');
                        string[] tmpXYPoint = listLines[i + 1].Split(' ');
                        tmpZData = "[" + tmpXXPoint[3].ToString() + "," + tmpXYPoint[4].ToString() + "]";
                        ++i;
                    }
                    else
                    {
                        if (i != (listLines.Count - 1))
                        {
                            listLines[i] = new System.Text.RegularExpressions.Regex("[\\s]+").Replace(listLines[i], " ");
                            listLines[i + 1] = new System.Text.RegularExpressions.Regex("[\\s]+").Replace(listLines[i + 1], " ");
                            string[] tmpXXPoint = listLines[i].Split(' ');
                            string[] tmpXYPoint = listLines[i + 1].Split(' ');
                            tmpZData = tmpZData + ",[" + tmpXXPoint[3].ToString() + "," + tmpXYPoint[3].ToString() + "]";
                            ++i;
                        }
                        else {
                            continue;
                        }
                    }
                }

                string DataInfoXYZ = "";
                if (SelectXianXYZ.Length == 3) {
                    DataInfoXYZ = "[{name:'" + XianName + SelectXianXYZ[0] + "',data: [" + tmpXData + "]}" + ",{name:'" + XianName + SelectXianXYZ[1] + "',data:[ " + tmpYData + "]}" + ",{name:'" + XianName + SelectXianXYZ[2] + "',data: [" + tmpZData + "]}]";
                }
                else if (SelectXianXYZ.Length == 1) {
                    if (SelectXianXYZ[0].ToString() == "X")
                    {
                        DataInfoXYZ = "[{name:'" + XianName + SelectXianXYZ[0] + "',data: [" + tmpXData + "]}]";
                    }
                    else if (SelectXianXYZ[0].ToString() == "Y")
                    {
                        DataInfoXYZ = "[{name:'" + XianName + SelectXianXYZ[0] + "',data: [" + tmpYData + "]}]";
                    }
                    else if (SelectXianXYZ[0].ToString() == "Z")
                    {
                        DataInfoXYZ = "[{name:'" + XianName + SelectXianXYZ[0] + "',data: [" + tmpZData + "]}]";
                    }
                }
                else if (SelectXianXYZ.Length == 2) {
                    for (var i = 0; i < SelectXianXYZ.Length; i++) {
                        if (i == 0)
                        {
                            if (SelectXianXYZ[i].ToString() == "X")
                            {
                                DataInfoXYZ = "[{name:'" + XianName + SelectXianXYZ[0] + "',data: [" + tmpXData + "]}";
                            }
                            else if (SelectXianXYZ[i].ToString() == "Y")
                            {
                                DataInfoXYZ = "[{name:'" + XianName + SelectXianXYZ[0] + "',data: [" + tmpYData + "]}";
                            }
                            else if (SelectXianXYZ[i].ToString() == "Z")
                            {
                                DataInfoXYZ = "[{name:'" + XianName + SelectXianXYZ[0] + "',data: [" + tmpZData + "]}";
                            }
                        }
                        else {
                            if (SelectXianXYZ[i].ToString() == "X")
                            {
                                DataInfoXYZ = DataInfoXYZ + ",{name:'" + XianName + SelectXianXYZ[0] + "',data: [" + tmpXData + "]}]";
                            }
                            else if (SelectXianXYZ[i].ToString() == "Y")
                            {
                                DataInfoXYZ = DataInfoXYZ + ",{name:'" + XianName + SelectXianXYZ[0] + "',data: [" + tmpYData + "]}]";
                            }
                            else if (SelectXianXYZ[i].ToString() == "Z")
                            {
                                DataInfoXYZ = DataInfoXYZ + ",{name:'" + XianName + SelectXianXYZ[0] + "',data: [" + tmpZData + "]}]";
                            }
                        }
                    }
                }




                List<object> lsNode = new List<object>();
                var zTreeData = new
                {
                    data = DataInfoXYZ
                };
                lsNode.Add(zTreeData);
                fs.Close();
                return Content(lsNode.ToJson());
            }
            catch (Exception e) {
                return null;
            }
        }

猜你喜欢

转载自blog.csdn.net/lxysoid/article/details/78936993