基于django的实验室网站管理平台设计与实现(四)

八、新闻动态模块
新闻动态模块主要用于实现实验室相关的新闻动态信息,主要包括行业新闻、学院新闻、通知公告等菜单,其业务模块图如下:。

1.模型设计

from django.db import models
from DjangoUeditor.models import UEditorField
import django.utils.timezone as timezone
import time
from loginApp.models import *

Create your models here.

m_y = (time.strftime("%y"))
m_m = (time.strftime("%m"))

Create your models here.

(六) 新闻类型表(XWLXB)

class XWLXB(models.Model):
XWLXBH = models.CharField(‘新闻类型编号’,max_length=2,unique=True)
XWLXMC = models.CharField(‘新闻类型名称’,max_length=50)
XH = models.IntegerField(‘序号’,default=0)
SYZT = models.IntegerField(‘使用状态’,default=0)
CJSJ = models.DateTimeField(‘创建时间’,default = timezone.now)
class Meta:
verbose_name = ‘新闻类型维护’
verbose_name_plural = verbose_name
ordering = ("-CJSJ",)
def str(self):
return self.XWLXMC

#(九)新闻信息表(XWXXB)
class XWXXB(models.Model):
XWBH = models.CharField(‘新闻编号’,max_length=50,unique=True)
XWLXBH = models.ForeignKey(‘XWLXB’,on_delete=models.CASCADE,verbose_name=‘新闻类型编号’)
XWBT = models.CharField(‘新闻标题’,max_length=100)
XWMS = UEditorField(u’内容’,default=’’,width=1000,height=300,imagePath=‘news/images/’+m_y+’/’+m_m+’/’,
filePath=‘news/files/’+m_y+’/’+m_m+’/’,upload_settings={‘imageMaxSizing’:1024000},)
BMBH = models.ForeignKey(‘loginApp.BMXXB’,on_delete=models.CASCADE,verbose_name=‘部门编号’)
VIEWS = models.PositiveIntegerField(‘访问量’,default=0)
FBRR = models.ForeignKey(‘loginApp.RYXXB’,on_delete=models.CASCADE,verbose_name=‘发布人员’)
CJSJ = models.DateTimeField(‘创建时间’,default = timezone.now)
class Meta:
verbose_name = ‘新闻信息维护’
verbose_name_plural = verbose_name
ordering = ("-CJSJ",)
def str(self):
return self.XWBT

2.后台管理设计
from django.contrib import admin
from .models import *

Register your models here.

class XWXXBAdmin(admin.ModelAdmin):
style_fields = {‘XWMS’: ‘ueditor’}

admin.site.register(XWXXB,XWXXBAdmin)
admin.site.register(XWLXB)
3.视图设计

from django.shortcuts import render
from .models import XWXXB,XWLXB
from django.core.paginator import Paginator
from django.shortcuts import get_object_or_404
from pyquery import PyQuery as pq

def news(request,newName):
# 解析请求的新闻类型
xwlxs = XWLXB.objects.all().order_by(’-XH’)
submenu = newName
strname=’’
print(newName)
strname = newName
xwlxbh = XWLXB.objects.get(XWLXBH=strname).XWLXBH
xwlxmc = XWLXB.objects.get(XWLXBH=strname).XWLXMC
newList = XWXXB.objects.all().filter(XWLXBH=xwlxbh).order_by(’-CJSJ’)
for xwxx in newList:
html = pq(xwxx.XWMS) # 使用pq方法解析html内容
xwxx.mytxt = pq(html)(‘p’).text() # 截取html段落文字
# 分页
p = Paginator(newList, 5)
if p.num_pages <= 1:
pageData = ‘’
else:
page = int(request.GET.get(‘page’, 1))
newList = p.page(page)
left = []
right = []
left_has_more = False
right_has_more = False
first = False
last = False
total_pages = p.num_pages
page_range = p.page_range
if page == 1:
right = page_range[page:page + 2]
print(total_pages)
if right[-1] < total_pages - 1:
right_has_more = True
if right[-1] < total_pages:
last = True
elif page == total_pages:
left = page_range[(page - 3) if (page - 3) > 0 else 0:page - 1]
if left[0] > 2:
left_has_more = True
if left[0] > 1:
first = True
else:
left = page_range[(page - 3) if (page - 3) > 0 else 0:page - 1]
right = page_range[page:page + 2]
if left[0] > 2:
left_has_more = True
if left[0] > 1:
first = True
if right[-1] < total_pages - 1:
right_has_more = True
if right[-1] < total_pages:
last = True
pageData = {
‘left’: left,
‘right’: right,
‘left_has_more’: left_has_more,
‘right_has_more’: right_has_more,
‘first’: first,
‘last’: last,
‘total_pages’: total_pages,
‘page’: page,
}
# print(xwlxs)
# print(newList)
return render(
request, ‘newList.html’, {
‘active_menu’: ‘news’,
‘sub_menu’: submenu,
‘xwlxmc’: xwlxmc,
‘xwlxs’:xwlxs,
‘newList’: newList,
‘pageData’: pageData,
})

