dever há 6 anos atrás
pai
commit
ed7f6b0aaf

+ 8 - 0
README.rst

@@ -0,0 +1,8 @@
+# 测试app
+
+安装
+
+python install.py
+
+前台:python front.py
+后台:python admin.py

+ 9 - 0
admin.py

@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+"""
+    demeter web
+    name:admin.py
+"""
+from demeter.core import *
+
+if __name__ == "__main__":
+	Demeter.webInit('admin')

+ 1 - 0
admin/__init__.py

@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-

+ 5 - 0
admin/main.py

@@ -0,0 +1,5 @@
+# -*- coding: utf-8 -*-
+from demeter.web import *
+import demeter.admin.page as admin_page
+import admin.page
+Web.start(application=[admin.page,admin_page])

+ 1 - 0
admin/page/__init__.py

@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-

+ 2 - 0
admin/page/__load__.py

@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+from demeter.admin.page.__load__ import *

+ 129 - 0
admin/page/site.py

@@ -0,0 +1,129 @@
+# -*- coding: utf-8 -*-
+"""
+    demeter web page
+    name:site.py 站点相关
+    author:rabin
+"""
+from .__load__ import *
+
+class site_path(Load):
+	@Web.auth
+	@Web.setting
+	def get(self):
+		self.set(
+			name = u'站点管理'
+			,path = '/site/site'
+			,width = '600'
+			,height = '600'
+			,search = (('label-1','workdate-time-start','workdate-time-end','name-input-mlike'), (u'日期范围',u'开始时间',u'截止时间',u'站点名称'))
+			,thead = (u'站点key', u'站点名称', u'快捷功能', u'站点token', u'更新时间')
+			,tbody = ('key','name','func', 'token', 'cdate')
+			,state = True
+		)
+		menu = (
+			{'name':'转换文件列表', 'url':'/site/convert'}
+			,
+			)
+		self.list('site')
+		if self.data['list']:
+			for key, value in enumerate(self.data['list']):
+				id = str(value['id'])
+				param = '?search_site_id-select-=' + id
+				self.data['list'][key]['func'] = ''
+				for i in menu:
+					self.data['list'][key]['func'] = self.data['list'][key]['func'] + '<a href="'+i['url']+''+param+'">'+i['name']+'</a>&nbsp;&nbsp;&nbsp;&nbsp;'
+		self.show('list')
+
+class site_update_path(Load):
+	@Web.auth
+	@Web.setting
+	def get(self):
+		self.set(
+			path = '/site/site'
+			,label = (u'站点名称',u'站点网址',u'站点key',u'站点token')
+			,update = ('name-input-required','link-input-required','key-input-required','token-input-required')
+		)
+		self.one('site')
+		self.show('update')
+	@Web.auth
+	@Web.setting
+	def post(self):
+		self.update('site')
+	@Web.auth
+	@Web.setting
+	def delete(self):
+		self.drop('site')
+
+class convert_path(Load):
+	@Web.auth
+	@Web.setting
+	def get(self):
+		self.set(
+			name = u'转换的文件'
+			,path = '/site/convert'
+			,width = '600'
+			,height = '600'
+			,search = (('label-1','cdate-time-start','cdate-time-end','site_id-select-','name-input-mlike'), (u'日期范围',u'开始时间',u'截止时间',u'选择站点',u'文件名'))
+			,thead = (u'所属站点', u'文件名', u'访问路径', u'状态', u'更新时间')
+			,tbody = ('site', 'name', 'url', 'status', 'cdate')
+			,state = True
+		)
+		self.data['common']['search_site_id-select-'] = self.service('common').list('site')
+		self.list('convert')
+		status = {}
+		status[1] = '待机'
+		status[2] = '转换中'
+		status[3] = '转换完成'
+		status[4] = '转换失败'
+		if self.data['list']:
+			for key, value in enumerate(self.data['list']):
+				site = self.service('common').one('site', id=value['site_id'])
+				self.data['list'][key]['site'] = site['name']
+				if value['status'] == 3:
+					self.data['list'][key]['url'] = '<a href="'+str(value['url'])+'" target="_blank">[点此访问]</a>'
+				else:
+					self.data['list'][key]['url'] = '无法访问'
+				self.data['list'][key]['status'] = status[value['status']]
+
+		self.show('list')
+
+class convert_update_path(Load):
+	@Web.auth
+	@Web.setting
+	def get(self):
+		status = [
+			{'id':'1', 'name': '待机'},
+		]
+		self.set(
+			path = '/site/convert'
+			,label = (u'所属站点', u'源文件路径')
+			,update = ('site_id-select-required', 'file-input-required', 'status-select-required')
+			,update_site_id = self.service('common').list('site')
+			,update_status = status
+		)
+		self.one('convert')
+		self.show('update')
+	@Web.auth
+	@Web.setting
+	def post(self):
+		model = Demeter.model('site')
+		model.id = self.data['update']['site_id']
+		site = model.select(type='fetchone')
+
+
+		info = self.service('convert').getFile(site['key'], self.data['update']['file'])
+		self.data['update']['name'] = info['name']
+		self.data['update']['key'] = info['key']
+		self.data['update']['ext'] = info['ext']
+
+		self.data['update']['local'] = info['local']		
+		self.data['update']['path'] = info['path']
+		self.data['update']['pdf'] = info['pdf']
+		self.data['update']['html'] = info['html']
+		self.data['update']['url'] = info['url']
+
+		self.update('convert')
+	@Web.auth
+	@Web.setting
+	def delete(self):
+		self.drop('convert')

