diff --git a/connect.py b/connect.py index 8558ed745..05d84dd8f 100644 --- a/connect.py +++ b/connect.py @@ -19,10 +19,11 @@ import struct, fcntl, signal, socket, select os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings' if django.get_version() != '1.6': django.setup() -from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object, mkdir -from jumpserver.api import logger, Log, TtyLog +from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object, mkdir, get_asset_info, get_role +from jumpserver.api import logger, Log, TtyLog, get_role_key +from jperm.perm_api import gen_resource, get_group_asset_perm, get_group_user_perm from jumpserver.settings import LOG_DIR - +from jperm.ansible_api import Command login_user = get_object(User, username=getpass.getuser()) VIM_FLAG = False @@ -73,15 +74,15 @@ class Tty(object): A virtual tty class 一个虚拟终端类,实现连接ssh和记录日志,基类 """ - def __init__(self, username, asset_name): - self.username = username - self.asset_name = asset_name + def __init__(self, user, asset, role): + self.username = user.username + self.asset_name = asset.hostname self.ip = None self.port = 22 self.channel = None - #self.asset = get_object(Asset, name=asset_name) - #self.user = get_object(User, username=username) - self.role = None + self.asset = asset + self.user = user + self.role = role self.ssh = None self.connect_info = None self.login_type = 'ssh' @@ -287,7 +288,10 @@ class Tty(object): # 2. get 映射用户 # 3. get 映射用户的账号,密码或者key # self.connect_info = {'user': '', 'asset': '', 'ip': '', 'port': 0, 'role_name': '', 'role_pass': '', 'role_key': ''} - self.connect_info = {'user': 'a', 'asset': 'b', 'ip': '127.0.0.1', 'port': 22, 'role_name': 'root', 'role_pass': 'redhat', 'role_key': ''} + asset_info = get_asset_info(self.asset) + self.connect_info = {'user': self.user, 'asset': self.asset, 'ip': asset_info.get('ip'), + 'port': int(asset_info.get('port')), 'role_name': self.role.name, + 'role_pass': self.role.password, 'role_key': self.role.key_path} return self.connect_info def get_connection(self): @@ -301,18 +305,24 @@ class Tty(object): ssh.load_system_host_keys() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: - if connect_info.get('role_pass'): - ssh.connect(connect_info.get('ip'), - port=connect_info.get('port'), - username=connect_info.get('role_name'), - password=connect_info.get('role_pass'), - look_for_keys=False) - else: - ssh.connect(connect_info.get('ip'), - port=connect_info.get('port'), - username=connect_info.get('role_name'), - key_filename=connect_info.get('role_key'), - look_for_keys=False) + role_key = get_role_key(self.user, self.role) + if role_key and os.path.isfile(role_key): + try: + ssh.connect(connect_info.get('ip'), + port=connect_info.get('port'), + username=connect_info.get('role_name'), + key_filename=role_key, + look_for_keys=False) + self.ssh = ssh + return ssh + except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException: + pass + + ssh.connect(connect_info.get('ip'), + port=connect_info.get('port'), + username=connect_info.get('role_name'), + password=connect_info.get('role_pass'), + look_for_keys=False) except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException: raise ServerError('认证失败 Authentication Error.') @@ -458,28 +468,12 @@ class SshTty(Tty): channel.close() ssh.close() - def execute(self, cmd): - """ - execute cmd on the asset - 执行命令 - """ - pass - - -def print_user_asset_group_info(user): - asset_groups = AssetGroup.objects.all() - for asset_group in asset_groups: - if asset_group.comment: - print '[%-2s] %-10s %s' % (asset_group.id, asset_group.name, asset_group.comment) - else: - print '[%-2s] %-10s' % (asset_group.id, asset_group.name) - print - class Nav(object): def __init__(self, user): self.user = user self.search_result = {} + self.user_perm = {} @staticmethod def print_nav(): @@ -510,7 +504,9 @@ class Nav(object): def search(self, str_r=''): gid_pattern = re.compile(r'^g\d+$') - user_asset_all = list(Asset.objects.all()) + if not self.user_perm: + self.user_perm = get_group_user_perm(self.user) + user_asset_all = self.user_perm.get('asset').keys() user_asset_search = [] if str_r: if gid_pattern.match(str_r): @@ -523,13 +519,15 @@ class Nav(object): user_asset_search = user_asset_all self.search_result = dict(zip(range(len(user_asset_search)), user_asset_search)) - - print '\033[32m[%-3s] %-15s %-15s %-5s %-5s %s \033[0m' % ('ID', 'AssetName', 'IP', 'Port', 'Role', 'Comment') + print '\033[32m[%-3s] %-15s %-15s %-5s %-10s %s \033[0m' % ('ID', 'AssetName', 'IP', 'Port', 'Role', 'Comment') for index, asset in self.search_result.items(): + asset_info = get_asset_info(asset) + role = [str(role.name) for role in self.user_perm.get('asset').get(asset).get('role')] if asset.comment: - print '[%-3s] %-15s %-15s %-5s %-5s %s' % (index, 'asset_name'+str(index), asset.ip, asset.port, 'role', asset.comment) + print '[%-3s] %-15s %-15s %-5s %-10s %s' % (index, asset.hostname, asset.ip, asset_info.get('port'), + role, asset.comment) else: - print '[%-3s] %-15s %-15s %-5s %-5s' % (index, 'asset_name'+str(index), asset.ip, asset.port, 'role') + print '[%-3s] %-15s %-15s %-5s %-10s' % (index, asset.hostname, asset.ip, asset_info.get('port'), role) print @staticmethod @@ -544,6 +542,50 @@ class Nav(object): print '[%-3s] %-15s' % (asset_group.id, asset_group.name) print + def exec_cmd(self): + self.search() + while True: + print "请输入主机名、IP或ansile支持的pattern, q退出" + try: + pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip() + if pattern == 'q': + break + else: + if not self.user_perm: + self.user_perm = get_group_user_perm(self.user) + res = gen_resource(self.user, perm=self.user_perm) + cmd = Command(res) + logger.debug(res) + for inv in cmd.inventory.get_hosts(pattern=pattern): + print inv.name + confirm_host = raw_input("\033[1;32mIs that [y/n]>:\033[0m ").strip() + if confirm_host == 'y': + while True: + print "请输入执行的命令, 按q退出" + command = raw_input("\033[1;32mCmds>:\033[0m ").strip() + if command == 'q': + break + result = cmd.run(module_name='shell', command=command, pattern=pattern) + for k, v in result.items(): + if k == 'ok': + for host, output in v.items(): + color_print("%s => %s" % (host, 'Ok'), 'green') + print output + print + else: + for host, output in v.items(): + color_print("%s => %s" % (host, k), 'red') + color_print(output, 'red') + print + print "=" * 20 + print + else: + continue + + except EOFError: + print + break + def main(): """ @@ -575,14 +617,35 @@ def main(): nav.print_asset_group() continue elif option in ['E', 'e']: - # exec_cmd_servers(login_name) - pass + nav.exec_cmd() + continue elif option in ['Q', 'q', 'exit']: sys.exit() else: try: asset = nav.search_result[int(option)] - ssh_tty = SshTty('a', 'b') + roles = get_role(login_user, asset) + if len(roles) > 1: + role_check = dict(zip(range(len(roles)), roles)) + print role_check + for index, role in role_check.items(): + print "[%s] %s" % (index, role.name) + print "输入角色ID, q退出" + try: + role_index = raw_input("\033[1;32mID>:\033[0m ").strip() + if role_index == 'q': + continue + else: + role = role_check[int(role_index)] + except IndexError: + color_print('请输入正确ID', 'red') + continue + elif len(roles) == 1: + role = roles[0] + else: + color_print('没有映射用户', 'red') + continue + ssh_tty = SshTty(login_user, asset, role) ssh_tty.connect() except (KeyError, ValueError): color_print('请输入正确ID', 'red') diff --git a/jasset/asset_api.py b/jasset/asset_api.py index 8103db23b..06c91a616 100644 --- a/jasset/asset_api.py +++ b/jasset/asset_api.py @@ -238,7 +238,6 @@ def db_asset_alert(asset, username, alert_dic): alert_list = [] asset_tuple_dic = {'status': ASSET_STATUS, 'env': ASSET_ENV, 'asset_type': ASSET_TYPE} for field, value in alert_dic.iteritems(): - print field field_name = Asset._meta.get_field_by_name(field)[0].verbose_name if field == 'idc': old = IDC.objects.filter(id=value[0]) if value[0] else u'' @@ -386,9 +385,9 @@ def excel_to_db(excel_file): if row: ip, port, hostname, use_default_auth, username, password, group = row use_default_auth = 1 if use_default_auth == u'默认' else 0 - if get_object(Asset, ip=ip): + if get_object(Asset, hostname=hostname): continue - if ip and port: + if hostname: asset = Asset(ip=ip, port=port, hostname=hostname, diff --git a/jasset/forms.py b/jasset/forms.py index f9af4d499..03eca04ed 100644 --- a/jasset/forms.py +++ b/jasset/forms.py @@ -28,5 +28,10 @@ class IdcForm(forms.ModelForm): class Meta: model = IDC fields = ['name', "bandwidth", "operator", 'linkman', 'phone', 'address', 'network', 'comment'] + widgets = { + 'name': forms.TextInput(attrs={'placeholder': 'Name'}), + 'network': forms.Textarea( + attrs={'placeholder': '192.168.1.0/24\n192.168.2.0/24'}) + } diff --git a/jasset/models.py b/jasset/models.py index f1e5b46fc..159d72254 100644 --- a/jasset/models.py +++ b/jasset/models.py @@ -42,7 +42,7 @@ class IDC(models.Model): address = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"机房地址") network = models.TextField(blank=True, null=True, verbose_name=u"IP地址段") date_added = models.DateField(auto_now=True, null=True) - operator = models.IntegerField(blank=True, null=True, verbose_name=u"运营商") + operator = models.CharField(max_length=32, blank=True, null=True, verbose_name=u"运营商") comment = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"备注") def __unicode__(self): @@ -57,17 +57,17 @@ class Asset(models.Model): """ asset modle """ - ip = models.GenericIPAddressField(unique=True, verbose_name=u"主机IP") + ip = models.GenericIPAddressField(blank=True, null=True, verbose_name=u"主机IP") other_ip = models.CharField(max_length=255, blank=True, null=True, verbose_name=u"其他IP") - hostname = models.CharField(max_length=64, blank=True, null=True, verbose_name=u"主机名") - port = models.IntegerField(verbose_name=u"端口号") + hostname = models.CharField(unique=True, max_length=128, verbose_name=u"主机名") + port = models.IntegerField(blank=True, null=True, verbose_name=u"端口号") group = models.ManyToManyField(AssetGroup, blank=True, verbose_name=u"所属主机组") username = models.CharField(max_length=16, blank=True, null=True, verbose_name=u"管理用户名") password = models.CharField(max_length=64, blank=True, null=True, verbose_name=u"密码") use_default_auth = models.BooleanField(default=True, verbose_name=u"使用默认管理账号") idc = models.ForeignKey(IDC, blank=True, null=True, on_delete=models.SET_NULL, verbose_name=u'机房') mac = models.CharField(max_length=20, blank=True, null=True, verbose_name=u"MAC地址") - remote_ip = models.CharField(max_length=16, blank=True, null=True, verbose_name=u'远控卡') + remote_ip = models.CharField(max_length=16, blank=True, null=True, verbose_name=u'远控卡IP') brand = models.CharField(max_length=64, blank=True, null=True, verbose_name=u'硬件厂商型号') cpu = models.CharField(max_length=64, blank=True, null=True, verbose_name=u'CPU') memory = models.CharField(max_length=128, blank=True, null=True, verbose_name=u'内存') diff --git a/jasset/urls.py b/jasset/urls.py index c9ec8c462..10d6dafc7 100644 --- a/jasset/urls.py +++ b/jasset/urls.py @@ -17,13 +17,11 @@ urlpatterns = patterns('', url(r'^group_list/$', group_list), url(r'^group_edit/$', group_edit), url(r'^group_list/$', group_list), - url(r'^group_detail/$', group_detail), # url(r'^group_del_host/$', group_del_host), url(r'^asset_edit_batch/$', asset_edit_batch), # url(r'^host_edit_common/batch/$', host_edit_common_batch), url(r'^idc_add/$', idc_add), url(r'^idc_list/$', idc_list), - url(r'^idc_detail/$', idc_detail), url(r'^idc_edit/$', idc_edit), url(r'^idc_del/$', idc_del), url(r'^upload/$', asset_upload), diff --git a/jasset/views.py b/jasset/views.py index 71448f22a..31282137e 100644 --- a/jasset/views.py +++ b/jasset/views.py @@ -26,13 +26,13 @@ def group_add(request): try: if not name: - error = u'组名不能为空' - raise ServerError(error) + emg = u'组名不能为空' + raise ServerError(emg) asset_group_test = get_object(AssetGroup, name=name) if asset_group_test: - error = u"该组名 %s 已存在" % name - raise ServerError(error) + emg = u"该组名 %s 已存在" % name + raise ServerError(emg) except ServerError: pass @@ -87,21 +87,6 @@ def group_edit(request): return my_render('jasset/group_edit.html', locals(), request) -@require_role('admin') -def group_detail(request): - """ - Group detail view - 主机组详情 - """ - header_title, path1, path2 = u'主机组详情', u'资产管理', u'主机组详情' - group_id = request.GET.get('id', '') - group = get_object(AssetGroup, id=group_id) - asset_all = Asset.objects.filter(group=group).order_by('ip') - - contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(asset_all, request) - return my_render('jasset/group_detail.html', locals(), request) - - @require_role('admin') def group_list(request): """ @@ -147,13 +132,13 @@ def asset_add(request): af = AssetForm() if request.method == 'POST': af_post = AssetForm(request.POST) - print af_post ip = request.POST.get('ip', '') + hostname = request.POST.get('hostname', '') is_active = True if request.POST.get('is_active') == '1' else False use_default_auth = request.POST.get('use_default_auth', '') try: - if Asset.objects.filter(ip=str(ip)): - error = u'该IP %s 已存在!' % ip + if Asset.objects.filter(hostname=str(hostname)): + error = u'该主机名 %s 已存在!' % hostname raise ServerError(error) except ServerError: @@ -165,13 +150,15 @@ def asset_add(request): password = request.POST.get('password', '') password_encode = password asset_save.password = password_encode + if not ip: + asset_save.ip = hostname asset_save.is_active = True if is_active else False asset_save.save() af_post.save_m2m() - msg = u'主机 %s 添加成功' % ip + msg = u'主机 %s 添加成功' % hostname else: - esg = u'主机 %s 添加失败' % ip + esg = u'主机 %s 添加失败' % hostname return my_render('jasset/asset_add.html', locals(), request) @@ -215,17 +202,21 @@ def asset_edit(request): asset_id = request.GET.get('id', '') username = request.session.get('username', 'admin') asset = get_object(Asset, id=asset_id) - asset_old = copy_model_instance(asset) + if asset: + password_old = asset.password + # asset_old = copy_model_instance(asset) af = AssetForm(instance=asset) if request.method == 'POST': af_post = AssetForm(request.POST, instance=asset) ip = request.POST.get('ip', '') - use_default_auth = request.POST.get('use_default_auth') + hostname = request.POST.get('hostname', '') + password = request.POST.get('password', '') + use_default_auth = request.POST.get('use_default_auth', '') try: - asset_test = get_object(Asset, ip=ip) + asset_test = get_object(Asset, hostname=hostname) if asset_test and asset_id != unicode(asset_test.id): - error = u'该IP %s 已存在!' % ip + error = u'该主机名 %s 已存在!' % hostname raise ServerError(error) except ServerError: pass @@ -235,6 +226,10 @@ def asset_edit(request): if use_default_auth: af_save.username = '' af_save.password = '' + else: + if password_old != password: + password_encode = CRYPTOR.encrypt(password) + af_save.password = password_encode af_save.save() af_post.save_m2m() # asset_new = get_object(Asset, id=asset_id) @@ -266,8 +261,19 @@ def asset_list(request): status = request.GET.get('status', '') keyword = request.GET.get('keyword', '') export = request.GET.get("export", False) + group_id = request.GET.get("group_id", '') + idc_id = request.GET.get("idc_id", '') + if group_id: + group = get_object(AssetGroup, id=group_id) + if group: + asset_find = Asset.objects.filter(group=group) + elif idc_id: + idc = get_object(IDC, id=idc_id) + if idc: + asset_find = Asset.objects.filter(idc=idc) + else: + asset_find = Asset.objects.all() - asset_find = Asset.objects.all() if idc_name: asset_find = asset_find.filter(idc__name__contains=idc_name) @@ -305,7 +311,82 @@ def asset_list(request): @require_role('admin') def asset_edit_batch(request): af = AssetForm() + name = request.session.get('username', 'admin') asset_group_all = AssetGroup.objects.all() + + if request.method == 'POST': + env = request.POST.get('env', '') + idc_id = request.POST.get('idc', '') + port = request.POST.get('port', '') + use_default_auth = request.POST.get('use_default_auth', '') + username = request.POST.get('username', '') + password = request.POST.get('password', '') + group = request.POST.getlist('group', []) + cabinet = request.POST.get('cabinet', '') + comment = request.POST.get('comment', '') + asset_id_all = unicode(request.GET.get('asset_id_all', '')) + asset_id_all = asset_id_all.split(',') + for asset_id in asset_id_all: + alert_list = [] + asset = get_object(Asset, id=asset_id) + if asset: + if env: + if asset.env != env: + asset.env = env + alert_list.append([u'运行环境', asset.env, env]) + if idc_id: + idc = get_object(IDC, id=idc_id) + name_old = asset.idc.name if asset.idc else u'' + if idc and idc.name != name_old: + asset.idc = idc + alert_list.append([u'机房', name_old, idc.name]) + if port: + if unicode(asset.port) != port: + asset.port = port + alert_list.append([u'端口号', asset.port, port]) + + if use_default_auth: + if use_default_auth == 'default': + asset.use_default_auth = 1 + asset.username = '' + asset.password = '' + alert_list.append([u'使用默认管理账号', asset.use_default_auth, u'默认']) + elif use_default_auth == 'user_passwd': + asset.use_default_auth = 0 + asset.username = username + password_encode = CRYPTOR.encrypt(password) + asset.password = password_encode + alert_list.append([u'使用默认管理账号', asset.use_default_auth, username]) + if group: + group_new, group_old, group_new_name, group_old_name = [], asset.group.all(), [], [] + for group_id in group: + g = get_object(AssetGroup, id=group_id) + if g: + group_new.append(g) + if not set(group_new) < set(group_old): + group_instance = list(set(group_new) | set(group_old)) + for g in group_instance: + group_new_name.append(g.name) + for g in group_old: + group_old_name.append(g.name) + asset.group = group_instance + alert_list.append([u'主机组', ','.join(group_old_name), ','.join(group_new_name)]) + if cabinet: + if asset.cabinet != cabinet: + asset.cabinet = cabinet + alert_list.append([u'机柜号', asset.cabinet, cabinet]) + if comment: + if asset.comment != comment: + asset.comment = comment + alert_list.append([u'备注', asset.comment, comment]) + asset.save() + + if alert_list: + username = unicode(name) + ' - ' + u'批量' + print alert_list + AssetRecord.objects.create(asset=asset, username=username, content=alert_list) + return HttpResponse('ok') + return my_render('jasset/asset_edit_batch.html', locals(), request) @@ -437,29 +518,17 @@ def idc_edit(request): return my_render('jasset/idc_edit.html', locals(), request) -@require_role('admin') -def idc_detail(request): - """ - IDC detail view - """ - header_title, path1, path2 = u'IDC详情', u'资产管理', u'IDC详情' - idc_id = request.GET.get('id', '') - idc = get_object(IDC, id=idc_id) - posts = Asset.objects.filter(idc=idc).order_by('ip') - contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) - - return my_render('jasset/idc_detail.html', locals(), request) - - @require_role('admin') def idc_del(request): """ IDC delete view """ - uuid = request.GET.get('id', '') - idc = get_object(IDC, id=uuid) - if idc: - idc.delete() + idc_ids = request.GET.get('id', '') + idc_id_list = idc_ids.split(',') + + for idc_id in idc_id_list: + IDC.objects.filter(id=idc_id).delete() + return HttpResponseRedirect('/jasset/idc_list/') diff --git a/jperm/ansible_api.py b/jperm/ansible_api.py index 4e66da246..1b0e5ce38 100644 --- a/jperm/ansible_api.py +++ b/jperm/ansible_api.py @@ -79,14 +79,17 @@ class MyInventory(object): for host in hosts: # set connection variables hostname = host.get("hostname") + hostip = host.get('ip', hostname) hostport = host.get("port") username = host.get("username") password = host.get("password") + ssh_key = host.get("ssh_key") my_host = Host(name=hostname, port=hostport) - my_host.set_variable('ansible_ssh_host', hostname) + my_host.set_variable('ansible_ssh_host', hostip) my_host.set_variable('ansible_ssh_port', hostport) my_host.set_variable('ansible_ssh_user', username) my_host.set_variable('ansible_ssh_pass', password) + my_host.set_variable('ansible_ssh_private_key_file', ssh_key) # set other variables for key, value in host.iteritems(): if key not in ["hostname", "port", "username", "password"]: @@ -107,43 +110,72 @@ class MyInventory(object): self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars")) +class MyRunner(MyInventory): + """ + This is a General object for parallel execute modules. + """ + def __init__(self, *args, **kwargs): + super(MyRunner, self).__init__(*args, **kwargs) + self.results = {} + + def run(self, module_name, module_args='', timeout=10, forks=10, pattern='', + sudo=False, sudo_user='root', sudo_pass=''): + """ + run module from andible ad-hoc. + module_name: ansible module_name + module_args: ansible module args + """ + hoc = Runner(module_name=module_name, + module_args=module_args, + timeout=timeout, + inventory=self.inventory, + pattern=pattern, + forks=forks, + become=sudo, + become_method='sudo', + become_user=sudo_user, + become_pass=sudo_pass + ) + self.results = hoc.run() + return self.results + + class Command(MyInventory): """ this is a command object for parallel execute command. """ def __init__(self, *args, **kwargs): super(Command, self).__init__(*args, **kwargs) - self.results = '' + self.results = {} - def run(self, command, module_name="command", timeout=10, forks=10, group='default_group', pattern='*'): + def run(self, command, module_name="command", timeout=10, forks=10, pattern='*'): """ run command from andible ad-hoc. command : 必须是一个需要执行的命令字符串, 比如 'uname -a' """ + data = {} if module_name not in ["raw", "command", "shell"]: raise CommandValueError("module_name", - "module_name must be of the 'raw, command, shell'") + "module_name must be of the 'raw, command, shell'") hoc = Runner(module_name=module_name, module_args=command, timeout=timeout, inventory=self.inventory, - subset=group, pattern=pattern, forks=forks, ) self.results = hoc.run() if self.stdout: - return {"ok": self.stdout} - else: - msg = [] - if self.stderr: - msg.append(self.stderr) - if self.dark: - msg.append(self.dark) - return {"failed": msg} + data['ok'] = self.stdout + if self.stderr: + data['err'] = self.stderr + if self.dark: + data['dark'] = self.dark + + return data @property def raw_results(self): @@ -174,7 +206,7 @@ class Command(MyInventory): result = {} all = self.results.get("contacted") for key, value in all.iteritems(): - result[key] = value.get("stdout") + result[key] = value.get("stdout") return result @property @@ -185,7 +217,8 @@ class Command(MyInventory): result = {} all = self.results.get("contacted") for key, value in all.iteritems(): - result[key] = { + if value.get("stderr") or value.get("warnings"): + result[key] = { "stderr": value.get("stderr"), "warnings": value.get("warnings"),} return result @@ -371,7 +404,7 @@ class Tasks(Command): result[key] = { "all_ip": setup.get("ansible_all_ipv4_addresses"), - "hostname" : setup.get("ansible_hostname" ), + "hostname" : setup.get("ansible_hostname"), "default_ip": setup.get("ansible_default_ipv4").get("address"), "default_mac": setup.get("ansible_default_ipv4").get("macaddress"), "product_name": setup.get("ansible_product_name"), @@ -388,8 +421,6 @@ class Tasks(Command): return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok", "result": result} - - class CustomAggregateStats(callbacks.AggregateStats): """ Holds stats about per-host activity during playbook runs. @@ -408,7 +439,6 @@ class CustomAggregateStats(callbacks.AggregateStats): self.results.append(runner_results) - def summarize(self, host): """ Return information about a particular host diff --git a/jperm/models.py b/jperm/models.py index dc8643b67..0a01f7593 100644 --- a/jperm/models.py +++ b/jperm/models.py @@ -5,20 +5,6 @@ from jasset.models import Asset, AssetGroup from juser.models import User, UserGroup -class PermLog(models.Model): - datetime = models.DateTimeField(auto_now_add=True) - action = models.CharField(max_length=100, null=True, blank=True, default='') - results = models.CharField(max_length=1000, null=True, blank=True, default='') - is_success = models.BooleanField(default=False) - is_finish = models.BooleanField(default=False) - - -class SysUser(models.Model): - username = models.CharField(max_length=100) - password = models.CharField(max_length=100) - comment = models.CharField(max_length=100, null=True, blank=True, default='') - - class PermRole(models.Model): name = models.CharField(max_length=100, unique=True) comment = models.CharField(max_length=100, null=True, blank=True, default='') @@ -41,4 +27,4 @@ class PermRule(models.Model): role = models.ManyToManyField(PermRole, related_name='perm_rule') def __unicode__(self): - return self.name \ No newline at end of file + return self.name diff --git a/jperm/perm_api.py b/jperm/perm_api.py index 1b363f547..856c13005 100644 --- a/jperm/perm_api.py +++ b/jperm/perm_api.py @@ -1,15 +1,163 @@ # coding: utf-8 - +from django.db.models.query import QuerySet from jumpserver.api import * import uuid import re -from jumpserver.tasks import playbook_run from jumpserver.models import Setting -from jperm.models import PermLog - from jperm.models import PermRole +from jperm.models import PermRule + + +def get_group_user_perm(ob): + """ + ob为用户或用户组 + 获取用户、用户组授权的资产、资产组 + return: + {’asset_group': { + asset_group1: {'asset': [], 'role': [role1, role2], 'rule': [rule1, rule2]}, + asset_group2: {'asset: [], 'role': [role1, role2], 'rule': [rule1, rule2]}, + } + 'asset':{ + asset1: {'role': [role1, role2], 'rule': [rule1, rule2]}, + asset2: {'role': [role1, role2], 'rule': [rule1, rule2]}, + } + ]}, + 'rule':[rule1, rule2,] + } + """ + perm = {} + if isinstance(ob, User): + rule_all = PermRule.objects.filter(user=ob) + elif isinstance(ob, UserGroup): + rule_all = PermRule.objects.filter(user_group=ob) + else: + rule_all = [] + + perm['rule'] = rule_all + perm_asset_group = perm['asset_group'] = {} + perm_asset = perm['asset'] = {} + for rule in rule_all: + asset_groups = rule.asset_group.all() + assets = rule.asset.all() + + # 获取一个规则用户授权的资产 + for asset in assets: + if perm_asset.get(asset): + perm_asset[asset].get('role', set()).update(set(rule.role.all())) + perm_asset[asset].get('rule', set()).add(rule) + else: + perm_asset[asset] = {'role': set(rule.role.all()), 'rule': set([rule])} + + # 获取一个规则用户授权的资产组 + for asset_group in asset_groups: + asset_group_assets = asset_group.asset_set.all() + if perm_asset_group.get(asset_group): + perm_asset_group[asset_group].get('role', set()).update(set(rule.role.all())) + perm_asset_group[asset_group].get('rule', set()).add(rule) + else: + perm_asset_group[asset_group] = {'role': set(rule.role.all()), 'rule': set([rule]), + 'asset': asset_group_assets} + + # 将资产组中的资产添加到资产授权中 + for asset in asset_group_assets: + if perm_asset.get(asset): + perm_asset[asset].get('role', set()).update(perm_asset_group[asset_group].get('role', set())) + perm_asset[asset].get('rule', set()).update(perm_asset_group[asset_group].get('rule', set())) + else: + perm_asset[asset] = {'role': perm_asset_group[asset_group].get('role', set()), + 'rule': perm_asset_group[asset_group].get('rule', set())} + return perm + + +def get_group_asset_perm(ob): + """ + ob为资产或资产组 + 获取资产,资产组授权的用户,用户组 + return: + {’user_group': { + user_group1: {'user': [], 'role': [role1, role2], 'rule': [rule1, rule2]}, + user_group2: {'user: [], 'role': [role1, role2], 'rule': [rule1, rule2]}, + } + 'user':{ + user1: {'role': [role1, role2], 'rule': [rule1, rule2]}, + user2: {'role': [role1, role2], 'rule': [rule1, rule2]}, + } + ]}, + 'rule':[rule1, rule2,] + } + """ + perm = {} + if isinstance(ob, Asset): + rule_all = PermRule.objects.filter(asset=ob) + elif isinstance(ob, AssetGroup): + rule_all = PermRule.objects.filter(asset_group=ob) + else: + rule_all = [] + + perm['rule'] = rule_all + perm_user_group = perm['user_group'] = {} + perm_user = perm['user'] = {} + for rule in rule_all: + user_groups = rule.user_group.all() + users = rule.user.all() + + # 获取一个规则资产的用户 + for user in users: + if perm_user.get(user): + perm_user[user].get('role', set()).update(set(rule.role.all())) + perm_user[user].get('rule', set()).add(rule) + else: + perm_user[user] = {'role': set(rule.role.all()), 'rule': set([rule])} + + # 获取一个规则资产授权的用户组 + for user_group in user_groups: + user_group_users = user_group.user_set.all() + if perm_user_group.get(user_group): + perm_user_group[user_group].get('role', set()).update(set(rule.role.all())) + perm_user_group[user_group].get('rule', set()).add(rule) + else: + perm_user_group[user_group] = {'role': set(rule.role.all()), 'rule': set([rule]), + 'user': user_group_users} + + # 将用户组中的资产添加到用户授权中 + for user in user_group_users: + if perm_user.get(user): + perm_user[user].get('role', set()).update(perm_user_group[user_group].get('role', set())) + perm_user[user].get('rule', set()).update(perm_user_group[user_group].get('rule', set())) + else: + perm_user[user] = {'role': perm_user_group[user_group].get('role', set()), + 'rule': perm_user_group[user_group].get('rule', set())} + return perm + + +def gen_resource(ob, perm=None): + """ + ob为用户或资产列表或资产queryset + 生成MyInventory需要的 resource文件 + """ + res = [] + if isinstance(ob, User): + if not perm: + perm = get_group_user_perm(ob) + + for asset, asset_info in perm.get('asset').items(): + asset_info = get_asset_info(asset) + info = {'hostname': asset.hostname, 'ip': asset.ip, 'port': asset_info.get('port', 22)} + try: + role = sorted(list(perm.get('asset').get(asset).get('role')))[0] + except IndexError: + continue + info['username'] = role.name + info['password'] = role.password + info['ssh_key'] = get_role_key(ob, role) + res.append(info) + elif isinstance(ob, (list, QuerySet)): + for asset in ob: + info = get_asset_info(asset) + res.append(info) + return res def get_object_list(model, id_list): @@ -22,267 +170,6 @@ def get_object_list(model, id_list): return object_list -def get_rand_file_path(base_dir=os.path.join(BASE_DIR, 'tmp')): - """获取随机文件路径""" - filename = uuid.uuid1().hex - return os.path.join(base_dir, filename) - - -def get_inventory(host_group): - """生成资产表库存清单""" - path = get_rand_file_path() - f = open(path, 'w') - for group, host_list in host_group.items(): - f.write('[%s]\n' % group) - for ip in host_list: - asset = get_object(Asset, ip=ip) - if asset.use_default: - f.write('%s\n' % ip) - else: - f.write('%s ansible_ssh_port=%s ansible_ssh_user=%s ansible_ssh_pass=%s\n' % - (ip, asset.port, asset.username, CRYPTOR.decrypt(asset.password))) - f.close() - return path - - -def get_playbook(template, var): - """根据playbook模板,生成playbook""" - str_playbook = open(template).read() - for k, v in var.items(): - str_playbook = re.sub(r'%s' % k, v, str_playbook) # 正则来替换传入的字符 - path = get_rand_file_path() - f = open(path, 'w') - f.write(str_playbook) - return path - - -def perm_user_api(perm_info): - """ - 用户授权api,通过调用ansible API完成用户新建等,传入参数必须如下,列表中可以是对象,也可以是用户名和ip - perm_info = {'del': {'users': [], - 'assets': [], - }, - 'new': {'users': [], - 'assets': []}} - """ - log = PermLog(action=perm_info.get('action', '')) - try: - new_users = perm_info.get('new', {}).get('users', []) - new_assets = perm_info.get('new', {}).get('assets', []) - del_users = perm_info.get('del', {}).get('users', []) - del_assets = perm_info.get('del', {}).get('assets', []) - print new_users, new_assets - except IndexError: - raise ServerError("Error: function perm_user_api传入参数错误") - - try: - new_ip = [asset.ip for asset in new_assets if isinstance(asset, Asset)] - del_ip = [asset.ip for asset in del_assets if isinstance(asset, Asset)] - new_username = [user.username for user in new_users] - del_username = [user.username for user in del_users] - except IndexError: - raise ServerError("Error: function perm_user_api传入参数类型错误") - - host_group = {'new': new_ip, 'del': del_ip} - inventory = get_inventory(host_group) - - the_new_users = ','.join(new_username) - the_del_users = ','.join(del_username) - - playbook = get_playbook(os.path.join(BASE_DIR, 'keys/../playbook', 'user_perm.yaml'), - {'the_new_group': 'new', 'the_del_group': 'del', - 'the_new_users': the_new_users, 'the_del_users': the_del_users, - 'KEY_DIR': os.path.join(SSH_KEY_DIR, 'sysuser')}) - - print playbook, inventory - - settings = get_object(Setting, name='default') - results = playbook_run(inventory, playbook, settings) - if not results.get('failures', 1) and not results.get('unreachable', ''): - is_success = True - else: - is_success = False - - log.results = results - log.is_finish = True - log.is_success = is_success - log.save() - return results - - -def user_group_permed(user_group): - assets = user_group.asset.all() - asset_groups = user_group.asset_group.all() - - for asset_group in asset_groups: - assets.extend(asset_group.asset.all()) - - return {'assets': assets, 'asset_groups': asset_groups} - - -def user_permed(user): - asset_groups = [] - assets = [] - user_groups = user.group.all() - asset_groups.extend(user.asset_group.all()) - assets.extend(user.asset.all()) - - for user_group in user_groups: - asset_groups.extend(user_group_permed(user_group).get('assets', [])) - assets.extend((user_group_permed(user_group).get('asset_groups', []))) - - return {'assets': assets, 'asset_groups': asset_groups} - - -def _public_perm_api(info): - """ - 公用的用户,用户组,主机,主机组编辑修改新建调用的api,用来完成授权 - info like that: - { - 'type': 'new_user', - 'user': 'a', - 'group': ['A', 'B'] - } - - { - 'type': 'edit_user', - 'user': 'a', - 'group': {'new': ['A'], 'del': []} - } - - { - 'type': 'del_user', - 'user': ['a', 'b'] - } - - { - 'type': 'edit_user_group', - 'group': 'A', - 'user': {'del': ['a', 'b'], 'new': ['c', 'd']} - } - - { - 'type': 'del_user_group', - 'group': ['A'] - } - - { - 'type': 'new_asset', - 'asset': 'a', - 'group': ['A', 'B'] - } - - { - 'type': 'edit_asset', - 'asset': 'a', - 'group': { - 'del': ['A', ['B'], - 'new': ['C', ['D']] - } - } - - { - 'type': 'del_asset', - 'asset': ['a', 'b'] - } - - { - 'type': 'edit_asset_group', - 'group': 'A', - 'asset': {'new': ['a', 'b'], 'del': ['c', 'd']} - } - - { - 'type': 'del_asset_group', - 'group': ['A', 'B'] - } - """ - - if info.get('type') == 'new_user': - new_assets = [] - user = info.get('user') - user_groups = info.get('group') - for user_group in user_groups: - new_assets.extend(user_group_permed(user_group).get('assets', [])) - - perm_info = { - 'action': 'new user: ' + user.name, - 'new': {'users': [user], 'assets': new_assets} - } - elif info.get('type') == 'edit_user': - new_assets = [] - del_assets = [] - user = info.get('user') - new_group = info.get('group').get('new') - del_group = info.get('group').get('del') - - for user_group in new_group: - new_assets.extend(user_group_permed(user_group).get('assets', [])) - - for user_group in del_group: - del_assets.extend((user_group_permed(user_group).get('assets', []))) - - perm_info = { - 'action': 'edit user: ' + user.name, - 'del': {'users': [user], 'assets': del_assets}, - 'new': {'users': [user], 'assets': new_assets} - } - - elif info.get('type') == 'del_user': - user = info.get('user') - del_assets = user_permed(user).get('assets', []) - perm_info = { - 'action': 'del user: ' + user.name, 'del': {'users': [user], 'assets': del_assets}, - } - - elif info.get('type') == 'edit_user_group': - user_group = info.get('group') - new_users = info.get('user').get('new') - del_users = info.get('user').get('del') - assets = user_group_permed(user_group).get('assets', []) - - perm_info = { - 'action': 'edit user group: ' + user_group.name, - 'new': {'users': new_users, 'assets': assets}, - 'del': {'users': del_users, 'assets': assets} - } - - elif info.get('type') == 'del_user_group': - user_group = info.get('group', []) - del_users = user_group.user_set.all() - assets = user_group_permed(user_group).get('assets', []) - - perm_info = { - 'action': "del user group: " + user_group.name, 'del': {'users': del_users, 'assets': assets} - } - else: - return - - try: - results = perm_user_api(perm_info) # 通过API授权或回收 - except ServerError, e: - return e - else: - return results - - -def push_user(user, asset_groups_id): - assets = [] - if not user: - return {'error': '没有该用户'} - for group_id in asset_groups_id: - asset_group = get_object(AssetGroup, id=group_id) - if asset_group: - assets.extend(asset_group.asset_set.all()) - perm_info = { - 'action': 'Push user:' + user.username, - 'new': {'users': [user], 'assets': assets} - } - - results = perm_user_api(perm_info) - return results - - def get_role_info(role_id, type="all"): """ 获取role对应的一些信息 diff --git a/jperm/urls.py b/jperm/urls.py index aa80f7f75..fd40dc1cd 100644 --- a/jperm/urls.py +++ b/jperm/urls.py @@ -13,11 +13,4 @@ urlpatterns = patterns('jperm.views', (r'^role/perm_role_detail/$', perm_role_detail), (r'^role/perm_role_edit/$', perm_role_edit), (r'^role/perm_role_push/$', perm_role_push), - - - (r'^log/$', log), - (r'^sys_user_add/$', sys_user_add), - (r'^perm_user_list/$', sys_user_list), - (r'^sys_user_del/$', sys_user_del), - (r'^sys_user_edit/$', sys_user_edit), ) diff --git a/jperm/utils.py b/jperm/utils.py index c8acff371..a6b3608ee 100644 --- a/jperm/utils.py +++ b/jperm/utils.py @@ -51,6 +51,7 @@ def gen_keys(): private_key = os.path.join(key_path_dir, 'id_rsa') public_key = os.path.join(key_path_dir, 'id_rsa.pub') key.write_private_key_file(private_key) + os.chmod(private_key, 0644) with open(public_key, 'w') as content_file: for data in [key.get_name(), diff --git a/jperm/views.py b/jperm/views.py index f961a8e07..1c9eaa15c 100644 --- a/jperm/views.py +++ b/jperm/views.py @@ -2,8 +2,6 @@ from django.db.models import Q from jperm.perm_api import * -from jperm.models import PermLog as Log -from jperm.models import SysUser from juser.user_api import gen_ssh_key @@ -380,8 +378,6 @@ def perm_role_edit(request): return my_render('jperm/perm_role_list.html', locals(), request) - - @require_role('admin') def perm_role_push(request): """ @@ -460,108 +456,3 @@ def perm_role_push(request): else: return HttpResponse(u"推送系统角色: %s" % ','.join(role_names)) - - - - - - - - - -@require_role('admin') -def perm_group_list(request): - header_title, path1, path2 = '用户组授权', '授权管理', '用户组授权' - keyword = request.GET.get('search', '') - user_groups_list = UserGroup.objects.all() - if keyword: - request = user_groups_list.filter(Q(name=keyword) | Q(comment=keyword)) - user_groups_list, p, user_groups, page_range, current_page, show_first, show_end = pages(user_groups_list, request) - return my_render('jperm/perm_group_list.html', locals(), request) - - - -@require_role('admin') -def perm_group_edit(request): - header_title, path1, path2 = '用户组授权', '授权管理', '授权更改' - user_group_id = request.GET.get('id', '') - user_group = get_object(UserGroup, id=user_group_id) - asset_all = Asset.objects.all() - asset_group_all = AssetGroup.objects.all() - asset_permed = user_group.asset.all() # 获取授权的资产对象列表 - asset_group_permed = user_group.asset_group.all() # 获取授权的资产组对象列表 - if request.method == 'GET' and user_group: - assets = [asset for asset in asset_all if asset not in asset_permed] - asset_groups = [asset_group for asset_group in asset_group_all if asset_group not in asset_group_permed] - return my_render('jperm/perm_group_edit.html', locals(), request) - elif request.method == 'POST' and user_group: - asset_id_select = request.POST.getlist('asset_select', []) - asset_group_id_select = request.POST.getlist('asset_groups_select', []) - asset_select = get_object_list(Asset, asset_id_select) - asset_group_select = get_object_list(AssetGroup, asset_group_id_select) - asset_new = list(set(asset_select) - set(asset_permed)) # 计算的得到新授权的资产对象列表 - asset_del = list(set(asset_permed) - set(asset_select)) # 计算得到回收权限的资产对象列表 - asset_group_new = list(set(asset_group_select) - set(asset_group_permed)) # 新授权的资产组对象列表 - asset_group_del = list(set(asset_group_permed) - set(asset_group_select)) # 回收的资产组对象列表 - users = user_group.user_set.all() - perm_info = { - 'action': 'perm group edit: ' + user_group.name, - 'del': {'users': users, 'assets': asset_del}, - 'new': {'users': users, 'assets': asset_new} - } - results = perm_user_api(perm_info) - unreachable_asset = [] - failures_asset = [] - for ip in results.get('unreachable'): - unreachable_asset.extend(filter(lambda x: x, Asset.objects.filter(ip=ip))) - for ip in results.get('failures'): - failures_asset.extend(filter(lambda x: x, Asset.objects.filter(ip=ip))) - failures_asset.extend(unreachable_asset) # 失败的授权要统计 - for asset in failures_asset: - if asset in asset_select: - asset_select.remove(asset) - else: - asset_select.append(asset) - user_group.asset = asset_select - user_group.asset_group = asset_group_select - user_group.save() # 保存到数据库 - return HttpResponse(json.dumps(results, sort_keys=True, indent=4), content_type="application/json") - else: - return HttpResponse('输入错误') - - -def log(request): - header_title, path1, path2 = '授权记录', '授权管理', '授权记录' - log_all = Log.objects.all().order_by('-datetime') - log_all, p, logs, page_range, current_page, show_first, show_end = pages(log_all, request) - return my_render('jperm/perm_log.html', locals(), request) - - -def sys_user_add(request): - asset_group_all = AssetGroup.objects.all() - if request.method == 'POST': - username = request.POST.get('username', '') - password = request.POST.get('password', '') - asset_groups_id = request.POST.getlist('asset_groups_select', []) - comment = request.POST.get('comment') - sys_user = SysUser(username=username, password=password, comment=comment) - sys_user.save() - gen_ssh_key(username, key_dir=os.path.join(SSH_KEY_DIR, 'sysuser'), authorized_keys=False) - results = push_user(sys_user, asset_groups_id) - return HttpResponse(json.dumps(results, sort_keys=True, indent=4), content_type="application/json") - return my_render('jperm/sys_user_add.html', locals(), request) - - -def sys_user_list(request): - users_list = SysUser.objects.all() - users_list, p, users, page_range, current_page, show_first, show_end = pages(users_list, request) - return my_render('jperm/sys_user_list.html', locals(), request) - - -def sys_user_edit(request): - pass - - -def sys_user_del(request): - pass - diff --git a/jumpserver/api.py b/jumpserver/api.py index 6dc1a1602..3ffa7566b 100644 --- a/jumpserver/api.py +++ b/jumpserver/api.py @@ -3,24 +3,27 @@ import os, sys, time, re from Crypto.Cipher import AES import crypt +import pwd from binascii import b2a_hex, a2b_hex import hashlib import datetime import random import subprocess -from settings import * +import json +import logging +from settings import * from django.core.paginator import Paginator, EmptyPage, InvalidPage from django.http import HttpResponse, Http404 from django.template import RequestContext from juser.models import User, UserGroup -from jlog.models import Log +from jlog.models import Log, TtyLog from jasset.models import Asset, AssetGroup +from jperm.models import PermRule, PermRole +from jumpserver.models import Setting from django.http import HttpResponseRedirect from django.shortcuts import render_to_response from django.core.mail import send_mail -import json -import logging def set_log(level): @@ -28,11 +31,15 @@ def set_log(level): return a log file object 根据提示设置log打印 """ + log_file = os.path.join(LOG_DIR, 'jumpserver.log') + if not os.path.isfile(log_file): + os.mknod(log_file) + os.chmod(log_file, 0777) log_level_total = {'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARN, 'error': logging.ERROR, 'critical': logging.CRITICAL} logger_f = logging.getLogger('jumpserver') logger_f.setLevel(logging.DEBUG) - fh = logging.FileHandler(os.path.join(LOG_DIR, 'jumpserver.log')) + fh = logging.FileHandler(log_file) fh.setLevel(log_level_total.get(level, logging.DEBUG)) formatter = logging.Formatter('%(asctime)s - %(filename)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) @@ -40,6 +47,60 @@ def set_log(level): return logger_f +def get_asset_info(asset): + default = get_object(Setting, name='default') + info = {'hostname': asset.hostname, 'ip': asset.ip} + if asset.use_default_auth: + if default: + info['port'] = default.default_port + info['username'] = default.default_user + info['password'] = CRYPTOR.decrypt(default.default_password) + info['ssh_key'] = default.default_pri_key_path + else: + info['port'] = asset.port + info['username'] = asset.username + info['password'] = asset.password + + return info + + +def get_role(user, asset): + roles = [] + rules = PermRule.objects.filter(user=user, asset=asset) + for rule in rules: + roles.extend(list(rule.role.all())) + return roles + + +def get_role_key(user, role): + """ + 由于role的key的权限是所有人可以读的, ansible要求为600,所以拷贝一份到特殊目录 + :param user: + :param role: + :return: self key path + """ + user_role_key_dir = os.path.join(KEY_DIR, 'user') + user_role_key_path = os.path.join(user_role_key_dir, '%s_%s.pem' % (user.username, role.name)) + mkdir(user_role_key_dir, mode=777) + if not os.path.isfile(user_role_key_path): + with open(os.path.join(role.key_path, 'id_rsa')) as fk: + with open(user_role_key_path, 'w') as fu: + fu.write(fk.read()) + + print user_role_key_path, user.username + chown(user_role_key_path, user.username) + os.chmod(user_role_key_path, 0600) + return user_role_key_path + + +def chown(path, user, group=''): + if not group: + group = user + uid = pwd.getpwnam(user).pw_uid + gid = pwd.getpwnam(group).pwd_gid + os.chown(path, uid, gid) + + def page_list_return(total, current=1): """ page @@ -56,7 +117,7 @@ def pages(post_objects, request): page public function , return page's object tuple 分页公用函数,返回分页的对象元组 """ - paginator = Paginator(post_objects, 10) + paginator = Paginator(post_objects, 20) try: current_page = int(request.GET.get('page', '1')) except ValueError: @@ -157,8 +218,7 @@ class PyCrypt(object): try: plain_text = cryptor.decrypt(a2b_hex(text)) except TypeError: - # raise ServerError('Decrypt password error, TYpe error.') - pass + raise ServerError('Decrypt password error, TYpe error.') return plain_text.rstrip('\0') @@ -386,16 +446,16 @@ def bash(cmd): return subprocess.call(cmd, shell=True) -def mkdir(dir_name, username='root', mode=0755): +def mkdir(dir_name, username='', mode=0755): """ insure the dir exist and mode ok 目录存在,如果不存在就建立,并且权限正确 """ if not os.path.isdir(dir_name): os.makedirs(dir_name) - os.chmod(dir_name, mode) + os.chmod(dir_name, mode) if username: - bash('chown %s:%s %s' % (username, username, dir_name)) + chown(dir_name, username) def http_success(request, msg): diff --git a/juser/user_api.py b/juser/user_api.py index 87e7b5cc5..0248e5c6d 100644 --- a/juser/user_api.py +++ b/juser/user_api.py @@ -130,7 +130,7 @@ def gen_ssh_key(username, password='', """ logger.debug('生成ssh key, 并设置authorized_keys') private_key_file = os.path.join(key_dir, username) - mkdir(key_dir) + mkdir(key_dir, mode=777) if os.path.isfile(private_key_file): os.unlink(private_key_file) ret = bash('echo -e "y\n"|ssh-keygen -t rsa -f %s -b %s -P "%s"' % (private_key_file, length, password)) @@ -143,7 +143,7 @@ def gen_ssh_key(username, password='', with open(authorized_key_file, 'w') as auth_f: auth_f.write(pub_f.read()) os.chmod(authorized_key_file, 0600) - bash('chown %s:%s %s' % (username, username, authorized_key_file)) + chown(authorized_key_file, username) def server_add_user(username, password, ssh_key_pwd, ssh_key_login_need): diff --git a/static/files/excels/cmdb_excel_2015_11_14_11_38.xlsx b/static/files/excels/cmdb_excel_2015_11_14_11_38.xlsx new file mode 100644 index 000000000..7be819d90 Binary files /dev/null and b/static/files/excels/cmdb_excel_2015_11_14_11_38.xlsx differ diff --git a/static/files/excels/cmdb_excel_2015_11_14_11_39.xlsx b/static/files/excels/cmdb_excel_2015_11_14_11_39.xlsx new file mode 100644 index 000000000..831f40144 Binary files /dev/null and b/static/files/excels/cmdb_excel_2015_11_14_11_39.xlsx differ diff --git a/static/files/excels/cmdb_excel_2015_11_19_22_05.xlsx b/static/files/excels/cmdb_excel_2015_11_19_22_05.xlsx new file mode 100644 index 000000000..0c2778b89 Binary files /dev/null and b/static/files/excels/cmdb_excel_2015_11_19_22_05.xlsx differ diff --git a/static/js/base.js b/static/js/base.js index 15b54dd49..a8aa99b70 100644 --- a/static/js/base.js +++ b/static/js/base.js @@ -86,17 +86,17 @@ function move(from, to, from_o, to_o) { }); } -//function move_left(from, to, from_o, to_o) { -// $("#" + from + " option").each(function () { -// if ($(this).prop("selected") == true) { -// $("#" + to).append(this); -// if( typeof from_o !== 'undefined'){ -// $("#"+to_o).append($("#"+from_o +" option[value='"+this.value+"']")); -// } -// } -// $(this).attr("selected",'true'); -// }); -//} +function move_left(from, to, from_o, to_o) { + $("#" + from + " option").each(function () { + if ($(this).prop("selected") == true) { + $("#" + to).append(this); + if( typeof from_o !== 'undefined'){ + $("#"+to_o).append($("#"+from_o +" option[value='"+this.value+"']")); + } + } + $(this).attr("selected",'true'); + }); +} //function move_all(from, to) { // $("#" + from).children().each(function () { diff --git a/static/js/layer/extend/layer.ext.js b/static/js/layer/extend/layer.ext.js old mode 100644 new mode 100755 index 2b3a23b4e..80cd0ab12 --- a/static/js/layer/extend/layer.ext.js +++ b/static/js/layer/extend/layer.ext.js @@ -1,12 +1,2 @@ -/** - - @Name: layer拓展类,依赖于layer - @Date: 2014.08.13 - @Author: 贤心 - @Versions:1.8.5-ext - @Api:http://sentsin.com/jquery/layer - @Desc: 本拓展会持续更新 - - */ - -layer.use("skin/layer.ext.css",function(){layer.ext&&layer.ext()}),layer.prompt=function(a,b,c){var d={},a=a||{},e={area:["auto","auto"],offset:[a.top||"",""],title:a.title||"信息",dialog:{btns:2,type:-1,msg:'',yes:function(c){var e=d.prompt.val();""===e?d.prompt.focus():e.replace(/\s/g,"").length>(a.length||1e3)?layer.tips("最多输入"+(a.length||1e3)+"个字数","#xubox_prompt",2):b&&b(e,c,d.prompt)},no:c},success:function(){d.prompt=$("#xubox_prompt"),d.prompt.focus()}};return 3===a.type&&(e.dialog.msg='"),$.layer(e)},layer.tab=function(a){var a=a||{},c=a.data||[],d={type:1,border:[0],area:["auto","auto"],bgcolor:"",title:!1,shade:a.shade,offset:a.offset,move:".xubox_tabmove",closeBtn:!1,page:{html:'
'}()+''+'
'+function(){var a=c.length,b=1,d="";if(a>0)for(d=''+c[0].title+"";a>b;b++)d+=""+c[b].title+"";return d}()+"
"+'"+'X'+"
"},success:function(a){var b=$(".xubox_tabtit").children(),c=$(".xubox_tab_main").children(),d=$(".xubox_tabclose");b.on("click",function(){var a=$(this),b=a.index();a.addClass("xubox_tabnow").siblings().removeClass("xubox_tabnow"),c.eq(b).show().siblings().hide()}),d.on("click",function(){layer.close(a.attr("times"))})}};return $.layer(d)},layer.photos=function(a){var b,c,d,e,f,g,h,i;if(a=a||{},b={imgIndex:1,end:null,html:$("html")},c=$(window),d=a.json,e=a.page,d){if(f=d.data,1!==d.status)return layer.msg("未请求到数据",2,8),void 0;if(b.imgLen=f.length,!(f.length>0))return layer.msg("没有任何图片",2,8),void 0;b.thissrc=f[d.start].src,b.pid=f[d.start].pid,b.imgsname=d.title||"",b.name=f[d.start].name,b.imgIndex=d.start+1}else g=$(e.parent).find("img"),h=g.eq(e.start),b.thissrc=h.attr("layer-img")||h.attr("src"),b.pid=h.attr("pid"),b.imgLen=g.length,b.imgsname=e.title||"",b.name=h.attr("alt"),b.imgIndex=e.start+1;return i={type:1,border:[0],area:[(a.html?915:600)+"px","auto"],title:!1,shade:[.9,"#000",!0],shadeClose:!0,offset:["25px",""],bgcolor:"",page:{html:'
'+(b.name||
'+function(){return b.imgLen>1?'':""}()+'
'+b.imgsname+" "+b.imgIndex+"/"+b.imgLen+"
"+function(){return a.html?'
'+a.html+"
":""}()},success:function(a){b.bigimg=a.find(".xubox_bigimg"),b.imgsee=b.bigimg.find(".xubox_imgsee"),b.imgbar=b.imgsee.find(".xubox_imgbar"),b.imgtit=b.imgbar.find(".xubox_imgtit"),b.layero=a;var c=b.imgs=b.bigimg.find("img");clearTimeout(b.timerr),b.timerr=setTimeout(function(){$("html").css("overflow","hidden").attr("layer-full",b.index)},10),c.load(function(){b.imgarea=[c.outerWidth(),c.outerHeight()],b.resize(a)}),b.event()},end:function(){layer.closeAll(),b.end=!0}},b.event=function(){b.bigimg.hover(function(){b.imgsee.show()},function(){b.imgsee.hide()}),i.imgprev=function(){b.imgIndex--,b.imgIndex<1&&(b.imgIndex=b.imgLen),b.tabimg()},b.bigimg.find(".xubox_prev").on("click",function(a){a.preventDefault(),i.imgprev()}),i.imgnext=function(){b.imgIndex++,b.imgIndex>b.imgLen&&(b.imgIndex=1),b.tabimg()},b.bigimg.find(".xubox_next").on("click",function(a){a.preventDefault(),i.imgnext()}),$(document).keyup(function(a){if(!b.end){var c=a.keyCode;a.preventDefault(),37===c?i.imgprev():39===c?i.imgnext():27===c&&layer.close(b.index)}}),b.tabimg=function(){var e,h,i,j,k;b.imgs.removeAttr("style"),d?(j=f[b.imgIndex-1],e=j.src,h=j.pid,i=j.name):(k=g.eq(b.imgIndex-1),e=k.attr("layer-img")||k.attr("src"),h=k.attr("layer-pid")||"",i=k.attr("alt")||""),b.imgs.attr({src:e,"layer-pid":h,alt:i}),b.imgtit.find("em").text(b.imgIndex+"/"+b.imgLen),b.imgsee.show(),a.tab&&a.tab({pid:h,name:i})}},b.resize=function(d){var g,e={},f=[c.width(),c.height()];e.limit=f[0]-f[0]/f[1]*(60*f[0]/f[1]),e.limit<600&&(e.limit=600),g=[e.limit,f[1]>400?f[1]-50:400],g[0]=a.html?g[0]:g[0]-300,layer.area(b.index,{width:g[0]+(a.html?15:0),height:g[1]}),e.flwidth=g[0]-(a.html?300:0),b.imgarea[0]>e.flwidth?b.imgs.css({width:e.flwidth}):b.imgs.css({width:b.imgarea[0]}),b.imgs.outerHeight()'+(a.value||"")+"":function(){return''}();return layer.open($.extend({btn:["确定","取消"],content:e,skin:"layui-layer-prompt"+b("prompt"),success:function(a){d=a.find(".layui-layer-input"),d.focus()},yes:function(b){var e=d.val();""===e?d.focus():e.length>(a.maxlength||500)?layer.tips("最多输入"+(a.maxlength||500)+"个字数",d,{tips:1}):c&&c(e,b,d)}},a))},layer.tab=function(a){a=a||{};var c=a.tab||{};return layer.open($.extend({type:1,skin:"layui-layer-tab"+b("tab"),title:function(){var a=c.length,b=1,d="";if(a>0)for(d=''+c[0].title+"";a>b;b++)d+=""+c[b].title+"";return d}(),content:'",success:function(a){var b=a.find(".layui-layer-title").children(),c=a.find(".layui-layer-tabmain").children();b.on("mousedown",function(a){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0;var b=$(this),d=b.index();b.addClass("layui-layer-tabnow").siblings().removeClass("layui-layer-tabnow"),c.eq(d).show().siblings().hide()})}},a))},layer.photos=function(a,c,d){function e(a,b,c){var d=new Image;d.onload=function(){d.onload=null,b(d)},d.onerror=function(a){d.onerror=null,c(a)},d.src=a}var f={};if(a=a||{},a.photos){var g=a.photos.constructor===Object,h=g?a.photos:{},i=h.data||[],j=h.start||0;if(f.imgIndex=j+1,g){if(0===i.length)return void layer.msg("没有图片")}else{var k=$(a.photos),l=k.find(a.img||"img");if(0===l.length)return;if(c||k.find(h.img||"img").each(function(b){var c=$(this);i.push({alt:c.attr("alt"),pid:c.attr("layer-pid"),src:c.attr("layer-src")||c.attr("src"),thumb:c.attr("src")}),c.on("click",function(){layer.photos($.extend(a,{photos:{start:b,data:i,tab:a.tab},full:a.full}),!0)})}),!c)return}f.imgprev=function(a){f.imgIndex--,f.imgIndex<1&&(f.imgIndex=i.length),f.tabimg(a)},f.imgnext=function(a,b){f.imgIndex++,f.imgIndex>i.length&&(f.imgIndex=1,b)||f.tabimg(a)},f.keyup=function(a){if(!f.end){var b=a.keyCode;a.preventDefault(),37===b?f.imgprev(!0):39===b?f.imgnext(!0):27===b&&layer.close(f.index)}},f.tabimg=function(b){i.length<=1||(h.start=f.imgIndex-1,layer.close(f.index),layer.photos(a,!0,b))},f.event=function(){f.bigimg.hover(function(){f.imgsee.show()},function(){f.imgsee.hide()}),f.bigimg.find(".layui-layer-imgprev").on("click",function(a){a.preventDefault(),f.imgprev()}),f.bigimg.find(".layui-layer-imgnext").on("click",function(a){a.preventDefault(),f.imgnext()}),$(document).on("keyup",f.keyup)},f.loadi=layer.load(1,{shade:"shade"in a?!1:.9,scrollbar:!1}),e(i[j].src,function(c){layer.close(f.loadi),f.index=layer.open($.extend({type:1,area:function(){var b=[c.width,c.height],d=[$(window).width()-100,$(window).height()-100];return!a.full&&b[0]>d[0]&&(b[0]=d[0],b[1]=b[0]*d[1]/b[0]),[b[0]+"px",b[1]+"px"]}(),title:!1,shade:.9,shadeClose:!0,closeBtn:!1,move:".layui-layer-phimg img",moveType:1,scrollbar:!1,moveOut:!0,shift:5*Math.random()|0,skin:"layui-layer-photos"+b("photos"),content:'
'+(i[j].alt||
'+(i.length>1?'':"")+'
'+(i[j].alt||"")+""+f.imgIndex+"/"+i.length+"
",success:function(b,c){f.bigimg=b.find(".layui-layer-phimg"),f.imgsee=b.find(".layui-layer-imguide,.layui-layer-imgbar"),f.event(b),a.tab&&a.tab(i[j],b)},end:function(){f.end=!0,$(document).off("keyup",f.keyup)}},a))},function(){layer.close(f.loadi),layer.msg("当前图片地址异常
是否继续查看下一张?",{time:3e4,btn:["下一张","不看了"],yes:function(){i.length>1&&f.imgnext(!0,!0)}})})}}}(); \ No newline at end of file diff --git a/static/js/layer/layer.js b/static/js/layer/layer.js new file mode 100755 index 000000000..8536abf06 --- /dev/null +++ b/static/js/layer/layer.js @@ -0,0 +1,2 @@ +/*! layer-v2.1 弹层组件 License LGPL http://layer.layui.com/ By 贤心 */ +;!function(a,b){"use strict";var c,d,e={getPath:function(){var a=document.scripts,b=a[a.length-1],c=b.src;if(!b.getAttribute("merge"))return c.substring(0,c.lastIndexOf("/")+1)}(),enter:function(a){13===a.keyCode&&a.preventDefault()},config:{},end:{},btn:["确定","取消"],type:["dialog","page","iframe","loading","tips"]},f={v:"2.1",ie6:!!a.ActiveXObject&&!a.XMLHttpRequest,index:0,path:e.getPath,config:function(a,b){var d=0;return a=a||{},f.cache=e.config=c.extend(e.config,a),f.path=e.config.path||f.path,"string"==typeof a.extend&&(a.extend=[a.extend]),f.use("skin/layer.css",a.extend&&a.extend.length>0?function g(){var c=a.extend;f.use(c[c[d]?d:d-1],d'+(i?f.title[0]:f.title)+"":"";return f.zIndex=g,b([f.shade?'
':"",'
'+(a&&2!=f.type?"":k)+'
'+(0==f.type&&-1!==f.icon?'':"")+(1==f.type&&a?"":f.content||"")+'
'+function(){var a=j?'':"";return f.closeBtn&&(a+=''),a}()+""+(f.btn?function(){var a="";"string"==typeof f.btn&&(f.btn=[f.btn]);for(var b=0,c=f.btn.length;c>b;b++)a+=''+f.btn[b]+"";return'
'+a+"
"}():"")+"
"],k),c},g.pt.creat=function(){var a=this,b=a.config,g=a.index,i=b.content,j="object"==typeof i;switch("string"==typeof b.area&&(b.area="auto"===b.area?["",""]:[b.area,""]),b.type){case 0:b.btn="btn"in b?b.btn:e.btn[0],f.closeAll("dialog");break;case 2:var i=b.content=j?b.content:[b.content||"http://layer.layui.com","auto"];b.content='';break;case 3:b.title=!1,b.closeBtn=!1,-1===b.icon&&0===b.icon,f.closeAll("loading");break;case 4:j||(b.content=[b.content,"body"]),b.follow=b.content[1],b.content=b.content[0]+'',b.title=!1,b.shade=!1,b.fix=!1,b.tips="object"==typeof b.tips?b.tips:[b.tips,!0],b.tipsMore||f.closeAll("tips")}a.vessel(j,function(d,e){c("body").append(d[0]),j?function(){2==b.type||4==b.type?function(){c("body").append(d[1])}():function(){i.parents("."+h[0])[0]||(i.show().addClass("layui-layer-wrap").wrap(d[1]),c("#"+h[0]+g).find("."+h[5]).before(e))}()}():c("body").append(d[1]),a.layero=c("#"+h[0]+g),b.scrollbar||h.html.css("overflow","hidden").attr("layer-full",g)}).auto(g),2==b.type&&f.ie6&&a.layero.find("iframe").attr("src",i[0]),c(document).off("keydown",e.enter).on("keydown",e.enter),a.layero.on("keydown",function(a){c(document).off("keydown",e.enter)}),4==b.type?a.tips():a.offset(),b.fix&&d.on("resize",function(){a.offset(),(/^\d+%$/.test(b.area[0])||/^\d+%$/.test(b.area[1]))&&a.auto(g),4==b.type&&a.tips()}),b.time<=0||setTimeout(function(){f.close(a.index)},b.time),a.move().callback()},g.pt.auto=function(a){function b(a){a=g.find(a),a.height(i[1]-j-k-2*(0|parseFloat(a.css("padding"))))}var e=this,f=e.config,g=c("#"+h[0]+a);""===f.area[0]&&f.maxWidth>0&&(/MSIE 7/.test(navigator.userAgent)&&f.btn&&g.width(g.innerWidth()),g.outerWidth()>f.maxWidth&&g.width(f.maxWidth));var i=[g.innerWidth(),g.innerHeight()],j=g.find(h[1]).outerHeight()||0,k=g.find("."+h[6]).outerHeight()||0;switch(f.type){case 2:b("iframe");break;default:""===f.area[1]?f.fix&&i[1]>=d.height()&&(i[1]=d.height(),b("."+h[5])):b("."+h[5])}return e},g.pt.offset=function(){var a=this,b=a.config,c=a.layero,e=[c.outerWidth(),c.outerHeight()],f="object"==typeof b.offset;a.offsetTop=(d.height()-e[1])/2,a.offsetLeft=(d.width()-e[0])/2,f?(a.offsetTop=b.offset[0],a.offsetLeft=b.offset[1]||a.offsetLeft):"auto"!==b.offset&&(a.offsetTop=b.offset,"rb"===b.offset&&(a.offsetTop=d.height()-e[1],a.offsetLeft=d.width()-e[0])),b.fix||(a.offsetTop=/%$/.test(a.offsetTop)?d.height()*parseFloat(a.offsetTop)/100:parseFloat(a.offsetTop),a.offsetLeft=/%$/.test(a.offsetLeft)?d.width()*parseFloat(a.offsetLeft)/100:parseFloat(a.offsetLeft),a.offsetTop+=d.scrollTop(),a.offsetLeft+=d.scrollLeft()),c.css({top:a.offsetTop,left:a.offsetLeft})},g.pt.tips=function(){var a=this,b=a.config,e=a.layero,f=[e.outerWidth(),e.outerHeight()],g=c(b.follow);g[0]||(g=c("body"));var i={width:g.outerWidth(),height:g.outerHeight(),top:g.offset().top,left:g.offset().left},j=e.find(".layui-layer-TipsG"),k=b.tips[0];b.tips[1]||j.remove(),i.autoLeft=function(){i.left+f[0]-d.width()>0?(i.tipLeft=i.left+i.width-f[0],j.css({right:12,left:"auto"})):i.tipLeft=i.left},i.where=[function(){i.autoLeft(),i.tipTop=i.top-f[1]-10,j.removeClass("layui-layer-TipsB").addClass("layui-layer-TipsT").css("border-right-color",b.tips[1])},function(){i.tipLeft=i.left+i.width+10,i.tipTop=i.top,j.removeClass("layui-layer-TipsL").addClass("layui-layer-TipsR").css("border-bottom-color",b.tips[1])},function(){i.autoLeft(),i.tipTop=i.top+i.height+10,j.removeClass("layui-layer-TipsT").addClass("layui-layer-TipsB").css("border-right-color",b.tips[1])},function(){i.tipLeft=i.left-f[0]-10,i.tipTop=i.top,j.removeClass("layui-layer-TipsR").addClass("layui-layer-TipsL").css("border-bottom-color",b.tips[1])}],i.where[k-1](),1===k?i.top-(d.scrollTop()+f[1]+16)<0&&i.where[2]():2===k?d.width()-(i.left+i.width+f[0]+16)>0||i.where[3]():3===k?i.top-d.scrollTop()+i.height+f[1]+16-d.height()>0&&i.where[0]():4===k&&f[0]+16-i.left>0&&i.where[1](),e.find("."+h[5]).css({"background-color":b.tips[1],"padding-right":b.closeBtn?"30px":""}),e.css({left:i.tipLeft,top:i.tipTop})},g.pt.move=function(){var a=this,b=a.config,e={setY:0,moveLayer:function(){var a=e.layero,b=parseInt(a.css("margin-left")),c=parseInt(e.move.css("left"));0===b||(c-=b),"fixed"!==a.css("position")&&(c-=a.parent().offset().left,e.setY=0),a.css({left:c,top:parseInt(e.move.css("top"))-e.setY})}},f=a.layero.find(b.move);return b.move&&f.attr("move","ok"),f.css({cursor:b.move?"move":"auto"}),c(b.move).on("mousedown",function(a){if(a.preventDefault(),"ok"===c(this).attr("move")){e.ismove=!0,e.layero=c(this).parents("."+h[0]);var f=e.layero.offset().left,g=e.layero.offset().top,i=e.layero.outerWidth()-6,j=e.layero.outerHeight()-6;c("#layui-layer-moves")[0]||c("body").append('
'),e.move=c("#layui-layer-moves"),b.moveType&&e.move.css({visibility:"hidden"}),e.moveX=a.pageX-e.move.position().left,e.moveY=a.pageY-e.move.position().top,"fixed"!==e.layero.css("position")||(e.setY=d.scrollTop())}}),c(document).mousemove(function(a){if(e.ismove){var c=a.pageX-e.moveX,f=a.pageY-e.moveY;if(a.preventDefault(),!b.moveOut){e.setY=d.scrollTop();var g=d.width()-e.move.outerWidth(),h=e.setY;0>c&&(c=0),c>g&&(c=g),h>f&&(f=h),f>d.height()-e.move.outerHeight()+e.setY&&(f=d.height()-e.move.outerHeight()+e.setY)}e.move.css({left:c,top:f}),b.moveType&&e.moveLayer(),c=f=g=h=null}}).mouseup(function(){try{e.ismove&&(e.moveLayer(),e.move.remove(),b.moveEnd&&b.moveEnd()),e.ismove=!1}catch(a){e.ismove=!1}}),a},g.pt.callback=function(){function a(){var a=g.cancel&&g.cancel(b.index);a===!1||f.close(b.index)}var b=this,d=b.layero,g=b.config;b.openLayer(),g.success&&(2==g.type?d.find("iframe").on("load",function(){g.success(d,b.index)}):g.success(d,b.index)),f.ie6&&b.IE6(d),d.find("."+h[6]).children("a").on("click",function(){var e=c(this).index();g["btn"+(e+1)]&&g["btn"+(e+1)](b.index,d),0===e?g.yes?g.yes(b.index,d):f.close(b.index):1===e?a():g["btn"+(e+1)]||f.close(b.index)}),d.find("."+h[7]).on("click",a),g.shadeClose&&c("#layui-layer-shade"+b.index).on("click",function(){f.close(b.index)}),d.find(".layui-layer-min").on("click",function(){f.min(b.index,g),g.min&&g.min(d)}),d.find(".layui-layer-max").on("click",function(){c(this).hasClass("layui-layer-maxmin")?(f.restore(b.index),g.restore&&g.restore(d)):(f.full(b.index,g),g.full&&g.full(d))}),g.end&&(e.end[b.index]=g.end)},e.reselect=function(){c.each(c("select"),function(a,b){var d=c(this);d.parents("."+h[0])[0]||1==d.attr("layer")&&c("."+h[0]).length<1&&d.removeAttr("layer").show(),d=null})},g.pt.IE6=function(a){function b(){a.css({top:f+(e.config.fix?d.scrollTop():0)})}var e=this,f=a.offset().top;b(),d.scroll(b),c("select").each(function(a,b){var d=c(this);d.parents("."+h[0])[0]||"none"===d.css("display")||d.attr({layer:"1"}).hide(),d=null})},g.pt.openLayer=function(){var a=this;f.zIndex=a.config.zIndex,f.setTop=function(a){var b=function(){f.zIndex++,a.css("z-index",f.zIndex+1)};return f.zIndex=parseInt(a[0].style.zIndex),a.on("mousedown",b),f.zIndex}},e.record=function(a){var b=[a.outerWidth(),a.outerHeight(),a.position().top,a.position().left+parseFloat(a.css("margin-left"))];a.find(".layui-layer-max").addClass("layui-layer-maxmin"),a.attr({area:b})},e.rescollbar=function(a){h.html.attr("layer-full")==a&&(h.html[0].style.removeProperty?h.html[0].style.removeProperty("overflow"):h.html[0].style.removeAttribute("overflow"),h.html.removeAttr("layer-full"))},a.layer=f,f.getChildFrame=function(a,b){return b=b||c("."+h[4]).attr("times"),c("#"+h[0]+b).find("iframe").contents().find(a)},f.getFrameIndex=function(a){return c("#"+a).parents("."+h[4]).attr("times")},f.iframeAuto=function(a){if(a){var b=f.getChildFrame("html",a).outerHeight(),d=c("#"+h[0]+a),e=d.find(h[1]).outerHeight()||0,g=d.find("."+h[6]).outerHeight()||0;d.css({height:b+e+g}),d.find("iframe").css({height:b})}},f.iframeSrc=function(a,b){c("#"+h[0]+a).find("iframe").attr("src",b)},f.style=function(a,b){var d=c("#"+h[0]+a),f=d.attr("type"),g=d.find(h[1]).outerHeight()||0,i=d.find("."+h[6]).outerHeight()||0;(f===e.type[1]||f===e.type[2])&&(d.css(b),f===e.type[2]&&d.find("iframe").css({height:parseFloat(b.height)-g-i}))},f.min=function(a,b){var d=c("#"+h[0]+a),g=d.find(h[1]).outerHeight()||0;e.record(d),f.style(a,{width:180,height:g,overflow:"hidden"}),d.find(".layui-layer-min").hide(),"page"===d.attr("type")&&d.find(h[4]).hide(),e.rescollbar(a)},f.restore=function(a){var b=c("#"+h[0]+a),d=b.attr("area").split(",");b.attr("type");f.style(a,{width:parseFloat(d[0]),height:parseFloat(d[1]),top:parseFloat(d[2]),left:parseFloat(d[3]),overflow:"visible"}),b.find(".layui-layer-max").removeClass("layui-layer-maxmin"),b.find(".layui-layer-min").show(),"page"===b.attr("type")&&b.find(h[4]).show(),e.rescollbar(a)},f.full=function(a){var b,g=c("#"+h[0]+a);e.record(g),h.html.attr("layer-full")||h.html.css("overflow","hidden").attr("layer-full",a),clearTimeout(b),b=setTimeout(function(){var b="fixed"===g.css("position");f.style(a,{top:b?0:d.scrollTop(),left:b?0:d.scrollLeft(),width:d.width(),height:d.height()}),g.find(".layui-layer-min").hide()},100)},f.title=function(a,b){var d=c("#"+h[0]+(b||f.index)).find(h[1]);d.html(a)},f.close=function(a){var b=c("#"+h[0]+a),d=b.attr("type");if(b[0]){if(d===e.type[1]&&"object"===b.attr("conType")){b.children(":not(."+h[5]+")").remove();for(var g=0;2>g;g++)b.find(".layui-layer-wrap").unwrap().hide()}else{if(d===e.type[2])try{var i=c("#"+h[4]+a)[0];i.contentWindow.document.write(""),i.contentWindow.close(),b.find("."+h[5])[0].removeChild(i)}catch(j){}b[0].innerHTML="",b.remove()}c("#layui-layer-moves, #layui-layer-shade"+a).remove(),f.ie6&&e.reselect(),e.rescollbar(a),c(document).off("keydown",e.enter),"function"==typeof e.end[a]&&e.end[a](),delete e.end[a]}},f.closeAll=function(a){c.each(c("."+h[0]),function(){var b=c(this),d=a?b.attr("type")===a:1;d&&f.close(b.attr("times")),d=null})},e.run=function(){c=jQuery,d=c(a),h.html=c("html"),f.open=function(a){var b=new g(a);return b.index}},"function"==typeof define?define(function(){return e.run(),f}):function(){e.run(),f.use("skin/layer.css")}()}(window); \ No newline at end of file diff --git a/static/js/layer/layer.min.js b/static/js/layer/layer.min.js deleted file mode 100644 index 4cd35e208..000000000 --- a/static/js/layer/layer.min.js +++ /dev/null @@ -1,16 +0,0 @@ -/**************************************** - - @Name:layer v1.8.5 弹层组件压缩版 - @Author:贤心 - @Date:2014-08-13 - @Blog:http://sentsin.com - @Copyright:Sentsin Xu(贤心) - @官网:http://sentsin.com/jquery/layer - - */ - -;!function(a,b){ -"use strict"; -var c,d, -e="", //组件存放目录,为空表示自动获取 -f={getPath:function(){var a=document.scripts,b=a[a.length-1].src;return e?e:b.substring(0,b.lastIndexOf("/")+1)},type:["dialog","page","iframe","loading","tips"]};a.layer={v:"1.8.5",ie6:!!a.ActiveXObject&&!a.XMLHttpRequest,index:0,path:f.getPath(),use:function(a,b){var d=c("head")[0],a=a.replace(/\s/g,""),e=/\.css$/.test(a),f=document.createElement(e?"link":"script"),g=a.replace(/\.|\//g,"");e&&(f.type="text/css",f.rel="stylesheet"),f[e?"href":"src"]=/^http:\/\//.test(a)?a:layer.path+a,f.id=g,c("#"+g)[0]||d.appendChild(f),b&&(document.all?c(f).ready(b):c(f).load(b))},alert:function(a,b,d,e){var f="function"==typeof d,g={dialog:{msg:a,type:b,yes:f?d:e},area:["auto","auto"]};return f||(g.title=d),c.layer(g)},confirm:function(a,b,d,e){var f="function"==typeof d,g={dialog:{msg:a,type:4,btns:2,yes:b,no:f?d:e}};return f||(g.title=d),c.layer(g)},msg:function(a,d,e,f){var g={title:!1,closeBtn:!1,time:d===b?2:d,dialog:{msg:""===a||a===b?" ":a},end:f};return"object"==typeof e?(g.dialog.type=e.type,g.shade=e.shade,g.shift=e.rate):"function"==typeof e?g.end=e:g.dialog.type=e,c.layer(g)},load:function(a,b){return"string"==typeof a?layer.msg(a,b||0,16):c.layer({time:a,loading:{type:b},bgcolor:b?"#fff":"",shade:b?[.1,"#000"]:[0],border:3!==b&&b?[6,.3,"#000"]:[0],type:3,title:["",!1],closeBtn:[0,!1]})},tips:function(a,b,d,e,f,g){var h={type:4,shade:!1,success:function(a){this.closeBtn||a.find(".xubox_tips").css({"padding-right":10})},bgcolor:"",tips:{msg:a,follow:b}};return h.time="object"==typeof d?d.time:0|d,d=d||{},h.closeBtn=d.closeBtn||!1,h.maxWidth=d.maxWidth||e,h.tips.guide=d.guide||f,h.tips.style=d.style||g,h.tips.more=d.more,c.layer(h)}};var g=["xubox_layer","xubox_iframe",".xubox_title",".xubox_text",".xubox_page",".xubox_main"],h=function(a){var b=this,d=b.config;layer.index++,b.index=layer.index,b.config=c.extend({},d,a),b.config.dialog=c.extend({},d.dialog,a.dialog),b.config.page=c.extend({},d.page,a.page),b.config.iframe=c.extend({},d.iframe,a.iframe),b.config.loading=c.extend({},d.loading,a.loading),b.config.tips=c.extend({},d.tips,a.tips),b.creat()};h.pt=h.prototype,h.pt.config={type:0,shade:[.3,"#000"],fix:!0,move:".xubox_title",title:"信息",offset:["","50%"],area:["310px","auto"],closeBtn:[0,!0],time:0,bgcolor:"#fff",border:[6,.3,"#000"],zIndex:19891014,maxWidth:400,dialog:{btns:1,btn:["确定","取消"],type:8,msg:"",yes:function(a){layer.close(a)},no:function(a){layer.close(a)}},page:{dom:"#xulayer",html:"",url:""},iframe:{src:"http://sentsin.com",scrolling:"auto"},loading:{type:0},tips:{msg:"",follow:"",guide:0,isGuide:!0,style:["background-color:#FF9900; color:#fff;","#FF9900"]},success:function(){},close:function(a){layer.close(a)},end:function(){}},h.pt.space=function(a){var b=this,a=a||"",c=b.index,d=b.config,e=d.dialog,f=-1===e.type?"":'',h=['
'+f+''+e.msg+"
",'
'+a+"
",'','','
'+d.tips.msg+'
'],i="",j="",k=d.zIndex+c,l="z-index:"+k+"; background-color:"+d.shade[1]+"; opacity:"+d.shade[0]+"; filter:alpha(opacity="+100*d.shade[0]+");";d.shade[0]&&(i='
'),d.zIndex=k;var m="",n="",o="z-index:"+(k-1)+"; background-color: "+d.border[2]+"; opacity:"+d.border[1]+"; filter:alpha(opacity="+100*d.border[1]+"); top:-"+d.border[0]+"px; left:-"+d.border[0]+"px;";d.border[0]&&(j='
'),!d.maxmin||1!==d.type&&2!==d.type||/^\d+%$/.test(d.area[0])&&/^\d+%$/.test(d.area[1])||(n=''),d.closeBtn[1]&&(n+='');var p="object"==typeof d.title;return d.title&&(m='
'+(p?d.title[0]:d.title)+"
"),[i,'
'+h[d.type]+m+''+n+'
'+j+"
"]},h.pt.creat=function(){var a=this,b="",d=a.config,e=d.dialog,f=a.index,h=d.page,i=c("body"),j=function(d){var d=d||"";b=a.space(d),i.append(c(b[0]))};switch(d.type){case 0:d.title||(d.area=["auto","auto"]),c(".xubox_dialog")[0]&&layer.close(c(".xubox_dialog").parents("."+g[0]).attr("times"));break;case 1:if(""!==h.html)j('
'+h.html+"
"),i.append(c(b[1]));else if(""!==h.url)j('
'+h.html+"
"),i.append(c(b[1])),c.get(h.url,function(a){c("#xuboxPageHtml"+f).html(a.toString()),h.ok&&h.ok(a)});else{if(0!=c(h.dom).parents(g[4]).length)return;j(),c(h.dom).show().wrap(c(b[1]))}break;case 3:d.title=!1,d.area=["auto","auto"],d.closeBtn=["",!1],c(".xubox_loading")[0]&&layer.closeLoad();break;case 4:d.title=!1,d.area=["auto","auto"],d.fix=!1,d.border=[0],d.tips.more||layer.closeTips()}1!==d.type&&(j(),i.append(c(b[1])));var k=a.layerE=c("#"+g[0]+f);if(k.css({width:d.area[0],height:d.area[1]}),d.fix||k.css({position:"absolute"}),d.title&&(3!==d.type||4!==d.type)){var l=0===d.type?e:d,m=k.find(".xubox_botton");switch(l.btn=d.btn||e.btn,l.btns){case 0:m.html("").hide();break;case 1:m.html(''+l.btn[0]+"");break;case 2:m.html(''+l.btn[0]+''+l.btn[1]+"")}}"auto"===k.css("left")?(k.hide(),setTimeout(function(){k.show(),a.set(f)},500)):a.set(f),d.time<=0||a.autoclose(),a.callback()},f.fade=function(a,b,c){a.css({opacity:0}).animate({opacity:c},b)},h.pt.offset=function(){var a=this,b=a.config,c=a.layerE,e=c.outerHeight();a.offsetTop=""===b.offset[0]&&ee.maxWidth&&i.width(e.maxWidth),o.tipColor=e.tips.style[1],m[0]=i.outerWidth(),o.autoLeft=function(){o.left+m[0]-d.width()>0?(o.tipLeft=o.left+o.width-m[0],p.css({right:12,left:"auto"})):o.tipLeft=o.left},o.where=[function(){o.autoLeft(),o.tipTop=o.top-m[1]-10,p.removeClass("layerTipsB").addClass("layerTipsT").css({"border-right-color":o.tipColor})},function(){o.tipLeft=o.left+o.width+10,o.tipTop=o.top,p.removeClass("layerTipsL").addClass("layerTipsR").css({"border-bottom-color":o.tipColor})},function(){o.autoLeft(),o.tipTop=o.top+o.height+10,p.removeClass("layerTipsT").addClass("layerTipsB").css({"border-right-color":o.tipColor})},function(){o.tipLeft=o.left-m[0]+10,o.tipTop=o.top,p.removeClass("layerTipsR").addClass("layerTipsL").css({"border-bottom-color":o.tipColor})}],o.where[e.tips.guide](),0===e.tips.guide?o.top-(d.scrollTop()+m[1]+16)<0&&o.where[2]():1===e.tips.guide?d.width()-(o.left+o.width+m[0]+16)>0||o.where[3]():2===e.tips.guide?o.top-d.scrollTop()+o.height+m[1]+16-d.height()>0&&o.where[0]():3===e.tips.guide?m[0]+16-o.left>0&&o.where[1]():4===e.tips.guide,i.css({left:o.tipLeft,top:o.tipTop})}e.fadeIn&&(f.fade(i,e.fadeIn,1),f.fade(c("#xubox_shade"+a),e.fadeIn,e.shade[0])),e.fix&&""===e.offset[0]&&!e.shift&&d.on("resize",function(){i.css({top:(d.height()-i.outerHeight())/2})}),b.move()},h.pt.shift=function(a,b,c){var e=this,f=e.config,g=e.layerE,h=0,i=d.width(),j=d.height()+(f.fix?0:d.scrollTop());h="50%"==f.offset[1]||""==f.offset[1]?g.outerWidth()/2:g.outerWidth();var k={t:{top:e.offsetTop},b:{top:j-g.outerHeight()-f.border[0]},cl:h+f.border[0],ct:-g.outerHeight(),cr:i-h-f.border[0]};switch(a){case"left-top":g.css({left:k.cl,top:k.ct}).animate(k.t,b);break;case"top":g.css({top:k.ct}).animate(k.t,b);break;case"right-top":g.css({left:k.cr,top:k.ct}).animate(k.t,b);break;case"right-bottom":g.css({left:k.cr,top:j}).animate(c?k.t:k.b,b);break;case"bottom":g.css({top:j}).animate(c?k.t:k.b,b);break;case"left-bottom":g.css({left:k.cl,top:j}).animate(c?k.t:k.b,b);break;case"left":g.css({left:-g.outerWidth()}).animate({left:e.offsetLeft},b)}},h.pt.autoArea=function(a){var b,d=this,a=a||d.index,e=d.config,f=e.page,h=c("#"+g[0]+a),i=h.find(g[2]),j=h.find(g[5]),k=e.title?i.innerHeight():0,l=0;switch("auto"===e.area[0]&&j.outerWidth()>=e.maxWidth&&h.css({width:e.maxWidth}),e.type){case 0:var m=h.find(".xubox_botton>a");b=h.find(g[3]).outerHeight()+20,m.length>0&&(l=m.outerHeight()+20);break;case 1:var n=h.find(g[4]);b=c(f.dom).outerHeight(),"auto"===e.area[0]&&h.css({width:n.outerWidth()}),(""!==f.html||""!==f.url)&&(b=n.outerHeight());break;case 2:h.find("iframe").css({width:h.outerWidth(),height:h.outerHeight()-(e.title?i.innerHeight():0)});break;case 3:var o=h.find(".xubox_loading");b=o.outerHeight(),j.css({width:o.width()})}"auto"===e.area[1]&&j.css({height:k+b+l}),c("#xubox_border"+a).css({width:h.outerWidth()+2*e.border[0],height:h.outerHeight()+2*e.border[0]}),layer.ie6&&"auto"!==e.area[0]&&j.css({width:h.outerWidth()}),h.css("50%"!==e.offset[1]&&""!=e.offset[1]||4===e.type?{marginLeft:0}:{marginLeft:-h.outerWidth()/2})},h.pt.move=function(){var a=this,b=a.config,e={setY:0,moveLayer:function(){if(0==parseInt(e.layerE.css("margin-left")))var a=parseInt(e.move.css("left"));else var a=parseInt(e.move.css("left"))+-parseInt(e.layerE.css("margin-left"));"fixed"!==e.layerE.css("position")&&(a-=e.layerE.parent().offset().left,e.setY=0),e.layerE.css({left:a,top:parseInt(e.move.css("top"))-e.setY})}},f=a.layerE.find(b.move);b.move&&f.attr("move","ok"),f.css(b.move?{cursor:"move"}:{cursor:"auto"}),c(b.move).on("mousedown",function(a){if(a.preventDefault(),"ok"===c(this).attr("move")){e.ismove=!0,e.layerE=c(this).parents("."+g[0]);var f=e.layerE.offset().left,h=e.layerE.offset().top,i=e.layerE.width()-6,j=e.layerE.height()-6;c("#xubox_moves")[0]||c("body").append('
'),e.move=c("#xubox_moves"),b.moveType&&e.move.css({opacity:0}),e.moveX=a.pageX-e.move.position().left,e.moveY=a.pageY-e.move.position().top,"fixed"!==e.layerE.css("position")||(e.setY=d.scrollTop())}}),c(document).mousemove(function(a){if(e.ismove){var c=a.pageX-e.moveX,f=a.pageY-e.moveY;if(a.preventDefault(),!b.moveOut){e.setY=d.scrollTop();var g=d.width()-e.move.outerWidth()-b.border[0],h=b.border[0]+e.setY;cg&&(c=g),h>f&&(f=h),f>d.height()-e.move.outerHeight()-b.border[0]+e.setY&&(f=d.height()-e.move.outerHeight()-b.border[0]+e.setY)}e.move.css({left:c,top:f}),b.moveType&&e.moveLayer(),c=null,f=null,g=null,h=null}}).mouseup(function(){try{e.ismove&&(e.moveLayer(),e.move.remove()),e.ismove=!1}catch(a){e.ismove=!1}b.moveEnd&&b.moveEnd()})},h.pt.autoclose=function(){var a=this,b=a.config.time,c=function(){b--,0===b&&(layer.close(a.index),clearInterval(a.autotime))};a.autotime=setInterval(c,1e3)},f.config={end:{}},h.pt.callback=function(){var a=this,b=a.layerE,d=a.config,e=d.dialog;a.openLayer(),a.config.success(b),layer.ie6&&a.IE6(b),b.find(".xubox_close").on("click",function(){d.close(a.index),layer.close(a.index)}),b.find(".xubox_yes").on("click",function(){d.yes?d.yes(a.index):e.yes(a.index)}),b.find(".xubox_no").on("click",function(){d.no?d.no(a.index):e.no(a.index),layer.close(a.index)}),a.config.shadeClose&&c("#xubox_shade"+a.index).on("click",function(){layer.close(a.index)}),b.find(".xubox_min").on("click",function(){layer.min(a.index,d),d.min&&d.min(b)}),b.find(".xubox_max").on("click",function(){c(this).hasClass("xubox_maxmin")?(layer.restore(a.index),d.restore&&d.restore(b)):(layer.full(a.index,d),d.full&&d.full(b))}),f.config.end[a.index]=d.end},f.reselect=function(){c.each(c("select"),function(){var a=c(this);a.parents("."+g[0])[0]||1==a.attr("layer")&&c("."+g[0]).length<1&&a.removeAttr("layer").show(),a=null})},h.pt.IE6=function(a){var b=this,e=a.offset().top;if(b.config.fix)var f=function(){a.css({top:d.scrollTop()+e})};else var f=function(){a.css({top:e})};f(),d.scroll(f),c.each(c("select"),function(){var a=c(this);a.parents("."+g[0])[0]||"none"==a.css("display")||a.attr({layer:"1"}).hide(),a=null})},h.pt.openLayer=function(){{var a=this;a.layerE}layer.autoArea=function(b){return a.autoArea(b)},layer.shift=function(b,c,d){a.shift(b,c,d)},layer.setMove=function(){return a.move()},layer.zIndex=a.config.zIndex,layer.setTop=function(a){var b=function(){layer.zIndex++,a.css("z-index",layer.zIndex+1)};return layer.zIndex=parseInt(a[0].style.zIndex),a.on("mousedown",b),layer.zIndex}},f.isauto=function(a,b,c){"auto"===b.area[0]&&(b.area[0]=a.outerWidth()),"auto"===b.area[1]&&(b.area[1]=a.outerHeight()),a.attr({area:b.area+","+c}),a.find(".xubox_max").addClass("xubox_maxmin")},f.rescollbar=function(a){g.html.attr("layer-full")==a&&(g.html[0].style.removeProperty?g.html[0].style.removeProperty("overflow"):g.html[0].style.removeAttribute("overflow"),g.html.removeAttr("layer-full"))},layer.getIndex=function(a){return c(a).parents("."+g[0]).attr("times")},layer.getChildFrame=function(a,b){return b=b||c("."+g[1]).parents("."+g[0]).attr("times"),c("#"+g[0]+b).find("."+g[1]).contents().find(a)},layer.getFrameIndex=function(a){return c(a?"#"+a:"."+g[1]).parents("."+g[0]).attr("times")},layer.iframeAuto=function(a){a=a||c("."+g[1]).parents("."+g[0]).attr("times");var b=layer.getChildFrame("body",a).outerHeight(),d=c("#"+g[0]+a),e=d.find(g[2]),f=0;e&&(f=e.height()),d.css({height:b+f});var h=-parseInt(c("#xubox_border"+a).css("top"));c("#xubox_border"+a).css({height:b+2*h+f}),c("#"+g[1]+a).css({height:b})},layer.iframeSrc=function(a,b){c("#"+g[0]+a).find("iframe").attr("src",b)},layer.area=function(a,b){var d=[c("#"+g[0]+a),c("#xubox_border"+a)],e=d[0].attr("type"),h=d[0].find(g[5]),i=d[0].find(g[2]);if(e===f.type[1]||e===f.type[2]){if(d[0].css(b),h.css({width:b.width,height:b.height}),e===f.type[2]){var j=d[0].find("iframe");j.css({width:b.width,height:i?b.height-i.innerHeight():b.height})}"0px"!==d[0].css("margin-left")&&(b.hasOwnProperty("top")&&d[0].css({top:b.top-(d[1][0]?parseFloat(d[1].css("top")):0)}),b.hasOwnProperty("left")&&d[0].css({left:b.left+d[0].outerWidth()/2-(d[1][0]?parseFloat(d[1].css("left")):0)}),d[0].css({marginLeft:-d[0].outerWidth()/2})),d[1][0]&&d[1].css({width:parseFloat(b.width)-2*parseFloat(d[1].css("left")),height:parseFloat(b.height)-2*parseFloat(d[1].css("top"))})}},layer.min=function(a,b){var d=c("#"+g[0]+a),e=[d.position().top,d.position().left+parseFloat(d.css("margin-left"))];f.isauto(d,b,e),layer.area(a,{width:180,height:35}),d.find(".xubox_min").hide(),"page"===d.attr("type")&&d.find(g[4]).hide(),f.rescollbar(a)},layer.restore=function(a){{var b=c("#"+g[0]+a),d=b.attr("area").split(",");b.attr("type")}layer.area(a,{width:parseFloat(d[0]),height:parseFloat(d[1]),top:parseFloat(d[2]),left:parseFloat(d[3])}),b.find(".xubox_max").removeClass("xubox_maxmin"),b.find(".xubox_min").show(),"page"===b.attr("type")&&b.find(g[4]).show(),f.rescollbar(a)},layer.full=function(a,b){var e,h=c("#"+g[0]+a),i=2*b.border[0]||6,j=[h.position().top,h.position().left+parseFloat(h.css("margin-left"))];f.isauto(h,b,j),g.html.attr("layer-full")||g.html.css("overflow","hidden").attr("layer-full",a),clearTimeout(e),e=setTimeout(function(){layer.area(a,{top:"fixed"===h.css("position")?0:d.scrollTop(),left:"fixed"===h.css("position")?0:d.scrollLeft(),width:d.width()-i,height:d.height()-i})},100)},layer.title=function(a,b){var d=c("#"+g[0]+(b||layer.index)).find(".xubox_title>em");d.html(a)},layer.close=function(a){var b=c("#"+g[0]+a),d=b.attr("type"),e=c("#xubox_moves, #xubox_shade"+a);if(b[0]){if(d==f.type[1])if(b.find(".xuboxPageHtml")[0])b[0].innerHTML="",b.remove();else{b.find(".xubox_setwin,.xubox_close,.xubox_botton,.xubox_title,.xubox_border").remove();for(var h=0;3>h;h++)b.find(".layer_pageContent").unwrap().hide()}else b[0].innerHTML="",b.remove();e.remove(),layer.ie6&&f.reselect(),f.rescollbar(a),"function"==typeof f.config.end[a]&&f.config.end[a](),delete f.config.end[a]}},layer.closeLoad=function(){layer.close(c(".xubox_loading").parents("."+g[0]).attr("times"))},layer.closeTips=function(){layer.closeAll("tips")},layer.closeAll=function(a){c.each(c("."+g[0]),function(){var b=c(this),d=a?b.attr("type")===a:1;d&&layer.close(b.attr("times")),d=null})},f.run=function(){c=jQuery,d=c(a),g.html=c("html"),layer.use("skin/layer.css"),c.layer=function(a){var b=new h(a);return b.index},(new Image).src=layer.path+"skin/default/xubox_ico0.png"},"function"==typeof define?define(function(){return f.run(),layer}):f.run()}(window); \ No newline at end of file diff --git a/static/js/layer/skin/default/icon-ext.png b/static/js/layer/skin/default/icon-ext.png new file mode 100755 index 000000000..bbbb669bb Binary files /dev/null and b/static/js/layer/skin/default/icon-ext.png differ diff --git a/static/js/layer/skin/default/icon.png b/static/js/layer/skin/default/icon.png new file mode 100755 index 000000000..3e17da8b1 Binary files /dev/null and b/static/js/layer/skin/default/icon.png differ diff --git a/static/js/layer/skin/default/icon_ext.png b/static/js/layer/skin/default/icon_ext.png deleted file mode 100644 index 8baee5979..000000000 Binary files a/static/js/layer/skin/default/icon_ext.png and /dev/null differ diff --git a/static/js/layer/skin/default/xubox_loading0.gif b/static/js/layer/skin/default/loading-0.gif old mode 100644 new mode 100755 similarity index 100% rename from static/js/layer/skin/default/xubox_loading0.gif rename to static/js/layer/skin/default/loading-0.gif diff --git a/static/js/layer/skin/default/xubox_loading1.gif b/static/js/layer/skin/default/loading-1.gif old mode 100644 new mode 100755 similarity index 100% rename from static/js/layer/skin/default/xubox_loading1.gif rename to static/js/layer/skin/default/loading-1.gif diff --git a/static/js/layer/skin/default/xubox_loading2.gif b/static/js/layer/skin/default/loading-2.gif old mode 100644 new mode 100755 similarity index 100% rename from static/js/layer/skin/default/xubox_loading2.gif rename to static/js/layer/skin/default/loading-2.gif diff --git a/static/js/layer/skin/default/textbg.png b/static/js/layer/skin/default/textbg.png deleted file mode 100644 index ad1040c42..000000000 Binary files a/static/js/layer/skin/default/textbg.png and /dev/null differ diff --git a/static/js/layer/skin/default/xubox_ico0.png b/static/js/layer/skin/default/xubox_ico0.png deleted file mode 100644 index 7754a47f7..000000000 Binary files a/static/js/layer/skin/default/xubox_ico0.png and /dev/null differ diff --git a/static/js/layer/skin/default/xubox_loading3.gif b/static/js/layer/skin/default/xubox_loading3.gif deleted file mode 100644 index fbe57be3c..000000000 Binary files a/static/js/layer/skin/default/xubox_loading3.gif and /dev/null differ diff --git a/static/js/layer/skin/default/xubox_title0.png b/static/js/layer/skin/default/xubox_title0.png deleted file mode 100644 index 4ffbe3155..000000000 Binary files a/static/js/layer/skin/default/xubox_title0.png and /dev/null differ diff --git a/static/js/layer/skin/layer.css b/static/js/layer/skin/layer.css old mode 100644 new mode 100755 index 4d04643f0..a3908881e --- a/static/js/layer/skin/layer.css +++ b/static/js/layer/skin/layer.css @@ -1,83 +1,7 @@ -/** +/*! @Name: layer's style - @Date: 2012.09.15 @Author: 贤心 - @blog: sentsin.com + @Blog: sentsin.com -**/ - -*html{background-image:url(about:blank); background-attachment:fixed;} - -/** common **/ -.xubox_shade, .xubox_layer{position:fixed; _position:absolute;} -.xubox_shade{top:0; left:0; width:100%; height:100%; _height:expression(document.body.offsetHeight+"px");} -.xubox_layer{top:150px; left:50%; height:auto; width:310px; margin-left:-155px;} -.xubox_border, .xubox_title, .xubox_title i, .xubox_page, .xubox_iframe, .xubox_title em, .xubox_close, .xubox_msgico, .xubox_moves{position:absolute;} -.xubox_border{border-radius: 5px;} -.xubox_title{left:0; top:0;} -.xubox_main{position:relative; height:100%; _float:left;} -.xubox_page{top:0; left:0;} -.xubox_load{background:url(default/xubox_loading0.gif) #fff center center no-repeat;} -.xubox_loading{display:block; float:left; text-decoration:none; color:#FFF; _float:none; } -.xulayer_png32{background:url(default/xubox_ico0.png) no-repeat;} -.xubox_moves{border:3px solid #666; cursor:move; background-color:rgba(255,255,255,.3); background-color:#fff\9; filter:alpha(opacity=50);} - -.xubox_msgico{width:32px; height:32px; top:52px; left:15px; background:url(default/xubox_ico0.png) no-repeat;} -.xubox_text{ padding-left:55px; float:left; line-height:25px; word-break:break-all; padding-right:20px; overflow:hidden; font-size:14px;} -.xubox_msgtype0{background-position:-91px -38px;} -.xubox_msgtype1{background-position:-128px -38px } -.xubox_msgtype2{background-position:-163px -38px;} -.xubox_msgtype3{background-position:-91px -75px;} -.xubox_msgtype4{background-position:-163px -75px;} -.xubox_msgtype5{background-position:-163px -112px;} -.xubox_msgtype6{background-position:-163px -148px;} -.xubox_msgtype7{background-position:-128px -75px;} -.xubox_msgtype8{background-position:-91px -6px;} -.xubox_msgtype9{background-position:-129px -6px;} -.xubox_msgtype10{background-position:-163px -6px;} -.xubox_msgtype11{background-position:-206px -6px;} -.xubox_msgtype12{background-position:-206px -44px;} -.xubox_msgtype13{background-position:-206px -81px;} -.xubox_msgtype14{background-position:-206px -122px;} -.xubox_msgtype15{background-position:-206px -157px;} -.xubox_loading_0{width:60px; height:24px; background:url(default/xubox_loading0.gif) no-repeat;} -.xubox_loading_1{width:37px; height:37px; background:url(default/xubox_loading1.gif) no-repeat;} -.xubox_loading_2, .xubox_msgtype16{width:32px; height:32px; background:url(default/xubox_loading2.gif) no-repeat;} -.xubox_loading_3{width:126px; height:22px; background:url(default/xubox_loading3.gif) no-repeat;} - -.xubox_setwin{position:absolute; right:10px; *right:0; top:10px; font-size:0;} -.xubox_setwin a{position:relative; display:inline-block; *display:inline; *zoom:1; vertical-align:top; width: 14px; height:14px; margin-left:10px; font-size:12px; _overflow:hidden;} -.xubox_setwin .xubox_min cite{position:absolute; width:14px; height:2px; left:0; top:50%; margin-top:-1px; background-color:#919191; cursor:pointer; _overflow:hidden;} -.xubox_setwin .xubox_min:hover cite{background-color:#2D93CA; } -.xubox_setwin .xubox_max{background-position:-6px -189px;} -.xubox_setwin .xubox_max:hover{background-position:-6px -206px;} -.xubox_setwin .xubox_maxmin{background-position:-29px -189px;} -.xubox_setwin .xubox_maxmin:hover{background-position:-29px -206px;} -.xubox_setwin .xubox_close0{ width:14px; height:14px; background-position: -31px -7px; cursor:pointer;} -.xubox_setwin .xubox_close0:hover{background-position:-51px -7px;} -.xubox_setwin .xubox_close1{position:absolute; right:-28px; top:-28px; width:30px; height:30px; margin-left:0; background-position:-60px -195px; *right:-18px; _right:-15px; _top:-23px; _width:14px; _height:14px; _background-position:-31px -7px;} -.xubox_setwin .xubox_close1:hover{ background-position:-91px -195px; _background-position:-51px -7px;} - -.xubox_title{width:100%; height:35px; line-height:35px; border-bottom:1px solid #D5D5D5; background:url(default/xubox_title0.png) #EBEBEB repeat-x; font-size:14px; color:#333;} -.xubox_title em{height:20px; line-height:20px; width:60%; top:7px; left:10px; font-style:normal; text-overflow: ellipsis; overflow: hidden; white-space: nowrap;} - -.xubox_botton a{position:absolute; bottom:10px; left:50%; background:url(default/xubox_ico0.png) repeat; text-decoration:none; color:#FFF; font-size:14px; text-align:center; font-weight:bold; overflow:hidden; } -.xubox_botton a:hover{text-decoration:none; color:#FFF; } -.xubox_botton .xubox_botton1{ width:79px; height:32px; line-height:32px; margin-left:-39px; background-position:-6px -34px;} -.xubox_botton1:hover{background-position:-6px -72px;} -.xubox_botton .xubox_botton2{margin-left:-76px; width:71px; height:29px; line-height:29px; background-position:-5px -114px;} -.xubox_botton2:hover{ background-position:-5px -146px;} -.xubox_botton .xubox_botton3{width:71px; height:29px; line-height:29px; margin-left:10px; background-position:-81px -114px;} -.xubox_botton3:hover{background-position:-81px -146px;} -.xubox_tips{position:relative; line-height:20px; min-width: 12px; padding:3px 30px 3px 10px; font-size:12px; _float:left; border-radius:3px; box-shadow: 1px 1px 3px rgba(0,0,0,.3);} -.xubox_tips i.layerTipsG{ position:absolute; width:0; height:0; border-width:8px; border-color:transparent; border-style:dashed; *overflow:hidden;} -.xubox_tips i.layerTipsT, .xubox_tips i.layerTipsB{left:5px; border-right-style:solid;} -.xubox_tips i.layerTipsT{bottom:-8px;} -.xubox_tips i.layerTipsB{top:-8px;} -.xubox_tips i.layerTipsR, .xubox_tips i.layerTipsL{top:1px; border-bottom-style:solid;} -.xubox_tips i.layerTipsR{left:-8px;} -.xubox_tips i.layerTipsL{right:-8px;} - - - + */*html{background-image:url(about:blank);background-attachment:fixed}html #layui_layer_skinlayercss{display:none;position:absolute;width:1989px}.layui-layer,.layui-layer-shade{position:fixed;_position:absolute;pointer-events:auto}.layui-layer-shade{top:0;left:0;width:100%;height:100%;_height:expression(document.body.offsetHeight+"px")}.layui-layer{top:150px;left:50%;margin:0;padding:0;background-color:#fff;-webkit-background-clip:content;box-shadow:1px 1px 50px rgba(0,0,0,.3);border-radius:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #B2B2B2;border:1px solid rgba(0,0,0,.3);box-shadow:1px 1px 5px rgba(0,0,0,.2)}.layui-layer-moves{position:absolute;border:3px solid #666;border:3px solid rgba(0,0,0,.5);cursor:move;background-color:#fff;background-color:rgba(255,255,255,.3);filter:alpha(opacity=50)}.layui-layer-load{background:url(default/loading-0.gif) center center no-repeat #fff}.layui-layer-ico{background:url(default/icon.png) no-repeat}.layui-layer-btn a,.layui-layer-dialog .layui-layer-ico,.layui-layer-setwin a{display:inline-block;*display:inline;*zoom:1;vertical-align:top}@-webkit-keyframes bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes bounceIn{0%{opacity:0;-webkit-transform:scale(.5);-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layui-anim{-webkit-animation-name:bounceIn;animation-name:bounceIn}@-webkit-keyframes bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.03);transform:scale(1.03)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes bounceOut{100%{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.03);-ms-transform:scale(1.03);transform:scale(1.03)}0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layui-anim-close{-webkit-animation-name:bounceOut;animation-name:bounceOut;-webkit-animation-duration:.2s;animation-duration:.2s}@-webkit-keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layui-anim-01{-webkit-animation-name:zoomInDown;animation-name:zoomInDown}@-webkit-keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.layui-anim-02{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}@-webkit-keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layui-anim-03{-webkit-animation-name:zoomInLeft;animation-name:zoomInLeft}@-webkit-keyframes rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}@keyframes rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);-ms-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}.layui-anim-04{-webkit-animation-name:rollIn;animation-name:rollIn}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.layui-anim-05{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translateX(10px)}}@keyframes shake{0%,100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}}.layui-anim-06{-webkit-animation-name:shake;animation-name:shake}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.layui-layer-title{padding:0 80px 0 20px;height:42px;line-height:42px;border-bottom:1px solid #eee;font-size:14px;color:#333;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background-color:#F8F8F8;border-radius:2px 2px 0 0}.layui-layer-setwin{position:absolute;right:15px;*right:0;top:15px;font-size:0;line-height:initial}.layui-layer-setwin a{position:relative;width:16px;height:16px;margin-left:10px;font-size:12px;_overflow:hidden}.layui-layer-setwin .layui-layer-min cite{position:absolute;width:14px;height:2px;left:0;top:50%;margin-top:-1px;background-color:#2E2D3C;cursor:pointer;_overflow:hidden}.layui-layer-setwin .layui-layer-min:hover cite{background-color:#2D93CA}.layui-layer-setwin .layui-layer-max{background-position:-32px -40px}.layui-layer-setwin .layui-layer-max:hover{background-position:-16px -40px}.layui-layer-setwin .layui-layer-maxmin{background-position:-65px -40px}.layui-layer-setwin .layui-layer-maxmin:hover{background-position:-49px -40px}.layui-layer-setwin .layui-layer-close1{background-position:0 -40px;cursor:pointer}.layui-layer-setwin .layui-layer-close1:hover{opacity:.7}.layui-layer-setwin .layui-layer-close2{position:absolute;right:-28px;top:-28px;width:30px;height:30px;margin-left:0;background-position:-149px -31px;*right:-18px;_display:none}.layui-layer-setwin .layui-layer-close2:hover{background-position:-180px -31px}.layui-layer-btn{text-align:right;padding:0 10px 12px;pointer-events:auto}.layui-layer-btn a{height:28px;line-height:28px;margin:0 6px;padding:0 15px;border:1px solid #dedede;background-color:#f1f1f1;color:#333;border-radius:2px;font-weight:400;cursor:pointer;text-decoration:none}.layui-layer-btn a:hover{opacity:.9;text-decoration:none}.layui-layer-btn a:active{opacity:.7}.layui-layer-btn .layui-layer-btn0{border-color:#4898d5;background-color:#2e8ded;color:#fff}.layui-layer-dialog{min-width:260px}.layui-layer-dialog .layui-layer-content{position:relative;padding:20px;line-height:24px;word-break:break-all;font-size:14px;overflow:auto}.layui-layer-dialog .layui-layer-content .layui-layer-ico{position:absolute;top:16px;left:15px;_left:-40px;width:30px;height:30px}.layui-layer-ico1{background-position:-30px 0}.layui-layer-ico2{background-position:-60px 0}.layui-layer-ico3{background-position:-90px 0}.layui-layer-ico4{background-position:-120px 0}.layui-layer-ico5{background-position:-150px 0}.layui-layer-ico6{background-position:-180px 0}.layui-layer-rim{border:6px solid #8D8D8D;border:6px solid rgba(0,0,0,.3);border-radius:5px;box-shadow:none}.layui-layer-msg{min-width:180px;border:1px solid #D3D4D3;box-shadow:none}.layui-layer-hui{min-width:100px;background-color:#000;filter:alpha(opacity=60);background-color:rgba(0,0,0,.6);color:#fff;border:none}.layui-layer-hui .layui-layer-content{padding:12px 25px;text-align:center}.layui-layer-dialog .layui-layer-padding{padding:20px 20px 20px 55px;text-align:left}.layui-layer-page .layui-layer-content{position:relative;overflow:auto}.layui-layer-iframe .layui-layer-btn,.layui-layer-page .layui-layer-btn{padding-top:10px}.layui-layer-nobg{background:0 0}.layui-layer-iframe .layui-layer-content{overflow:hidden}.layui-layer-iframe iframe{display:block;width:100%}.layui-layer-loading{border-radius:100%;background:0 0;box-shadow:none;border:none}.layui-layer-loading .layui-layer-content{width:60px;height:24px;background:url(default/loading-0.gif) no-repeat}.layui-layer-loading .layui-layer-loading1{width:37px;height:37px;background:url(default/loading-1.gif) no-repeat}.layui-layer-ico16,.layui-layer-loading .layui-layer-loading2{width:32px;height:32px;background:url(default/loading-2.gif) no-repeat}.layui-layer-tips{background:0 0;box-shadow:none;border:none}.layui-layer-tips .layui-layer-content{position:relative;line-height:22px;min-width:12px;padding:5px 10px;font-size:12px;_float:left;border-radius:3px;box-shadow:1px 1px 3px rgba(0,0,0,.3);background-color:#F90;color:#fff}.layui-layer-tips .layui-layer-close{right:-2px;top:-1px}.layui-layer-tips i.layui-layer-TipsG{position:absolute;width:0;height:0;border-width:8px;border-color:transparent;border-style:dashed;*overflow:hidden}.layui-layer-tips i.layui-layer-TipsB,.layui-layer-tips i.layui-layer-TipsT{left:5px;border-right-style:solid;border-right-color:#F90}.layui-layer-tips i.layui-layer-TipsT{bottom:-8px}.layui-layer-tips i.layui-layer-TipsB{top:-8px}.layui-layer-tips i.layui-layer-TipsL,.layui-layer-tips i.layui-layer-TipsR{top:1px;border-bottom-style:solid;border-bottom-color:#F90}.layui-layer-tips i.layui-layer-TipsR{left:-8px}.layui-layer-tips i.layui-layer-TipsL{right:-8px}.layui-layer-lan[type=dialog]{min-width:280px}.layui-layer-lan .layui-layer-title{background:#4476A7;color:#fff;border:none}.layui-layer-lan .layui-layer-lan .layui-layer-btn{padding:10px;text-align:right;border-top:1px solid #E9E7E7}.layui-layer-lan .layui-layer-btn a{background:#BBB5B5;border:none}.layui-layer-lan .layui-layer-btn .layui-layer-btn1{background:#C9C5C5}.layui-layer-molv .layui-layer-title{background:#009f95;color:#fff;border:none}.layui-layer-molv .layui-layer-btn a{background:#009f95}.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92B8B1} \ No newline at end of file diff --git a/static/js/layer/skin/layer.ext.css b/static/js/layer/skin/layer.ext.css old mode 100644 new mode 100755 index 6570a05d9..7a02607b2 --- a/static/js/layer/skin/layer.ext.css +++ b/static/js/layer/skin/layer.ext.css @@ -1,45 +1,8 @@ -/** +/*! @Name: layer拓展样式 @Date: 2012.12.13 @Author: 贤心 @blog: sentsin.com -**/ - -.xubox_iconext{background:url(default/icon_ext.png) no-repeat;} - -/* prompt模式 */ -.xubox_layer .xubox_form{width:240px; height:30px; line-height:30px; padding: 0 5px; border: 1px solid #ccc; background: url(default/textbg.png) #fff repeat-x; color:#333;} -.xubox_layer .xubox_formArea{width:300px; height:100px; line-height:20px;} - -/* tab模式 */ -.xubox_layer .xubox_tab{position:relative; background-color:#fff; box-shadow:1px 1px 50px rgba(0,0,0,.4)} -.xubox_layer .xubox_tabmove{position:absolute; width:600px; height:30px; top:0; left:0;} -.xubox_layer .xubox_tabtit{ display:block; height:34px; border-bottom:1px solid #ccc; background-color:#eee;} -.xubox_layer .xubox_tabtit span{position:relative; float:left; width:120px; height:34px; line-height:34px; text-align:center; cursor:default;} -.xubox_layer .xubox_tabtit span.xubox_tabnow{left:-1px; _top:1px; height:35px; border-left:1px solid #ccc; border-right:1px solid #ccc; background-color:#fff; z-index:10;} -.xubox_layer .xubox_tab_main{line-height:24px; clear:both;} -.xubox_layer .xubox_tab_main .xubox_tabli{display:none;} -.xubox_layer .xubox_tab_main .xubox_tabli.xubox_tab_layer{display:block;} -.xubox_layer .xubox_tabclose{position:absolute; right:10px; top:5px; cursor:pointer;} - -/* photo模式 */ -.xubox_bigimg, .xubox_intro{height:300px} -.xubox_bigimg{position:relative; display:block; width:600px; text-align:center; background:url(default/xubox_loading1.gif) center center no-repeat #000; overflow:hidden; } -.xubox_bigimg img{position:relative; display:inline-block; visibility: hidden;} -.xubox_intro{position:absolute; right:-315px; top:0; width:300px; background-color:#fff; overflow-x:hidden; overflow-y:auto;} -.xubox_imgsee{display:none;} -.xubox_prev, .xubox_next{position:absolute; top:50%; width:27px; _width:44px; height:44px; margin-top:-22px; outline:none;blr:expression(this.onFocus=this.blur());} -.xubox_prev{left:10px; background-position:-5px -5px; _background-position:-70px -5px;} -.xubox_prev:hover{background-position:-33px -5px; _background-position:-120px -5px;} -.xubox_next{right:10px; _right:8px; background-position:-5px -50px; _background-position:-70px -50px;} -.xubox_next:hover{background-position:-33px -50px; _background-position:-120px -50px;} -.xubox_imgbar{position:absolute; left:0; bottom:0; width:100%; height:32px; line-height:32px; background-color:rgba(0,0,0,.8); background-color:#000\9; filter:Alpha(opacity=80); color:#fff; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; font-size:0;} -.xubox_imgtit{/*position:absolute; left:20px;*/} -.xubox_imgtit *{display:inline-block; *display:inline; *zoom:1; vertical-align:top; font-size:12px;} -.xubox_imgtit a{max-width:65%; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; color:#fff;} -.xubox_imgtit a:hover{color:#fff; text-decoration:underline;} -.xubox_imgtit em{padding-left:10px;} - - + */.layui-layer-imgbar,.layui-layer-imgtit a,.layui-layer-tab .layui-layer-title span{text-overflow:ellipsis;white-space:nowrap}.layui-layer-iconext{background:url(default/icon-ext.png) no-repeat}html #layui_layer_skinlayerextcss{display:none;position:absolute;width:1989px}.layui-layer-prompt .layui-layer-input{display:block;width:220px;height:30px;margin:0 auto;line-height:30px;padding:0 5px;border:1px solid #ccc;box-shadow:1px 1px 5px rgba(0,0,0,.1) inset;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px}.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}.layui-layer-tab .layui-layer-title{padding-left:0;border-bottom:1px solid #ccc;background-color:#eee;overflow:visible}.layui-layer-tab .layui-layer-title span{position:relative;float:left;min-width:80px;max-width:260px;padding:0 20px;text-align:center;cursor:default;overflow:hidden}.layui-layer-tab .layui-layer-title span.layui-layer-tabnow{height:43px;border-left:1px solid #ccc;border-right:1px solid #ccc;background-color:#fff;z-index:10}.layui-layer-tab .layui-layer-title span:first-child{border-left:none}.layui-layer-tabmain{line-height:24px;clear:both}.layui-layer-tabmain .layui-layer-tabli{display:none}.layui-layer-tabmain .layui-layer-tabli.xubox_tab_layer{display:block}.xubox_tabclose{position:absolute;right:10px;top:5px;cursor:pointer}.layui-layer-photos{-webkit-animation-duration:1s;animation-duration:1s;background:url(default/xubox_loading1.gif) center center no-repeat #000}.layui-layer-photos .layui-layer-content{overflow:hidden;text-align:center}.layui-layer-photos .layui-layer-phimg img{position:relative;width:100%;display:inline-block;*display:inline;*zoom:1;vertical-align:top}.layui-layer-imgbar,.layui-layer-imguide{display:none}.layui-layer-imgnext,.layui-layer-imgprev{position:absolute;top:50%;width:27px;_width:44px;height:44px;margin-top:-22px;outline:0;blr:expression(this.onFocus=this.blur())}.layui-layer-imgprev{left:10px;background-position:-5px -5px;_background-position:-70px -5px}.layui-layer-imgprev:hover{background-position:-33px -5px;_background-position:-120px -5px}.layui-layer-imgnext{right:10px;_right:8px;background-position:-5px -50px;_background-position:-70px -50px}.layui-layer-imgnext:hover{background-position:-33px -50px;_background-position:-120px -50px}.layui-layer-imgbar{position:absolute;left:0;bottom:0;width:100%;height:32px;line-height:32px;background-color:rgba(0,0,0,.8);background-color:#000\9;filter:Alpha(opacity=80);color:#fff;overflow:hidden;font-size:0}.layui-layer-imgtit *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:12px}.layui-layer-imgtit a{max-width:65%;overflow:hidden;color:#fff}.layui-layer-imgtit a:hover{color:#fff;text-decoration:underline}.layui-layer-imgtit em{padding-left:10px;font-style:normal} \ No newline at end of file diff --git a/templates/foot_script.html b/templates/foot_script.html index 719670369..c9db331b9 100644 --- a/templates/foot_script.html +++ b/templates/foot_script.html @@ -19,7 +19,7 @@ - + diff --git a/templates/jasset/asset_add.html b/templates/jasset/asset_add.html index 1d8eacc28..7ef74920a 100644 --- a/templates/jasset/asset_add.html +++ b/templates/jasset/asset_add.html @@ -42,13 +42,11 @@
+ {{ af.hostname|bootstrap_horizontal }} + +
{{ af.ip|bootstrap_horizontal }} - -
- {{ af.port|bootstrap_horizontal }} - -
- {{ af.idc|bootstrap_horizontal }} +

Tips: 如果IP地址不填写, IP默认会设置与主机名一致

@@ -63,6 +61,7 @@
+ +
{{ af.group|bootstrap_horizontal }} @@ -113,15 +120,17 @@ $('document').ready(function(){ $('#id_use_default_auth').click(function(){ if ($(this).is(':checked')){ - $('#admin_account').css('display', 'none') + $('#admin_account').css('display', 'none'); + $('#id_port').css('display', 'none') } else { - $('#admin_account').css('display', 'block') + $('#admin_account').css('display', 'block'); + $('#id_port').css('display', 'block') } }) }); - var required_fields = ["id_hostname", "id_ip", "id_port"]; + var required_fields = ["id_hostname", "id_port"]; required_fields.forEach(function(field) { $('label[for="' + field + '"]').parent().addClass("required"); }); @@ -134,18 +143,24 @@ check_port: [/^\d{1,5}$/, '端口号不正确'], }, fields: { - "ip": { - rule: "required;check_ip", - tip: "输入IP", +{# "ip": {#} +{# rule: "required;check_ip",#} +{# tip: "输入IP",#} +{# ok: "",#} +{# msg: {required: "必须填写!"}#} +{# },#} + "hostname": { + rule: "required", + tip: "填写主机名", ok: "", msg: {required: "必须填写!"} }, - "port": { - rule: "required;check_port", - tip: "输入端口号", - ok: "", - msg: {required: "必须填写!"} - } +{# "port": {#} +{# rule: "required;check_port",#} +{# tip: "输入端口号",#} +{# ok: "",#} +{# msg: {required: "必须填写!"}#} +{# }#} }, valid: function(form) { form.submit(); diff --git a/templates/jasset/asset_add_bak.html b/templates/jasset/asset_add_bak.html deleted file mode 100644 index 397d60aeb..000000000 --- a/templates/jasset/asset_add_bak.html +++ /dev/null @@ -1,166 +0,0 @@ -{% extends 'base.html' %} -{% load mytags %} -{% block content %} -{% include 'nav_cat_bar.html' %} -
-
-
-
-
-
填写资产基本信息
- -
- -
-
- -
-
-
- {% if error %} -
{{ error }}
- {% endif %} - {% if msg %} -
{{ msg }}
- {% endif %} - -
-
-
- -
-
- -
- -
-
- -
-
- -
-
- -
-
-
- - - -
-
- -
- -
-
- -
-
-
-
- - -
-
-
- -
-
-
-
- -
-
-
- - -
-
- -
-
-
-
-
-
-
-
-
-{% endblock %} - -{% block self_footer_js %} - - -{% endblock %} \ No newline at end of file diff --git a/templates/jasset/asset_detail.html b/templates/jasset/asset_detail.html index ef202bae9..4efb669a3 100644 --- a/templates/jasset/asset_detail.html +++ b/templates/jasset/asset_detail.html @@ -200,6 +200,7 @@
主机修改记录
+     点击修改 +
{{ af.group|bootstrap_horizontal }} @@ -156,15 +165,17 @@ $('document').ready(function(){ $('#id_use_default_auth').click(function(){ if ($(this).is(':checked')){ - $('#admin_account').css('display', 'none') + $('#admin_account').css('display', 'none'); + $('#id_port').css('display', 'none') } else { - $('#admin_account').css('display', 'block') + $('#admin_account').css('display', 'block'); + $('#id_port').css('display', 'block') } }) }); - var required_fields = ["id_ip", "id_port"]; + var required_fields = ["id_hostname", "id_port"]; required_fields.forEach(function(field) { $('label[for="' + field + '"]').parent().addClass("required"); }); @@ -177,18 +188,23 @@ check_port: [/^\d{1,5}$/, '端口号不正确'], }, fields: { - "ip": { - rule: "required;check_ip", - tip: "输入IP", + "hostname": { + rule: "required", + tip: "填写主机名", ok: "", msg: {required: "必须填写!"} }, - "port": { - rule: "required;check_port", - tip: "输入端口号", - ok: "", - msg: {required: "必须填写!"} - } +{# "ip": {#} +{# rule: "required;check_ip",#} +{# tip: "输入IP",#} +{# ok: "",#} +{# msg: {required: "必须填写!"}#} +{# },#} +{# "port": {#} +{# rule: "required;check_port",#} +{# tip: "输入端口号",#} +{# ok: "",#} +{# msg: {required: "必须填写!"}#} }, valid: function(form) { form.submit(); diff --git a/templates/jasset/asset_edit_batch.html b/templates/jasset/asset_edit_batch.html index 5422a75b1..47232c9d2 100644 --- a/templates/jasset/asset_edit_batch.html +++ b/templates/jasset/asset_edit_batch.html @@ -7,9 +7,9 @@ -{# #} + {% load bootstrap %} @@ -20,21 +20,21 @@
- +{#
#} +{#
填写修改主机信息.
#} +{#
#} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{#
#} +{#
#}
@@ -49,33 +49,43 @@ {{ af.port|bootstrap_horizontal }}
-
+
- - -{% endblock %} \ No newline at end of file diff --git a/templates/jasset/group_edit.html b/templates/jasset/group_edit.html index 8cb4ca9bb..a105c278b 100644 --- a/templates/jasset/group_edit.html +++ b/templates/jasset/group_edit.html @@ -31,10 +31,6 @@ @@ -44,13 +40,13 @@ - {% for asset in asset_select %} - + {% endfor %} @@ -86,7 +82,7 @@
@@ -103,7 +99,7 @@
diff --git a/templates/jasset/group_list.html b/templates/jasset/group_list.html index d7bc42d3c..5141127af 100644 --- a/templates/jasset/group_list.html +++ b/templates/jasset/group_list.html @@ -58,10 +58,10 @@ {{ asset_group.name }} -
{{ asset_group.asset_set.count }} + {{ asset_group.asset_set.count }} {{ asset_group.comment }} - 详情 + 详情 编辑 删除 diff --git a/templates/jasset/host_add_multi.html b/templates/jasset/host_add_multi.html deleted file mode 100644 index 122ca2ec3..000000000 --- a/templates/jasset/host_add_multi.html +++ /dev/null @@ -1,68 +0,0 @@ -{% extends 'base.html' %} -{% block content %} -{% include 'nav_cat_bar.html' %} -
-
-
-
-
-
填写主机基本信息
- -
- -
-
- -
-
- {% if emg %} -
{{ emg }}
- {% endif %} - {% if smg %} -
{{ smg }}
- {% endif %} -

请严格按照文本框内主机信息格式填写, 多台主机回车换行, 具体格式如下:

-

IP地址 端口号 登录方式 IDC名 所属主机组 所属部门 激活/禁用 备注

-
-
-
-
-
- - -
-
-
-
-
-
-
-
-
-
-
-
- - -{% endblock %} \ No newline at end of file diff --git a/templates/jasset/host_list_common.html b/templates/jasset/host_list_common.html deleted file mode 100644 index 3ea78f019..000000000 --- a/templates/jasset/host_list_common.html +++ /dev/null @@ -1,172 +0,0 @@ -{% extends 'base.html' %} -{% load mytags %} -{% block content %} -{% include 'nav_cat_bar.html' %} - -
-
-
-
-
-
主机详细信息列表
- -
- -
-
- 点击别名栏修改主机别名, 可在跳板机上使用别名直接登录. - -
- -
- - - - - - - - - - - - - - - - - {% for post in contacts.object_list %} - - - - - - - - - - - - - {% endfor %} - -
IP地址 端口号 登录方式 所属IDC 所属部门 所属主机组 别名 备注 操作
{{ post.ip }} {{ post.port }} {{ post.login_type|get_login_type }} {{ post.idc.name }} {{ post.dept.all | group_str2 }}{{ post.bis_group.all | group_str2_all }} {{ post|get_user_alias:user_id }} {{ post.comment }} - 详情 -
-
-
- -
- {% include 'paginator.html' %} -
-
-
-
-
-
-
- - - -{% endblock %} \ No newline at end of file diff --git a/templates/jasset/host_list_nop.html b/templates/jasset/host_list_nop.html deleted file mode 100644 index eb1e3dd34..000000000 --- a/templates/jasset/host_list_nop.html +++ /dev/null @@ -1,177 +0,0 @@ -{% extends 'base.html' %} -{% load mytags %} -{% block content %} -{% include 'nav_cat_bar.html' %} - -
-
-
-
-
-
主机详细信息列表
- -
- -
-
- 添加 - - - - - - - - - - - -
- -
- - - - - - - - - - - - - - - - - {% for post in posts %} - - - - - - - - - - - - - {% endfor %} - -
IP地址 端口号 登录方式 所属IDC 所属部门 所属主机组 是否激活 备注 操作
{{ post.ip }} {{ post.port }} {{ post.login_type|get_login_type }} {{ post.idc.name }} {{ post.dept.all | group_str2 }}{{ post.bis_group.all | group_str2_all }} {{ post.is_active|bool2str }} {{ post.comment }} - 详情 - {% ifnotequal session_role_id 0 %} - 编辑 - 删除 - {% endifnotequal %} -
-
-
- - -
- -
-
-
-
-
-
-
- - - -{% endblock %} \ No newline at end of file diff --git a/templates/jasset/host_search.html b/templates/jasset/host_search.html deleted file mode 100644 index 38ed8c1ad..000000000 --- a/templates/jasset/host_search.html +++ /dev/null @@ -1,169 +0,0 @@ -{% load mytags %} - - - - - - - - - - {% ifnotequal session_role_id 0 %} - - {% else %} - - {% endifnotequal %} - - - - - - - {% for post in contacts.object_list %} - - - - - - - - {% ifnotequal session_role_id 0 %} - - {% else %} - - {% endifnotequal %} - - - - - {% endfor %} - -
IP地址 端口号 登录方式 所属IDC 所属业务组 是否激活 别名 添加时间 备注 操作
{{ post.ip }} {{ post.port }} {{ post.login_type|get_login_type }} {{ post.idc.name }} {{ post.bis_group.all | group_str2 }} {{ post.is_active|bool2str }} {{ post|get_user_alias:user_id }} {{ post.date_added|date:"Y-m-d H:i:s" }} {{ post.comment }} - 详情 - {% ifnotequal session_role_id 0 %} - 编辑 - 删除 - {% endifnotequal %} -
-
-
- - -
-
-
-
    - - {% if contacts.has_previous %} - - {% else %} - - {% endif %} - {% ifequal show_first 1 %} -
  • 1...
  • - {% endifequal %} - {% for page in page_range %} - {% ifequal current_page page %} -
  • {{ page }}
  • - {% else %} -
  • {{ page }}
  • - {% endifequal %} - {% endfor %} - {% ifequal show_end 1 %} -
  • ...{{ p.num_pages }}
  • - {% endifequal %} - {% if contacts.has_next %} - - {% else %} - - {% endif %} -
-
-
- -
- - diff --git a/templates/jasset/idc_detail.html b/templates/jasset/idc_detail.html deleted file mode 100644 index 0d61dfa1c..000000000 --- a/templates/jasset/idc_detail.html +++ /dev/null @@ -1,229 +0,0 @@ -{% extends 'base.html' %} -{% load mytags %} -{% block content %} -{% include 'nav_cat_bar.html' %} - -
-
-
-
-
-
IDC {{ idc.name }} 详细信息列表
- -
- -
- {% if emg %} -
{{ emg }}
- {% endif %} - {% if smg %} -
{{ smg }}
- {% endif %} - - -
- - - - - - - - - - - - - - - {% for asset in contact_list %} - - - - - - - - - - - {% endfor %} - -
- - IP地址 主机名 IDC 所属主机组 配置信息 使用默认管理 操作
- - {{ asset.ip }} {{ asset.hostname }} {{ asset.idc.name }} {{ asset.group.all|group_str2 }}{{ asset.cpu }}|{{ asset.memory }}|{{ asset.disk }} {{ asset.use_default_auth|bool2str }} - 详情 - {% ifnotequal session_role_id 0 %} - 编辑 - 删除 - {% endifnotequal %} -
-
-
- - 修改 -
-
-
-
    - {% if keyword %} - {% if contacts.has_previous %} - - {% else %} - - {% endif %} - {% ifequal show_first 1 %} -
  • 1...
  • - {% endifequal %} - {% for page in page_range %} - {% ifequal current_page page %} -
  • {{ page }}
  • - {% else %} -
  • {{ page }}
  • - {% endifequal %} - {% endfor %} - {% ifequal show_end 1 %} -
  • ...{{ p.num_pages }}
  • - {% endifequal %} - {% if contacts.has_next %} - - {% else %} - - {% endif %} - - {% else %} - {% if contacts.has_previous %} - - {% else %} - - {% endif %} - {% ifequal show_first 1 %} -
  • 1...
  • - {% endifequal %} - {% for page in page_range %} - {% ifequal current_page page %} -
  • {{ page }}
  • - {% else %} -
  • {{ page }}
  • - {% endifequal %} - {% endfor %} - {% ifequal show_end 1 %} -
  • ...{{ p.num_pages }}
  • - {% endifequal %} - {% if contacts.has_next %} - - {% else %} - - {% endif %} - {% endif %} -
-
-
-
-
-
-
-
-
-
- - - -{% endblock %} \ No newline at end of file diff --git a/templates/jasset/idc_list.html b/templates/jasset/idc_list.html index 85a409ea2..05812783c 100644 --- a/templates/jasset/idc_list.html +++ b/templates/jasset/idc_list.html @@ -52,6 +52,8 @@ {% endifequal %} 机房名 主机数量 + 联系人 + 电话 备注 操作 @@ -59,14 +61,16 @@ {% for post in contacts.object_list %} - + {{ post.name }} - {{ post.asset_set.count }} + {{ post.asset_set.count }} + {{ post.linkman }} + {{ post.phone }} {{ post.comment }} - 详情 + 详情 编辑 - 删除 + 删除 {% endfor %} @@ -75,7 +79,7 @@
{% ifequal session_role_id 2 %} - + {% endifequal %}
@@ -89,27 +93,37 @@
{% endblock %} \ No newline at end of file diff --git a/templates/jperm/perm_rule_add.html b/templates/jperm/perm_rule_add.html index 6a34cfcf4..3eef4eb00 100644 --- a/templates/jperm/perm_rule_add.html +++ b/templates/jperm/perm_rule_add.html @@ -118,6 +118,37 @@ {% endblock %} {% block self_footer_js %}