def newDetail(request, id):
xwlxs = XWLXB.objects.all().order_by(’-XH’)
# print(strname)
# xwlxbh = XWLXB.objects.get(XWLXBH=strname).XWLXBH
# print(xwlxbh)
# print(id)
mynew = get_object_or_404(XWXXB, id=id)
mynew.VIEWS += 1
mynew.save()
print(mynew)
return render(request, ‘newDetail.html’, {
‘active_menu’: ‘news’,
# ‘xwlxmc’: xwlxmc,
‘xwlxs’:xwlxs,
‘mynew’: mynew,
})
4.访问路由设计
from django.urls import path
from . import views

app_name = ‘newsApp’

urlpatterns = [
path(‘news/str:newName/’, views.news, name=‘news’),#新闻列表
path(‘newDetail/int:id/’, views.newDetail, name=‘newDetail’),#新闻详情
]
5.新闻信息列表模板设计

{% extends “base.html” %}
{% load static %}
{% block title %}
{{xwlxmc}}
{% endblock %}
{% block content %}

{{xwlxmc}} {{xwlxmc}} {% for mynew in newList %} {% endfor %}
{{mynew.XWBT}} 【{{mynew.CJSJ|date:"Y-m-d"}}】

摘要:{{mynew.mytxt|truncatechars:"110"}}...

{% if pageData %}
  • {% if pageData.first %}
  • 1
  • {% endif %} {% if pageData.left %} {% if pageData.left_has_more %}
  • ...
  • {% endif %} {% for i in pageData.left %}
  • {{i}}
  • {% endfor %} {% endif %}
  • {{pageData.page}}
  • {% if pageData.right %} {% for i in pageData.right %}
  • {{i}}
  • {% endfor %} {% if pageData.right_has_more %}
  • ...
  • {% endif %} {% endif %} {% if pageData.last %}
  • {{pageData.total_pages}}
  • {% endif %}
{% endif %} {% endblock %}

6.新闻详情模板设计
{% extends “base.html” %}
{% load static %}
{% block title %}
{{mynew.XWLXBH}}
{% endblock %}
{% block content %}

    <!-- 侧边导航栏 -->
<div class="col-lg-3">
	<div class="model-title">
		{{mynew.XWLXBH}}
	</div>
	<div class="model-list">
		<ul class="list-group">
			{% for xwlx in xwlxs %}					
			<li class="list-group-item" id='{{xwlx.XWLXMC}}'>
				<a href="{% url 'newsApp:news' xwlx.XWLXBH %}">{{xwlx.XWLXMC}}</a>
			</li>
			{% endfor %}
		</ul>
	</div>
</div>
<div class="col-lg-9">
	<div class="model-details-product-title">
		{{mynew.XWBT}}
		<div class="model-foot">发布时间:{{mynew.CJSJ|date:"Y-m-d"}} &nbsp;&nbsp;
			浏览次数:{{mynew.VIEWS}}</div>
	</div>
	<div class="model-details">
		{{ mynew.XWMS | safe }}
	</div>
</div>
{% endblock %}

九、规章制度模块
规章制度模块主要用于显示有关规章制度信息,主要包括*规章制度、行业级规章制度、学院级规章制度、系级规章制度、规章制度详情等功能,其业务模块图如下:。

1.模型设计

from django.db import models
from DjangoUeditor.models import UEditorField
import django.utils.timezone as timezone
import time
from loginApp.models import *

Create your models here.

m_y = (time.strftime("%y"))
m_m = (time.strftime("%m"))

Create your models here.