+ 61 - 0
conf/dev.conf

@@ -0,0 +1,61 @@
+[base]
+;开发环境配置
+[setting]
+name				= 文档转换系统
+site				= http://doc.dever.cc/
+copyright			= 2018 dever.cc v1.0.0
+;打印路由表
+route				= True
+
+[db]
+rdb					= mysql
+
+[mysql]
+host				= 0.0.0.0
+port				= 3309
+username			= root
+password			= 123456
+dbname				= office_convert
+prefix				= oc
+charset				= utf8
+;允许自动建表
+create				= True
+
+[redis]
+host				= 0.0.0.0
+port				= 6379
+name				= office_file
+prefix				= convert_
+
+;定义一些tornado的配置,可为空
+[tornado]
+
+;后台配置
+[admin]
+port				= 8087
+debug				= True
+;请求的buffersize
+max_buffer_size		= 210763776
+;子进程
+process				= 0
+;定义后台父级菜单
+menu_parent			= 站点设置:&#xe62e;
+;定义后台子级菜单
+menu_child			= 站点管理:/site/site,转换文件列表:/site/convert
+
+;cookie
+cookie_secret       = 61oETzKXQAGaYekL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=
+login_url           = /user/login
+;是否使用安全cookie
+xsrf_cookies        = True
+
+;前台配置
+[front]
+port				= 8088
+debug				= True
+;请求的buffersize
+max_buffer_size		= 210763776
+;子进程
+process				= 0
+;支持手机版
+mobile				= True

+ 60 - 0
conf/env.conf

