mirror of
https://github.com/chatopera/cosin.git
synced 2025-08-01 16:38:02 +08:00
#937 add license mng menu
Signed-off-by: Hai Liang Wang <hai@chatopera.com>
This commit is contained in:
parent
63c5750181
commit
f55785883a
@ -226,4 +226,9 @@ public class Constants {
|
||||
public static final String LICENSEIDS = "LICENSEIDS";
|
||||
public static final String METAKV_DATATYPE_STRING = "string";
|
||||
|
||||
public static final String SHORTID = "shortId";
|
||||
public static final String LICENSES = "licenses";
|
||||
public static final String ADDDATE = "addDate";
|
||||
public static final String LICENSE = "license";
|
||||
public static final String UPDATETIME = "updateTime";
|
||||
}
|
||||
|
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd.
|
||||
* <https://www.chatopera.com>, Licensed under the Chunsong Public
|
||||
* License, Version 1.0 (the "License"), https://docs.cskefu.com/licenses/v1.html
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.cskefu.cc.controller.admin;
|
||||
|
||||
import com.chatopera.store.sdk.exceptions.InvalidResponseException;
|
||||
import com.cskefu.cc.basic.Constants;
|
||||
import com.cskefu.cc.controller.Handler;
|
||||
import com.cskefu.cc.exception.MetaKvInvalidKeyException;
|
||||
import com.cskefu.cc.model.User;
|
||||
import com.cskefu.cc.proxy.LicenseProxy;
|
||||
import com.cskefu.cc.util.Menu;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/license")
|
||||
public class LicenseCtrl extends Handler {
|
||||
private final static Logger logger = LoggerFactory.getLogger(LicenseCtrl.class);
|
||||
|
||||
@Autowired
|
||||
private LicenseProxy licenseProxy;
|
||||
|
||||
@RequestMapping("/index")
|
||||
@Menu(type = "admin", subtype = "license")
|
||||
public ModelAndView index(ModelMap map, HttpServletRequest request) {
|
||||
User user = super.getUser(request);
|
||||
if (user.isSuperadmin()) {
|
||||
|
||||
try {
|
||||
List<JSONObject> licenses = licenseProxy.getLicensesFromStore();
|
||||
map.addAttribute(Constants.UPDATETIME, new Date());
|
||||
map.addAttribute(Constants.LICENSES, licenses);
|
||||
} catch (InvalidResponseException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return request(super.createView("/admin/license/index"));
|
||||
} else {
|
||||
return request(super.createView("/public/error"));
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping("/add")
|
||||
@Menu(type = "admin", subtype = "license")
|
||||
public ModelAndView add(ModelMap map, HttpServletRequest request) {
|
||||
User user = super.getUser(request);
|
||||
if (user.isSuperadmin()) {
|
||||
return request(super.createView("/admin/license/add"));
|
||||
} else {
|
||||
return request(super.createView("/public/error"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存新的证书
|
||||
*
|
||||
* @param map
|
||||
* @param request
|
||||
* @param licenseShortId
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/save")
|
||||
@Menu(type = "admin", subtype = "license")
|
||||
public ModelAndView save(ModelMap map,
|
||||
HttpServletRequest request,
|
||||
@Valid String licenseShortId) throws MetaKvInvalidKeyException {
|
||||
User user = super.getUser(request);
|
||||
logger.info("[save] licenseShortId {}", licenseShortId);
|
||||
|
||||
if (user.isSuperadmin()) {
|
||||
// 验证该证书不在当前证书列表中
|
||||
JSONArray currents = licenseProxy.getLicensesInMetakv();
|
||||
String msg = "";
|
||||
boolean isAddedBefore = false;
|
||||
|
||||
for (int i = 0; i < currents.length(); i++) {
|
||||
JSONObject item = (JSONObject) currents.get(i);
|
||||
if (StringUtils.equals(item.getString("shortId"), licenseShortId)) {
|
||||
isAddedBefore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isAddedBefore) {
|
||||
msg = "already_added";
|
||||
return request(super.createView(
|
||||
"redirect:/admin/license/index.html?msg=" + msg));
|
||||
}
|
||||
|
||||
// 验证该证书存在
|
||||
try {
|
||||
JSONObject licenseData = licenseProxy.getLicenseFromStore(licenseShortId);
|
||||
JSONObject licenseKvData = new JSONObject();
|
||||
licenseKvData.put(Constants.SHORTID, licenseData.getJSONObject(Constants.LICENSE).getString(Constants.SHORTID));
|
||||
licenseKvData.put(Constants.ADDDATE, new Date());
|
||||
|
||||
// 添加该证书
|
||||
currents.put(0, licenseKvData);
|
||||
licenseProxy.createOrUpdateMetaKv(Constants.LICENSEIDS, currents.toString(), Constants.METAKV_DATATYPE_STRING);
|
||||
|
||||
// 跳转回到证书列表
|
||||
List<JSONObject> licenses = licenseProxy.getLicensesFromStore();
|
||||
map.addAttribute(Constants.LICENSES, licenses);
|
||||
map.addAttribute("updateTime", new Date());
|
||||
|
||||
return request(super.createView("/admin/license/index"));
|
||||
} catch (InvalidResponseException e) {
|
||||
logger.warn("[save] error in getLicenseFromStore", e);
|
||||
msg = "invalid_id";
|
||||
return request(super.createView(
|
||||
"redirect:/admin/license/index.html?msg=" + msg));
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
return request(super.createView("/public/error"));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd.
|
||||
* <https://www.chatopera.com>, Licensed under the Chunsong Public
|
||||
* License, Version 1.0 (the "License"), https://docs.cskefu.com/licenses/v1.html
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright (C) 2019-Jun. 2023 Chatopera Inc, <https://www.chatopera.com>,
|
||||
* Licensed under the Apache License, Version 2.0,
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package com.cskefu.cc.exception;
|
||||
|
||||
public class MetaKvInvalidKeyException extends Exception{
|
||||
public MetaKvInvalidKeyException(final String s){
|
||||
super(s);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd.
|
||||
* <https://www.chatopera.com>, Licensed under the Chunsong Public
|
||||
* License, Version 1.0 (the "License"), https://docs.cskefu.com/licenses/v1.html
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright (C) 2019-Jun. 2023 Chatopera Inc, <https://www.chatopera.com>,
|
||||
* Licensed under the Apache License, Version 2.0,
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package com.cskefu.cc.exception;
|
||||
|
||||
public class MetaKvNotExistException extends Exception{
|
||||
public MetaKvNotExistException(final String s){
|
||||
super(s);
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ import java.util.Date;
|
||||
@Entity
|
||||
@Table(name = "cs_metakv")
|
||||
@org.hibernate.annotations.Proxy(lazy = false)
|
||||
public class Metakv implements java.io.Serializable {
|
||||
public class MetaKv implements java.io.Serializable {
|
||||
|
||||
@Id
|
||||
private String metakey;
|
@ -10,13 +10,13 @@
|
||||
*/
|
||||
package com.cskefu.cc.persistence.repository;
|
||||
|
||||
import com.cskefu.cc.model.Metakv;
|
||||
import com.cskefu.cc.model.MetaKv;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface MetakvRepository extends JpaRepository<Metakv, String> {
|
||||
public interface MetaKvRepository extends JpaRepository<MetaKv, String> {
|
||||
|
||||
Optional<Metakv> findFirstByMetakey(final String p1);
|
||||
Optional<MetaKv> findFirstByMetakey(final String p1);
|
||||
|
||||
}
|
@ -16,25 +16,33 @@ import com.chatopera.store.sdk.exceptions.InvalidResponseException;
|
||||
import com.cskefu.cc.basic.Constants;
|
||||
import com.cskefu.cc.basic.MainContext;
|
||||
import com.cskefu.cc.basic.MainUtils;
|
||||
import com.cskefu.cc.model.Metakv;
|
||||
import com.cskefu.cc.persistence.repository.MetakvRepository;
|
||||
import com.cskefu.cc.exception.MetaKvInvalidKeyException;
|
||||
import com.cskefu.cc.exception.MetaKvNotExistException;
|
||||
import com.cskefu.cc.model.MetaKv;
|
||||
import com.cskefu.cc.persistence.repository.MetaKvRepository;
|
||||
import com.cskefu.cc.util.Base62;
|
||||
import com.cskefu.cc.util.DateConverter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 证书服务
|
||||
*/
|
||||
@Service
|
||||
public class LicenseProxy {
|
||||
private final static Logger logger = LoggerFactory.getLogger(LicenseProxy.class);
|
||||
|
||||
@Autowired
|
||||
private MetakvRepository metkvRes;
|
||||
private MetaKvRepository metaKvRes;
|
||||
|
||||
@Autowired
|
||||
private QuotaWdClient quotaWdClient;
|
||||
@ -65,24 +73,65 @@ public class LicenseProxy {
|
||||
/**
|
||||
* Init local data for License
|
||||
*/
|
||||
Optional<Metakv> metaServerinstIdOpt = metkvRes.findFirstByMetakey(Constants.LICENSE_SERVER_INST_ID);
|
||||
Optional<MetaKv> metaServerinstIdOpt = metaKvRes.findFirstByMetakey(Constants.LICENSE_SERVER_INST_ID);
|
||||
if (metaServerinstIdOpt.isEmpty()) {
|
||||
// 没有 serverinstId 信息,初始化
|
||||
final String serverinstId = MainUtils.getUUID();
|
||||
createMetakv(Constants.LICENSE_SERVER_INST_ID, serverinstId, Constants.METAKV_DATATYPE_STRING);
|
||||
createMetaKv(Constants.LICENSE_SERVER_INST_ID, serverinstId, Constants.METAKV_DATATYPE_STRING);
|
||||
}
|
||||
|
||||
Optional<Metakv> metaServicenameOpt = metkvRes.findFirstByMetakey(Constants.LICENSE_SERVICE_NAME);
|
||||
Optional<MetaKv> metaServicenameOpt = metaKvRes.findFirstByMetakey(Constants.LICENSE_SERVICE_NAME);
|
||||
if (metaServicenameOpt.isEmpty()) {
|
||||
// 没有 Service Name 信息,初始化
|
||||
final String serviceName = generateLicenseServiceName();
|
||||
createMetakv(Constants.LICENSE_SERVICE_NAME, serviceName, Constants.METAKV_DATATYPE_STRING);
|
||||
createMetaKv(Constants.LICENSE_SERVICE_NAME, serviceName, Constants.METAKV_DATATYPE_STRING);
|
||||
}
|
||||
|
||||
Optional<Metakv> metaLicensesOpt = metkvRes.findFirstByMetakey(Constants.LICENSEIDS);
|
||||
Optional<MetaKv> metaLicensesOpt = metaKvRes.findFirstByMetakey(Constants.LICENSEIDS);
|
||||
if (metaLicensesOpt.isEmpty()) {
|
||||
// 没有 license 信息,初始化
|
||||
createMetakv(Constants.LICENSEIDS, (new JSONArray()).toString(), Constants.METAKV_DATATYPE_STRING);
|
||||
createMetaKv(Constants.LICENSEIDS, (new JSONArray()).toString(), Constants.METAKV_DATATYPE_STRING);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 MetaKv 表中取得数据 MetaKv
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
* @throws MetaKvNotExistException
|
||||
*/
|
||||
public MetaKv retrieveMetaKv(final String key) throws MetaKvNotExistException, MetaKvInvalidKeyException {
|
||||
|
||||
if (StringUtils.isBlank(key)) {
|
||||
throw new MetaKvInvalidKeyException("Key must not be empy");
|
||||
}
|
||||
|
||||
Optional<MetaKv> kvOpt = metaKvRes.findFirstByMetakey(key);
|
||||
if (kvOpt.isEmpty()) {
|
||||
throw new MetaKvNotExistException(key + " not exist");
|
||||
} else {
|
||||
return kvOpt.get();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建或更新 MetaKv
|
||||
* UpdateOnExist
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
* @param datatype
|
||||
*/
|
||||
public MetaKv createOrUpdateMetaKv(final String key, final String value, final String datatype) throws MetaKvInvalidKeyException {
|
||||
try {
|
||||
MetaKv kv = retrieveMetaKv(key);
|
||||
kv.setMetavalue(value);
|
||||
kv.setUpdatetime(new Date());
|
||||
metaKvRes.save(kv);
|
||||
return kv;
|
||||
} catch (MetaKvNotExistException e) {
|
||||
return createMetaKv(key, value, datatype);
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,16 +143,17 @@ public class LicenseProxy {
|
||||
* @param value
|
||||
* @param datatype
|
||||
*/
|
||||
public void createMetakv(final String key, final String value, final String datatype) {
|
||||
public MetaKv createMetaKv(final String key, final String value, final String datatype) {
|
||||
Date now = new Date();
|
||||
Metakv metakv = new Metakv();
|
||||
MetaKv metakv = new MetaKv();
|
||||
metakv.setCreatetime(now);
|
||||
metakv.setUpdatetime(now);
|
||||
metakv.setMetakey(key);
|
||||
metakv.setMetavalue(value);
|
||||
metakv.setDatatype(datatype);
|
||||
|
||||
metkvRes.save(metakv);
|
||||
metaKvRes.save(metakv);
|
||||
return metakv;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,4 +169,81 @@ public class LicenseProxy {
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从数据库及证书商店获得证书列表信息
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<JSONObject> getLicensesFromStore() throws InvalidResponseException {
|
||||
List<JSONObject> result = new ArrayList<>();
|
||||
|
||||
try {
|
||||
JSONArray ja = new JSONArray((retrieveMetaKv(Constants.LICENSEIDS).getMetavalue()));
|
||||
HashMap<String, String> addDates = new HashMap<>();
|
||||
List<String> licenseIds = new ArrayList<>();
|
||||
for (int i = 0; i < ja.length(); i++) {
|
||||
JSONObject obj = ((JSONObject) ja.get(i));
|
||||
licenseIds.add(obj.getString(Constants.SHORTID));
|
||||
addDates.put(obj.getString(Constants.SHORTID), obj.getString(Constants.ADDDATE));
|
||||
}
|
||||
|
||||
Response resp = quotaWdClient.getLicensesInfo(licenseIds);
|
||||
JSONArray data = (JSONArray) resp.getData();
|
||||
|
||||
for (int i = 0; i < data.length(); i++) {
|
||||
JSONObject lic = (JSONObject) data.get(i);
|
||||
try {
|
||||
Date addDate = DateConverter.parseCSTAsChinaTimezone(addDates.get(lic.getJSONObject(Constants.LICENSE).getString(Constants.SHORTID)));
|
||||
lic.put(Constants.ADDDATE, addDate);
|
||||
} catch (ParseException e) {
|
||||
logger.info("[getLicensesFromStore] can not resolve add date");
|
||||
}
|
||||
result.add(lic);
|
||||
}
|
||||
|
||||
} catch (MetaKvNotExistException e) {
|
||||
logger.info("[getLicenses] no LICENSEIDS data in MySQL DB");
|
||||
} catch (MetaKvInvalidKeyException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得在 MetaKV 表中的 license 信息
|
||||
*
|
||||
* @return JSONArray
|
||||
*/
|
||||
public JSONArray getLicensesInMetakv() {
|
||||
try {
|
||||
String value = retrieveMetaKv(Constants.LICENSEIDS).getMetavalue();
|
||||
return new JSONArray(value);
|
||||
} catch (MetaKvNotExistException e) {
|
||||
return new JSONArray();
|
||||
} catch (MetaKvInvalidKeyException e) {
|
||||
return new JSONArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param licenseShortId
|
||||
* @return
|
||||
* @throws InvalidResponseException
|
||||
*/
|
||||
public JSONObject getLicenseFromStore(final String licenseShortId) throws InvalidResponseException {
|
||||
Response resp = quotaWdClient.getLicenseInfo(licenseShortId);
|
||||
if (resp.getRc() == 0) {
|
||||
JSONArray data = (JSONArray) resp.getData();
|
||||
if (data.length() != 1)
|
||||
throw new InvalidResponseException("Unexpected data in Response.");
|
||||
|
||||
return (JSONObject) (data).get(0);
|
||||
} else {
|
||||
throw new InvalidResponseException("Unexpected Response.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,10 +16,17 @@ package com.cskefu.cc.util;
|
||||
|
||||
import org.apache.commons.beanutils.converters.DateTimeConverter;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
public class DateConverter extends DateTimeConverter {
|
||||
|
||||
final public static String ZONE_ID_DEFAULT = "Asia/Shanghai";
|
||||
// format date string like `Wed Aug 30 16:30:23 CST 2023` to Date
|
||||
public static SimpleDateFormat TIMEZONE_CHINA_FORMAT_DEFAULT = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
|
||||
|
||||
public DateConverter() {
|
||||
}
|
||||
|
||||
@ -51,4 +58,17 @@ public class DateConverter extends DateTimeConverter {
|
||||
}
|
||||
return super.convertToType(arg0, arg1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Java将CST的时间字符串转换成需要的日期格式字符串
|
||||
* https://blog.csdn.net/qq_44868502/article/details/103511505
|
||||
* (new Date()).toString() 与 String to Date 的转化
|
||||
*
|
||||
* @param dstr
|
||||
* @return
|
||||
* @throws ParseException
|
||||
*/
|
||||
static public Date parseCSTAsChinaTimezone(final String dstr) throws ParseException {
|
||||
return (Date) TIMEZONE_CHINA_FORMAT_DEFAULT.parse(dstr);
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ package com.cskefu.cc.util;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
@ -42,8 +43,39 @@ public class PugHelper {
|
||||
return new String(charr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在字符串中替换一些字符为 *, 起到混淆、加密、遮盖的敏感信息的目的
|
||||
*
|
||||
* @param prev
|
||||
* @return
|
||||
*/
|
||||
public String messupStringWithStars(final String prev) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
if (prev.length() >= 6) {
|
||||
sb.append("***");
|
||||
int initial = prev.length() - 4;
|
||||
for (int i = initial; i < prev.length(); i++) {
|
||||
sb.append(prev.charAt(i));
|
||||
}
|
||||
} else { // < 6
|
||||
if (prev.length() <= 2 && prev.length() > 0) {
|
||||
return "***";
|
||||
} else { // 2 < length < 6
|
||||
sb.append("***");
|
||||
int initial = prev.length() - 2;
|
||||
for (int i = initial; i < prev.length(); i++) {
|
||||
sb.append(prev.charAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 String 转化为 JSONArray
|
||||
*
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
|
@ -51,6 +51,13 @@ ul.layui-nav.layui-nav-tree(lay-filter='demo')
|
||||
dd(class={'layui-this': subtype == 'interf'})
|
||||
a(href='/admin/weixin/interf.html') 接口管理
|
||||
| –>
|
||||
if user.superadmin
|
||||
li.layui-nav-item.layui-nav-itemed
|
||||
a.layui-nav-title(href='javascript:;') 人工智能
|
||||
dl.layui-nav-child
|
||||
if models.contains("chatbot") && (user.roleAuthMap["A09"] || user.admin)
|
||||
dd
|
||||
a(href='javascript:void(0)',data-title="智能机器人",onclick="openChatbot()",data-href="/admin/system/chatbot/index.html",class="iframe_btn",data-id="chatbotIntegrationWin", data-type="tabAdd") 智能机器人
|
||||
if user.superadmin
|
||||
li.layui-nav-item.layui-nav-itemed
|
||||
a.layui-nav-title(href='javascript:;') 系统设置
|
||||
@ -61,15 +68,14 @@ ul.layui-nav.layui-nav-tree(lay-filter='demo')
|
||||
a(href='/admin/sysdic/index.html') 字典管理
|
||||
dd(class={'layui-this': subtype == 'metadata'})
|
||||
a(href='/admin/metadata/index.html') 元数据
|
||||
if models.contains("chatbot") && (user.roleAuthMap["A09"] || user.admin)
|
||||
dd
|
||||
a(href='javascript:void(0)',data-title="智能机器人",onclick="openChatbot()",data-href="/admin/system/chatbot/index.html",class="iframe_btn",data-id="chatbotIntegrationWin", data-type="tabAdd") 智能机器人
|
||||
dd(class={'layui-this': subtype == 'template'})
|
||||
a(href='/admin/template/index.html') 系统模板
|
||||
dd(class={'layui-this': subtype == 'email'})
|
||||
a(href='/admin/email/index.html') 邮件通知设置
|
||||
dd(class={'layui-this': subtype == 'sms'})
|
||||
a(href='/admin/sms/index.html') 短信通知设置
|
||||
dd(class={'layui-this': subtype == 'license'})
|
||||
a(href='/admin/license/index.html') 使用授权证书
|
||||
//dd(class={'layui-this': subtype == 'email'})
|
||||
// a(href='/admin/email/index.html') 邮件通知设置
|
||||
//dd(class={'layui-this': subtype == 'sms'})
|
||||
// a(href='/admin/sms/index.html') 短信通知设置
|
||||
|
||||
script.
|
||||
function openChatbot() {
|
||||
|
@ -0,0 +1,31 @@
|
||||
//- Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd.
|
||||
//- <https://www.chatopera.com>, Licensed under the Chunsong Public
|
||||
//- License, Version 1.0 (the "License"), https://docs.cskefu.com/licenses/v1.html
|
||||
//- Unless required by applicable law or agreed to in writing, software
|
||||
//- distributed under the License is distributed on an "AS IS" BASIS,
|
||||
//- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//- See the License for the specific language governing permissions and
|
||||
//- limitations under the License.
|
||||
.uk-layui-form
|
||||
form.layui-form(action='/admin/license/save.html', method='post')
|
||||
.layui-form-item(style='margin-top:10px;')
|
||||
.layui-inline
|
||||
label.layui-form-label(style='width:150px;') 证书短标识:
|
||||
.layui-input-inline
|
||||
input.layui-input(type='text', name='licenseShortId', required, lay-verify='required', autocomplete='off')
|
||||
.layui-form-mid.layui-word-aux
|
||||
font(color='red') *
|
||||
.layui-form-button
|
||||
.layui-button-block
|
||||
button.layui-btn(lay-submit, lay-filter='formNewLicense') 立即提交
|
||||
button.layui-btn.layui-btn-original(type='reset') 重置
|
||||
|
||||
script.
|
||||
layui.use('form', function () {
|
||||
var form = layui.form();
|
||||
form.render(); //更新全部
|
||||
});
|
||||
layui.use('element', function () {
|
||||
var element = layui.element();
|
||||
});
|
||||
|
@ -0,0 +1,78 @@
|
||||
//- Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd.
|
||||
//- <https://www.chatopera.com>, Licensed under the Chunsong Public
|
||||
//- License, Version 1.0 (the "License"), https://docs.cskefu.com/licenses/v1.html
|
||||
//- Unless required by applicable law or agreed to in writing, software
|
||||
//- distributed under the License is distributed on an "AS IS" BASIS,
|
||||
//- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//- See the License for the specific language governing permissions and
|
||||
//- limitations under the License.
|
||||
extends /admin/include/layout.pug
|
||||
block content
|
||||
.row: .col-lg-12
|
||||
h1.site-h1(style='background-color:#FFFFFF;')
|
||||
| 使用授权证书列表 (#{licenses.size()})
|
||||
| ,更新时间 #{pugHelper.formatDate('yyyy-MM-dd HH:mm:ss', updateTime)}
|
||||
span(style='float:right;')
|
||||
button.layui-btn.layui-btn-small.green(href='/admin/license/add.html', data-toggle='ajax', data-width='550', data-height='450', data-title='添加使用授权证书')
|
||||
| 添加使用授权证书
|
||||
|
||||
.row(style='padding:5px;')
|
||||
.col-lg-12
|
||||
table.layui-table(lay-skin='line')
|
||||
colgroup
|
||||
col(width='10%')
|
||||
col(width='10%')
|
||||
col(width='15%')
|
||||
col(width='10%')
|
||||
col(width='15%')
|
||||
col(width='10%')
|
||||
col(width='10%')
|
||||
col(width='1%')
|
||||
thead
|
||||
tr
|
||||
th 证书标识
|
||||
th 产品标识
|
||||
th 产品名称
|
||||
th 有效期截止
|
||||
th 配额剩余
|
||||
th 所属人昵称
|
||||
th 添加时间
|
||||
th(style='white-space:nowrap;', nowrap) 操作
|
||||
tbody
|
||||
for item in licenses
|
||||
tr
|
||||
td= pugHelper.messupStringWithStars(item.license.shortId)
|
||||
td= item.product.shortId
|
||||
td= item.product.name
|
||||
td= item.license.effectivedateend
|
||||
td= item.license.quotaeffectiveremaining
|
||||
td= item.user.nickname
|
||||
td= pugHelper.formatDate('yyyy-MM-dd HH:mm:ss', item.addDate)
|
||||
td(style="white-space:nowrap;" nowrap="nowrap")
|
||||
a(href="/admin/license/edit.html?id=" + item.license.shortId, data-toggle="ajax", data-width="550", data-height="450", data-title="编辑使用授权证书")
|
||||
i.layui-icon 
|
||||
span 编辑
|
||||
a(href="/admin/license/delete.html?id=" + item.license.shortId style="margin-left:10px;" data-toggle="tip" title="请确认是否删除使用授权证书?")
|
||||
i.layui-icon(style="color:red;") ဆ
|
||||
span 删除
|
||||
.row(style='padding:5px;')
|
||||
.col-lg-12#page(style='text-align:center;')
|
||||
|
||||
script.
|
||||
layui.use(['laypage', 'layer'], function () {
|
||||
var laypage = layui.laypage
|
||||
, layer = layui.layer;
|
||||
|
||||
// laypage({
|
||||
// cont: 'page'
|
||||
// , pages: #{emailList.totalPages} //总页数
|
||||
// , curr: #{emailList.number + 1}
|
||||
// , groups: 5 //连续显示分页数
|
||||
// , jump: function (data, first) {
|
||||
// if (!first) {
|
||||
// location.href = "/admin/email/index.html?p=" + data.curr;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
});
|
||||
|
@ -2229,7 +2229,6 @@ CREATE TABLE `uk_organ` (
|
||||
-- Records of uk_organ
|
||||
-- ----------------------------
|
||||
INSERT INTO `uk_organ` VALUES ('2c9e80867d65eb5c017d65f17ceb0019', '售前坐席A组', null, null, null, null, null, null, '4028a0866f9403f1016f9405a05d000e', '1', '');
|
||||
INSERT INTO `uk_organ` VALUES ('40288296874ae16101874ae4f2670016', '机器人平台', null, null, null, null, null, null, '4028a0866f9403f1016f9405a05d000e', '0', '');
|
||||
INSERT INTO `uk_organ` VALUES ('4028a0866f9403f1016f9405a05d000e', '我的企业', null, null, null, null, 'cskefu', null, '0', '0', '');
|
||||
|
||||
-- ----------------------------
|
||||
|
Loading…
x
Reference in New Issue
Block a user