#(四)规章制度类型表(GZZDLXB)
class GZZDLXB(models.Model):
GZZDLXBH = models.CharField(‘规章制度类型编号’,max_length=2,unique=True)
GZZDLXMC = models.CharField(‘规章制度类型名称’,max_length=50)
XH = models.IntegerField(‘序号’,default=0)
SYZT = models.IntegerField(‘使用状态’,default=0)
CJSJ = models.DateTimeField(‘创建时间’,default = timezone.now)
class Meta:
verbose_name = ‘规章制度类型维护’
verbose_name_plural = verbose_name
ordering = ("-CJSJ",)
def str(self):
return self.GZZDLXMC
#(四)规章制度类别表(GZZDLBB)
class GZZDLBB(models.Model):
GZZDLBBH = models.CharField(‘规章制度类别编号’,max_length=2,unique=True)
# GZZDLXBH = models.ForeignKey(‘GZZDLXB’,on_delete=models.CASCADE,verbose_name=‘规章制度类型编号’)
XH = models.IntegerField(‘序号’,default=0)
GZZDLXMC = models.CharField(‘规章制度类别名称’,max_length=50)
SYZT = models.IntegerField(‘使用状态’,default=0)
CJSJ = models.DateTimeField(‘创建时间’,default = timezone.now)
class Meta:
verbose_name = ‘规章制度类别维护’
verbose_name_plural = verbose_name
ordering = ("-CJSJ",)
def str(self):
return self.GZZDLXMC
#(九)规章制度信息表(GZZDXXB)
class GZZDXXB(models.Model):
GZZDBH = models.CharField(‘规章制度编号’,max_length=50,unique=True)
GZZDLXBH = models.ForeignKey(‘GZZDLXB’,on_delete=models.CASCADE,verbose_name=‘规章制度类型编号’)
GZZDLBBH = models.ForeignKey(‘GZZDLBB’,on_delete=models.CASCADE,verbose_name=‘规章制度类别编号’)
GZZDBT = models.CharField(‘规章制度标题’,max_length=100)
GZZDMS = UEditorField(u’内容’,default=’’,width=1000,height=300,imagePath=‘rules/images/’+m_y+’/’+m_m+’/’,
filePath=‘rules/files/’+m_y+’/’+m_m+’/’,upload_settings={‘imageMaxSizing’:1024000},)
BMBH = models.ForeignKey(‘loginApp.BMXXB’,on_delete=models.CASCADE,verbose_name=‘部门编号’)
VIEWS = models.PositiveIntegerField(‘访问量’,default=0)
FBRR = models.ForeignKey(‘loginApp.RYXXB’,on_delete=models.CASCADE,verbose_name=‘发布人员’)
CJSJ = models.DateTimeField(‘创建时间’,default = timezone.now)
class Meta:
verbose_name = ‘规章制度信息维护’
verbose_name_plural = verbose_name
ordering = ("-CJSJ",)
def str(self):
return self.GZZDBT

2.后台管理设计
from django.contrib import admin
from .models import *

Register your models here.

class GZZDXXBAdmin(admin.ModelAdmin):
style_fields = {‘GZZDMS’: ‘ueditor’}

admin.site.register(GZZDXXB,GZZDXXBAdmin)
admin.site.register(GZZDLXB)
admin.site.register(GZZDLBB)
3.视图设计

from django.shortcuts import render
from .models import *
from django.core.paginator import Paginator
from django.shortcuts import get_object_or_404
from pyquery import PyQuery as pq

def rules(request,newName):
# 解析请求的新闻类型
rulelxs = GZZDLXB.objects.all().order_by(’-XH’)
submenu = newName
strname=’’
# print(newName)
# if newName == ‘1’:
# strname = ‘01’
# elif newName == ‘2’:
# strname = ‘02’
# elif newName == ‘3’:
# strname = ‘03’
# else:
# strname = ‘09’
# print(strname)
strname = newName
gzzdlxbh = GZZDLXB.objects.get(GZZDLXBH=strname).GZZDLXBH
# print(gzzdlxbh)
gzzdlxmc = GZZDLXB.objects.get(GZZDLXBH=strname).GZZDLXMC
# print(rulelxmc)