@@ -0,0 +1,60 @@
+[base]
+;线上环境配置,请设置环境变量DEMETER_CONF = env
+[setting]
+name				= 抢购平台
+site				= http://www.dever.cc/
+copyright			= 2017 dever.cc v1.0.0
+phantomjs			= http://192.168.15.10:8910/
+
+[db]
+rdb					= mysql
+
+[mysql]
+host				= 0.0.0.0
+port				= 3309
+username			= root
+password			= 123456
+dbname				= office_convert
+prefix				= oc
+charset				= utf8
+;允许自动建表
+create				= True
+
+[redis]
+host				= 0.0.0.0
+port				= 6379
+name				= office_file
+prefix				= convert_
+
+;定义一些tornado的配置,可为空
+[tornado]
+
+;后台配置
+[admin]
+port				= 8087
+debug				= True
+;请求的buffersize
+max_buffer_size		= 210763776
+;子进程
+process				= 0
+;定义后台父级菜单
+menu_parent			= 站点设置:&#xe62e;
+;定义后台子级菜单
+menu_child			= 站点管理:/site/site,转换文件列表:/site/convert
+
+;cookie
+cookie_secret		= 61oETzKXQAGaYekL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=
+login_url			= /user/login
+;是否使用安全cookie
+xsrf_cookies		= True
+
+;前台配置
+[front]
+port				= 8088
+debug				= True
+;请求的buffersize
+max_buffer_size		= 210763776
+;子进程
+process				= 0
+;支持手机版
+mobile				= True

+ 81 - 0
convert.py

@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+import sys
+sys.getdefaultencoding()
+reload(sys)
+sys.setdefaultencoding('UTF-8')
+from demeter.core import *
+import os
+import os.path
+import requests
+import shutil
+
+# 测试命令行传参 python convert.py -f file.doc
+param = {}
+param['file'] = 'f'
+Demeter.getopt(param)
+
+def command(file):
+	id = int(file)
+	model = Demeter.model('convert')
+	model.id = id
+	info = convert.select(type='fetchone')
+
+	status = True
+	if info['status'] == 1 or info['status'] == 4:
+		status = False
+
+	if info and status == False:
+		model.id = id
+		update = {}
+		update['status'] = 2
+		#model.update(update)
+
+		if not File.exists(info['local']):
+			if 'http' in info['file']:
+				r = requests.get(info['file'], stream=True)
+				with open(info['local'], 'wb') as up:
+					for chunk in r.iter_content(chunk_size=1024):
+						if chunk:
+							up.write(chunk)
+
+			else:
+				shutil.copyfile(info['file'], info['local'])
+
+		if not File.exists(info['html']):
+			convert = 'cd ' + info['path'] + ' && '
+			convert = convert + 'libreoffice  --invisible --convert-to pdf ' + info['local']
+			convert = convert + ' && '
+			convert = convert + 'pdf2htmlEX --zoom 1.3 --no-drm 1 --split-pages 1 '
+			convert = convert + '--embed-css 1  --embed-javascript 0 --embed-image 0 --embed-font 1 '
+			convert = convert + '--embed-external-font 0 --dest-dir '+info['path']+' --page-filename %d.page ' + info['pdf']
+
+			print convert
+			return
+			Shell.popen(convert)
+			if File.exists(info['html']):
+				# 获取有多少页
+				page = total(info['path'])
+				model.id = id
+				update = {}
+				update['page'] = page
+				update['status'] = 3
+				model.update(update)
+				return
+
+		model.id = id
+		update = {}
+		update['status'] = 4
+		model.update(update)
+		
+
+
+def total(path):
+	page = 0
+	for parentdir,dirname,filenames in os.walk(path):  
+		for filename in filenames:
+			if os.path.splitext(filename)[1]=='.page':
+				page = page + 1
+	return page
+
+file = Demeter.option['file']
+command(file)

+ 30 - 0
cron.py

@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+import time
+from demeter.core import *
+'''
+from gevent import monkey; monkey.patch_socket()
+import gevent
+'''
+timeSleep = 50
+
+def command(file):
+	return 'python '+File.path()+'convert.py -f ' + file
+
+# 文档转换
+def convert():
+	r = Demeter.redis()
+	c = Demeter.config['redis']
+	i = 0
+	while 1:
+		file = r.lpop(c['name'])
+		if file:
+			Shell.popen(command(file))
+		i++
+		if i >= 10
+			time.sleep(timeSleep)
+			i = 0
+
+def handle():
+	convert()
+
+handle()

