|
|
@@ -0,0 +1,910 @@
|
|
|
+<!DOCTYPE html>
|
|
|
+<html lang="zh-CN">
|
|
|
+<head>
|
|
|
+ <meta charset="UTF-8">
|
|
|
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
|
+ <title>订单询价</title>
|
|
|
+ <meta property="og:title" content="订单询价">
|
|
|
+ <meta property="og:image" content="{:htmlentities(default_admin_avatar_url())}">
|
|
|
+ <link rel="shortcut icon" href="{:htmlentities(default_admin_avatar_url())}" type="image/png">
|
|
|
+ <link rel="icon" href="{:htmlentities(default_admin_avatar_url())}" type="image/png">
|
|
|
+ <link rel="apple-touch-icon" href="{:htmlentities(default_admin_avatar_url())}">
|
|
|
+ <style>
|
|
|
+ * { box-sizing: border-box; }
|
|
|
+ html, body { margin: 0; height: 100%; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; background: #f5f5f5; color: #333; }
|
|
|
+ :root {
|
|
|
+ --bar-h: 52px;
|
|
|
+ --tabbar-h: 52px;
|
|
|
+ --safe-bottom: env(safe-area-inset-bottom, 0px);
|
|
|
+ }
|
|
|
+ body.layout-orders { overflow: hidden; }
|
|
|
+ body.layout-me { overflow: hidden; }
|
|
|
+ .bar {
|
|
|
+ position: fixed; top: 0; left: 0; right: 0; z-index: 50;
|
|
|
+ height: var(--bar-h); padding: 0 14px;
|
|
|
+ background: #3c8dbc; color: #fff;
|
|
|
+ display: flex; align-items: center; justify-content: center;
|
|
|
+ }
|
|
|
+ .bar h1 {
|
|
|
+ position: absolute; left: 0; right: 0;
|
|
|
+ margin: 0; font-size: 1.05rem; font-weight: 600;
|
|
|
+ text-align: center; pointer-events: none;
|
|
|
+ }
|
|
|
+ .bar a {
|
|
|
+ margin-left: auto; position: relative; z-index: 1;
|
|
|
+ color: #fff; text-decoration: none; font-size: 13px;
|
|
|
+ padding: 5px 10px; border: 1px solid rgba(255,255,255,.6); border-radius: 6px;
|
|
|
+ }
|
|
|
+ body.layout-orders .bar-logout { display: none !important; }
|
|
|
+ #pane-orders {
|
|
|
+ position: fixed; left: 0; right: 0; z-index: 10;
|
|
|
+ top: var(--bar-h); bottom: calc(var(--tabbar-h) + var(--safe-bottom));
|
|
|
+ display: flex; flex-direction: column; overflow: hidden; background: #f5f5f5;
|
|
|
+ }
|
|
|
+ #pane-me {
|
|
|
+ position: fixed; left: 0; right: 0; z-index: 10;
|
|
|
+ top: var(--bar-h); bottom: calc(var(--tabbar-h) + var(--safe-bottom));
|
|
|
+ overflow-y: auto; -webkit-overflow-scrolling: touch; background: #f5f5f5;
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+ .toolbar {
|
|
|
+ flex-shrink: 0; padding: 10px 12px; background: #e8f4fc;
|
|
|
+ border-bottom: 1px solid #d2e7f4; display: flex; gap: 8px; align-items: center;
|
|
|
+ }
|
|
|
+ .toolbar input[type="search"] {
|
|
|
+ flex: 1; min-width: 0; padding: 10px 12px; border: 1px solid #bcd8ea;
|
|
|
+ border-radius: 8px; font-size: 15px; background: #fff;
|
|
|
+ }
|
|
|
+ .toolbar input:focus { outline: none; border-color: #3c8dbc; }
|
|
|
+ .toolbar .btn-search,
|
|
|
+ .toolbar .btn-add {
|
|
|
+ flex-shrink: 0; padding: 10px 12px; border: none; border-radius: 8px;
|
|
|
+ font-size: 14px; font-weight: 600; font-family: inherit; cursor: pointer;
|
|
|
+ }
|
|
|
+ .toolbar .btn-search { background: #3c8dbc; color: #fff; }
|
|
|
+ .toolbar .btn-add { background: #27ae60; color: #fff; }
|
|
|
+ .list-wrap {
|
|
|
+ flex: 1 1 0%; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch;
|
|
|
+ padding: 10px 12px 20px;
|
|
|
+ }
|
|
|
+ .card {
|
|
|
+ background: #fff; border-radius: 10px; padding: 12px 14px;
|
|
|
+ margin-bottom: 10px; box-shadow: 0 1px 4px rgba(0,0,0,.06);
|
|
|
+ }
|
|
|
+ .card .ord { font-size: 15px; font-weight: 700; color: #222; line-height: 1.4; word-break: break-all; }
|
|
|
+ .card .meta { margin-top: 8px; font-size: 13px; color: #555; line-height: 1.55; }
|
|
|
+ .card .meta b { color: #888; font-weight: 500; }
|
|
|
+ .card .tags {
|
|
|
+ margin-top: 8px; display: flex; flex-wrap: wrap; gap: 6px 10px;
|
|
|
+ font-size: 12px; color: #666; align-items: center;
|
|
|
+ }
|
|
|
+ .card .progress {
|
|
|
+ display: inline-block; padding: 2px 8px; border-radius: 10px;
|
|
|
+ background: #eef6fb; color: #3c8dbc; font-weight: 600;
|
|
|
+ }
|
|
|
+ .card .progress.is-done { background: #eaf7ee; color: #27ae60; }
|
|
|
+ .card .time { color: #999; }
|
|
|
+ .card .btn-view-quote {
|
|
|
+ margin-left: auto; padding: 4px 10px; border: 1px solid #3c8dbc;
|
|
|
+ border-radius: 6px; background: #fff; color: #3c8dbc;
|
|
|
+ font-size: 12px; font-weight: 600; font-family: inherit; cursor: pointer;
|
|
|
+ }
|
|
|
+ .card .btn-view-quote:active { background: #eef6fb; }
|
|
|
+ .empty { text-align: center; color: #999; padding: 48px 16px; font-size: 14px; }
|
|
|
+ .rfq-mask {
|
|
|
+ display: none; position: fixed; inset: 0; z-index: 2000;
|
|
|
+ background: rgba(0,0,0,.45); align-items: center; justify-content: center;
|
|
|
+ padding: 24px 28px;
|
|
|
+ padding-bottom: calc(24px + var(--safe-bottom));
|
|
|
+ }
|
|
|
+ .rfq-mask.show { display: flex; }
|
|
|
+ .rfq-sheet {
|
|
|
+ width: 100%; max-width: 340px; max-height: min(72vh, 560px);
|
|
|
+ background: #fff; border-radius: 12px;
|
|
|
+ display: flex; flex-direction: column; overflow: hidden;
|
|
|
+ box-shadow: 0 8px 28px rgba(0,0,0,.18);
|
|
|
+ }
|
|
|
+ .rfq-sheet-head {
|
|
|
+ flex: 0 0 auto; padding: 10px 12px; border-bottom: 1px solid #eee;
|
|
|
+ display: flex; align-items: center; justify-content: space-between;
|
|
|
+ }
|
|
|
+ .rfq-sheet-head h2 { margin: 0; font-size: 15px; font-weight: 700; color: #222; }
|
|
|
+ .rfq-sheet-head .rfq-close {
|
|
|
+ border: none; background: transparent; color: #888; font-size: 20px;
|
|
|
+ line-height: 1; padding: 0 4px; cursor: pointer;
|
|
|
+ }
|
|
|
+ .rfq-sheet-body {
|
|
|
+ flex: 1 1 auto; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch;
|
|
|
+ padding: 10px 12px 6px;
|
|
|
+ }
|
|
|
+ .rfq-field { margin-bottom: 8px; }
|
|
|
+ .rfq-field label {
|
|
|
+ display: block; font-size: 12px; color: #666; margin-bottom: 4px; font-weight: 600;
|
|
|
+ }
|
|
|
+ .rfq-field label .req { color: #e74c3c; margin-left: 2px; }
|
|
|
+ .rfq-field input,
|
|
|
+ .rfq-field textarea {
|
|
|
+ width: 100%; padding: 8px 10px; border: 1px solid #ddd; border-radius: 8px;
|
|
|
+ font-size: 14px; font-family: inherit; background: #fff; color: #333;
|
|
|
+ }
|
|
|
+ .rfq-field input:focus,
|
|
|
+ .rfq-field textarea:focus { outline: none; border-color: #3c8dbc; }
|
|
|
+ .rfq-field input[readonly] { background: #f5f5f5; color: #555; }
|
|
|
+ .rfq-field textarea { resize: vertical; min-height: 64px; }
|
|
|
+ .rfq-dept-combo { position: relative; }
|
|
|
+ .rfq-dept-combo .rfq-dept-row {
|
|
|
+ display: flex; align-items: stretch; gap: 0;
|
|
|
+ border: 1px solid #ddd; border-radius: 8px; background: #fff; overflow: hidden;
|
|
|
+ }
|
|
|
+ .rfq-dept-combo .rfq-dept-row:focus-within { border-color: #3c8dbc; }
|
|
|
+ .rfq-dept-combo #cclbmmc {
|
|
|
+ flex: 1 1 auto; min-width: 0; border: none; border-radius: 0;
|
|
|
+ padding: 8px 10px; font-size: 14px;
|
|
|
+ }
|
|
|
+ .rfq-dept-combo #cclbmmc:focus { outline: none; }
|
|
|
+ .rfq-dept-combo .rfq-dept-toggle {
|
|
|
+ flex: 0 0 38px; border: none; border-left: 1px solid #e5e5e5;
|
|
|
+ background: #fafafa; color: #666; font-size: 11px; cursor: pointer;
|
|
|
+ }
|
|
|
+ .rfq-dept-combo .rfq-dept-menu {
|
|
|
+ display: none; position: absolute; left: 0; right: 0; top: calc(100% + 4px);
|
|
|
+ z-index: 5; max-height: 160px; overflow-y: auto;
|
|
|
+ background: #fff; border: 1px solid #ddd; border-radius: 8px;
|
|
|
+ box-shadow: 0 6px 18px rgba(0,0,0,.12);
|
|
|
+ }
|
|
|
+ .rfq-dept-combo.open .rfq-dept-menu { display: block; }
|
|
|
+ .rfq-dept-combo .rfq-dept-item {
|
|
|
+ display: block; width: 100%; padding: 9px 10px; border: none;
|
|
|
+ background: #fff; text-align: left; font-size: 13px; color: #333;
|
|
|
+ font-family: inherit; cursor: pointer; border-bottom: 1px solid #f3f3f3;
|
|
|
+ }
|
|
|
+ .rfq-dept-combo .rfq-dept-item:last-child { border-bottom: none; }
|
|
|
+ .rfq-dept-combo .rfq-dept-item:active,
|
|
|
+ .rfq-dept-combo .rfq-dept-item:hover { background: #f0f7fb; color: #3c8dbc; }
|
|
|
+ .rfq-dept-combo .rfq-dept-empty {
|
|
|
+ display: none; padding: 10px; color: #999; font-size: 12px; text-align: center;
|
|
|
+ }
|
|
|
+ .rfq-sheet-acts {
|
|
|
+ flex: 0 0 auto; display: flex; gap: 8px; padding: 10px 12px;
|
|
|
+ border-top: 1px solid #eee; background: #fff;
|
|
|
+ }
|
|
|
+ .rfq-sheet-acts button {
|
|
|
+ flex: 1; padding: 10px 8px; border: none; border-radius: 8px;
|
|
|
+ font-size: 14px; font-weight: 600; font-family: inherit; cursor: pointer;
|
|
|
+ }
|
|
|
+ .rfq-quote-table {
|
|
|
+ width: 100%; border-collapse: collapse; font-size: 13px;
|
|
|
+ }
|
|
|
+ .rfq-quote-table th,
|
|
|
+ .rfq-quote-table td {
|
|
|
+ padding: 8px 6px; border-bottom: 1px solid #eee; text-align: left;
|
|
|
+ vertical-align: middle; word-break: break-all;
|
|
|
+ }
|
|
|
+ .rfq-quote-table th {
|
|
|
+ color: #888; font-weight: 600; font-size: 12px; background: #fafafa;
|
|
|
+ }
|
|
|
+ .rfq-quote-table td.col-amt { text-align: right; white-space: nowrap; width: 88px; }
|
|
|
+ .rfq-quote-table .muted { color: #bbb; }
|
|
|
+ .rfq-quote-empty { text-align: center; color: #999; padding: 28px 8px; font-size: 13px; }
|
|
|
+ .rfq-sheet-acts .btn-reset { background: #f0f0f0; color: #555; }
|
|
|
+ .rfq-sheet-acts .btn-submit { background: #3c8dbc; color: #fff; }
|
|
|
+ .rfq-sheet-acts .btn-submit:disabled { opacity: .55; }
|
|
|
+ .me-panel { padding: 16px 14px 24px; max-width: 480px; margin: 0 auto; }
|
|
|
+ .me-card { background: #fff; border-radius: 12px; padding: 18px 16px; box-shadow: 0 1px 6px rgba(0,0,0,.06); }
|
|
|
+ .me-row { font-size: 14px; line-height: 1.7; padding: 8px 0; border-bottom: 1px solid #f0f0f0; }
|
|
|
+ .me-row span { display: inline-block; min-width: 5em; color: #888; }
|
|
|
+ .btn-me-pwd {
|
|
|
+ display: block; width: 100%; margin-top: 16px; padding: 12px;
|
|
|
+ border: 1px solid #3c8dbc; border-radius: 8px; background: #fff;
|
|
|
+ color: #3c8dbc; font-size: 15px; font-weight: 600; text-align: center;
|
|
|
+ cursor: pointer; font-family: inherit;
|
|
|
+ }
|
|
|
+ .pwd-mask {
|
|
|
+ display: none; position: fixed; inset: 0; z-index: 2100;
|
|
|
+ background: rgba(0,0,0,.45); align-items: center; justify-content: center;
|
|
|
+ padding: 24px 28px; padding-bottom: calc(24px + var(--safe-bottom));
|
|
|
+ }
|
|
|
+ .pwd-mask.show { display: flex; }
|
|
|
+ .pwd-sheet {
|
|
|
+ width: 100%; max-width: 360px; background: #fff; border-radius: 14px;
|
|
|
+ padding: 18px 18px 20px; box-shadow: 0 8px 32px rgba(0,0,0,.12);
|
|
|
+ }
|
|
|
+ .pwd-sheet .pwd-head { font-size: 16px; font-weight: 600; margin: 0 0 14px; color: #222; }
|
|
|
+ .pwd-field { margin-bottom: 14px; }
|
|
|
+ .pwd-field label { display: block; font-size: 13px; color: #666; margin-bottom: 6px; }
|
|
|
+ .pwd-field input {
|
|
|
+ width: 100%; padding: 11px 12px; border: 1px solid #ddd; border-radius: 8px;
|
|
|
+ font-size: 16px; font-family: inherit;
|
|
|
+ }
|
|
|
+ .pwd-acts { display: flex; gap: 10px; margin-top: 18px; }
|
|
|
+ .pwd-acts button {
|
|
|
+ flex: 1; padding: 12px; border-radius: 8px; font-size: 15px; border: none;
|
|
|
+ cursor: pointer; font-family: inherit;
|
|
|
+ }
|
|
|
+ .pwd-acts .pwd-cancel { background: #f0f0f0; color: #555; }
|
|
|
+ .pwd-acts .pwd-ok { background: #3c8dbc; color: #fff; font-weight: 600; }
|
|
|
+ .tabbar {
|
|
|
+ position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
|
|
|
+ display: flex; background: #fff; border-top: 1px solid #e5e5e5;
|
|
|
+ box-shadow: 0 -2px 10px rgba(0,0,0,.05);
|
|
|
+ padding-bottom: var(--safe-bottom);
|
|
|
+ }
|
|
|
+ .tabbar .tabbar-btn {
|
|
|
+ flex: 1; text-align: center; padding: 10px 4px 12px; color: #666;
|
|
|
+ font-size: 14px; line-height: 1.25; border: none; border-top: 3px solid transparent;
|
|
|
+ margin-top: -1px; background: #fff; cursor: pointer; font-family: inherit;
|
|
|
+ }
|
|
|
+ .tabbar .tabbar-btn.active { color: #3c8dbc; font-weight: 600; border-top-color: #3c8dbc; background: #f8fbfd; }
|
|
|
+ .toast {
|
|
|
+ position: fixed; left: 50%; bottom: 90px; transform: translateX(-50%);
|
|
|
+ max-width: 86vw; padding: 10px 16px; border-radius: 8px;
|
|
|
+ background: rgba(0,0,0,.78); color: #fff; font-size: 14px;
|
|
|
+ z-index: 3000; opacity: 0; pointer-events: none; transition: opacity .2s;
|
|
|
+ }
|
|
|
+ .toast.show { opacity: 1; }
|
|
|
+ .toast.ok { background: #27ae60; }
|
|
|
+ .toast.err { background: #c0392b; }
|
|
|
+ </style>
|
|
|
+</head>
|
|
|
+<body class="layout-orders">
|
|
|
+<div class="bar">
|
|
|
+ <h1 id="barTitle">订单询价</h1>
|
|
|
+ <a href="{:url('index/index/logout')}" class="bar-logout" id="barLogout">退出</a>
|
|
|
+</div>
|
|
|
+
|
|
|
+<div id="pane-orders">
|
|
|
+ <div class="toolbar">
|
|
|
+ <input type="search" id="qInput" placeholder="请输入搜索内容" maxlength="120" enterkeyhint="search" autocomplete="off">
|
|
|
+ <button type="button" class="btn-search" id="btnSearch">搜索</button>
|
|
|
+ <button type="button" class="btn-add" id="btnOpenAdd">新增询价</button>
|
|
|
+ </div>
|
|
|
+ <div class="list-wrap" id="listMain">
|
|
|
+ {if $rows}
|
|
|
+ {volist name="rows" id="row"}
|
|
|
+ <div class="card">
|
|
|
+ <div class="ord">{$row.CCYDH|default=''|htmlentities}{if $row.CYJMC} {$row.CYJMC|htmlentities}{/if}</div>
|
|
|
+ <div class="meta">
|
|
|
+ <div><b>需求部门:</b>{$row.CCLBMMC|default=''|htmlentities}</div>
|
|
|
+ <div><b>工序:</b>{$row.CGYMC|default=''|htmlentities}</div>
|
|
|
+ <div><b>发起人:</b>{$row.cywyxm|default=''|htmlentities}</div>
|
|
|
+ </div>
|
|
|
+ <div class="tags">
|
|
|
+ <span class="progress{if condition="$row.progress_text eq '已完结'"} is-done{/if}">{$row.progress_text|default='待询价'|htmlentities}</span>
|
|
|
+ {if $row.createtime}<span class="time">{$row.createtime|htmlentities}</span>{/if}
|
|
|
+ <button type="button" class="btn-view-quote" data-scydgy-id="{$row.scydgy_id}">查看报价</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ {/volist}
|
|
|
+ {else/}
|
|
|
+ <div class="empty" id="emptyTip">暂无询价单,点击右上角「新增询价」</div>
|
|
|
+ {/if}
|
|
|
+ </div>
|
|
|
+</div>
|
|
|
+
|
|
|
+<div id="pane-me" class="me-panel">
|
|
|
+ <div class="me-card">
|
|
|
+ <div class="me-row"><span>账号</span>{$mprocProfile.account|default=''|htmlentities}</div>
|
|
|
+ <div class="me-row"><span>姓名</span>{$mprocProfile.contact_name|default=''|htmlentities}</div>
|
|
|
+ <div class="me-row"><span>部门</span>{$mprocProfile.department|default=''|htmlentities}</div>
|
|
|
+ <div class="me-row"><span>手机号</span>{$mprocProfile.phone|default=''|htmlentities}</div>
|
|
|
+ <div class="me-row"><span>邮箱</span>{$mprocProfile.email|default=''|htmlentities}</div>
|
|
|
+ <button type="button" class="btn-me-pwd" id="btn-me-change-pwd">修改密码</button>
|
|
|
+ </div>
|
|
|
+</div>
|
|
|
+
|
|
|
+<nav class="tabbar" id="tabbar" aria-label="主导航">
|
|
|
+ <button type="button" class="tabbar-btn active" data-main-tab="orders">首页</button>
|
|
|
+ <button type="button" class="tabbar-btn" data-main-tab="me">我的</button>
|
|
|
+</nav>
|
|
|
+
|
|
|
+<div class="rfq-mask" id="rfqMask" aria-hidden="true">
|
|
|
+ <div class="rfq-sheet" id="rfqSheet">
|
|
|
+ <div class="rfq-sheet-head">
|
|
|
+ <h2>新增询价</h2>
|
|
|
+ <button type="button" class="rfq-close" id="rfqClose" aria-label="关闭">×</button>
|
|
|
+ </div>
|
|
|
+ <div class="rfq-sheet-body">
|
|
|
+ <div class="rfq-field">
|
|
|
+ <label>需求编号</label>
|
|
|
+ <input type="text" id="ccydh" value="{$nextOrderCcydh|default=''|htmlentities}" readonly>
|
|
|
+ </div>
|
|
|
+ <div class="rfq-field">
|
|
|
+ <label>印件名称<span class="req">*</span></label>
|
|
|
+ <input type="text" id="cyjmc" maxlength="200" autocomplete="off" placeholder="请输入印件名称">
|
|
|
+ </div>
|
|
|
+ <div class="rfq-field">
|
|
|
+ <label>需求部门<span class="req">*</span></label>
|
|
|
+ <div class="rfq-dept-combo" id="rfqDeptCombo">
|
|
|
+ <div class="rfq-dept-row">
|
|
|
+ <input type="text" id="cclbmmc" value="{$defaultCclbmmc|default='营销中心'|htmlentities}" maxlength="100" autocomplete="off" placeholder="可下拉选择或自行输入">
|
|
|
+ <button type="button" class="rfq-dept-toggle" id="rfqDeptToggle" aria-label="选择部门">▼</button>
|
|
|
+ </div>
|
|
|
+ <div class="rfq-dept-menu" id="rfqDeptMenu">
|
|
|
+ {volist name="rfqDeptOptions" id="deptName"}
|
|
|
+ <button type="button" class="rfq-dept-item" data-value="{$deptName|htmlentities}">{$deptName|htmlentities}</button>
|
|
|
+ {/volist}
|
|
|
+ <div class="rfq-dept-empty">无匹配部门,可直接输入</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="rfq-field">
|
|
|
+ <label>工序名称</label>
|
|
|
+ <input type="text" id="cgymc" maxlength="200" autocomplete="off">
|
|
|
+ </div>
|
|
|
+ <div class="rfq-field">
|
|
|
+ <label>单位</label>
|
|
|
+ <input type="text" id="cdw" maxlength="50" autocomplete="off">
|
|
|
+ </div>
|
|
|
+ <div class="rfq-field">
|
|
|
+ <label>本次数量</label>
|
|
|
+ <input type="text" id="thisQty" maxlength="50" autocomplete="off" inputmode="decimal">
|
|
|
+ </div>
|
|
|
+ <div class="rfq-field">
|
|
|
+ <label>最高限价</label>
|
|
|
+ <input type="text" id="ceilingPrice" maxlength="50" autocomplete="off" inputmode="decimal">
|
|
|
+ </div>
|
|
|
+ <div class="rfq-field">
|
|
|
+ <label>订法</label>
|
|
|
+ <input type="text" id="cdf" maxlength="100" autocomplete="off">
|
|
|
+ </div>
|
|
|
+ <div class="rfq-field">
|
|
|
+ <label>需求发起人</label>
|
|
|
+ <input type="text" id="cywyxm" value="{$adminNickname|default=''|htmlentities}" readonly>
|
|
|
+ </div>
|
|
|
+ <div class="rfq-field">
|
|
|
+ <label>备注</label>
|
|
|
+ <textarea id="mbz" maxlength="500"></textarea>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="rfq-sheet-acts">
|
|
|
+ <button type="button" class="btn-reset" id="btnReset">重置</button>
|
|
|
+ <button type="button" class="btn-submit" id="btnSubmit">新增</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</div>
|
|
|
+
|
|
|
+<div class="rfq-mask" id="quoteMask" aria-hidden="true">
|
|
|
+ <div class="rfq-sheet" id="quoteSheet" style="max-height:min(68vh,480px);">
|
|
|
+ <div class="rfq-sheet-head">
|
|
|
+ <h2 id="quoteTitle">查看报价</h2>
|
|
|
+ <button type="button" class="rfq-close" id="quoteClose" aria-label="关闭">×</button>
|
|
|
+ </div>
|
|
|
+ <div class="rfq-sheet-body" id="quoteBody">
|
|
|
+ <div class="rfq-quote-empty">加载中…</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</div>
|
|
|
+
|
|
|
+<div class="toast" id="toast"></div>
|
|
|
+<div class="pwd-mask" id="pwdMask" aria-hidden="true">
|
|
|
+ <div class="pwd-sheet" id="pwdSheet">
|
|
|
+ <p class="pwd-head">修改密码</p>
|
|
|
+ <div class="pwd-field">
|
|
|
+ <label for="inp-old-pwd">原密码</label>
|
|
|
+ <input type="password" id="inp-old-pwd" autocomplete="current-password" maxlength="20">
|
|
|
+ </div>
|
|
|
+ <div class="pwd-field">
|
|
|
+ <label for="inp-new-pwd">新密码</label>
|
|
|
+ <input type="password" id="inp-new-pwd" autocomplete="new-password" maxlength="20" placeholder="8~20位,须含字母和数字">
|
|
|
+ </div>
|
|
|
+ <div class="pwd-field">
|
|
|
+ <label for="inp-renew-pwd">确认新密码</label>
|
|
|
+ <input type="password" id="inp-renew-pwd" autocomplete="new-password" maxlength="20" placeholder="再次输入新密码">
|
|
|
+ </div>
|
|
|
+ <div class="pwd-acts">
|
|
|
+ <button type="button" class="pwd-cancel" id="pwdCancel">取消</button>
|
|
|
+ <button type="button" class="pwd-ok" id="pwdSave">确定</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</div>
|
|
|
+
|
|
|
+<script>
|
|
|
+(function () {
|
|
|
+ var listUrl = "{:url('index/index/rfqaddlist')}";
|
|
|
+ var saveUrl = "{:url('index/index/rfqaddsave')}";
|
|
|
+ var quotesUrl = "{:url('index/index/rfqaddquotes')}";
|
|
|
+ var loginUrl = "{:url('index/index/login')}";
|
|
|
+ var changePwdUrl = "{:url('index/index/mprocChangePwd')}";
|
|
|
+ var token = {:json_encode(isset($mprocBootstrapToken) ? $mprocBootstrapToken : '', JSON_UNESCAPED_UNICODE)};
|
|
|
+ var keepHours = {$mprocBootstrapKeepHours|default=72};
|
|
|
+ var defaultDept = {:json_encode(isset($defaultCclbmmc) ? (string)$defaultCclbmmc : '营销中心', JSON_UNESCAPED_UNICODE)};
|
|
|
+ var defaultStarter = {:json_encode(isset($adminNickname) ? (string)$adminNickname : '', JSON_UNESCAPED_UNICODE)};
|
|
|
+ var nextCcydh = {:json_encode(isset($nextOrderCcydh) ? (string)$nextOrderCcydh : '', JSON_UNESCAPED_UNICODE)};
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (token) {
|
|
|
+ localStorage.setItem('mproc_token', token);
|
|
|
+ localStorage.setItem('mproc_token_exp', String(Date.now() + keepHours * 3600 * 1000));
|
|
|
+ }
|
|
|
+ } catch (e) {}
|
|
|
+
|
|
|
+ function clearLocalLoginToken() {
|
|
|
+ try {
|
|
|
+ localStorage.removeItem('mproc_token');
|
|
|
+ localStorage.removeItem('mproc_token_exp');
|
|
|
+ } catch (e) {}
|
|
|
+ }
|
|
|
+
|
|
|
+ document.querySelectorAll('a.bar-logout').forEach(function (a) {
|
|
|
+ a.addEventListener('click', function () { clearLocalLoginToken(); });
|
|
|
+ });
|
|
|
+
|
|
|
+ function showToast(msg, type) {
|
|
|
+ var el = document.getElementById('toast');
|
|
|
+ if (!el) return;
|
|
|
+ el.textContent = msg || '';
|
|
|
+ el.className = 'toast show' + (type === 'ok' ? ' ok' : (type === 'err' ? ' err' : ''));
|
|
|
+ clearTimeout(showToast._t);
|
|
|
+ showToast._t = setTimeout(function () { el.className = 'toast'; }, 2800);
|
|
|
+ }
|
|
|
+
|
|
|
+ function esc(s) {
|
|
|
+ return String(s == null ? '' : s)
|
|
|
+ .replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
|
+ .replace(/"/g, '"');
|
|
|
+ }
|
|
|
+
|
|
|
+ function postForm(url, data) {
|
|
|
+ var body = Object.keys(data).map(function (k) {
|
|
|
+ return encodeURIComponent(k) + '=' + encodeURIComponent(data[k] == null ? '' : data[k]);
|
|
|
+ }).join('&');
|
|
|
+ var headers = {
|
|
|
+ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
|
|
+ 'X-Requested-With': 'XMLHttpRequest'
|
|
|
+ };
|
|
|
+ try {
|
|
|
+ var t = localStorage.getItem('mproc_token') || '';
|
|
|
+ if (t) headers['X-Mproc-Token'] = t;
|
|
|
+ } catch (e) {}
|
|
|
+ return fetch(url, {
|
|
|
+ method: 'POST',
|
|
|
+ headers: headers,
|
|
|
+ body: body,
|
|
|
+ credentials: 'same-origin'
|
|
|
+ }).then(function (r) { return r.json(); });
|
|
|
+ }
|
|
|
+
|
|
|
+ function getJson(url) {
|
|
|
+ var headers = { 'X-Requested-With': 'XMLHttpRequest' };
|
|
|
+ try {
|
|
|
+ var t = localStorage.getItem('mproc_token') || '';
|
|
|
+ if (t) headers['X-Mproc-Token'] = t;
|
|
|
+ } catch (e) {}
|
|
|
+ return fetch(url, { method: 'GET', headers: headers, credentials: 'same-origin' })
|
|
|
+ .then(function (r) { return r.json(); });
|
|
|
+ }
|
|
|
+
|
|
|
+ var paneOrders = document.getElementById('pane-orders');
|
|
|
+ var paneMe = document.getElementById('pane-me');
|
|
|
+ var barTitle = document.getElementById('barTitle');
|
|
|
+ var barLogout = document.getElementById('barLogout');
|
|
|
+ document.querySelectorAll('#tabbar .tabbar-btn').forEach(function (btn) {
|
|
|
+ btn.addEventListener('click', function () {
|
|
|
+ var tab = btn.getAttribute('data-main-tab') || 'orders';
|
|
|
+ document.querySelectorAll('#tabbar .tabbar-btn').forEach(function (b) {
|
|
|
+ b.classList.toggle('active', b === btn);
|
|
|
+ });
|
|
|
+ if (tab === 'me') {
|
|
|
+ document.body.className = 'layout-me';
|
|
|
+ if (paneOrders) paneOrders.style.display = 'none';
|
|
|
+ if (paneMe) paneMe.style.display = 'block';
|
|
|
+ if (barTitle) barTitle.textContent = '我的';
|
|
|
+ if (barLogout) barLogout.style.display = '';
|
|
|
+ } else {
|
|
|
+ document.body.className = 'layout-orders';
|
|
|
+ if (paneOrders) paneOrders.style.display = 'flex';
|
|
|
+ if (paneMe) paneMe.style.display = 'none';
|
|
|
+ if (barTitle) barTitle.textContent = '订单询价';
|
|
|
+ if (barLogout) barLogout.style.display = 'none';
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ function renderRows(rows) {
|
|
|
+ var main = document.getElementById('listMain');
|
|
|
+ if (!main) return;
|
|
|
+ rows = Array.isArray(rows) ? rows : [];
|
|
|
+ if (!rows.length) {
|
|
|
+ main.innerHTML = '<div class="empty" id="emptyTip">暂无询价单,点击右上角「新增询价」</div>';
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var html = '';
|
|
|
+ rows.forEach(function (row) {
|
|
|
+ var title = String(row.CCYDH || '').trim();
|
|
|
+ var name = String(row.CYJMC || '').trim();
|
|
|
+ if (title && name) title += ' ' + name;
|
|
|
+ else title = title || name || '';
|
|
|
+ var progress = String(row.progress_text || '待询价');
|
|
|
+ html += '<div class="card">'
|
|
|
+ + '<div class="ord">' + esc(title) + '</div>'
|
|
|
+ + '<div class="meta">'
|
|
|
+ + '<div><b>需求部门:</b>' + esc(row.CCLBMMC || '') + '</div>'
|
|
|
+ + '<div><b>工序:</b>' + esc(row.CGYMC || '') + '</div>'
|
|
|
+ + '<div><b>发起人:</b>' + esc(row.cywyxm || '') + '</div>'
|
|
|
+ + '</div>'
|
|
|
+ + '<div class="tags">'
|
|
|
+ + '<span class="progress' + (progress === '已完结' ? ' is-done' : '') + '">' + esc(progress) + '</span>'
|
|
|
+ + (row.createtime ? '<span class="time">' + esc(row.createtime) + '</span>' : '')
|
|
|
+ + '<button type="button" class="btn-view-quote" data-scydgy-id="' + esc(row.scydgy_id || '') + '">查看报价</button>'
|
|
|
+ + '</div></div>';
|
|
|
+ });
|
|
|
+ main.innerHTML = html;
|
|
|
+ }
|
|
|
+
|
|
|
+ function loadList() {
|
|
|
+ var q = (document.getElementById('qInput').value || '').trim();
|
|
|
+ var url = listUrl + (listUrl.indexOf('?') >= 0 ? '&' : '?') + 'q=' + encodeURIComponent(q);
|
|
|
+ getJson(url).then(function (ret) {
|
|
|
+ if (ret && (ret.code === 1 || ret.code === '1')) {
|
|
|
+ var data = ret.data || {};
|
|
|
+ renderRows(data.rows || []);
|
|
|
+ } else if (ret && (ret.code === 401 || ret.code === '401')) {
|
|
|
+ clearLocalLoginToken();
|
|
|
+ window.location.href = loginUrl;
|
|
|
+ } else {
|
|
|
+ showToast((ret && ret.msg) ? ret.msg : '加载失败', 'err');
|
|
|
+ }
|
|
|
+ }).catch(function () {
|
|
|
+ showToast('网络错误', 'err');
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ document.getElementById('btnSearch').addEventListener('click', loadList);
|
|
|
+ document.getElementById('qInput').addEventListener('keydown', function (e) {
|
|
|
+ if (e.key === 'Enter') {
|
|
|
+ e.preventDefault();
|
|
|
+ loadList();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ var rfqMask = document.getElementById('rfqMask');
|
|
|
+ var rfqSheet = document.getElementById('rfqSheet');
|
|
|
+ function openAddModal() {
|
|
|
+ resetForm(false);
|
|
|
+ if (rfqMask) {
|
|
|
+ rfqMask.classList.add('show');
|
|
|
+ rfqMask.setAttribute('aria-hidden', 'false');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ function closeAddModal() {
|
|
|
+ if (rfqMask) {
|
|
|
+ rfqMask.classList.remove('show');
|
|
|
+ rfqMask.setAttribute('aria-hidden', 'true');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ document.getElementById('btnOpenAdd').addEventListener('click', openAddModal);
|
|
|
+ document.getElementById('rfqClose').addEventListener('click', closeAddModal);
|
|
|
+ if (rfqMask) {
|
|
|
+ rfqMask.addEventListener('click', function (e) {
|
|
|
+ if (e.target === rfqMask) closeAddModal();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (rfqSheet) rfqSheet.addEventListener('click', function (e) { e.stopPropagation(); });
|
|
|
+
|
|
|
+ var quoteMask = document.getElementById('quoteMask');
|
|
|
+ var quoteSheet = document.getElementById('quoteSheet');
|
|
|
+ var quoteBody = document.getElementById('quoteBody');
|
|
|
+ var quoteTitle = document.getElementById('quoteTitle');
|
|
|
+ function closeQuoteModal() {
|
|
|
+ if (quoteMask) {
|
|
|
+ quoteMask.classList.remove('show');
|
|
|
+ quoteMask.setAttribute('aria-hidden', 'true');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ function openQuoteModal(sid) {
|
|
|
+ if (!quoteMask || !quoteBody) return;
|
|
|
+ if (quoteTitle) quoteTitle.textContent = '查看报价';
|
|
|
+ quoteBody.innerHTML = '<div class="rfq-quote-empty">加载中…</div>';
|
|
|
+ quoteMask.classList.add('show');
|
|
|
+ quoteMask.setAttribute('aria-hidden', 'false');
|
|
|
+ var url = quotesUrl + (quotesUrl.indexOf('?') >= 0 ? '&' : '?') + 'scydgy_id=' + encodeURIComponent(sid);
|
|
|
+ getJson(url).then(function (ret) {
|
|
|
+ if (ret && (ret.code === 1 || ret.code === '1')) {
|
|
|
+ var data = ret.data || {};
|
|
|
+ var list = Array.isArray(data.list) ? data.list : [];
|
|
|
+ var head = String(data.CCYDH || '').trim();
|
|
|
+ var name = String(data.CYJMC || '').trim();
|
|
|
+ if (quoteTitle) {
|
|
|
+ quoteTitle.textContent = head ? ('报价 · ' + head) : '查看报价';
|
|
|
+ }
|
|
|
+ if (!list.length) {
|
|
|
+ quoteBody.innerHTML = '<div class="rfq-quote-empty">暂无报价</div>';
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var html = '<table class="rfq-quote-table"><thead><tr>'
|
|
|
+ + '<th>供应商</th><th class="col-amt">单价</th>'
|
|
|
+ + '</tr></thead><tbody>';
|
|
|
+ list.forEach(function (item) {
|
|
|
+ var cn = item && item.company_name != null ? String(item.company_name) : '';
|
|
|
+ var quoted = item && (parseInt(item.is_quoted, 10) === 1);
|
|
|
+ var amt = item && item.amount_text != null ? String(item.amount_text) : '';
|
|
|
+ html += '<tr><td>' + esc(cn) + '</td><td class="col-amt">'
|
|
|
+ + (quoted ? esc(amt) : '<span class="muted">未填写</span>')
|
|
|
+ + '</td></tr>';
|
|
|
+ });
|
|
|
+ html += '</tbody></table>';
|
|
|
+ if (name) {
|
|
|
+ html = '<div style="margin:0 0 8px;font-size:12px;color:#888;">' + esc(name) + '</div>' + html;
|
|
|
+ }
|
|
|
+ quoteBody.innerHTML = html;
|
|
|
+ } else if (ret && (ret.code === 401 || ret.code === '401')) {
|
|
|
+ clearLocalLoginToken();
|
|
|
+ window.location.href = loginUrl;
|
|
|
+ } else {
|
|
|
+ quoteBody.innerHTML = '<div class="rfq-quote-empty">' + esc((ret && ret.msg) ? ret.msg : '加载失败') + '</div>';
|
|
|
+ }
|
|
|
+ }).catch(function () {
|
|
|
+ quoteBody.innerHTML = '<div class="rfq-quote-empty">网络错误</div>';
|
|
|
+ });
|
|
|
+ }
|
|
|
+ var listMain = document.getElementById('listMain');
|
|
|
+ if (listMain) {
|
|
|
+ listMain.addEventListener('click', function (e) {
|
|
|
+ var btn = e.target && e.target.closest ? e.target.closest('.btn-view-quote') : null;
|
|
|
+ if (!btn) return;
|
|
|
+ e.preventDefault();
|
|
|
+ var sid = btn.getAttribute('data-scydgy-id') || '';
|
|
|
+ if (!sid) {
|
|
|
+ showToast('缺少询价单标识', 'err');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ openQuoteModal(sid);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ var quoteClose = document.getElementById('quoteClose');
|
|
|
+ if (quoteClose) quoteClose.addEventListener('click', closeQuoteModal);
|
|
|
+ if (quoteMask) {
|
|
|
+ quoteMask.addEventListener('click', function (e) {
|
|
|
+ if (e.target === quoteMask) closeQuoteModal();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (quoteSheet) quoteSheet.addEventListener('click', function (e) { e.stopPropagation(); });
|
|
|
+
|
|
|
+ function resetForm(keepCcydh) {
|
|
|
+ document.getElementById('cyjmc').value = '';
|
|
|
+ document.getElementById('cclbmmc').value = defaultDept || '营销中心';
|
|
|
+ document.getElementById('cgymc').value = '';
|
|
|
+ document.getElementById('cdw').value = '';
|
|
|
+ document.getElementById('thisQty').value = '';
|
|
|
+ document.getElementById('ceilingPrice').value = '';
|
|
|
+ document.getElementById('cdf').value = '';
|
|
|
+ document.getElementById('mbz').value = '';
|
|
|
+ document.getElementById('cywyxm').value = defaultStarter || '';
|
|
|
+ if (!keepCcydh) {
|
|
|
+ document.getElementById('ccydh').value = nextCcydh || '';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ document.getElementById('btnReset').addEventListener('click', function () {
|
|
|
+ resetForm(true);
|
|
|
+ });
|
|
|
+
|
|
|
+ (function bindDeptCombo() {
|
|
|
+ var combo = document.getElementById('rfqDeptCombo');
|
|
|
+ var input = document.getElementById('cclbmmc');
|
|
|
+ var toggle = document.getElementById('rfqDeptToggle');
|
|
|
+ var menu = document.getElementById('rfqDeptMenu');
|
|
|
+ if (!combo || !input || !menu) return;
|
|
|
+ var items = menu.querySelectorAll('.rfq-dept-item');
|
|
|
+ var emptyEl = menu.querySelector('.rfq-dept-empty');
|
|
|
+
|
|
|
+ function openMenu() {
|
|
|
+ combo.classList.add('open');
|
|
|
+ filterMenu(input.value || '');
|
|
|
+ }
|
|
|
+ function closeMenu() {
|
|
|
+ combo.classList.remove('open');
|
|
|
+ }
|
|
|
+ function filterMenu(keyword) {
|
|
|
+ var kw = String(keyword || '').trim().toLowerCase();
|
|
|
+ var hit = 0;
|
|
|
+ items.forEach(function (btn) {
|
|
|
+ var text = String(btn.getAttribute('data-value') || btn.textContent || '').trim();
|
|
|
+ var show = !kw || text.toLowerCase().indexOf(kw) !== -1;
|
|
|
+ btn.style.display = show ? '' : 'none';
|
|
|
+ if (show) hit++;
|
|
|
+ });
|
|
|
+ if (emptyEl) emptyEl.style.display = hit === 0 ? 'block' : 'none';
|
|
|
+ }
|
|
|
+
|
|
|
+ if (toggle) {
|
|
|
+ toggle.addEventListener('click', function (e) {
|
|
|
+ e.preventDefault();
|
|
|
+ e.stopPropagation();
|
|
|
+ if (combo.classList.contains('open')) closeMenu();
|
|
|
+ else openMenu();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ input.addEventListener('focus', function () {
|
|
|
+ openMenu();
|
|
|
+ });
|
|
|
+ input.addEventListener('click', function () {
|
|
|
+ openMenu();
|
|
|
+ });
|
|
|
+ input.addEventListener('input', function () {
|
|
|
+ openMenu();
|
|
|
+ filterMenu(input.value || '');
|
|
|
+ });
|
|
|
+ items.forEach(function (btn) {
|
|
|
+ btn.addEventListener('click', function (e) {
|
|
|
+ e.preventDefault();
|
|
|
+ var v = String(btn.getAttribute('data-value') || btn.textContent || '').trim();
|
|
|
+ input.value = v;
|
|
|
+ closeMenu();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ document.addEventListener('click', function (e) {
|
|
|
+ if (!combo.contains(e.target)) closeMenu();
|
|
|
+ });
|
|
|
+ if (rfqSheet) {
|
|
|
+ rfqSheet.addEventListener('scroll', closeMenu, true);
|
|
|
+ }
|
|
|
+ var sheetBody = document.querySelector('.rfq-sheet-body');
|
|
|
+ if (sheetBody) {
|
|
|
+ sheetBody.addEventListener('scroll', closeMenu);
|
|
|
+ }
|
|
|
+ })();
|
|
|
+
|
|
|
+ document.getElementById('btnSubmit').addEventListener('click', function () {
|
|
|
+ var cyjmc = (document.getElementById('cyjmc').value || '').trim();
|
|
|
+ var cclbmmc = (document.getElementById('cclbmmc').value || '').trim();
|
|
|
+ if (!cyjmc) {
|
|
|
+ showToast('请填写印件名称', 'err');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!cclbmmc) {
|
|
|
+ showToast('请填写需求部门', 'err');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var btn = document.getElementById('btnSubmit');
|
|
|
+ btn.disabled = true;
|
|
|
+ postForm(saveUrl, {
|
|
|
+ CYJMC: cyjmc,
|
|
|
+ CCLBMMC: cclbmmc,
|
|
|
+ CGYMC: (document.getElementById('cgymc').value || '').trim(),
|
|
|
+ CDW: (document.getElementById('cdw').value || '').trim(),
|
|
|
+ This_quantity: (document.getElementById('thisQty').value || '').trim(),
|
|
|
+ ceilingPrice: (document.getElementById('ceilingPrice').value || '').trim(),
|
|
|
+ CDF: (document.getElementById('cdf').value || '').trim(),
|
|
|
+ MBZ: (document.getElementById('mbz').value || '').trim()
|
|
|
+ }).then(function (ret) {
|
|
|
+ btn.disabled = false;
|
|
|
+ if (ret && (ret.code === 1 || ret.code === '1')) {
|
|
|
+ var data = ret.data || {};
|
|
|
+ if (data.nextOrderCcydh) {
|
|
|
+ nextCcydh = String(data.nextOrderCcydh);
|
|
|
+ document.getElementById('ccydh').value = nextCcydh;
|
|
|
+ }
|
|
|
+ showToast((ret.msg || '新增成功') + (data.CCYDH ? (':' + data.CCYDH) : ''), 'ok');
|
|
|
+ closeAddModal();
|
|
|
+ loadList();
|
|
|
+ } else if (ret && (ret.code === 401 || ret.code === '401')) {
|
|
|
+ clearLocalLoginToken();
|
|
|
+ window.location.href = loginUrl;
|
|
|
+ } else {
|
|
|
+ showToast((ret && ret.msg) ? ret.msg : '新增失败', 'err');
|
|
|
+ }
|
|
|
+ }).catch(function () {
|
|
|
+ btn.disabled = false;
|
|
|
+ showToast('网络错误', 'err');
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ function passwordHasSequentialRun(pwd, runLen) {
|
|
|
+ runLen = runLen || 4;
|
|
|
+ var lower = String(pwd || '').toLowerCase();
|
|
|
+ var n = lower.length;
|
|
|
+ if (n < runLen) return false;
|
|
|
+ for (var i = 0; i <= n - runLen; i++) {
|
|
|
+ var asc = true, desc = true;
|
|
|
+ for (var j = 1; j < runLen; j++) {
|
|
|
+ var prev = lower.charCodeAt(i + j - 1);
|
|
|
+ var cur = lower.charCodeAt(i + j);
|
|
|
+ if (cur !== prev + 1) asc = false;
|
|
|
+ if (cur !== prev - 1) desc = false;
|
|
|
+ if (!asc && !desc) break;
|
|
|
+ }
|
|
|
+ if (asc || desc) return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ function validateStrongPassword(pwd) {
|
|
|
+ pwd = String(pwd || '');
|
|
|
+ if (pwd.length < 8 || pwd.length > 20) return '密码长度须为8~20位';
|
|
|
+ if (/\s/.test(pwd)) return '密码不能包含空格';
|
|
|
+ if (/^\d+$/.test(pwd)) return '密码不能为纯数字,请同时包含字母';
|
|
|
+ if (/^[a-zA-Z]+$/.test(pwd)) return '密码不能为纯字母,请同时包含数字';
|
|
|
+ if (!/[a-zA-Z]/.test(pwd) || !/\d/.test(pwd)) return '密码须同时包含字母和数字';
|
|
|
+ if (/(.)\1{3,}/.test(pwd)) return '密码不能包含过多重复字符(如1111、aaaa)';
|
|
|
+ if (passwordHasSequentialRun(pwd, 4)) return '密码不能包含连续字符(如1234、abcd)';
|
|
|
+ var weak = {
|
|
|
+ '12345678': 1, '123456789': 1, '1234567890': 1, '87654321': 1, '01234567': 1,
|
|
|
+ 'password': 1, 'password1': 1, 'passw0rd': 1, 'qwerty12': 1, 'qwertyui': 1,
|
|
|
+ 'abc12345': 1, 'abcd1234': 1, 'a1b2c3d4': 1, '11111111': 1, '00000000': 1,
|
|
|
+ '88888888': 1, '66666666': 1, '11223344': 1, '1qaz2wsx': 1, 'qazwsxed': 1
|
|
|
+ };
|
|
|
+ if (weak[pwd.toLowerCase()]) return '密码过于简单,请重新设置';
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+ (function bindChangePwd() {
|
|
|
+ var pwdMask = document.getElementById('pwdMask');
|
|
|
+ var pwdSheet = document.getElementById('pwdSheet');
|
|
|
+ var btnMePwd = document.getElementById('btn-me-change-pwd');
|
|
|
+ var inpOldPwd = document.getElementById('inp-old-pwd');
|
|
|
+ var inpNewPwd = document.getElementById('inp-new-pwd');
|
|
|
+ var inpRenewPwd = document.getElementById('inp-renew-pwd');
|
|
|
+ var btnPwdSave = document.getElementById('pwdSave');
|
|
|
+ var btnPwdCancel = document.getElementById('pwdCancel');
|
|
|
+ function openPwdModal() {
|
|
|
+ if (inpOldPwd) inpOldPwd.value = '';
|
|
|
+ if (inpNewPwd) inpNewPwd.value = '';
|
|
|
+ if (inpRenewPwd) inpRenewPwd.value = '';
|
|
|
+ if (pwdMask) {
|
|
|
+ pwdMask.classList.add('show');
|
|
|
+ pwdMask.setAttribute('aria-hidden', 'false');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ function closePwdModal() {
|
|
|
+ if (pwdMask) {
|
|
|
+ pwdMask.classList.remove('show');
|
|
|
+ pwdMask.setAttribute('aria-hidden', 'true');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (btnMePwd) btnMePwd.addEventListener('click', openPwdModal);
|
|
|
+ if (btnPwdCancel) btnPwdCancel.addEventListener('click', closePwdModal);
|
|
|
+ if (pwdMask) {
|
|
|
+ pwdMask.addEventListener('click', function (e) {
|
|
|
+ if (e.target === pwdMask) closePwdModal();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (pwdSheet) pwdSheet.addEventListener('click', function (e) { e.stopPropagation(); });
|
|
|
+ if (btnPwdSave) {
|
|
|
+ btnPwdSave.addEventListener('click', function () {
|
|
|
+ var oldP = inpOldPwd ? inpOldPwd.value : '';
|
|
|
+ var newP = inpNewPwd ? inpNewPwd.value : '';
|
|
|
+ var renP = inpRenewPwd ? inpRenewPwd.value : '';
|
|
|
+ if (!oldP || !newP || !renP) {
|
|
|
+ showToast('请填写完整', 'err');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var tip = validateStrongPassword(newP);
|
|
|
+ if (tip) {
|
|
|
+ showToast(tip, 'err');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (newP !== renP) {
|
|
|
+ showToast('两次输入的新密码不一致', 'err');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (oldP === newP) {
|
|
|
+ showToast('新密码不能与旧密码相同', 'err');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ btnPwdSave.disabled = true;
|
|
|
+ postForm(changePwdUrl, {
|
|
|
+ old_password: oldP,
|
|
|
+ new_password: newP,
|
|
|
+ renew_password: renP
|
|
|
+ }).then(function (ret) {
|
|
|
+ btnPwdSave.disabled = false;
|
|
|
+ if (ret && (ret.code === 1 || ret.code === '1')) {
|
|
|
+ closePwdModal();
|
|
|
+ clearLocalLoginToken();
|
|
|
+ showToast(ret.msg || '密码已修改,请重新登录', 'ok');
|
|
|
+ setTimeout(function () {
|
|
|
+ window.location.href = ret.url || loginUrl;
|
|
|
+ }, 900);
|
|
|
+ } else {
|
|
|
+ showToast((ret && ret.msg) ? ret.msg : '修改失败', 'err');
|
|
|
+ }
|
|
|
+ }).catch(function () {
|
|
|
+ btnPwdSave.disabled = false;
|
|
|
+ showToast('网络错误', 'err');
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ })();
|
|
|
+})();
|
|
|
+</script>
|
|
|
+</body>
|
|
|
+</html>
|