ruleList = GZZDXXB.objects.all().filter(GZZDLXBH=gzzdlxbh).order_by('-CJSJ')
for rulexx in ruleList:
    html = pq(rulexx.GZZDMS)  # 使用pq方法解析html内容
    rulexx.mytxt = pq(html)('p').text()  # 截取html段落文字
# 分页
p = Paginator(ruleList, 5)
if p.num_pages <= 1:
    pageData = ''
else:
    page = int(request.GET.get('page', 1))
    ruleList = p.page(page)
    left = []
    right = []
    left_has_more = False
    right_has_more = False
    first = False
    last = False
    total_pages = p.num_pages
    page_range = p.page_range
    if page == 1:
        right = page_range[page:page + 2]
        print(total_pages)
        if right[-1] < total_pages - 1:
            right_has_more = True
        if right[-1] < total_pages:
            last = True
    elif page == total_pages:
        left = page_range[(page - 3) if (page - 3) > 0 else 0:page - 1]
        if left[0] > 2:
            left_has_more = True
        if left[0] > 1:
            first = True
    else:
        left = page_range[(page - 3) if (page - 3) > 0 else 0:page - 1]
        right = page_range[page:page + 2]
        if left[0] > 2:
            left_has_more = True
        if left[0] > 1:
            first = True
        if right[-1] < total_pages - 1:
            right_has_more = True
        if right[-1] < total_pages:
            last = True
    pageData = {
        'left': left,
        'right': right,
        'left_has_more': left_has_more,
        'right_has_more': right_has_more,
        'first': first,
        'last': last,
        'total_pages': total_pages,
        'page': page,
    }
print(rulelxs)
print(ruleList)
return render(
    request, 'rulesList.html', {
        'active_menu': 'rules',
        'sub_menu': submenu,
        'gzzdlxmc': gzzdlxmc,
        'rulelxs':rulelxs,
        'ruleList': ruleList,
        'pageData': pageData,
    })

def ruleDetail(request, id):
rulelxs = GZZDLXB.objects.all().order_by(’-XH’)

myrule = get_object_or_404(GZZDXXB, id=id)
myrule.VIEWS += 1
myrule.save()
print(myrule)
return render(request, 'ruleDetail.html', {
    'active_menu': 'rules',
    # 'rulelxmc': rulelxmc,
    'rulelxs':rulelxs,
    'myrule': myrule,
})

4.访问路由设计
from django.urls import path
from . import views

app_name = ‘rulesApp’

urlpatterns = [
path(‘rules/str:newName/’, views.rules, name=‘rules’),#实验室列表
path(‘ruleDetail/int:id/’, views.ruleDetail, name=‘ruleDetail’),#实验室详情
]
5.规章制度列表模板设计

{% extends “base.html” %}
{% load static %}

{% block title %}
{{gzzdlxmc}}
{% endblock %}

{% block content %}

{{gzzdlxmc}} {{gzzdlxmc}}
		{% for myrule in ruleList %}	
		<tr>
			<td>
			<div class="news-model">
				<a href="{% url 'rulesApp:ruleDetail' myrule.id %}"><b>{{myrule.GZZDBT}}</b></a>
				<span>【{{myrule.CJSJ|date:"Y-m-d"}}】</span>
				<p>
					<!-- 添加新闻简要说明 -->
					摘要:{{myrule.mytxt|truncatechars:"110"}}...
				</p>
			</div>
			</td>
		</tr>
		{% endfor %}
		 </table>
		{% if pageData %}
		<div class="paging">
			<ul id="pages" class="pagination">
				{% if pageData.first %}
				<li><a href="?page=1">1</a></li>
				{% endif %}
				{% if pageData.left %}
				{% if pageData.left_has_more %}
				<li><span>...</span></li>
				{% endif %}
				{% for i in pageData.left %}
				<li><a href="?page={{i}}">{{i}}</a></li>
				{% endfor %}
				{% endif %}
				<li class="active"><a href="?page={{pageData.page}}">
						{{pageData.page}}</a></li>
				{% if pageData.right %}
				{% for i in pageData.right %}
				<li><a href="?page={{i}}">{{i}}</a></li>
				{% endfor %}
				{% if pageData.right_has_more %}
				<li><span>...</span></li>
				{% endif %}
				{% endif %}
				{% if pageData.last %}
				<li><a href="?page={{pageData.total_pages}}">
						{{pageData.total_pages}}</a></li>
				{% endif %}
			</ul>
		</div>
		{% endif %}		  
	</div>