+ 9 - 0
front.py

@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+"""
+    demeter web
+    name:front.py
+"""
+from demeter.core import *
+
+if __name__ == "__main__":
+	Demeter.webInit('front')

+ 1 - 0
front/__init__.py

@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-

+ 1 - 0
front/api/__init__.py

@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-

+ 39 - 0
front/api/__load__.py

@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+"""
+    demeter load
+    author:rabin
+"""
+from demeter.web import *
+
+#可以在此定义一些核心类库
+
+# 这个是基类
+class Load(Base):
+	# user是权限
+	KEYS = ('user',)
+
+	def setting(self):
+		self.user()
+
+	def user(self):
+		ajax = self.input('ajax')
+		if ajax:
+			self.data['ajax'] = True
+		else:
+			self.data['ajax'] = False
+		self.data['auth'] = True
+
+		# 权限判断
+		if 'user' in self.data['setting'] and self.data['setting']['user'] > 0:
+			self.data['setting']['userInfo'] = self.service('common').one('farm_user', id=self.data['setting']['user'])
+		else:
+			# 没有权限
+			return
+
+		if '/' in self.request.uri:
+			temp = self.request.uri.split('/')
+			slen = len(temp)
+			if slen > 1 and temp[1]:
+				cur = temp[1]
+		self.data['setting']['cur'] = cur
+

+ 67 - 0
front/api/main.py

@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+"""
+    demeter web page
+    name:work.py
+    author:rabin
+"""
+from .__load__ import *
+
+# 请求转换 /main/convert
+class convert_path(Load):
+	@Web.setting
+	def get(self):
+		# 从get、post获取数据,默认值为1
+		key = int(self.input('site', 1))
+		token = self.input('token')
+		file = self.input('file')
+		site = Demeter.model('site')
+		site.key = key
+		data = {}
+		data['site'] = site.select(type='fetchone')
+
+		if not file:
+			self.out('错误的文件信息')
+
+		if not data['site']:
+			self.out('站点信息不存在')
+
+		if data['site']['token'] != token:
+			self.out('验证失败')
+
+		service = Demeter.service('convert')
+		data['file'] = service.update(data['site']['id'], key,  file)
+
+		# 推入到redis队列
+		if data['file']['status'] == 1:
+			redis = Demeter.redis()
+			config = Demeter.config['redis']
+			send = {}
+			#redis.rpush(config['name'], data['file']['id'])
+
+		self.out('yes', data)
+
+# 获取信息
+class get_path(Load):
+	@Web.setting
+	def get(self):
+		key = int(self.input('site', 1))
+		token = self.input('token')
+		file = self.input('file')
+		site = Demeter.model('site')
+		site.key = key
+		data = {}
+		data['site'] = site.select(type='fetchone')
+
+		if not file:
+			self.out('错误的文件信息')
+
+		if not data['site']:
+			self.out('站点信息不存在')
+
+		if data['site']['token'] != token:
+			self.out('验证失败')
+
+		service = Demeter.service('convert')
+		data['file'] = service.get(data['site']['id'], key,  file);
+
+		self.out('yes', data)

+ 4 - 0
front/main.py

@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+from demeter.web import *
+import front.api
+Web.start(application=[front.api,])

+ 24 - 0
install.py

@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+from demeter.core import *
+
+def manage():
+	model = Demeter.model('manage_admin')
+	model.id = 1
+	info = model.select(type='fetchone')
+	if not info:
+		model.role_id = 1
+		model.username = 'admin'
+		model.mobile = '15810090845'
+		model.password = '123456'
+		model.insert()
+
+	model = Demeter.model('manage_role')
+	model.id = 1
+	info = model.select(type='fetchone')
+	if not info:
+		model.name = u'管理员'
+		model.insert()
+
+manage()
+
+Demeter.echo('install success!')

+ 1 - 0
model/__init__.py

@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-

+ 7 - 0
model/__load__.py

@@ -0,0 +1,7 @@
+# -*- coding: utf-8 -*-
+"""
+    demeter database
+    name:__load__.py
+"""
+from demeter.model import *
+from demeter.core import *

+ 25 - 0
model/convert.py

@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+"""
+    demeter database
+    name:convert.py
+"""
+from .__load__ import *
+
+class Convert(Model):
+	__table__ = 'convert'
+	__comment__ = '转换表'
+	id = Fields(type='int', primaryKey=True, autoIncrement=True, comment='ID')
+	site_id = Fields(type='int', comment='所属站点')
+	name = Fields(type='varchar(200)', comment='文件名')
+	file = Fields(type='varchar(500)', comment='源文件路径')
+	key = Fields(type='varchar(100)', comment='文件key')
+	ext = Fields(type='varchar(20)', comment='后缀名')
+	local = Fields(type='varchar(200)', comment='本地地址')
+	pdf = Fields(type='varchar(200)', comment='本地pdf地址')
+	path = Fields(type='varchar(200)', comment='本地html目录')
+	html = Fields(type='varchar(200)', comment='本地html首页地址')
+	url = Fields(type='varchar(200)', comment='生成的html的url')
+	page = Fields(type='int', comment='页数')
+	state = Fields(type='boolean', default='True', comment='数据存在状态')
+	status = Fields(type='int', default='1', comment='转换状态1待机2转换中3转换完成4转换失败')
+	cdate = Fields(type='int', default='time', comment='创建时间')

+ 17 - 0
model/site.py

@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+"""
+    demeter database
+    name:site.py
+"""
+from .__load__ import *
+
+class Site(Model):
+	__table__ = 'site'
+	__comment__ = '站点主表'
+	id = Fields(type='int', primaryKey=True, autoIncrement=True, comment='站点ID')
+	name = Fields(type='varchar(50)', comment='站点名')
+	link = Fields(type='varchar(200)', comment='站点网址')
+	key = Fields(type='varchar(30)', comment='站点key')
+	token = Fields(type='varchar(300)', comment='授权token')
+	state = Fields(type='boolean', default='True', comment='数据存在状态')
+	cdate = Fields(type='int', default='time', comment='创建时间')

+ 15 - 0
opt.py

@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+"""
+    demeter web
+    name:front.py
+"""
+from demeter.core import *
+
+# 测试命令行传参 python opt.py -a act
+param = {}
+param['action'] = 'a'
+param['name'] = 'n'
+param['param'] = 'p'
+Demeter.getopt(param)
+
+Demeter.echo(Demeter.option['action'])

+ 6 - 0
runtime/__init__.py

@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter init
+    author:rabin
+"""

+ 1 - 0
runtime/mysql/convert

@@ -0,0 +1 @@
+[["status", 1], ["file", 1], ["state", 1], ["url", 1], ["site_id", 1], ["ext", 1], ["page", 1], ["cdate", 1], ["html", 1], ["key", 1], ["pdf", 1], ["path", 1], ["local", 1], ["id", 1], ["name", 1]]

+ 1 - 0
runtime/mysql/manage_admin

@@ -0,0 +1 @@
+[["username", 1], ["mobile", 1], ["cdate", 1], ["role_id", 1], ["state", 1], ["password", 1], ["id", 1]]

+ 1 - 0
runtime/mysql/manage_log

@@ -0,0 +1 @@
+[["cdate", 1], ["admin_id", 1], ["method", 1], ["state", 1], ["model", 1], ["data", 1], ["id", 1]]

+ 1 - 0
runtime/mysql/manage_role

@@ -0,0 +1 @@
+[["oper", 1], ["name", 1], ["top", 1], ["state", 1], ["auth", 1], ["cdate", 1], ["id", 1]]

+ 1 - 0
runtime/mysql/site

@@ -0,0 +1 @@
+[["name", 1], ["state", 1], ["cdate", 1], ["token", 1], ["link", 1], ["key", 1], ["id", 1]]

+ 7 - 0
service/__init__.py

@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    demeter init
+    author:rabin
+    实现具体的业务逻辑,前台、后台、接口都走这一套逻辑,此处可以直接生成接口
+"""