</div>
{% endblock %}

6.规章制度详情模板设计
{% extends “base.html” %}
{% load static %}
{% block title %}
{{myrule.GZZDLXBH}}
{% endblock %}
{% block content %}

    <!-- 侧边导航栏 -->
<div class="col-md-3">
	<div class="model-title">
		{{myrule.GZZDLXBH}}
	</div>
	<div class="model-list">
		<ul class="list-group">
			{% for rulelx in rulelxs %}					
			<li class="list-group-item" id='{{rulelx.GZZDLXMC}}'>
				<a href="{% url 'rulesApp:rules' rulelx.GZZDLXBH  %}">{{rulelx.GZZDLXMC}}</a>
			</li>
			{% endfor %}
		</ul>
	</div>
</div>
<div class="col-md-9">
	<div class="model-details-product-title">
		{{myrule.GZZDBT}}
		<div class="model-foot">发布时间:{{myrule.CJSJ|date:"Y-m-d"}} &nbsp;&nbsp;
			浏览次数:{{myrule.VIEWS}}</div>
	</div>
	<div class="model-details">
		{{ myrule.GZZDMS | safe }}
	</div>
</div>
{% endblock %}

十、下载专区模块
规章制度模块主要用于显示有关规章制度信息,主要包括*规章制度、行业级规章制度、学院级规章制度、系级规章制度、规章制度详情等功能,其业务模块图如下:。

1.模型设计

from django.db import models
from DjangoUeditor.models import UEditorField
import django.utils.timezone as timezone
import time
from loginApp.models import *

Create your models here.

m_y = (time.strftime("%y"))
m_m = (time.strftime("%m"))

Create your models here.

(七) 下载类型表(XZLXB)

class XZLXB(models.Model):
XZLXBH = models.CharField(‘下载类型编号’,max_length=2,unique=True)
XZLXMC = models.CharField(‘下载类型名称’,max_length=50)
XH = models.IntegerField(‘序号’,default=0)
SYZT = models.IntegerField(‘使用状态’,default=0)
CJSJ = models.DateTimeField(‘创建时间’,default = timezone.now)

class Meta:	
	verbose_name = '下载类型维护'
	verbose_name_plural = verbose_name
	ordering = ("-CJSJ",)
	
def __str__(self):
	return self.XZLXMC

#(十三) 下载信息表(XZXXB)
class XZXXB(models.Model):
XZBH = models.CharField(‘下载编号’,max_length=50,unique=True)
XZLXBH = models.ForeignKey(‘XZLXB’,on_delete=models.CASCADE,verbose_name=‘下载类型编号’)
XZMC = models.CharField(‘资料名称’,max_length=50)
file = models.FileField(upload_to=‘Service/’,
blank=True,
verbose_name=‘文件资料’)
VIEWS = models.PositiveIntegerField(‘点击量’,default=0)
FBRR = models.ForeignKey(‘loginApp.RYXXB’,on_delete=models.CASCADE,verbose_name=‘发布人员’)
CJSJ = models.DateTimeField(‘创建时间’,default = timezone.now)

class Meta:	
	verbose_name = '资料'
	verbose_name_plural = verbose_name
	ordering = ("-CJSJ",)
	
def __str__(self):
	return self.XZMC

2.后台管理设计
from django.contrib import admin
from .models import *

Register your models here.

admin.site.register(XZLXB)
admin.site.register(XZXXB)
3.视图设计

from django.shortcuts import render
from django.shortcuts import HttpResponse
from .models import *
from django.core.paginator import Paginator

from django.shortcuts import get_object_or_404
from django.http import StreamingHttpResponse
import os

Create your views here.

def read_file(file_name, size): #分批读取文件
with open(file_name, mode=‘rb’) as fp:
while True:
c = fp.read(size)
if c:
yield c
else:
break

def downloads(request,newName):
submenu = ‘download’
downloadlxs = XZLXB.objects.all().order_by(’-XH’)
submenu = newName
strname=’’
strname = newName
xzlxbh = XZLXB.objects.get(XZLXBH=strname).XZLXBH
# print(xzlxbh)
xzlxmc = XZLXB.objects.get(XZLXBH=strname).XZLXMC