+ 119 - 0
service/convert.py

@@ -0,0 +1,119 @@
+# -*- coding: utf-8 -*-
+from demeter.core import *
+from datetime import *
+import uuid
+import requests
+import shutil
+
+class Convert(object):
+
+	def getKey(self, site_key, file):
+		return Demeter.md5(str(site_key) + '_' + file)
+
+	def get(self, site, site_key, file):
+		convert = Demeter.model('convert')
+		convert.site_id = site
+		convert.key = self.getKey(site_key, file)
+
+		data = convert.select(type='fetchone')
+
+		return data
+
+	def update(self, site, site_key, file):
+
+		info = self.getFile(site_key, file)
+
+		convert = Demeter.model('convert')
+		convert.site_id = site
+		convert.key = info['key']
+
+		data = convert.select(type='fetchone')
+		if not data:
+			convert.site_id = site
+			convert.file = info['file']
+			convert.key = info['key']
+			convert.name = info['name']
+			convert.ext = info['ext']
+
+			convert.local = info['local']
+			convert.path = info['path']
+			convert.pdf = info['pdf']
+			convert.html = info['html']
+			convert.url = info['url']
+
+			id = convert.insert()
+
+			info['status'] = 1
+			info['id'] = id
+
+		else:
+			info['id'] = data['id']
+			info['status'] = data['status']
+
+		return info
+
+
+	def getFile(self, site_key, file):
+		info = {}
+
+		(filepath,temp) = os.path.split(file)
+		(filename,extension) = os.path.splitext(temp)
+
+		info['file'] = file
+		info['key'] = self.getKey(site_key, file)
+		info['ext'] = extension
+		info['name'] = filename
+
+		info = self.getLocalFile(site_key, file, info)
+
+		return info
+
+	def getLocalFile(self, site_key, file, info):
+
+		day = str(date.today())
+		day = day.split('-')
+
+		#filename =  Demeter.md5(str(uuid.uuid5(uuid.uuid1(), info['key'])))
+		filename =  info['key']
+		filepath = str(site_key) + '/' + day[0] + '/' + day[1] + '/' + day[2]
+		filepath = File.mkdirs(os.path.join(Demeter.path, 'runtime','upload', filepath)) + '/' + filename
+
+		local = filepath + info['ext']
+
+		info['local'] = local
+		info['pdf'] = filepath + '/' + filename + '.pdf'
+		info['html'] = filepath + '/' + filename + '.html'
+		info['url'] = info['html'].replace(Demeter.path + 'runtime', '')
+		info['path'] = filepath + '/'
+
+		return info
+		if File.exists(local):
+			return info
+		else:
+			self.download(file, local);
+			return info
+
+	def download(file, local):
+		if 'http' in file:
+			r = requests.get(file, stream=True)
+			with open(local, 'wb') as up:
+				for chunk in r.iter_content(chunk_size=1024):
+					if chunk:
+						up.write(chunk)
+
+		else:
+			shutil.copyfile(file, local)
+
+		if File.exists(local):
+			return True
+		return False
+
+	def handle(self, file, key, ext, path, pdf):
+		convert = 'libreoffice  --invisible --convert-to pdf ' + file
+		convert = convert + ' && '
+		convert = convert + 'pdf2htmlEX --zoom 1.3 --no-drm 1 --split-pages 1 '
+		convert = convert + '--embed-css 1  --embed-javascript 0 --embed-image 0 --embed-font 1 '
+		convert = convert + '--embed-external-font 0 --dest-dir '+path+' --page-filename %d.page ' + pdf
+
+		print convert
+		return