docList = XZXXB.objects.all().filter(XZLXBH=xzlxbh).order_by('-CJSJ')
print(docList)
# ruleList = GZZDXXB.objects.all().filter(GZZDLXBH=gzzdlxbh).order_by('-CJSJ')
p = Paginator(docList, 5)
if p.num_pages <= 1:
    pageData = ''
else:
    page = int(request.GET.get('page', 1))
    newList = p.page(page)
    left = []
    right = []
    left_has_more = False
    right_has_more = False
    first = False
    last = False
    total_pages = p.num_pages
    page_range = p.page_range
    if page == 1:
        right = page_range[page:page + 2]
        print(total_pages)
        if right[-1] < total_pages - 1:
            right_has_more = True
        if right[-1] < total_pages:
            last = True
    elif page == total_pages:
        left = page_range[(page - 3) if (page - 3) > 0 else 0:page - 1]
        if left[0] > 2:
            left_has_more = True
        if left[0] > 1:
            first = True
    else:
        left = page_range[(page - 3) if (page - 3) > 0 else 0:page - 1]
        right = page_range[page:page + 2]
        if left[0] > 2:
            left_has_more = True
        if left[0] > 1:
            first = True
        if right[-1] < total_pages - 1:
            right_has_more = True
        if right[-1] < total_pages:
            last = True
    pageData = {
        'left': left,
        'right': right,
        'left_has_more': left_has_more,
        'right_has_more': right_has_more,
        'first': first,
        'last': last,
        'total_pages': total_pages,
        'page': page,
    }
return render(
    request, 'docList.html', {
        'active_menu': 'download',
        'sub_menu': submenu,
        'xzlxmc': xzlxmc,
        'downloadlxs':downloadlxs,
        'docList': docList,
        'pageData': pageData,
    })

def getDoc(request, id):
doc = get_object_or_404(XZXXB, id=id)
update_to, filename = str(doc.file).split(’/’)
filepath = ‘%s/media/%s/%s’ % (os.getcwd(), update_to, filename)
response = StreamingHttpResponse(read_file(filepath, 512))
response[‘Content-Type’] = ‘application/octet-stream’
response[‘Content-Disposition’] = ‘attachment;filename="{}"’.format(
filename)
return response

4.访问路由设计
from django.urls import path
from . import views

app_name = ‘downloadApp’

urlpatterns = [
path(‘downloads/str:newName/’, views.downloads, name=‘downloads’), # 资料下载页面
path(‘getDoc/int:id/’, views.getDoc, name=‘getDoc’),#单项资料下载
]
5.文档下载模板设计

{% extends “base.html” %}
{% load static %}

{% block title %}
资料下载
{% endblock %}

{% block content %}

{{downloadlx.XZLXMC}} 资料列表 {% for doc in docList %} 基于django的实验室网站管理平台设计与实现(四){{doc.XZMC}}  路径: {{doc.file.url}}  下载量:{{doc.VIEWS}} 【{{doc.CJSJ|date:"Y-m-d"}}】 {% endfor %}
            {% if pageData %}
            <div class="paging">
                <ul id="pages" class="pagination">
                    {% if pageData.first %}
                    <li><a href="?page=1">1</a></li>
                    {% endif %}
                    {% if pageData.left %}
                    {% if pageData.left_has_more %}
                    <li><span>...</span></li>
                    {% endif %}
                    {% for i in pageData.left %}
                    <li><a href="?page={{i}}">{{i}}</a></li>
                    {% endfor %}
                    {% endif %}
                    <li class="active"><a href="?page={{pageData.page}}">
                            {{pageData.page}}</a></li>
                    {% if pageData.right %}
                    {% for i in pageData.right %}
                    <li><a href="?page={{i}}">{{i}}</a></li>
                    {% endfor %}
                    {% if pageData.right_has_more %}
                    <li><span>...</span></li>
                    {% endif %}
                    {% endif %}
                    {% if pageData.last %}
                    <li><a href="?page={{pageData.total_pages}}">
                            {{pageData.total_pages}}</a></li>
                    {% endif %}
                </ul>
            </div>
            {% endif %}
        </div>
    </div>
</div>
{% endblock %}
上一篇:SpringBoot SpringSecurity4整合,灵活权限配置,弃用注解方式.


下一篇:linux 下 shell脚本报错:-bash: ./build.sh: /bin/sh^M: bad interpreter: No such file or directory